|
import { useStore } from '@nanostores/react'; |
|
import { useEffect } from 'react'; |
|
import { shortcutsStore, type Shortcuts } from '~/lib/stores/settings'; |
|
|
|
class ShortcutEventEmitter { |
|
#emitter = new EventTarget(); |
|
|
|
dispatch(type: keyof Shortcuts) { |
|
this.#emitter.dispatchEvent(new Event(type)); |
|
} |
|
|
|
on(type: keyof Shortcuts, cb: VoidFunction) { |
|
this.#emitter.addEventListener(type, cb); |
|
|
|
return () => { |
|
this.#emitter.removeEventListener(type, cb); |
|
}; |
|
} |
|
} |
|
|
|
export const shortcutEventEmitter = new ShortcutEventEmitter(); |
|
|
|
export function useShortcuts(): void { |
|
const shortcuts = useStore(shortcutsStore); |
|
|
|
useEffect(() => { |
|
const handleKeyDown = (event: KeyboardEvent): void => { |
|
const { key, ctrlKey, shiftKey, altKey, metaKey } = event; |
|
|
|
for (const name in shortcuts) { |
|
const shortcut = shortcuts[name as keyof Shortcuts]; |
|
|
|
if ( |
|
shortcut.key.toLowerCase() === key.toLowerCase() && |
|
(shortcut.ctrlOrMetaKey |
|
? ctrlKey || metaKey |
|
: (shortcut.ctrlKey === undefined || shortcut.ctrlKey === ctrlKey) && |
|
(shortcut.metaKey === undefined || shortcut.metaKey === metaKey)) && |
|
(shortcut.shiftKey === undefined || shortcut.shiftKey === shiftKey) && |
|
(shortcut.altKey === undefined || shortcut.altKey === altKey) |
|
) { |
|
shortcutEventEmitter.dispatch(name as keyof Shortcuts); |
|
event.preventDefault(); |
|
event.stopPropagation(); |
|
|
|
shortcut.action(); |
|
|
|
break; |
|
} |
|
} |
|
}; |
|
|
|
window.addEventListener('keydown', handleKeyDown); |
|
|
|
return () => { |
|
window.removeEventListener('keydown', handleKeyDown); |
|
}; |
|
}, [shortcuts]); |
|
} |
|
|