-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseKey.ts
43 lines (38 loc) · 1.31 KB
/
useKey.ts
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
import { DependencyList, useMemo } from 'react';
import useEvent, { UseEventOptions, UseEventTarget } from './useEvent';
import { noop } from './misc/util';
export type KeyPredicate = (event: KeyboardEvent) => boolean;
export type KeyFilter = null | undefined | string | ((event: KeyboardEvent) => boolean);
export type Handler = (event: KeyboardEvent) => void;
export interface UseKeyOptions<T extends UseEventTarget> {
event?: 'keydown' | 'keypress' | 'keyup';
target?: T | null;
options?: UseEventOptions<T>;
}
const createKeyPredicate = (keyFilter: KeyFilter): KeyPredicate =>
typeof keyFilter === 'function'
? keyFilter
: typeof keyFilter === 'string'
? (event: KeyboardEvent) => event.key === keyFilter
: keyFilter
? () => true
: () => false;
const useKey = <T extends UseEventTarget>(
key: KeyFilter,
fn: Handler = noop,
opts: UseKeyOptions<T> = {},
deps: DependencyList = [key]
) => {
const { event = 'keydown', target, options } = opts;
const useMemoHandler = useMemo(() => {
const predicate: KeyPredicate = createKeyPredicate(key);
const handler: Handler = (handlerEvent) => {
if (predicate(handlerEvent)) {
return fn(handlerEvent);
}
};
return handler;
}, deps);
useEvent(event, useMemoHandler, target, options);
};
export default useKey;