Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ if (import.meta.server) {
const keyboardShortcuts = useKeyboardShortcuts()
const { settings } = useSettings()

initKeyShortcuts()

onKeyDown(
'/',
e => {
Expand Down
22 changes: 4 additions & 18 deletions app/components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<script setup lang="ts">
import { LinkBase } from '#components'
import type { NavigationConfig, NavigationConfigWithGroups } from '~/types'
import { isEditableElement } from '~/utils/input'
import { NPMX_DOCS_SITE } from '#shared/utils/constants'

const keyboardShortcuts = useKeyboardShortcuts()
const discord = useDiscordLink()

withDefaults(
Expand Down Expand Up @@ -200,22 +198,10 @@ function handleSearchFocus() {
showFullSearch.value = true
}

onKeyStroke(
e => {
if (!keyboardShortcuts.value || isEditableElement(e.target)) {
return
}

for (const link of desktopLinks.value) {
if (link.to && link.keyshortcut && isKeyWithoutModifiers(e, link.keyshortcut)) {
e.preventDefault()
navigateTo(link.to)
break
}
}
},
{ dedupe: true },
)
useShortcuts({
'c': () => ({ name: 'compare' }),
',': () => ({ name: 'settings' }),
})
</script>

<template>
Expand Down
62 changes: 7 additions & 55 deletions app/components/Package/Header.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { RouteLocationRaw } from 'vue-router'
import { SCROLL_TO_TOP_THRESHOLD } from '~/composables/useScrollToTop'
import { isEditableElement } from '~/utils/input'

const props = defineProps<{
pkg?: Pick<SlimPackument, 'name' | 'versions' | 'dist-tags'> | null
Expand Down Expand Up @@ -72,7 +71,6 @@ function hasProvenance(version: PackumentVersion | null): boolean {
return !!(version.dist as { attestations?: unknown }).attestations
}

const router = useRouter()
// Docs URL: use our generated API docs
const docsLink = computed(() => {
if (!props.resolvedVersion) return null
Expand Down Expand Up @@ -120,59 +118,13 @@ const diffLink = computed((): RouteLocationRaw | null => {
return diffRoute(props.pkg.name, props.resolvedVersion, props.latestVersion.version)
})

const keyboardShortcuts = useKeyboardShortcuts()

onKeyStroke(
e => keyboardShortcuts.value && isKeyWithoutModifiers(e, '.') && !isEditableElement(e.target),
e => {
if (codeLink.value === null) return
e.preventDefault()

navigateTo(codeLink.value)
},
{ dedupe: true },
)

onKeyStroke(
e => keyboardShortcuts.value && isKeyWithoutModifiers(e, 'm') && !isEditableElement(e.target),
e => {
if (mainLink.value === null) return
e.preventDefault()

navigateTo(mainLink.value)
},
{ dedupe: true },
)

onKeyStroke(
e => keyboardShortcuts.value && isKeyWithoutModifiers(e, 'd') && !isEditableElement(e.target),
e => {
if (!docsLink.value) return
e.preventDefault()
navigateTo(docsLink.value)
},
{ dedupe: true },
)

onKeyStroke(
e => keyboardShortcuts.value && isKeyWithoutModifiers(e, 'c') && !isEditableElement(e.target),
e => {
if (!props.pkg) return
e.preventDefault()
router.push({ name: 'compare', query: { packages: props.pkg.name } })
},
{ dedupe: true },
)

onKeyStroke(
e => keyboardShortcuts.value && isKeyWithoutModifiers(e, 'f') && !isEditableElement(e.target),
e => {
if (diffLink.value === null) return
e.preventDefault()
navigateTo(diffLink.value)
},
{ dedupe: true },
)
useShortcuts({
'.': () => codeLink.value,
'm': () => mainLink.value,
'd': () => docsLink.value,
'c': () => props.pkg && { name: 'compare' as const, query: { packages: props.pkg.name } },
'f': () => diffLink.value,
})

const fundingUrl = computed(() => {
let funding = props.displayVersion?.funding
Expand Down
47 changes: 47 additions & 0 deletions app/composables/useShortcuts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { RouteLocationRaw } from 'vue-router'
import { isEditableElement, isKeyWithoutModifiers } from '~/utils/input'

type ShortcutTarget = RouteLocationRaw | null | false | undefined
type ShortcutTargetFactory = () => ShortcutTarget

const registry = new Map<string, ShortcutTargetFactory[]>()

export function initKeyShortcuts() {
const keyboardShortcuts = useKeyboardShortcuts()

onKeyStroke(
e => !e.repeat && keyboardShortcuts.value && !isEditableElement(e.target),
e => {
for (const [key, stack] of registry) {
if (!isKeyWithoutModifiers(e, key)) continue
const getTarget = stack.at(-1)
if (!getTarget) continue
const target = getTarget()
if (!target) return
e.preventDefault()
navigateTo(target)
return
}
},
)
}

export function useShortcuts(map: Record<string, () => ShortcutTarget>) {
if (!import.meta.client) return

for (const [key, fn] of Object.entries(map)) {
const entry = registry.get(key) ?? []
if (entry.includes(fn)) continue
entry.push(fn)
registry.set(key, entry)
}

onScopeDispose(() => {
for (const [key, fn] of Object.entries(map)) {
const stack = registry.get(key)
if (!stack) continue
const idx = stack.lastIndexOf(fn)
if (idx !== -1) stack.splice(idx, 1)
}
})
}
Loading