-
Notifications
You must be signed in to change notification settings - Fork 222
/
Copy pathshortcuts.tsx
49 lines (45 loc) · 1.48 KB
/
shortcuts.tsx
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
import { useCallback, useEffect, useState } from 'react';
export const useKeyDown = (
shortcutMap: Map<string[], Function>,
node = document
) => {
const [currentShortcutKeys, setCurrentShortcutKeys] = useState<string[]>([]);
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
// If key is already depressed, return early
if (currentShortcutKeys.includes(event.key)) {
return;
}
const newShortcutKeys = currentShortcutKeys.concat([event.key]);
for (const [keys, cb] of shortcutMap.entries()) {
// Note: this implementation cares about order of keys pressed
if (
keys.length === newShortcutKeys.length &&
keys.every((val, i) => newShortcutKeys[i] === val)
) {
cb(event);
}
}
setCurrentShortcutKeys(newShortcutKeys);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[shortcutMap]
);
const handleKeyUp = (event: KeyboardEvent) => {
setCurrentShortcutKeys((prev) => {
const keyIndex = prev.indexOf(event.key);
if (keyIndex !== -1) {
return prev.slice(0, keyIndex).concat(prev.slice(keyIndex + 1));
}
return prev;
});
};
useEffect(() => {
node.addEventListener('keydown', handleKeyDown);
node.addEventListener('keyup', handleKeyUp);
return () => {
node.removeEventListener('keydown', handleKeyDown);
node.removeEventListener('keydown', handleKeyUp);
};
}, [handleKeyDown, node]);
};