78 lines
1.7 KiB
TypeScript
78 lines
1.7 KiB
TypeScript
// Original source from Mantine
|
|
// https://github.com/mantinedev/mantine/blob/master/src/mantine-hooks/src/use-hotkeys/parse-hotkey.ts
|
|
|
|
export type KeyboardModifiers = {
|
|
alt: boolean;
|
|
ctrl: boolean;
|
|
meta: boolean;
|
|
mod: boolean;
|
|
shift: boolean;
|
|
};
|
|
|
|
export type Hotkey = KeyboardModifiers & {
|
|
key?: string;
|
|
};
|
|
|
|
type CheckHotkeyMatch = (event: KeyboardEvent) => boolean;
|
|
|
|
export function parseHotkey(hotkey: string): Hotkey {
|
|
const keys = hotkey
|
|
.toLowerCase()
|
|
.split('+')
|
|
.map((part) => part.trim());
|
|
|
|
const modifiers: KeyboardModifiers = {
|
|
alt: keys.includes('alt'),
|
|
ctrl: keys.includes('ctrl'),
|
|
meta: keys.includes('meta'),
|
|
mod: keys.includes('mod'),
|
|
shift: keys.includes('shift'),
|
|
};
|
|
|
|
const reservedKeys = ['alt', 'ctrl', 'meta', 'shift', 'mod'];
|
|
|
|
const freeKey = keys.find((key) => !reservedKeys.includes(key));
|
|
|
|
return {
|
|
...modifiers,
|
|
key: freeKey,
|
|
};
|
|
}
|
|
|
|
function isExactHotkey(hotkey: Hotkey, event: KeyboardEvent): boolean {
|
|
const {
|
|
alt, ctrl, meta, mod, shift, key,
|
|
} = hotkey;
|
|
const {
|
|
altKey, ctrlKey, metaKey, shiftKey, key: pressedKey,
|
|
} = event;
|
|
|
|
if (alt !== altKey) {
|
|
return false;
|
|
}
|
|
|
|
if (mod) {
|
|
if (!ctrlKey && !metaKey) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (ctrl !== ctrlKey) {
|
|
return false;
|
|
}
|
|
if (meta !== metaKey) {
|
|
return false;
|
|
}
|
|
}
|
|
if (shift !== shiftKey) {
|
|
return false;
|
|
}
|
|
|
|
return Boolean(key
|
|
&& (pressedKey.toLowerCase() === key.toLowerCase()
|
|
|| event.code.replace('Key', '').toLowerCase() === key.toLowerCase()));
|
|
}
|
|
|
|
export function getHotkeyMatcher(hotkey: string): CheckHotkeyMatch {
|
|
return (event) => isExactHotkey(parseHotkey(hotkey), event);
|
|
}
|