diff options
Diffstat (limited to 'packages/client/src/scripts/hotkey.ts')
| -rw-r--r-- | packages/client/src/scripts/hotkey.ts | 90 |
1 files changed, 0 insertions, 90 deletions
diff --git a/packages/client/src/scripts/hotkey.ts b/packages/client/src/scripts/hotkey.ts deleted file mode 100644 index 4a0ded637d..0000000000 --- a/packages/client/src/scripts/hotkey.ts +++ /dev/null @@ -1,90 +0,0 @@ -import keyCode from './keycode'; - -type Callback = (ev: KeyboardEvent) => void; - -type Keymap = Record<string, Callback>; - -type Pattern = { - which: string[]; - ctrl?: boolean; - shift?: boolean; - alt?: boolean; -}; - -type Action = { - patterns: Pattern[]; - callback: Callback; - allowRepeat: boolean; -}; - -const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([patterns, callback]): Action => { - const result = { - patterns: [], - callback, - allowRepeat: true, - } as Action; - - if (patterns.match(/^\(.*\)$/) !== null) { - result.allowRepeat = false; - patterns = patterns.slice(1, -1); - } - - result.patterns = patterns.split('|').map(part => { - const pattern = { - which: [], - ctrl: false, - alt: false, - shift: false, - } as Pattern; - - const keys = part.trim().split('+').map(x => x.trim().toLowerCase()); - for (const key of keys) { - switch (key) { - case 'ctrl': pattern.ctrl = true; break; - case 'alt': pattern.alt = true; break; - case 'shift': pattern.shift = true; break; - default: pattern.which = keyCode(key).map(k => k.toLowerCase()); - } - } - - return pattern; - }); - - return result; -}); - -const ignoreElemens = ['input', 'textarea']; - -function match(ev: KeyboardEvent, patterns: Action['patterns']): boolean { - const key = ev.code.toLowerCase(); - return patterns.some(pattern => pattern.which.includes(key) && - pattern.ctrl === ev.ctrlKey && - pattern.shift === ev.shiftKey && - pattern.alt === ev.altKey && - !ev.metaKey, - ); -} - -export const makeHotkey = (keymap: Keymap) => { - const actions = parseKeymap(keymap); - - return (ev: KeyboardEvent) => { - if (document.activeElement) { - if (ignoreElemens.some(el => document.activeElement!.matches(el))) return; - if (document.activeElement.attributes['contenteditable']) return; - } - - for (const action of actions) { - const matched = match(ev, action.patterns); - - if (matched) { - if (!action.allowRepeat && ev.repeat) return; - - ev.preventDefault(); - ev.stopPropagation(); - action.callback(ev); - break; - } - } - }; -}; |