52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
type ShortcutHandler = {
|
|
key: string;
|
|
ctrl?: boolean;
|
|
shift?: boolean;
|
|
handler: () => void;
|
|
when?: () => boolean;
|
|
};
|
|
|
|
let registered = false;
|
|
let shortcuts: ShortcutHandler[] = [];
|
|
let cleanup: (() => void) | null = null;
|
|
|
|
export function setShortcuts(handlers: ShortcutHandler[]) {
|
|
shortcuts = handlers;
|
|
}
|
|
|
|
export function registerShortcuts() {
|
|
if (registered) return;
|
|
registered = true;
|
|
|
|
const onKeyDown = (e: KeyboardEvent) => {
|
|
// skip when typing in inputs
|
|
const tag = (e.target as HTMLElement)?.tagName;
|
|
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;
|
|
|
|
for (const s of shortcuts) {
|
|
const ctrlMatch = s.ctrl ? (e.ctrlKey || e.metaKey) : !(e.ctrlKey || e.metaKey);
|
|
const shiftMatch = s.shift ? e.shiftKey : !e.shiftKey;
|
|
const keyMatch = e.key === s.key || e.code === s.key;
|
|
|
|
if (keyMatch && ctrlMatch && shiftMatch) {
|
|
if (s.when && !s.when()) continue;
|
|
e.preventDefault();
|
|
s.handler();
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', onKeyDown);
|
|
cleanup = () => {
|
|
window.removeEventListener('keydown', onKeyDown);
|
|
registered = false;
|
|
};
|
|
}
|
|
|
|
export function unregisterShortcuts() {
|
|
cleanup?.();
|
|
cleanup = null;
|
|
shortcuts = [];
|
|
}
|