[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: prefer vueuse `onKeyStroke` (#1039)

authored by

Robin and committed by
GitHub
0d40d1ed fabe1c29

+75 -59
+24 -20
app/app.vue
··· 1 1 <script setup lang="ts"> 2 2 import type { Directions } from '@nuxtjs/i18n' 3 - import { useEventListener } from '@vueuse/core' 3 + import { useEventListener, onKeyDown, onKeyUp } from '@vueuse/core' 4 4 import { isEditableElement } from '~/utils/input' 5 5 6 6 const route = useRoute() ··· 47 47 setJsonLd(createWebSiteSchema()) 48 48 } 49 49 50 - // Global keyboard shortcut: 51 - // "/" focuses search or navigates to search page 52 - // "?" highlights all keyboard shortcut elements 53 - function handleGlobalKeydown(e: KeyboardEvent) { 54 - if (isEditableElement(e.target)) return 55 - 56 - if (isKeyWithoutModifiers(e, '/')) { 50 + onKeyDown( 51 + '/', 52 + e => { 53 + if (isEditableElement(e.target)) return 57 54 e.preventDefault() 58 55 59 - // Try to find and focus search input on current page 60 56 const searchInput = document.querySelector<HTMLInputElement>( 61 57 'input[type="search"], input[name="q"]', 62 58 ) ··· 67 63 } 68 64 69 65 router.push('/search') 70 - } 66 + }, 67 + { dedupe: true }, 68 + ) 71 69 72 - // For "?" we check the key property directly since it's usually combined with shift 73 - if (e.key === '?') { 70 + onKeyDown( 71 + '?', 72 + e => { 73 + if (isEditableElement(e.target)) return 74 74 e.preventDefault() 75 75 showKbdHints.value = true 76 - } 77 - } 76 + }, 77 + { dedupe: true }, 78 + ) 78 79 79 - function handleGlobalKeyup() { 80 - showKbdHints.value = false 81 - } 80 + onKeyUp( 81 + '?', 82 + e => { 83 + if (isEditableElement(e.target)) return 84 + e.preventDefault() 85 + showKbdHints.value = false 86 + }, 87 + { dedupe: true }, 88 + ) 82 89 83 90 // Light dismiss fallback for browsers that don't support closedby="any" (Safari + old Chrome/Firefox) 84 91 // https://codepen.io/paramagicdev/pen/gbYompq ··· 99 106 } 100 107 101 108 if (import.meta.client) { 102 - useEventListener(document, 'keydown', handleGlobalKeydown) 103 - useEventListener(document, 'keyup', handleGlobalKeyup) 104 - 105 109 // Feature check for native light dismiss support via closedby="any" 106 110 // https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog#closedby 107 111 const supportsClosedBy =
+9 -5
app/components/ColumnPicker.vue
··· 1 1 <script setup lang="ts"> 2 2 import type { ColumnConfig, ColumnId } from '#shared/types/preferences' 3 + import { onKeyDown } from '@vueuse/core' 3 4 4 5 const props = defineProps<{ 5 6 columns: ColumnConfig[] ··· 26 27 }, 27 28 ) 28 29 29 - // Close on Escape key 30 - useEventListener('keydown', event => { 31 - if (event.key === 'Escape' && isOpen.value) { 30 + onKeyDown( 31 + 'Escape', 32 + e => { 33 + if (!isOpen.value) return 32 34 isOpen.value = false 33 35 buttonRef.value?.focus() 34 - } 35 - }) 36 + }, 37 + { dedupe: true }, 38 + ) 39 + 36 40 // Columns that can be toggled (name is always visible) 37 41 const toggleableColumns = computed(() => props.columns.filter(col => col.id !== 'name')) 38 42
+41 -33
app/components/DependencyPathPopup.vue
··· 1 1 <script setup lang="ts"> 2 + import { onKeyDown } from '@vueuse/core' 3 + import { UseFocusTrap } from '@vueuse/integrations/useFocusTrap/component' 4 + 2 5 defineProps<{ 3 6 /** Dependency path from root to vulnerable package (readonly from VulnerabilityTreeResult) */ 4 7 path: readonly string[] ··· 17 20 if (isOpen.value) closePopup() 18 21 }) 19 22 20 - // Close popup on ESC or scroll 21 - function handleKeydown(e: KeyboardEvent) { 22 - if (e.key === 'Escape') closePopup() 23 - } 23 + onKeyDown( 24 + 'Escape', 25 + e => { 26 + e.preventDefault() 27 + closePopup() 28 + }, 29 + { dedupe: true, target: popupEl }, 30 + ) 24 31 25 - useEventListener(document, 'keydown', handleKeydown) 26 - useEventListener('scroll', closePopup, true) 32 + useEventListener('scroll', closePopup, { passive: true }) 27 33 28 34 function togglePopup(event: MouseEvent) { 29 35 if (isOpen.value) { ··· 77 83 class="fixed z-[100] bg-bg-elevated border border-border rounded-lg shadow-xl p-3 min-w-64 max-w-sm" 78 84 :style="getPopupStyle()" 79 85 > 80 - <ul class="list-none m-0 p-0 space-y-0.5"> 81 - <li 82 - v-for="(pathItem, idx) in path" 83 - :key="idx" 84 - class="font-mono text-xs" 85 - :style="{ paddingLeft: `${idx * 12}px` }" 86 - > 87 - <span v-if="idx > 0" class="text-fg-subtle me-1">└─</span> 88 - <NuxtLink 89 - :to="{ 90 - name: 'package', 91 - params: { 92 - package: [ 93 - ...parsePackageString(pathItem).name.split('/'), 94 - 'v', 95 - parsePackageString(pathItem).version, 96 - ], 97 - }, 98 - }" 99 - class="hover:underline" 100 - :class="idx === path.length - 1 ? 'text-fg font-medium' : 'text-fg-muted'" 101 - @click="closePopup" 86 + <UseFocusTrap :options="{ immediate: true }"> 87 + <ul class="list-none m-0 p-0 space-y-0.5"> 88 + <li 89 + v-for="(pathItem, idx) in path" 90 + :key="idx" 91 + class="font-mono text-xs" 92 + :style="{ paddingLeft: `${idx * 12}px` }" 102 93 > 103 - {{ pathItem }} 104 - </NuxtLink> 105 - <span v-if="idx === path.length - 1" class="ms-1 text-amber-500">⚠</span> 106 - </li> 107 - </ul> 94 + <span v-if="idx > 0" class="text-fg-subtle me-1">└─</span> 95 + <NuxtLink 96 + :to="{ 97 + name: 'package', 98 + params: { 99 + package: [ 100 + ...parsePackageString(pathItem).name.split('/'), 101 + 'v', 102 + parsePackageString(pathItem).version, 103 + ], 104 + }, 105 + }" 106 + class="hover:underline" 107 + :class="idx === path.length - 1 ? 'text-fg font-medium' : 'text-fg-muted'" 108 + @click="closePopup" 109 + > 110 + {{ pathItem }} 111 + </NuxtLink> 112 + <span v-if="idx === path.length - 1" class="ms-1 text-amber-500">⚠</span> 113 + </li> 114 + </ul> 115 + </UseFocusTrap> 108 116 </div> 109 117 </div> 110 118 </template>
+1 -1
app/components/ReadmeTocDropdown.vue
··· 69 69 } 70 70 close() 71 71 } 72 - useEventListener('scroll', handleScroll, true) 72 + useEventListener('scroll', handleScroll, { passive: true }) 73 73 74 74 // Generate unique ID for accessibility 75 75 const inputId = useId()