Skip to content

Commit e71c25b

Browse files
committed
useKeyDownHandler: add types and remove unused class componnent helper
1 parent 00a91b2 commit e71c25b

File tree

1 file changed

+38
-43
lines changed

1 file changed

+38
-43
lines changed

client/common/useKeyDownHandlers.ts

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,27 @@ import { mapKeys } from 'lodash';
22
import PropTypes from 'prop-types';
33
import { useCallback, useEffect, useRef } from 'react';
44

5+
/**
6+
* Function to call upon keydown
7+
*/
8+
export type KeydownHandler = (e: KeyboardEvent) => void;
9+
/**
10+
* An object mapping from keys like 'ctrl-s' or 'ctrl-shift-1' to handlers.
11+
*/
12+
export type KeydownHandlerMap = Record<string, KeydownHandler>;
13+
514
/**
615
* Attaches keydown handlers to the global document.
7-
*
816
* Handles Mac/PC switching of Ctrl to Cmd.
917
*
10-
* @param {Record<string, (e: KeyboardEvent) => void>} keyHandlers - an object
11-
* which maps from the key to its event handler. The object keys are a combination
12-
* of the key and prefixes `ctrl-` `shift-` (ie. 'ctrl-f', 'ctrl-shift-f')
13-
* and the values are the function to call when that specific key is pressed.
18+
* @param keyHandlers - an object which maps from the key to its event handler. The object keys are a combination of the key and prefixes `ctrl-` `shift-` (ie. 'ctrl-f', 'ctrl-shift-f') and the values are the function to call when that specific key is pressed.
1419
*/
15-
export default function useKeyDownHandlers(keyHandlers) {
20+
export default function useKeyDownHandlers(keyHandlers: KeydownHandlerMap) {
1621
/**
1722
* Instead of memoizing the handlers, use a ref and call the current
1823
* handler at the time of the event.
1924
*/
20-
const handlers = useRef(keyHandlers);
25+
const handlers = useRef<KeydownHandlerMap>(keyHandlers);
2126

2227
useEffect(() => {
2328
handlers.current = mapKeys(keyHandlers, (value, key) => key?.toLowerCase());
@@ -26,47 +31,37 @@ export default function useKeyDownHandlers(keyHandlers) {
2631
/**
2732
* Will call all matching handlers, starting with the most specific: 'ctrl-shift-f' => 'ctrl-f' => 'f'.
2833
* Can use e.stopPropagation() to prevent subsequent handlers.
29-
* @type {(function(KeyboardEvent): void)}
3034
*/
31-
const handleEvent = useCallback((e) => {
32-
if (!e.key) return;
33-
const isMac = navigator.userAgent.toLowerCase().indexOf('mac') !== -1;
34-
const isCtrl = isMac ? e.metaKey : e.ctrlKey;
35-
if (e.shiftKey && isCtrl) {
36-
handlers.current[
37-
`ctrl-shift-${
38-
/^\d+$/.test(e.code.at(-1)) ? e.code.at(-1) : e.key.toLowerCase()
39-
}`
40-
]?.(e);
41-
} else if (isCtrl && e.altKey && e.code === 'KeyN') {
42-
// specifically for creating a new file
43-
handlers.current[`ctrl-alt-n`]?.(e);
44-
} else if (isCtrl) {
45-
handlers.current[`ctrl-${e.key.toLowerCase()}`]?.(e);
46-
}
47-
handlers.current[e.key?.toLowerCase()]?.(e);
48-
}, []);
35+
const handleEvent: (e: KeyboardEvent) => void = useCallback(
36+
(e: KeyboardEvent) => {
37+
if (!e.key) return;
38+
39+
const isMac = navigator.userAgent.toLowerCase().indexOf('mac') !== -1;
40+
const isCtrl = isMac ? e.metaKey : e.ctrlKey;
41+
42+
if (e.shiftKey && isCtrl) {
43+
handlers.current[
44+
`ctrl-shift-${
45+
/^\d+$/.test(e.code.at(-1) || '')
46+
? e.code.at(-1)
47+
: e.key.toLowerCase()
48+
}`
49+
]?.(e);
50+
} else if (isCtrl && e.altKey && e.code === 'KeyN') {
51+
// specifically for creating a new file
52+
handlers.current[`ctrl-alt-n`]?.(e);
53+
} else if (isCtrl) {
54+
handlers.current[`ctrl-${e.key.toLowerCase()}`]?.(e);
55+
}
56+
57+
handlers.current[e.key?.toLowerCase()]?.(e);
58+
},
59+
[]
60+
);
4961

5062
useEffect(() => {
5163
document.addEventListener('keydown', handleEvent);
5264

5365
return () => document.removeEventListener('keydown', handleEvent);
5466
}, [handleEvent]);
5567
}
56-
57-
/**
58-
* Component version can be used in class components where hooks can't be used.
59-
*
60-
* @param {Record<string, (e: KeyboardEvent) => void>} handlers
61-
*/
62-
export const DocumentKeyDown = ({ handlers }) => {
63-
useKeyDownHandlers(handlers);
64-
return null;
65-
};
66-
DocumentKeyDown.propTypes = {
67-
handlers: PropTypes.objectOf(PropTypes.func)
68-
};
69-
70-
DocumentKeyDown.defaultProps = {
71-
handlers: {}
72-
};

0 commit comments

Comments
 (0)