@workday/canvas-kit-react 10.0.0-alpha.540-next.0 → 10.0.0-alpha.546-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/collection/index.ts +1 -0
- package/collection/lib/useBaseListModel.tsx +3 -3
- package/collection/lib/useListItemRegister.tsx +1 -1
- package/collection/lib/useListRenderItem.tsx +2 -2
- package/combobox/index.ts +11 -4
- package/combobox/lib/Combobox.tsx +1 -1
- package/combobox/lib/ComboboxCard.tsx +1 -1
- package/combobox/lib/ComboboxInput.tsx +2 -90
- package/combobox/lib/ComboboxMenu.tsx +4 -3
- package/combobox/lib/ComboboxMenuItem.tsx +9 -8
- package/combobox/lib/ComboboxMenuList.tsx +1 -1
- package/combobox/lib/ComboboxPopper.tsx +20 -0
- package/combobox/lib/hooks/index.ts +9 -0
- package/combobox/lib/hooks/useComboboxInput.ts +88 -0
- package/combobox/lib/hooks/useComboboxKeyboardTypeAhead.ts +127 -0
- package/combobox/lib/hooks/useComboboxListKeyboardHandler.ts +23 -0
- package/combobox/lib/{useComboboxModel.tsx → hooks/useComboboxModel.tsx} +6 -2
- package/combobox/lib/hooks/useComboboxMoveCursorToSelected.tsx +27 -0
- package/combobox/lib/hooks/useComboboxResetCursorToSelected.tsx +18 -0
- package/combobox/lib/hooks/useSetPopupWidth.ts +16 -0
- package/common/lib/utils/components.ts +284 -274
- package/common/lib/utils/models.ts +67 -84
- package/dist/commonjs/collection/index.d.ts +1 -0
- package/dist/commonjs/collection/index.d.ts.map +1 -1
- package/dist/commonjs/collection/index.js +3 -1
- package/dist/commonjs/collection/lib/useBaseListModel.d.ts +1 -1
- package/dist/commonjs/collection/lib/useBaseListModel.d.ts.map +1 -1
- package/dist/commonjs/collection/lib/useBaseListModel.js +2 -2
- package/dist/commonjs/collection/lib/useListItemRegister.js +2 -2
- package/dist/commonjs/collection/lib/useListRenderItem.js +2 -2
- package/dist/commonjs/combobox/index.d.ts +1 -4
- package/dist/commonjs/combobox/index.d.ts.map +1 -1
- package/dist/commonjs/combobox/index.js +11 -9
- package/dist/commonjs/combobox/lib/Combobox.d.ts +9 -3
- package/dist/commonjs/combobox/lib/Combobox.d.ts.map +1 -1
- package/dist/commonjs/combobox/lib/Combobox.js +2 -2
- package/dist/commonjs/combobox/lib/ComboboxCard.js +3 -3
- package/dist/commonjs/combobox/lib/ComboboxInput.d.ts +1 -106
- package/dist/commonjs/combobox/lib/ComboboxInput.d.ts.map +1 -1
- package/dist/commonjs/combobox/lib/ComboboxInput.js +4 -71
- package/dist/commonjs/combobox/lib/ComboboxMenu.d.ts +9 -3
- package/dist/commonjs/combobox/lib/ComboboxMenu.d.ts.map +1 -1
- package/dist/commonjs/combobox/lib/ComboboxMenu.js +5 -4
- package/dist/commonjs/combobox/lib/ComboboxMenuItem.d.ts +7 -1
- package/dist/commonjs/combobox/lib/ComboboxMenuItem.d.ts.map +1 -1
- package/dist/commonjs/combobox/lib/ComboboxMenuItem.js +7 -7
- package/dist/commonjs/combobox/lib/ComboboxMenuList.js +2 -2
- package/dist/commonjs/combobox/lib/ComboboxPopper.d.ts +97 -0
- package/dist/commonjs/combobox/lib/ComboboxPopper.d.ts.map +1 -0
- package/dist/commonjs/{select/lib/SelectOption.js → combobox/lib/ComboboxPopper.js} +12 -8
- package/dist/commonjs/combobox/lib/hooks/index.d.ts +10 -0
- package/dist/commonjs/combobox/lib/hooks/index.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/index.js +21 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxInput.d.ts +107 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxInput.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxInput.js +74 -0
- package/dist/{es6/combobox/lib → commonjs/combobox/lib/hooks}/useComboboxInputOpenWithArrowKeys.d.ts +6 -6
- package/dist/commonjs/combobox/lib/hooks/useComboboxInputOpenWithArrowKeys.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxKeyboardTypeAhead.d.ts +101 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxKeyboardTypeAhead.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxKeyboardTypeAhead.js +109 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxListKeyboardHandler.d.ts +84 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxListKeyboardHandler.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxListKeyboardHandler.js +22 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxLoader.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/{useComboboxModel.d.ts → hooks/useComboboxModel.d.ts} +196 -196
- package/dist/commonjs/combobox/lib/hooks/useComboboxModel.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/{useComboboxModel.js → hooks/useComboboxModel.js} +3 -2
- package/dist/commonjs/combobox/lib/hooks/useComboboxMoveCursorToSelected.d.ts +82 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxMoveCursorToSelected.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxMoveCursorToSelected.js +33 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxResetCursorToSelected.d.ts +82 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxResetCursorToSelected.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useComboboxResetCursorToSelected.js +23 -0
- package/dist/commonjs/combobox/lib/hooks/useSetPopupWidth.d.ts +82 -0
- package/dist/commonjs/combobox/lib/hooks/useSetPopupWidth.d.ts.map +1 -0
- package/dist/commonjs/combobox/lib/hooks/useSetPopupWidth.js +22 -0
- package/dist/commonjs/common/lib/utils/components.d.ts.map +1 -1
- package/dist/commonjs/common/lib/utils/models.d.ts +4 -4
- package/dist/commonjs/common/lib/utils/models.d.ts.map +1 -1
- package/dist/commonjs/common/lib/utils/models.js +7 -8
- package/dist/commonjs/form-field/lib/FormField.d.ts.map +1 -1
- package/dist/commonjs/form-field/lib/FormField.js +3 -2
- package/dist/commonjs/menu/lib/MenuPopper.d.ts.map +1 -1
- package/dist/commonjs/menu/lib/MenuPopper.js +10 -1
- package/dist/commonjs/popup/lib/PopupPopper.d.ts.map +1 -1
- package/dist/commonjs/popup/lib/PopupPopper.js +10 -1
- package/dist/commonjs/select/index.d.ts +1 -1
- package/dist/commonjs/select/index.d.ts.map +1 -1
- package/dist/commonjs/select/index.js +1 -1
- package/dist/commonjs/select/lib/Select.d.ts +2634 -18
- package/dist/commonjs/select/lib/Select.d.ts.map +1 -1
- package/dist/commonjs/select/lib/Select.js +141 -84
- package/dist/commonjs/select/lib/hooks/index.d.ts +4 -0
- package/dist/commonjs/select/lib/hooks/index.d.ts.map +1 -0
- package/dist/commonjs/select/lib/hooks/index.js +15 -0
- package/dist/commonjs/select/lib/hooks/useSelectCard.d.ts +83 -0
- package/dist/commonjs/select/lib/hooks/useSelectCard.d.ts.map +1 -0
- package/dist/commonjs/select/lib/hooks/useSelectCard.js +13 -0
- package/dist/commonjs/select/lib/hooks/useSelectInput.d.ts +112 -0
- package/dist/commonjs/select/lib/hooks/useSelectInput.d.ts.map +1 -0
- package/dist/commonjs/select/lib/hooks/useSelectInput.js +49 -0
- package/dist/commonjs/select/lib/hooks/useSelectModel.d.ts +1779 -0
- package/dist/commonjs/select/lib/hooks/useSelectModel.d.ts.map +1 -0
- package/dist/commonjs/select/lib/hooks/useSelectModel.js +32 -0
- package/dist/es6/collection/index.d.ts +1 -0
- package/dist/es6/collection/index.d.ts.map +1 -1
- package/dist/es6/collection/index.js +1 -0
- package/dist/es6/collection/lib/useBaseListModel.d.ts +1 -1
- package/dist/es6/collection/lib/useBaseListModel.d.ts.map +1 -1
- package/dist/es6/collection/lib/useBaseListModel.js +2 -2
- package/dist/es6/collection/lib/useListItemRegister.js +2 -2
- package/dist/es6/collection/lib/useListRenderItem.js +2 -2
- package/dist/es6/combobox/index.d.ts +1 -4
- package/dist/es6/combobox/index.d.ts.map +1 -1
- package/dist/es6/combobox/index.js +1 -4
- package/dist/es6/combobox/lib/Combobox.d.ts +9 -3
- package/dist/es6/combobox/lib/Combobox.d.ts.map +1 -1
- package/dist/es6/combobox/lib/Combobox.js +1 -1
- package/dist/es6/combobox/lib/ComboboxCard.js +1 -1
- package/dist/es6/combobox/lib/ComboboxInput.d.ts +1 -106
- package/dist/es6/combobox/lib/ComboboxInput.d.ts.map +1 -1
- package/dist/es6/combobox/lib/ComboboxInput.js +2 -69
- package/dist/es6/combobox/lib/ComboboxMenu.d.ts +9 -3
- package/dist/es6/combobox/lib/ComboboxMenu.d.ts.map +1 -1
- package/dist/es6/combobox/lib/ComboboxMenu.js +4 -3
- package/dist/es6/combobox/lib/ComboboxMenuItem.d.ts +7 -1
- package/dist/es6/combobox/lib/ComboboxMenuItem.d.ts.map +1 -1
- package/dist/es6/combobox/lib/ComboboxMenuItem.js +7 -7
- package/dist/es6/combobox/lib/ComboboxMenuList.js +1 -1
- package/dist/es6/combobox/lib/ComboboxPopper.d.ts +97 -0
- package/dist/es6/combobox/lib/ComboboxPopper.d.ts.map +1 -0
- package/dist/es6/combobox/lib/ComboboxPopper.js +12 -0
- package/dist/es6/combobox/lib/hooks/index.d.ts +10 -0
- package/dist/es6/combobox/lib/hooks/index.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/index.js +9 -0
- package/dist/es6/combobox/lib/hooks/useComboboxInput.d.ts +107 -0
- package/dist/es6/combobox/lib/hooks/useComboboxInput.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxInput.js +68 -0
- package/dist/{commonjs/combobox/lib → es6/combobox/lib/hooks}/useComboboxInputOpenWithArrowKeys.d.ts +6 -6
- package/dist/es6/combobox/lib/hooks/useComboboxInputOpenWithArrowKeys.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxKeyboardTypeAhead.d.ts +101 -0
- package/dist/es6/combobox/lib/hooks/useComboboxKeyboardTypeAhead.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxKeyboardTypeAhead.js +103 -0
- package/dist/es6/combobox/lib/hooks/useComboboxListKeyboardHandler.d.ts +84 -0
- package/dist/es6/combobox/lib/hooks/useComboboxListKeyboardHandler.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxListKeyboardHandler.js +19 -0
- package/dist/es6/combobox/lib/hooks/useComboboxLoader.d.ts.map +1 -0
- package/dist/es6/combobox/lib/{useComboboxModel.d.ts → hooks/useComboboxModel.d.ts} +196 -196
- package/dist/es6/combobox/lib/hooks/useComboboxModel.d.ts.map +1 -0
- package/dist/es6/combobox/lib/{useComboboxModel.js → hooks/useComboboxModel.js} +3 -2
- package/dist/es6/combobox/lib/hooks/useComboboxMoveCursorToSelected.d.ts +82 -0
- package/dist/es6/combobox/lib/hooks/useComboboxMoveCursorToSelected.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxMoveCursorToSelected.js +27 -0
- package/dist/es6/combobox/lib/hooks/useComboboxResetCursorToSelected.d.ts +82 -0
- package/dist/es6/combobox/lib/hooks/useComboboxResetCursorToSelected.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useComboboxResetCursorToSelected.js +17 -0
- package/dist/es6/combobox/lib/hooks/useSetPopupWidth.d.ts +82 -0
- package/dist/es6/combobox/lib/hooks/useSetPopupWidth.d.ts.map +1 -0
- package/dist/es6/combobox/lib/hooks/useSetPopupWidth.js +16 -0
- package/dist/es6/common/lib/utils/components.d.ts.map +1 -1
- package/dist/es6/common/lib/utils/models.d.ts +4 -4
- package/dist/es6/common/lib/utils/models.d.ts.map +1 -1
- package/dist/es6/common/lib/utils/models.js +7 -8
- package/dist/es6/form-field/lib/FormField.d.ts.map +1 -1
- package/dist/es6/form-field/lib/FormField.js +3 -2
- package/dist/es6/menu/lib/MenuPopper.d.ts.map +1 -1
- package/dist/es6/menu/lib/MenuPopper.js +10 -1
- package/dist/es6/popup/lib/PopupPopper.d.ts.map +1 -1
- package/dist/es6/popup/lib/PopupPopper.js +10 -1
- package/dist/es6/select/index.d.ts +1 -1
- package/dist/es6/select/index.d.ts.map +1 -1
- package/dist/es6/select/index.js +1 -1
- package/dist/es6/select/lib/Select.d.ts +2634 -18
- package/dist/es6/select/lib/Select.d.ts.map +1 -1
- package/dist/es6/select/lib/Select.js +139 -66
- package/dist/es6/select/lib/hooks/index.d.ts +4 -0
- package/dist/es6/select/lib/hooks/index.d.ts.map +1 -0
- package/dist/es6/select/lib/hooks/index.js +3 -0
- package/dist/es6/select/lib/hooks/useSelectCard.d.ts +83 -0
- package/dist/es6/select/lib/hooks/useSelectCard.d.ts.map +1 -0
- package/dist/es6/select/lib/hooks/useSelectCard.js +10 -0
- package/dist/es6/select/lib/hooks/useSelectInput.d.ts +112 -0
- package/dist/es6/select/lib/hooks/useSelectInput.d.ts.map +1 -0
- package/dist/es6/select/lib/hooks/useSelectInput.js +46 -0
- package/dist/es6/select/lib/hooks/useSelectModel.d.ts +1779 -0
- package/dist/es6/select/lib/hooks/useSelectModel.d.ts.map +1 -0
- package/dist/es6/select/lib/hooks/useSelectModel.js +29 -0
- package/form-field/lib/FormField.tsx +8 -2
- package/menu/lib/MenuPopper.tsx +14 -1
- package/package.json +4 -4
- package/popup/lib/Popper.tsx +1 -1
- package/popup/lib/PopupPopper.tsx +17 -1
- package/select/index.ts +1 -1
- package/select/lib/Select.tsx +175 -111
- package/select/lib/hooks/index.ts +3 -0
- package/select/lib/hooks/useSelectCard.ts +11 -0
- package/select/lib/hooks/useSelectInput.ts +74 -0
- package/select/lib/hooks/useSelectModel.tsx +30 -0
- package/dist/commonjs/combobox/lib/useComboboxInputOpenWithArrowKeys.d.ts.map +0 -1
- package/dist/commonjs/combobox/lib/useComboboxLoader.d.ts.map +0 -1
- package/dist/commonjs/combobox/lib/useComboboxModel.d.ts.map +0 -1
- package/dist/commonjs/select/lib/SelectOption.d.ts +0 -20
- package/dist/commonjs/select/lib/SelectOption.d.ts.map +0 -1
- package/dist/es6/combobox/lib/useComboboxInputOpenWithArrowKeys.d.ts.map +0 -1
- package/dist/es6/combobox/lib/useComboboxLoader.d.ts.map +0 -1
- package/dist/es6/combobox/lib/useComboboxModel.d.ts.map +0 -1
- package/dist/es6/select/lib/SelectOption.d.ts +0 -20
- package/dist/es6/select/lib/SelectOption.d.ts.map +0 -1
- package/dist/es6/select/lib/SelectOption.js +0 -7
- package/select/lib/SelectOption.tsx +0 -33
- /package/combobox/lib/{useComboboxInputOpenWithArrowKeys.ts → hooks/useComboboxInputOpenWithArrowKeys.ts} +0 -0
- /package/combobox/lib/{useComboboxLoader.ts → hooks/useComboboxLoader.ts} +0 -0
- /package/dist/commonjs/combobox/lib/{useComboboxInputOpenWithArrowKeys.js → hooks/useComboboxInputOpenWithArrowKeys.js} +0 -0
- /package/dist/commonjs/combobox/lib/{useComboboxLoader.d.ts → hooks/useComboboxLoader.d.ts} +0 -0
- /package/dist/commonjs/combobox/lib/{useComboboxLoader.js → hooks/useComboboxLoader.js} +0 -0
- /package/dist/es6/combobox/lib/{useComboboxInputOpenWithArrowKeys.js → hooks/useComboboxInputOpenWithArrowKeys.js} +0 -0
- /package/dist/es6/combobox/lib/{useComboboxLoader.d.ts → hooks/useComboboxLoader.d.ts} +0 -0
- /package/dist/es6/combobox/lib/{useComboboxLoader.js → hooks/useComboboxLoader.js} +0 -0
package/collection/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from './lib/useGridModel';
|
|
|
15
15
|
export * from './lib/useListActiveDescendant';
|
|
16
16
|
export * from './lib/useListItemAllowChildStrings';
|
|
17
17
|
export {ListBox, ListBoxProps} from './lib/ListBox';
|
|
18
|
+
export {keyboardEventToCursorEvents} from './lib/keyUtils';
|
|
18
19
|
export {
|
|
19
20
|
singleSelectionManager,
|
|
20
21
|
multiSelectionManager,
|
|
@@ -10,7 +10,7 @@ export const defaultGetId = (item: any): string => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export const defaultGetTextValue = (item: any): string => {
|
|
13
|
-
return typeof item === 'string' ? item : item.text || '';
|
|
13
|
+
return typeof item === 'string' ? item : item.text || item.id || '';
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
export interface Item<T> {
|
|
@@ -20,7 +20,7 @@ export interface Item<T> {
|
|
|
20
20
|
/**
|
|
21
21
|
* Used by components that allow jumping to an item based on typing
|
|
22
22
|
*/
|
|
23
|
-
textValue
|
|
23
|
+
textValue: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// interface Collection<T> {
|
|
@@ -124,7 +124,7 @@ export const useBaseListModel = createModelHook({
|
|
|
124
124
|
const getTextValueRef = React.useRef(defaultGetTextValue);
|
|
125
125
|
|
|
126
126
|
const getId = config.getId || defaultGetId;
|
|
127
|
-
const getTextValue = config.getTextValue || defaultGetTextValue;
|
|
127
|
+
const getTextValue = config.getTextValue || config.getId || defaultGetTextValue;
|
|
128
128
|
getIdRef.current = getId;
|
|
129
129
|
getTextValueRef.current = getTextValue;
|
|
130
130
|
|
|
@@ -94,7 +94,7 @@ export const useListItemRegister = createElemPropsHook(useListModel)(
|
|
|
94
94
|
disabled: elemProps.disabled || state.nonInteractiveIds.includes(localId) ? true : undefined,
|
|
95
95
|
item: null, // remove `item` from prop list
|
|
96
96
|
virtual: null, // remove `virtual` from prop list
|
|
97
|
-
'aria-setsize': elemProps.virtual
|
|
97
|
+
'aria-setsize': elemProps.virtual ? state.UNSTABLE_virtual.totalSize : undefined,
|
|
98
98
|
'aria-posinset': elemProps.virtual ? elemProps.item!.index + 1 : undefined,
|
|
99
99
|
style,
|
|
100
100
|
id: slugify(`${state.id}-${localId}`),
|
|
@@ -34,7 +34,7 @@ export function useListRenderItems<T>(
|
|
|
34
34
|
// about capital letters in attributes. React thinks this will be applied to the DOM
|
|
35
35
|
// element even though we remove it later...
|
|
36
36
|
virtual,
|
|
37
|
-
key: item.id,
|
|
37
|
+
key: item.id || item.index,
|
|
38
38
|
item,
|
|
39
39
|
});
|
|
40
40
|
}
|
|
@@ -44,7 +44,7 @@ export function useListRenderItems<T>(
|
|
|
44
44
|
const child = children(item.value, item.index);
|
|
45
45
|
if (React.isValidElement(child)) {
|
|
46
46
|
return React.cloneElement(child, {
|
|
47
|
-
key: item.id,
|
|
47
|
+
key: item.id || item.index,
|
|
48
48
|
item: item.value,
|
|
49
49
|
});
|
|
50
50
|
}
|
package/combobox/index.ts
CHANGED
|
@@ -2,7 +2,14 @@ export {Combobox} from './lib/Combobox';
|
|
|
2
2
|
export {useComboboxCard} from './lib/ComboboxCard';
|
|
3
3
|
export {useComboboxMenuItem} from './lib/ComboboxMenuItem';
|
|
4
4
|
export {useComboboxMenuList} from './lib/ComboboxMenuList';
|
|
5
|
-
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
export {
|
|
6
|
+
useComboboxLoader,
|
|
7
|
+
useComboboxModel,
|
|
8
|
+
useComboboxInputOpenWithArrowKeys,
|
|
9
|
+
useComboboxKeyboardTypeAhead,
|
|
10
|
+
useSetPopupWidth,
|
|
11
|
+
useComboboxMoveCursorToSelected,
|
|
12
|
+
useComboboxInput,
|
|
13
|
+
useComboboxListKeyboardHandler,
|
|
14
|
+
useComboboxResetCursorToSelected,
|
|
15
|
+
} from './lib/hooks';
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import {createContainer} from '@workday/canvas-kit-react/common';
|
|
4
4
|
|
|
5
|
-
import {useComboboxModel} from './
|
|
5
|
+
import {useComboboxModel} from './hooks';
|
|
6
6
|
import {ComboboxInput} from './ComboboxInput';
|
|
7
7
|
import {ComboboxMenu} from './ComboboxMenu';
|
|
8
8
|
export interface ComboboxProps {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from '@workday/canvas-kit-react/common';
|
|
8
8
|
import {Menu} from '@workday/canvas-kit-react/menu';
|
|
9
9
|
|
|
10
|
-
import {useComboboxModel} from './
|
|
10
|
+
import {useComboboxModel} from './hooks';
|
|
11
11
|
|
|
12
12
|
export interface ComboboxCardProps extends ExtractProps<typeof Menu.Card> {}
|
|
13
13
|
|
|
@@ -1,97 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
composeHooks,
|
|
5
|
-
createElemPropsHook,
|
|
6
|
-
createSubcomponent,
|
|
7
|
-
dispatchInputEvent,
|
|
8
|
-
ExtractProps,
|
|
9
|
-
useForkRef,
|
|
10
|
-
} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {createSubcomponent, ExtractProps} from '@workday/canvas-kit-react/common';
|
|
11
4
|
import {TextInput} from '@workday/canvas-kit-react/text-input';
|
|
12
|
-
import {usePopupTarget} from '@workday/canvas-kit-react/popup';
|
|
13
|
-
import {
|
|
14
|
-
useListActiveDescendant,
|
|
15
|
-
useListKeyboardHandler,
|
|
16
|
-
} from '@workday/canvas-kit-react/collection';
|
|
17
5
|
|
|
18
|
-
import {useComboboxModel} from './
|
|
19
|
-
import {useComboboxInputOpenWithArrowKeys} from './useComboboxInputOpenWithArrowKeys';
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Adds all attributes necessary to start with a {@link ComboboxInput Combobox.Input}. It opens the
|
|
23
|
-
* menu with arrow keys, uses {@link useListActiveDescendant}, and handles keyboard arrows to
|
|
24
|
-
* navigate items of the menu. You may also compose this hook to add more specific behaviors for
|
|
25
|
-
* your {@link ComboboxInput Combobox.Input}.
|
|
26
|
-
*/
|
|
27
|
-
export const useComboboxInput = composeHooks(
|
|
28
|
-
createElemPropsHook(useComboboxModel)((model, ref) => {
|
|
29
|
-
const elementRef = useForkRef(ref, model.state.inputRef);
|
|
30
|
-
|
|
31
|
-
React.useEffect(() => {
|
|
32
|
-
if (model.state.cursorId && model.state.visibility === 'visible') {
|
|
33
|
-
const item = model.navigation.getItem(model.state.cursorId, model);
|
|
34
|
-
if (model.state.isVirtualized && item) {
|
|
35
|
-
model.state.UNSTABLE_virtual.scrollToIndex(item.index);
|
|
36
|
-
} else {
|
|
37
|
-
const listboxId = model.state.inputRef.current?.getAttribute('aria-controls');
|
|
38
|
-
if (listboxId) {
|
|
39
|
-
const menuItem = document.querySelector(
|
|
40
|
-
`[id="${listboxId}"] [data-id="${model.state.cursorId}"]`
|
|
41
|
-
);
|
|
42
|
-
if (menuItem) {
|
|
43
|
-
menuItem.scrollIntoView({block: 'nearest'});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// we only want to run this effect if the cursor changes and not any other time
|
|
50
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
-
}, [model.state.cursorId]);
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
onKeyDown(event: React.KeyboardEvent) {
|
|
55
|
-
if (event.key === 'Escape') {
|
|
56
|
-
dispatchInputEvent(event.currentTarget as HTMLElement, '');
|
|
57
|
-
}
|
|
58
|
-
if (event.key === 'Enter' && !event.metaKey && model.state.visibility === 'visible') {
|
|
59
|
-
const element = document.querySelector(`[data-id="${model.state.cursorId}"]`);
|
|
60
|
-
if (element && element?.getAttribute('aria-disabled') !== 'true') {
|
|
61
|
-
model.events.select({id: model.state.cursorId});
|
|
62
|
-
if (model.state.mode === 'single') {
|
|
63
|
-
model.events.hide(event);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// We don't want to submit forms while the combobox is open
|
|
68
|
-
event.preventDefault();
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
onBlur(event: React.FocusEvent) {
|
|
72
|
-
model.events.hide(event);
|
|
73
|
-
},
|
|
74
|
-
onChange: model.onChange,
|
|
75
|
-
onClick(event: React.MouseEvent) {
|
|
76
|
-
if (model.state.visibility === 'hidden') {
|
|
77
|
-
model.events.setWidth(event.currentTarget.clientWidth);
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
value: model.state.value,
|
|
81
|
-
role: 'combobox',
|
|
82
|
-
'aria-haspopup': true,
|
|
83
|
-
'aria-expanded': model.state.visibility === 'visible',
|
|
84
|
-
'aria-autocomplete': 'list',
|
|
85
|
-
'aria-controls': `${model.state.id}-list`,
|
|
86
|
-
id: model.state.id,
|
|
87
|
-
ref: elementRef,
|
|
88
|
-
} as const;
|
|
89
|
-
}),
|
|
90
|
-
useComboboxInputOpenWithArrowKeys,
|
|
91
|
-
useListActiveDescendant,
|
|
92
|
-
useListKeyboardHandler,
|
|
93
|
-
usePopupTarget
|
|
94
|
-
);
|
|
6
|
+
import {useComboboxModel, useComboboxInput} from './hooks';
|
|
95
7
|
|
|
96
8
|
export const ComboboxInput = createSubcomponent(TextInput)({
|
|
97
9
|
modelHook: useComboboxModel,
|
|
@@ -3,10 +3,11 @@ import React from 'react';
|
|
|
3
3
|
import {createSubcomponent} from '@workday/canvas-kit-react/common';
|
|
4
4
|
import {Menu} from '@workday/canvas-kit-react/menu';
|
|
5
5
|
|
|
6
|
-
import {useComboboxModel} from './
|
|
6
|
+
import {useComboboxModel} from './hooks';
|
|
7
7
|
import {ComboboxMenuList} from './ComboboxMenuList';
|
|
8
8
|
import {ComboboxMenuItem} from './ComboboxMenuItem';
|
|
9
9
|
import {ComboboxCard} from './ComboboxCard';
|
|
10
|
+
import {ComboboxMenuPopper} from './ComboboxPopper';
|
|
10
11
|
|
|
11
12
|
export interface ComboboxMenuProps {
|
|
12
13
|
/**
|
|
@@ -23,9 +24,9 @@ export const ComboboxMenu = createSubcomponent()({
|
|
|
23
24
|
* {@link ComboboxInput Combobox.Input}. It renders a `div` element that is portalled to the
|
|
24
25
|
* `document.body` which is controlled by the {@link PopupStack}. The `PopupStack` is not part
|
|
25
26
|
* of React. This means no extra props given to this component will be forwarded to the `div`
|
|
26
|
-
* element, but the `ref` will be forwarded.
|
|
27
|
+
* element, but the `ref` will be forwarded. Also fallback placements for the popper with be either `top` or `bottom`.
|
|
27
28
|
*/
|
|
28
|
-
Popper:
|
|
29
|
+
Popper: ComboboxMenuPopper,
|
|
29
30
|
/**
|
|
30
31
|
* The combobox menu list follows the Collections API. A list can either contain static items or
|
|
31
32
|
* a render prop and `items` to the model.
|
|
@@ -4,15 +4,17 @@ import {
|
|
|
4
4
|
composeHooks,
|
|
5
5
|
createElemPropsHook,
|
|
6
6
|
createSubcomponent,
|
|
7
|
+
styled,
|
|
7
8
|
} from '@workday/canvas-kit-react/common';
|
|
8
9
|
import {StyledMenuItem, useMenuModel} from '@workday/canvas-kit-react/menu';
|
|
10
|
+
import {SystemIcon} from '@workday/canvas-kit-react/icon';
|
|
9
11
|
import {
|
|
10
12
|
useListItemAllowChildStrings,
|
|
11
13
|
useListItemRegister,
|
|
12
14
|
} from '@workday/canvas-kit-react/collection';
|
|
13
15
|
import {OverflowTooltip} from '@workday/canvas-kit-react/tooltip';
|
|
14
16
|
|
|
15
|
-
import {useComboboxModel} from './
|
|
17
|
+
import {useComboboxModel} from './hooks';
|
|
16
18
|
|
|
17
19
|
export interface ComboboxMenuItemProps {
|
|
18
20
|
children: React.ReactNode;
|
|
@@ -26,17 +28,13 @@ export interface ComboboxMenuItemProps {
|
|
|
26
28
|
* added when the item has "focus" (when the cursor is on the item).
|
|
27
29
|
*/
|
|
28
30
|
export const useComboboxMenuItem = composeHooks(
|
|
29
|
-
createElemPropsHook(useMenuModel)((model,
|
|
31
|
+
createElemPropsHook(useMenuModel)((model, ref, elemProps: {'data-id'?: string} = {}) => {
|
|
30
32
|
const id = elemProps['data-id'] || '';
|
|
33
|
+
|
|
31
34
|
const onMouseDown = (event: React.MouseEvent<HTMLElement>) => {
|
|
32
|
-
if (
|
|
33
|
-
model.state.nonInteractiveIds.includes(id) ||
|
|
34
|
-
event.currentTarget.hasAttribute('aria-disabled')
|
|
35
|
-
) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
35
|
if (event.currentTarget.getAttribute('aria-disabled') !== 'true') {
|
|
39
36
|
model.events.select({id});
|
|
37
|
+
|
|
40
38
|
if (model.state.mode === 'single') {
|
|
41
39
|
model.events.hide(event);
|
|
42
40
|
}
|
|
@@ -63,6 +61,9 @@ export const useComboboxMenuItem = composeHooks(
|
|
|
63
61
|
export const ComboboxMenuItem = createSubcomponent('li')({
|
|
64
62
|
modelHook: useComboboxModel,
|
|
65
63
|
elemPropsHook: useComboboxMenuItem,
|
|
64
|
+
subComponents: {
|
|
65
|
+
Icon: styled(SystemIcon)({alignSelf: 'start'}),
|
|
66
|
+
},
|
|
66
67
|
})<ComboboxMenuItemProps>(({children, ...elemProps}, Element) => {
|
|
67
68
|
return (
|
|
68
69
|
<OverflowTooltip placement="left">
|
|
@@ -5,7 +5,7 @@ import {createElemPropsHook, createSubcomponent} from '@workday/canvas-kit-react
|
|
|
5
5
|
import {useMenuModel} from '@workday/canvas-kit-react/menu';
|
|
6
6
|
import {ListBox, ListBoxProps} from '@workday/canvas-kit-react/collection';
|
|
7
7
|
|
|
8
|
-
import {useComboboxModel} from './
|
|
8
|
+
import {useComboboxModel} from './hooks';
|
|
9
9
|
|
|
10
10
|
export interface ComboboxMenuListProps<T = any> extends ListBoxProps<T> {}
|
|
11
11
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {createSubcomponent, ExtractProps} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {usePopupPopper, Popper} from '@workday/canvas-kit-react/popup';
|
|
5
|
+
|
|
6
|
+
import {Menu, useMenuModel} from '@workday/canvas-kit-react/menu';
|
|
7
|
+
|
|
8
|
+
export const useMenuPopper = usePopupPopper;
|
|
9
|
+
|
|
10
|
+
export const ComboboxMenuPopper = createSubcomponent('div')({
|
|
11
|
+
displayName: 'Combobox.Menu.Popper',
|
|
12
|
+
modelHook: useMenuModel,
|
|
13
|
+
elemPropsHook: useMenuPopper,
|
|
14
|
+
})<ExtractProps<typeof Popper>>(({children, ...elemProps}) => {
|
|
15
|
+
return (
|
|
16
|
+
<Menu.Popper fallbackPlacements={['top', 'bottom']} {...elemProps}>
|
|
17
|
+
{children}
|
|
18
|
+
</Menu.Popper>
|
|
19
|
+
);
|
|
20
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './useComboboxInputOpenWithArrowKeys';
|
|
2
|
+
export * from './useComboboxLoader';
|
|
3
|
+
export * from './useComboboxModel';
|
|
4
|
+
export * from './useComboboxMoveCursorToSelected';
|
|
5
|
+
export * from './useSetPopupWidth';
|
|
6
|
+
export * from './useComboboxKeyboardTypeAhead';
|
|
7
|
+
export * from './useComboboxListKeyboardHandler';
|
|
8
|
+
export * from './useComboboxInput';
|
|
9
|
+
export * from './useComboboxResetCursorToSelected';
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import {composeHooks, createElemPropsHook, useForkRef} from '@workday/canvas-kit-react/common';
|
|
4
|
+
import {usePopupTarget} from '@workday/canvas-kit-react/popup';
|
|
5
|
+
|
|
6
|
+
import {useListActiveDescendant} from '@workday/canvas-kit-react/collection';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
useComboboxModel,
|
|
10
|
+
useComboboxInputOpenWithArrowKeys,
|
|
11
|
+
useSetPopupWidth,
|
|
12
|
+
useComboboxListKeyboardHandler,
|
|
13
|
+
} from './index';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `useComboboxInput` Adds all attributes necessary to start with a {@link ComboboxInput Combobox.Input}. It opens the
|
|
17
|
+
* menu with arrow keys, uses {@link useListActiveDescendant}, and handles keyboard arrows to
|
|
18
|
+
* navigate items of the menu. You may also compose this hook to add more specific behaviors for
|
|
19
|
+
* your {@link ComboboxInput Combobox.Input}.
|
|
20
|
+
*/
|
|
21
|
+
export const useComboboxInput = composeHooks(
|
|
22
|
+
createElemPropsHook(useComboboxModel)((model, ref) => {
|
|
23
|
+
const elementRef = useForkRef(ref, model.state.inputRef);
|
|
24
|
+
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
if (model.state.cursorId && model.state.visibility === 'visible') {
|
|
27
|
+
const item = model.navigation.getItem(model.state.cursorId, model);
|
|
28
|
+
if (model.state.isVirtualized && item) {
|
|
29
|
+
model.state.UNSTABLE_virtual.scrollToIndex(item.index);
|
|
30
|
+
} else {
|
|
31
|
+
const listboxId = model.state.inputRef.current?.getAttribute('aria-controls');
|
|
32
|
+
if (listboxId) {
|
|
33
|
+
const menuItem = document.querySelector(
|
|
34
|
+
`[id="${listboxId}"] [data-id="${model.state.cursorId}"]`
|
|
35
|
+
);
|
|
36
|
+
if (menuItem) {
|
|
37
|
+
requestAnimationFrame(() => {
|
|
38
|
+
menuItem.scrollIntoView({block: 'nearest'});
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// we only want to run this effect if the cursor, visibility and selectedIds change and not any other time
|
|
46
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
47
|
+
}, [model.state.cursorId, model.state.selectedIds, model.state.visibility]);
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
onKeyDown(event: React.KeyboardEvent) {
|
|
51
|
+
if (event.key === 'Enter' && !event.metaKey && model.state.visibility === 'visible') {
|
|
52
|
+
const element = document.querySelector(`[data-id="${model.state.cursorId}"]`);
|
|
53
|
+
if (element && element?.getAttribute('aria-disabled') !== 'true') {
|
|
54
|
+
model.events.select({id: model.state.cursorId});
|
|
55
|
+
if (model.state.mode === 'single') {
|
|
56
|
+
model.events.hide(event);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// We don't want to submit forms while the combobox is open
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
onBlur(event: React.FocusEvent) {
|
|
65
|
+
model.events.hide(event);
|
|
66
|
+
},
|
|
67
|
+
onChange: model.onChange,
|
|
68
|
+
onClick(event: React.MouseEvent) {
|
|
69
|
+
if (model.state.visibility === 'hidden') {
|
|
70
|
+
model.events.setWidth(event.currentTarget.clientWidth);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
value: model.state.value,
|
|
74
|
+
role: 'combobox',
|
|
75
|
+
'aria-haspopup': true,
|
|
76
|
+
'aria-expanded': model.state.visibility === 'visible',
|
|
77
|
+
'aria-autocomplete': 'list',
|
|
78
|
+
'aria-controls': `${model.state.id}-list`,
|
|
79
|
+
id: model.state.id,
|
|
80
|
+
ref: elementRef,
|
|
81
|
+
} as const;
|
|
82
|
+
}),
|
|
83
|
+
useSetPopupWidth,
|
|
84
|
+
useComboboxInputOpenWithArrowKeys,
|
|
85
|
+
useListActiveDescendant,
|
|
86
|
+
useComboboxListKeyboardHandler,
|
|
87
|
+
usePopupTarget
|
|
88
|
+
);
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {createElemPropsHook} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {useComboboxModel} from './useComboboxModel';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `useComboboxKeyboardTypeAhead` handles type-ahead. It will try and find a matching item in the list. It also returns the keys types so far.
|
|
7
|
+
* This hook is best used when composing hooks and in conjunction with `useComboboxInput`.
|
|
8
|
+
*
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // Example for a `Select` input
|
|
11
|
+
* export const useSelectInput = composeHooks(
|
|
12
|
+
* createElemPropsHook(useComboboxModel)((model, ref, elemProps: {keySofar?: string} = {}) => {
|
|
13
|
+
* return {
|
|
14
|
+
* onKeyDown(event: React.KeyboardEvent) {
|
|
15
|
+
* // onKeyDown logic ...
|
|
16
|
+
* },
|
|
17
|
+
* } as const;
|
|
18
|
+
* }),
|
|
19
|
+
* useComboboxKeyboardTypeAhead,
|
|
20
|
+
* useComboboxInput
|
|
21
|
+
* );
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export const useComboboxKeyboardTypeAhead = createElemPropsHook(useComboboxModel)(model => {
|
|
25
|
+
const keySofar = React.useRef('');
|
|
26
|
+
const timer = React.useRef<ReturnType<typeof setTimeout>>();
|
|
27
|
+
const [keyTypedSofar, setKeyTypedSofar] = React.useState(keySofar.current);
|
|
28
|
+
|
|
29
|
+
const startClearKeysSoFarTimer = () => {
|
|
30
|
+
if (timer.current) {
|
|
31
|
+
clearTimeout(timer.current);
|
|
32
|
+
}
|
|
33
|
+
timer.current = setTimeout(() => {
|
|
34
|
+
keySofar.current = '';
|
|
35
|
+
setKeyTypedSofar(keySofar.current);
|
|
36
|
+
}, 500);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Based on the the key typed, this will try and find an index in the array where it matches the string
|
|
40
|
+
// so if a user types `de` it will try and find an index in the array whose id matches `de` like denver
|
|
41
|
+
const getIndexByStartString = (
|
|
42
|
+
startIndex: number,
|
|
43
|
+
startString: string,
|
|
44
|
+
endIndex: number = model.state.items.length,
|
|
45
|
+
ignoreDisabled: boolean = true
|
|
46
|
+
): number => {
|
|
47
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
48
|
+
const label = model.state.items[i].textValue.toLowerCase();
|
|
49
|
+
if (
|
|
50
|
+
label.startsWith(startString.toLowerCase()) &&
|
|
51
|
+
(!ignoreDisabled ||
|
|
52
|
+
(ignoreDisabled && !model.state.nonInteractiveIds.includes(model.state.items[i].id)))
|
|
53
|
+
) {
|
|
54
|
+
return i;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return -1;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const currentItem = model.navigation.getItem(model.state.cursorId, model);
|
|
61
|
+
const cursorFocusedIndex = currentItem.index;
|
|
62
|
+
|
|
63
|
+
const handleKeyboardTypeAhead = (key: string, numOptions: number) => {
|
|
64
|
+
// If the starting point is beyond the list of options, reset it
|
|
65
|
+
// to the beginning of the list
|
|
66
|
+
const startNumber = keySofar.current.length === 0 ? cursorFocusedIndex + 1 : cursorFocusedIndex;
|
|
67
|
+
|
|
68
|
+
const start = startNumber === numOptions ? 0 : startNumber;
|
|
69
|
+
|
|
70
|
+
// Keeps track of the current key types and adds to it
|
|
71
|
+
// if you type `de` vs `d` for denver
|
|
72
|
+
keySofar.current += key;
|
|
73
|
+
setKeyTypedSofar(keySofar.current);
|
|
74
|
+
startClearKeysSoFarTimer();
|
|
75
|
+
|
|
76
|
+
// First, look for a match from start to end
|
|
77
|
+
let matchIndex = getIndexByStartString(start, keySofar.current);
|
|
78
|
+
getIndexByStartString(start, keySofar.current);
|
|
79
|
+
|
|
80
|
+
// If a match isn't found between start and end, wrap the search
|
|
81
|
+
// around and search again from the beginning (0) to start
|
|
82
|
+
if (matchIndex === -1) {
|
|
83
|
+
matchIndex = getIndexByStartString(0, keySofar.current, start);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A match was found...
|
|
87
|
+
if (matchIndex > -1) {
|
|
88
|
+
model.events.goTo({id: model.state.items[matchIndex].id});
|
|
89
|
+
if (model.state.visibility === 'hidden') {
|
|
90
|
+
// If the menu is closed, fire the change event
|
|
91
|
+
// go to that item and select based on its id
|
|
92
|
+
model.events.select({id: model.state.items[matchIndex].id});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
onKeyDown(event: React.KeyboardEvent) {
|
|
99
|
+
// Call type ahead excluding backspace
|
|
100
|
+
if (event.key.length === 1 && event.key.match(/\S/)) {
|
|
101
|
+
handleKeyboardTypeAhead(event.key, model.state.items.length);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// If spacebar is typed
|
|
105
|
+
if (
|
|
106
|
+
(event.key === 'Spacebar' || event.key === ' ') &&
|
|
107
|
+
model.state.visibility === 'visible' &&
|
|
108
|
+
keySofar.current !== ''
|
|
109
|
+
) {
|
|
110
|
+
// If the user is in the middle of typing a string, treat
|
|
111
|
+
// space key as type-ahead rather than option selection
|
|
112
|
+
handleKeyboardTypeAhead(' ', model.state.items.length);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
(event.key === 'Spacebar' || event.key === ' ') &&
|
|
117
|
+
model.state.visibility === 'hidden' &&
|
|
118
|
+
keySofar.current !== ''
|
|
119
|
+
) {
|
|
120
|
+
// If the user is in the middle of typing a string, treat
|
|
121
|
+
// space key as type-ahead rather than option selection
|
|
122
|
+
handleKeyboardTypeAhead(' ', model.state.items.length);
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
keySofar: keyTypedSofar,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {createElemPropsHook, useIsRTL} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {keyboardEventToCursorEvents} from '@workday/canvas-kit-react/collection';
|
|
4
|
+
|
|
5
|
+
import {useComboboxModel} from './index';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `useComboboxListKeyboardHandler` handle calling keyboard events like ArrowUp and ArrowDown only when the menu is visible.
|
|
9
|
+
*/
|
|
10
|
+
export const useComboboxListKeyboardHandler = createElemPropsHook(useComboboxModel)(model => {
|
|
11
|
+
const isRTL = useIsRTL();
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
onKeyDown(event: React.KeyboardEvent) {
|
|
15
|
+
if (model.state.visibility === 'visible') {
|
|
16
|
+
const handled = keyboardEventToCursorEvents(event, model, isRTL);
|
|
17
|
+
if (handled) {
|
|
18
|
+
event.preventDefault();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
});
|
|
@@ -43,21 +43,25 @@ export const useComboboxModel = createModelHook({
|
|
|
43
43
|
defaultConfig: {
|
|
44
44
|
...useInputModel.defaultConfig,
|
|
45
45
|
...useMenuModel.defaultConfig,
|
|
46
|
+
shouldVirtualize: true,
|
|
46
47
|
},
|
|
48
|
+
|
|
47
49
|
requiredConfig: {
|
|
48
50
|
...useInputModel.requiredConfig,
|
|
49
51
|
...useMenuModel.requiredConfig,
|
|
50
52
|
},
|
|
51
53
|
})(config => {
|
|
52
54
|
const input = useInputModel(config);
|
|
55
|
+
|
|
53
56
|
const menu = useMenuModel(
|
|
54
57
|
useMenuModel.mergeConfig(config, {
|
|
55
|
-
shouldVirtualize: true,
|
|
56
58
|
onSelect({id}) {
|
|
57
|
-
|
|
59
|
+
const textValue = menu.navigation.getItem(id, menu).textValue || id;
|
|
60
|
+
dispatchInputEvent(menu.state.targetRef.current, textValue);
|
|
58
61
|
},
|
|
59
62
|
})
|
|
60
63
|
);
|
|
64
|
+
|
|
61
65
|
const [width, setWidth] = React.useState(0);
|
|
62
66
|
|
|
63
67
|
const state = {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {createElemPropsHook} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {useComboboxModel} from './useComboboxModel';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* If there is nothing selected, move cursor to the first item, otherwise, move the cursor to the selected item
|
|
7
|
+
*/
|
|
8
|
+
export const useComboboxMoveCursorToSelected = createElemPropsHook(useComboboxModel)(model => {
|
|
9
|
+
React.useLayoutEffect(() => {
|
|
10
|
+
const cursorItemId = model.state.items.find(item => item.id === model.state.cursorId)?.id;
|
|
11
|
+
// If there is no selected item and items exists we want to set the cursor to the first item in the array
|
|
12
|
+
if (!model.state.selectedIds.length && model.state.items.length && !cursorItemId) {
|
|
13
|
+
model.events.goTo({id: model.state.items[0].id});
|
|
14
|
+
} else if (model.state.selectedIds.length && !cursorItemId) {
|
|
15
|
+
// If the user wants an item selected by default by passing `initialSelectedId` we select that item
|
|
16
|
+
model.events.goTo({id: model.state.selectedIds[0]});
|
|
17
|
+
}
|
|
18
|
+
}, [
|
|
19
|
+
model.state.selectedIds,
|
|
20
|
+
model.events,
|
|
21
|
+
model.state.items,
|
|
22
|
+
model.state.cursorId,
|
|
23
|
+
model.state.visibility,
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
return {};
|
|
27
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {createElemPropsHook} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {useComboboxModel} from './useComboboxModel';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reset the cursor to the selected item when the Menu is closed
|
|
7
|
+
*/
|
|
8
|
+
export const useComboboxResetCursorToSelected = createElemPropsHook(useComboboxModel)(model => {
|
|
9
|
+
const visible = model.state.visibility !== 'hidden';
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
// when closed, the cursor should reset to the selected item if something is selected
|
|
12
|
+
if (!visible && model.state.selectedIds.length) {
|
|
13
|
+
model.events.goTo({id: model.state.selectedIds[0]});
|
|
14
|
+
}
|
|
15
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
|
+
}, [visible, model.events, model.state.selectedIds]);
|
|
17
|
+
return {};
|
|
18
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {createElemPropsHook} from '@workday/canvas-kit-react/common';
|
|
3
|
+
import {useComboboxModel} from './useComboboxModel';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sets the width of the Menu to the target element when the menu is visible
|
|
7
|
+
*/
|
|
8
|
+
export const useSetPopupWidth = createElemPropsHook(useComboboxModel)(model => {
|
|
9
|
+
const visible = model.state.visibility !== 'hidden';
|
|
10
|
+
React.useLayoutEffect(() => {
|
|
11
|
+
if (visible) {
|
|
12
|
+
model.events.setWidth(model.state.targetRef.current?.clientWidth || 0);
|
|
13
|
+
}
|
|
14
|
+
}, [visible, model.events, model.state.targetRef]);
|
|
15
|
+
return {};
|
|
16
|
+
});
|