-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
use-combobox-target-props.ts
93 lines (80 loc) · 2.64 KB
/
use-combobox-target-props.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
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
import { useState } from 'react';
import { useComboboxContext } from '../Combobox.context';
interface UseComboboxTargetPropsInput {
targetType: 'input' | 'button' | undefined;
withAriaAttributes: boolean | undefined;
withKeyboardNavigation: boolean | undefined;
withExpandedAttribute: boolean | undefined;
onKeyDown: React.KeyboardEventHandler<HTMLInputElement> | undefined;
}
export function useComboboxTargetProps({
onKeyDown,
withKeyboardNavigation,
withAriaAttributes,
withExpandedAttribute,
targetType,
}: UseComboboxTargetPropsInput) {
const ctx = useComboboxContext();
const [selectedOptionId, setSelectedOptionId] = useState<string | null>(null);
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
onKeyDown?.(event);
if (ctx.readOnly) {
return;
}
if (withKeyboardNavigation) {
if (event.nativeEvent.code === 'ArrowDown') {
event.preventDefault();
if (!ctx.store.dropdownOpened) {
ctx.store.openDropdown('keyboard');
setSelectedOptionId(ctx.store.selectActiveOption());
} else {
setSelectedOptionId(ctx.store.selectNextOption());
}
}
if (event.nativeEvent.code === 'ArrowUp') {
event.preventDefault();
if (!ctx.store.dropdownOpened) {
ctx.store.openDropdown('keyboard');
setSelectedOptionId(ctx.store.selectActiveOption());
} else {
setSelectedOptionId(ctx.store.selectPreviousOption());
}
}
if (event.nativeEvent.code === 'Enter') {
if (ctx.store.dropdownOpened) {
event.preventDefault();
ctx.store.clickSelectedOption();
} else if (targetType === 'button') {
event.preventDefault();
ctx.store.openDropdown('keyboard');
}
}
if (event.nativeEvent.code === 'Escape') {
ctx.store.closeDropdown('keyboard');
}
if (event.nativeEvent.code === 'Space') {
if (targetType === 'button') {
event.preventDefault();
ctx.store.toggleDropdown('keyboard');
}
}
}
};
const ariaAttributes = withAriaAttributes
? {
'aria-haspopup': 'listbox',
'aria-expanded':
(withExpandedAttribute && !!(ctx.store.listId && ctx.store.dropdownOpened)) || undefined,
'aria-controls': ctx.store.listId,
'aria-activedescendant': ctx.store.dropdownOpened
? selectedOptionId || undefined
: undefined,
autoComplete: 'off',
'data-expanded': ctx.store.dropdownOpened ? true : undefined,
}
: {};
return {
...ariaAttributes,
onKeyDown: handleKeyDown,
};
}