Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | import { onMounted, onUnmounted } from 'vue' export interface ShortcutConfig { key: string ctrl?: boolean meta?: boolean shift?: boolean alt?: boolean handler: () => void preventDefault?: boolean } export function useKeyboardShortcuts(shortcuts: Record<string, () => void> | ShortcutConfig[]) { const normalizedShortcuts: ShortcutConfig[] = [] if (Array.isArray(shortcuts)) { normalizedShortcuts.push(...shortcuts) } else { for (const [combo, handler] of Object.entries(shortcuts)) { const parts = combo.toLowerCase().split('+') const lastPart = parts[parts.length - 1] if (!lastPart) continue // Skip invalid shortcuts const config: ShortcutConfig = { key: lastPart, handler, preventDefault: true, } for (const part of parts.slice(0, -1)) { if (part === 'ctrl') config.ctrl = true if (part === 'cmd' || part === 'meta') config.meta = true if (part === 'shift') config.shift = true if (part === 'alt') config.alt = true } normalizedShortcuts.push(config) } } const handleKeyDown = (event: KeyboardEvent) => { for (const shortcut of normalizedShortcuts) { const ctrlOrMeta = shortcut.ctrl || shortcut.meta const isCtrlPressed = event.ctrlKey || event.metaKey const matchesShift = shortcut.shift ? event.shiftKey : !event.shiftKey const matchesAlt = shortcut.alt ? event.altKey : !event.altKey if ( shortcut.key === event.key.toLowerCase() && (!ctrlOrMeta || isCtrlPressed === true) && matchesShift && matchesAlt ) { if (shortcut.preventDefault !== false) { event.preventDefault() } shortcut.handler() break } } } const register = () => { document.addEventListener('keydown', handleKeyDown) } const unregister = () => { document.removeEventListener('keydown', handleKeyDown) } // Auto register/unregister with component lifecycle onMounted(register) onUnmounted(unregister) return { register, unregister, } } |