-
Notifications
You must be signed in to change notification settings - Fork 199
Expand file tree
/
Copy pathuseInputKeyboardController.ts
More file actions
95 lines (88 loc) · 2.58 KB
/
useInputKeyboardController.ts
File metadata and controls
95 lines (88 loc) · 2.58 KB
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import * as React from 'react';
import { useGlobalEscKeyDown } from '../../../hooks/useGlobalEscKeyDown';
import { Keys, pressedKey } from '../../../lib/accessibility';
import type { SelectProps } from '../CustomSelect';
import type { UseFocusedOptionControllerReturn } from './useFocusedOptionController';
const KEYS_TO_PREVENT_DEFAULT: string[] = [Keys.ARROW_UP, Keys.ARROW_DOWN, Keys.ESCAPE, Keys.ENTER];
/* eslint-disable jsdoc/require-jsdoc */
interface UseInputKeyboardController
extends Pick<UseFocusedOptionControllerReturn, 'resetFocusedOption' | 'focusOption'>,
Pick<SelectProps, 'onInputKeyDown'> {
opened: boolean;
scrollBoxRef: React.RefObject<HTMLDivElement | null>;
selectFocused: () => void;
open: () => void;
close: () => void;
}
/* eslint-enable jsdoc/require-jsdoc */
export function useInputKeyboardController({
opened,
resetFocusedOption,
focusOption,
scrollBoxRef,
selectFocused,
onInputKeyDown,
open,
close,
}: UseInputKeyboardController) {
const handleKeyDownSelect = React.useCallback(
(event: React.KeyboardEvent) => {
const key = pressedKey(event);
if (event.key.length === 1 && key !== Keys.SPACE) {
open();
resetFocusedOption();
return;
}
if (!key) {
return;
}
const areOptionsShown = () => scrollBoxRef.current !== null;
if (KEYS_TO_PREVENT_DEFAULT.includes(key)) {
event.preventDefault();
}
switch (key) {
case Keys.ARROW_UP:
if (opened) {
areOptionsShown() && focusOption('prev');
} else {
open();
}
break;
case Keys.ARROW_DOWN:
if (opened) {
areOptionsShown() && focusOption('next');
} else {
open();
}
break;
case Keys.BACKSPACE:
case Keys.DELETE: {
open();
resetFocusedOption();
break;
}
case Keys.ENTER:
case Keys.SPACE:
if (opened) {
areOptionsShown() && selectFocused();
} else {
open();
}
break;
}
},
[scrollBoxRef, opened, focusOption, open, resetFocusedOption, selectFocused],
);
useGlobalEscKeyDown(opened, () => close());
const handleInputKeydown = React.useCallback(
(event: React.KeyboardEvent) => {
onInputKeyDown?.(event, opened);
},
[opened, onInputKeyDown],
);
const _onInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
handleKeyDownSelect(event);
handleInputKeydown(event);
};
return _onInputKeyDown;
}