@fluentui/react-combobox 9.7.4 → 9.8.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/CHANGELOG.md +41 -9
- package/dist/index.d.ts +54 -11
- package/lib/components/Combobox/Combobox.types.js.map +1 -1
- package/lib/components/Combobox/renderCombobox.js +15 -11
- package/lib/components/Combobox/renderCombobox.js.map +1 -1
- package/lib/components/Combobox/useCombobox.js +12 -4
- package/lib/components/Combobox/useCombobox.js.map +1 -1
- package/lib/components/Combobox/useInputTriggerSlot.js +14 -12
- package/lib/components/Combobox/useInputTriggerSlot.js.map +1 -1
- package/lib/components/Dropdown/Dropdown.types.js.map +1 -1
- package/lib/components/Dropdown/renderDropdown.js +19 -15
- package/lib/components/Dropdown/renderDropdown.js.map +1 -1
- package/lib/components/Dropdown/useButtonTriggerSlot.js +51 -31
- package/lib/components/Dropdown/useButtonTriggerSlot.js.map +1 -1
- package/lib/components/Dropdown/useDropdown.js +14 -4
- package/lib/components/Dropdown/useDropdown.js.map +1 -1
- package/lib/components/Listbox/Listbox.types.js.map +1 -1
- package/lib/components/Listbox/renderListbox.js +7 -3
- package/lib/components/Listbox/renderListbox.js.map +1 -1
- package/lib/components/Listbox/useListbox.js +43 -35
- package/lib/components/Listbox/useListbox.js.map +1 -1
- package/lib/components/Option/Option.types.js.map +1 -1
- package/lib/components/Option/useOption.js +7 -11
- package/lib/components/Option/useOption.js.map +1 -1
- package/lib/components/Option/useOptionStyles.styles.js +27 -28
- package/lib/components/Option/useOptionStyles.styles.js.map +1 -1
- package/lib/contexts/useComboboxContextValues.js +14 -5
- package/lib/contexts/useComboboxContextValues.js.map +1 -1
- package/lib/contexts/useListboxContextValues.js +12 -5
- package/lib/contexts/useListboxContextValues.js.map +1 -1
- package/lib/utils/ComboboxBase.types.js.map +1 -1
- package/lib/utils/OptionCollection.types.js.map +1 -1
- package/lib/utils/Selection.types.js.map +1 -1
- package/lib/utils/dropdownKeyActions.js +0 -21
- package/lib/utils/dropdownKeyActions.js.map +1 -1
- package/lib/utils/useComboboxBaseState.js +52 -14
- package/lib/utils/useComboboxBaseState.js.map +1 -1
- package/lib/utils/useOptionCollection.js +18 -45
- package/lib/utils/useOptionCollection.js.map +1 -1
- package/lib/utils/useTriggerSlot.js +86 -33
- package/lib/utils/useTriggerSlot.js.map +1 -1
- package/lib-commonjs/components/Combobox/renderCombobox.js +15 -11
- package/lib-commonjs/components/Combobox/renderCombobox.js.map +1 -1
- package/lib-commonjs/components/Combobox/useCombobox.js +12 -4
- package/lib-commonjs/components/Combobox/useCombobox.js.map +1 -1
- package/lib-commonjs/components/Combobox/useInputTriggerSlot.js +14 -12
- package/lib-commonjs/components/Combobox/useInputTriggerSlot.js.map +1 -1
- package/lib-commonjs/components/Dropdown/renderDropdown.js +19 -15
- package/lib-commonjs/components/Dropdown/renderDropdown.js.map +1 -1
- package/lib-commonjs/components/Dropdown/useButtonTriggerSlot.js +51 -31
- package/lib-commonjs/components/Dropdown/useButtonTriggerSlot.js.map +1 -1
- package/lib-commonjs/components/Dropdown/useDropdown.js +14 -4
- package/lib-commonjs/components/Dropdown/useDropdown.js.map +1 -1
- package/lib-commonjs/components/Listbox/renderListbox.js +7 -3
- package/lib-commonjs/components/Listbox/renderListbox.js.map +1 -1
- package/lib-commonjs/components/Listbox/useListbox.js +42 -34
- package/lib-commonjs/components/Listbox/useListbox.js.map +1 -1
- package/lib-commonjs/components/Option/useOption.js +7 -11
- package/lib-commonjs/components/Option/useOption.js.map +1 -1
- package/lib-commonjs/components/Option/useOptionStyles.styles.js +85 -85
- package/lib-commonjs/components/Option/useOptionStyles.styles.js.map +1 -1
- package/lib-commonjs/contexts/useComboboxContextValues.js +13 -5
- package/lib-commonjs/contexts/useComboboxContextValues.js.map +1 -1
- package/lib-commonjs/contexts/useListboxContextValues.js +13 -5
- package/lib-commonjs/contexts/useListboxContextValues.js.map +1 -1
- package/lib-commonjs/utils/dropdownKeyActions.js +3 -30
- package/lib-commonjs/utils/dropdownKeyActions.js.map +1 -1
- package/lib-commonjs/utils/useComboboxBaseState.js +52 -14
- package/lib-commonjs/utils/useComboboxBaseState.js.map +1 -1
- package/lib-commonjs/utils/useOptionCollection.js +18 -45
- package/lib-commonjs/utils/useOptionCollection.js.map +1 -1
- package/lib-commonjs/utils/useTriggerSlot.js +84 -31
- package/lib-commonjs/utils/useTriggerSlot.js.map +1 -1
- package/package.json +9 -8
- package/lib/utils/useScrollOptionsIntoView.js +0 -29
- package/lib/utils/useScrollOptionsIntoView.js.map +0 -1
- package/lib-commonjs/utils/useScrollOptionsIntoView.js +0 -40
- package/lib-commonjs/utils/useScrollOptionsIntoView.js.map +0 -1
|
@@ -2,23 +2,26 @@ import * as React from 'react';
|
|
|
2
2
|
/**
|
|
3
3
|
* A hook for managing a collection of child Options
|
|
4
4
|
*/ export const useOptionCollection = ()=>{
|
|
5
|
-
const
|
|
5
|
+
const optionsById = React.useRef(new Map());
|
|
6
6
|
const collectionAPI = React.useMemo(()=>{
|
|
7
|
-
const getCount = ()=>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
const getIndexOfId = (id)=>nodes.current.findIndex((node)=>node.option.id === id);
|
|
7
|
+
const getCount = ()=>optionsById.current.size;
|
|
8
|
+
// index searches are no longer used
|
|
9
|
+
const getOptionAtIndex = ()=>undefined;
|
|
10
|
+
const getIndexOfId = ()=>-1;
|
|
13
11
|
const getOptionById = (id)=>{
|
|
14
|
-
|
|
15
|
-
return item === null || item === void 0 ? void 0 : item.option;
|
|
12
|
+
return optionsById.current.get(id);
|
|
16
13
|
};
|
|
17
14
|
const getOptionsMatchingText = (matcher)=>{
|
|
18
|
-
return
|
|
15
|
+
return Array.from(optionsById.current.values()).filter(({ text })=>matcher(text));
|
|
19
16
|
};
|
|
20
17
|
const getOptionsMatchingValue = (matcher)=>{
|
|
21
|
-
|
|
18
|
+
const matches = [];
|
|
19
|
+
for (const option of optionsById.current.values()){
|
|
20
|
+
if (matcher(option.value)) {
|
|
21
|
+
matches.push(option);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return matches;
|
|
22
25
|
};
|
|
23
26
|
return {
|
|
24
27
|
getCount,
|
|
@@ -29,43 +32,13 @@ import * as React from 'react';
|
|
|
29
32
|
getOptionsMatchingValue
|
|
30
33
|
};
|
|
31
34
|
}, []);
|
|
32
|
-
const registerOption = React.useCallback((option
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!node.element || !element) {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
if (node.option.id === option.id) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
// use the DOM method compareDocumentPosition to order the current node against registered nodes
|
|
42
|
-
// eslint-disable-next-line no-bitwise
|
|
43
|
-
return node.element.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_PRECEDING;
|
|
44
|
-
});
|
|
45
|
-
// do not register the option if it already exists
|
|
46
|
-
if (((_nodes_current_index = nodes.current[index]) === null || _nodes_current_index === void 0 ? void 0 : _nodes_current_index.option.id) !== option.id) {
|
|
47
|
-
const newItem = {
|
|
48
|
-
element,
|
|
49
|
-
option
|
|
50
|
-
};
|
|
51
|
-
// If an index is not found we will push the element to the end.
|
|
52
|
-
if (index === -1) {
|
|
53
|
-
nodes.current = [
|
|
54
|
-
...nodes.current,
|
|
55
|
-
newItem
|
|
56
|
-
];
|
|
57
|
-
} else {
|
|
58
|
-
nodes.current.splice(index, 0, newItem);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
// return the unregister function
|
|
62
|
-
return ()=>{
|
|
63
|
-
nodes.current = nodes.current.filter((node)=>node.option.id !== option.id);
|
|
64
|
-
};
|
|
35
|
+
const registerOption = React.useCallback((option)=>{
|
|
36
|
+
optionsById.current.set(option.id, option);
|
|
37
|
+
return ()=>optionsById.current.delete(option.id);
|
|
65
38
|
}, []);
|
|
66
39
|
return {
|
|
67
40
|
...collectionAPI,
|
|
68
|
-
options:
|
|
41
|
+
options: Array.from(optionsById.current.values()),
|
|
69
42
|
registerOption
|
|
70
43
|
};
|
|
71
44
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useOptionCollection.ts"],"sourcesContent":["import * as React from 'react';\nimport type { OptionCollectionState, OptionValue } from './OptionCollection.types';\n\n/**\n * A hook for managing a collection of child Options\n */\nexport const useOptionCollection = (): OptionCollectionState => {\n const
|
|
1
|
+
{"version":3,"sources":["useOptionCollection.ts"],"sourcesContent":["import * as React from 'react';\nimport type { OptionCollectionState, OptionValue } from './OptionCollection.types';\n\n/**\n * A hook for managing a collection of child Options\n */\nexport const useOptionCollection = (): OptionCollectionState => {\n const optionsById = React.useRef(new Map<string, OptionValue>());\n\n const collectionAPI = React.useMemo(() => {\n const getCount = () => optionsById.current.size;\n\n // index searches are no longer used\n const getOptionAtIndex = () => undefined;\n const getIndexOfId = () => -1;\n\n const getOptionById = (id: string) => {\n return optionsById.current.get(id);\n };\n const getOptionsMatchingText = (matcher: (text: string) => boolean) => {\n return Array.from(optionsById.current.values()).filter(({ text }) => matcher(text));\n };\n\n const getOptionsMatchingValue = (matcher: (value: string) => boolean) => {\n const matches: OptionValue[] = [];\n for (const option of optionsById.current.values()) {\n if (matcher(option.value)) {\n matches.push(option);\n }\n }\n\n return matches;\n };\n\n return {\n getCount,\n getOptionAtIndex,\n getIndexOfId,\n getOptionById,\n getOptionsMatchingText,\n getOptionsMatchingValue,\n };\n }, []);\n\n const registerOption = React.useCallback((option: OptionValue) => {\n optionsById.current.set(option.id, option);\n\n return () => optionsById.current.delete(option.id);\n }, []);\n\n return {\n ...collectionAPI,\n options: Array.from(optionsById.current.values()),\n registerOption,\n };\n};\n"],"names":["React","useOptionCollection","optionsById","useRef","Map","collectionAPI","useMemo","getCount","current","size","getOptionAtIndex","undefined","getIndexOfId","getOptionById","id","get","getOptionsMatchingText","matcher","Array","from","values","filter","text","getOptionsMatchingValue","matches","option","value","push","registerOption","useCallback","set","delete","options"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B;;CAEC,GACD,OAAO,MAAMC,sBAAsB;IACjC,MAAMC,cAAcF,MAAMG,MAAM,CAAC,IAAIC;IAErC,MAAMC,gBAAgBL,MAAMM,OAAO,CAAC;QAClC,MAAMC,WAAW,IAAML,YAAYM,OAAO,CAACC,IAAI;QAE/C,oCAAoC;QACpC,MAAMC,mBAAmB,IAAMC;QAC/B,MAAMC,eAAe,IAAM,CAAC;QAE5B,MAAMC,gBAAgB,CAACC;YACrB,OAAOZ,YAAYM,OAAO,CAACO,GAAG,CAACD;QACjC;QACA,MAAME,yBAAyB,CAACC;YAC9B,OAAOC,MAAMC,IAAI,CAACjB,YAAYM,OAAO,CAACY,MAAM,IAAIC,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKL,QAAQK;QAC/E;QAEA,MAAMC,0BAA0B,CAACN;YAC/B,MAAMO,UAAyB,EAAE;YACjC,KAAK,MAAMC,UAAUvB,YAAYM,OAAO,CAACY,MAAM,GAAI;gBACjD,IAAIH,QAAQQ,OAAOC,KAAK,GAAG;oBACzBF,QAAQG,IAAI,CAACF;gBACf;YACF;YAEA,OAAOD;QACT;QAEA,OAAO;YACLjB;YACAG;YACAE;YACAC;YACAG;YACAO;QACF;IACF,GAAG,EAAE;IAEL,MAAMK,iBAAiB5B,MAAM6B,WAAW,CAAC,CAACJ;QACxCvB,YAAYM,OAAO,CAACsB,GAAG,CAACL,OAAOX,EAAE,EAAEW;QAEnC,OAAO,IAAMvB,YAAYM,OAAO,CAACuB,MAAM,CAACN,OAAOX,EAAE;IACnD,GAAG,EAAE;IAEL,OAAO;QACL,GAAGT,aAAa;QAChB2B,SAASd,MAAMC,IAAI,CAACjB,YAAYM,OAAO,CAACY,MAAM;QAC9CQ;IACF;AACF,EAAE"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { useSetKeyboardNavigation } from '@fluentui/react-tabster';
|
|
3
|
+
import { mergeCallbacks, slot, useEventCallback, useMergedRefs } from '@fluentui/react-utilities';
|
|
4
|
+
import { getDropdownActionFromKey } from '../utils/dropdownKeyActions';
|
|
4
5
|
/**
|
|
5
6
|
* Shared trigger behaviour for combobox and dropdown
|
|
6
7
|
* @returns trigger slot with desired behaviour and props
|
|
7
8
|
*/ export function useTriggerSlot(triggerSlotFromProp, ref, options) {
|
|
8
|
-
const { state: {
|
|
9
|
+
const { state: { open, setOpen, setHasFocus }, defaultProps, elementType, activeDescendantController } = options;
|
|
9
10
|
const trigger = slot.always(triggerSlotFromProp, {
|
|
10
11
|
defaultProps: {
|
|
11
12
|
type: 'text',
|
|
12
13
|
'aria-expanded': open,
|
|
13
|
-
'aria-activedescendant': open ? activeOption === null || activeOption === void 0 ? void 0 : activeOption.id : undefined,
|
|
14
14
|
role: 'combobox',
|
|
15
15
|
...typeof defaultProps === 'object' && defaultProps
|
|
16
16
|
},
|
|
@@ -33,49 +33,102 @@ import { getDropdownActionFromKey, getIndexFromAction } from '../utils/dropdownK
|
|
|
33
33
|
setOpen(event, !open);
|
|
34
34
|
}, trigger.onClick);
|
|
35
35
|
// handle combobox keyboard interaction
|
|
36
|
-
trigger.onKeyDown = mergeCallbacks((
|
|
37
|
-
|
|
36
|
+
trigger.onKeyDown = mergeCallbacks(useTriggerKeydown({
|
|
37
|
+
activeDescendantController,
|
|
38
|
+
...options.state
|
|
39
|
+
}), trigger.onKeyDown);
|
|
40
|
+
return trigger;
|
|
41
|
+
}
|
|
42
|
+
function useTriggerKeydown(options) {
|
|
43
|
+
const { activeDescendantController, getOptionById, setOpen, selectOption, multiselect, open } = options;
|
|
44
|
+
const getActiveOption = React.useCallback(()=>{
|
|
45
|
+
const activeOptionId = activeDescendantController.active();
|
|
46
|
+
return activeOptionId ? getOptionById(activeOptionId) : undefined;
|
|
47
|
+
}, [
|
|
48
|
+
activeDescendantController,
|
|
49
|
+
getOptionById
|
|
50
|
+
]);
|
|
51
|
+
const first = ()=>{
|
|
52
|
+
activeDescendantController.first();
|
|
53
|
+
};
|
|
54
|
+
const next = (activeOption)=>{
|
|
55
|
+
if (activeOption) {
|
|
56
|
+
activeDescendantController.next();
|
|
57
|
+
} else {
|
|
58
|
+
activeDescendantController.first();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const previous = (activeOption)=>{
|
|
62
|
+
if (activeOption) {
|
|
63
|
+
activeDescendantController.prev();
|
|
64
|
+
} else {
|
|
65
|
+
activeDescendantController.first();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const pageUp = ()=>{
|
|
69
|
+
for(let i = 0; i < 10; i++){
|
|
70
|
+
activeDescendantController.prev();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const pageDown = ()=>{
|
|
74
|
+
for(let i = 0; i < 10; i++){
|
|
75
|
+
activeDescendantController.next();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const setKeyboardNavigation = useSetKeyboardNavigation();
|
|
79
|
+
return useEventCallback((e)=>{
|
|
80
|
+
const action = getDropdownActionFromKey(e, {
|
|
38
81
|
open,
|
|
39
82
|
multiselect
|
|
40
83
|
});
|
|
41
|
-
const
|
|
42
|
-
const activeIndex = activeOption ? getIndexOfId(activeOption.id) : -1;
|
|
43
|
-
let newIndex = activeIndex;
|
|
84
|
+
const activeOption = getActiveOption();
|
|
44
85
|
switch(action){
|
|
86
|
+
case 'First':
|
|
87
|
+
case 'Next':
|
|
88
|
+
case 'Previous':
|
|
89
|
+
case 'PageDown':
|
|
90
|
+
case 'PageUp':
|
|
45
91
|
case 'Open':
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
92
|
+
case 'Close':
|
|
93
|
+
case 'CloseSelect':
|
|
94
|
+
case 'Select':
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
setKeyboardNavigation(true);
|
|
99
|
+
switch(action){
|
|
100
|
+
case 'First':
|
|
101
|
+
first();
|
|
102
|
+
break;
|
|
103
|
+
case 'Next':
|
|
104
|
+
next(activeOption);
|
|
105
|
+
break;
|
|
106
|
+
case 'Previous':
|
|
107
|
+
previous(activeOption);
|
|
108
|
+
break;
|
|
109
|
+
case 'PageDown':
|
|
110
|
+
pageDown();
|
|
111
|
+
break;
|
|
112
|
+
case 'PageUp':
|
|
113
|
+
pageUp();
|
|
114
|
+
break;
|
|
115
|
+
case 'Open':
|
|
116
|
+
setOpen(e, true);
|
|
49
117
|
break;
|
|
50
118
|
case 'Close':
|
|
51
119
|
// stop propagation for escape key to avoid dismissing any parent popups
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
setOpen(event, false);
|
|
120
|
+
e.stopPropagation();
|
|
121
|
+
setOpen(e, false);
|
|
55
122
|
break;
|
|
56
123
|
case 'CloseSelect':
|
|
57
|
-
!multiselect && !(activeOption === null || activeOption === void 0 ? void 0 : activeOption.disabled) && setOpen(
|
|
124
|
+
!multiselect && !(activeOption === null || activeOption === void 0 ? void 0 : activeOption.disabled) && setOpen(e, false);
|
|
58
125
|
// fallthrough
|
|
59
126
|
case 'Select':
|
|
60
|
-
activeOption && selectOption(
|
|
61
|
-
event.preventDefault();
|
|
127
|
+
activeOption && selectOption(e, activeOption);
|
|
62
128
|
break;
|
|
63
129
|
case 'Tab':
|
|
64
|
-
!multiselect && activeOption && selectOption(
|
|
130
|
+
!multiselect && activeOption && selectOption(e, activeOption);
|
|
65
131
|
break;
|
|
66
|
-
default:
|
|
67
|
-
newIndex = getIndexFromAction(action, activeIndex, maxIndex);
|
|
68
|
-
}
|
|
69
|
-
if (newIndex !== activeIndex) {
|
|
70
|
-
// prevent default page scroll/keyboard action if the index changed
|
|
71
|
-
event.preventDefault();
|
|
72
|
-
setActiveOption(getOptionAtIndex(newIndex));
|
|
73
|
-
setFocusVisible(true);
|
|
74
132
|
}
|
|
75
|
-
}
|
|
76
|
-
trigger.onMouseOver = mergeCallbacks((event)=>{
|
|
77
|
-
setFocusVisible(false);
|
|
78
|
-
}, trigger.onMouseOver);
|
|
79
|
-
// TODO fix cast
|
|
80
|
-
return trigger;
|
|
133
|
+
});
|
|
81
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useTriggerSlot.ts"],"sourcesContent":["import * as React from 'react';\nimport { mergeCallbacks, slot, useMergedRefs } from '@fluentui/react-utilities';\nimport type { ExtractSlotProps, Slot, SlotComponentType } from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey
|
|
1
|
+
{"version":3,"sources":["useTriggerSlot.ts"],"sourcesContent":["import * as React from 'react';\nimport { useSetKeyboardNavigation } from '@fluentui/react-tabster';\nimport type { ActiveDescendantImperativeRef } from '@fluentui/react-aria';\nimport { mergeCallbacks, slot, useEventCallback, useMergedRefs } from '@fluentui/react-utilities';\nimport type { ExtractSlotProps, Slot, SlotComponentType } from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey } from '../utils/dropdownKeyActions';\nimport type { ComboboxBaseState } from './ComboboxBase.types';\nimport { OptionValue } from './OptionCollection.types';\n\nexport type UseTriggerSlotState = Pick<\n ComboboxBaseState,\n 'open' | 'getOptionById' | 'selectOption' | 'setOpen' | 'multiselect' | 'setHasFocus'\n>;\n\ntype UseTriggerSlotOptions = {\n state: UseTriggerSlotState;\n defaultProps: unknown;\n activeDescendantController: ActiveDescendantImperativeRef;\n};\n\nexport function useTriggerSlot(\n triggerSlotFromProp: NonNullable<Slot<'button'>>,\n ref: React.Ref<HTMLButtonElement>,\n options: UseTriggerSlotOptions & { elementType: 'button' },\n): SlotComponentType<ExtractSlotProps<Slot<'button'>>>;\n\nexport function useTriggerSlot(\n triggerSlotFromProp: NonNullable<Slot<'input'>>,\n ref: React.Ref<HTMLInputElement>,\n options: UseTriggerSlotOptions & { elementType: 'input' },\n): SlotComponentType<ExtractSlotProps<Slot<'input'>>>;\n\n/**\n * Shared trigger behaviour for combobox and dropdown\n * @returns trigger slot with desired behaviour and props\n */\nexport function useTriggerSlot(\n triggerSlotFromProp: NonNullable<Slot<'input'>> | NonNullable<Slot<'button'>>,\n ref: React.Ref<HTMLButtonElement> | React.Ref<HTMLInputElement>,\n options: UseTriggerSlotOptions & { elementType: 'input' | 'button' },\n): SlotComponentType<ExtractSlotProps<Slot<'button'>>> | SlotComponentType<ExtractSlotProps<Slot<'input'>>> {\n const {\n state: { open, setOpen, setHasFocus },\n defaultProps,\n elementType,\n activeDescendantController,\n } = options;\n\n const trigger = slot.always(triggerSlotFromProp, {\n defaultProps: {\n type: 'text',\n 'aria-expanded': open,\n role: 'combobox',\n ...(typeof defaultProps === 'object' && defaultProps),\n },\n elementType,\n });\n\n // handle trigger focus/blur\n const triggerRef = React.useRef<HTMLButtonElement | HTMLInputElement>(null);\n trigger.ref = useMergedRefs(triggerRef, trigger.ref, ref) as React.Ref<HTMLButtonElement & HTMLInputElement>;\n\n // the trigger should open/close the popup on click or blur\n trigger.onBlur = mergeCallbacks((event: React.FocusEvent<HTMLButtonElement> & React.FocusEvent<HTMLInputElement>) => {\n setOpen(event, false);\n setHasFocus(false);\n }, trigger.onBlur);\n\n trigger.onFocus = mergeCallbacks(\n (event: React.FocusEvent<HTMLButtonElement> & React.FocusEvent<HTMLInputElement>) => {\n if (event.target === event.currentTarget) {\n setHasFocus(true);\n }\n },\n trigger.onFocus,\n );\n trigger.onClick = mergeCallbacks(\n (event: React.MouseEvent<HTMLButtonElement> & React.MouseEvent<HTMLInputElement>) => {\n setOpen(event, !open);\n },\n trigger.onClick,\n );\n\n // handle combobox keyboard interaction\n trigger.onKeyDown = mergeCallbacks(\n useTriggerKeydown({ activeDescendantController, ...options.state }),\n trigger.onKeyDown,\n );\n\n return trigger as SlotComponentType<ExtractSlotProps<Slot<'input'>>>;\n}\n\nfunction useTriggerKeydown(\n options: {\n activeDescendantController: ActiveDescendantImperativeRef;\n } & Pick<UseTriggerSlotState, 'setOpen' | 'selectOption' | 'getOptionById' | 'multiselect' | 'open'>,\n) {\n const { activeDescendantController, getOptionById, setOpen, selectOption, multiselect, open } = options;\n\n const getActiveOption = React.useCallback(() => {\n const activeOptionId = activeDescendantController.active();\n return activeOptionId ? getOptionById(activeOptionId) : undefined;\n }, [activeDescendantController, getOptionById]);\n\n const first = () => {\n activeDescendantController.first();\n };\n\n const next = (activeOption: OptionValue | undefined) => {\n if (activeOption) {\n activeDescendantController.next();\n } else {\n activeDescendantController.first();\n }\n };\n\n const previous = (activeOption: OptionValue | undefined) => {\n if (activeOption) {\n activeDescendantController.prev();\n } else {\n activeDescendantController.first();\n }\n };\n\n const pageUp = () => {\n for (let i = 0; i < 10; i++) {\n activeDescendantController.prev();\n }\n };\n\n const pageDown = () => {\n for (let i = 0; i < 10; i++) {\n activeDescendantController.next();\n }\n };\n\n const setKeyboardNavigation = useSetKeyboardNavigation();\n return useEventCallback((e: React.KeyboardEvent<HTMLInputElement> & React.KeyboardEvent<HTMLButtonElement>) => {\n const action = getDropdownActionFromKey(e, { open, multiselect });\n const activeOption = getActiveOption();\n\n switch (action) {\n case 'First':\n case 'Next':\n case 'Previous':\n case 'PageDown':\n case 'PageUp':\n case 'Open':\n case 'Close':\n case 'CloseSelect':\n case 'Select':\n e.preventDefault();\n break;\n }\n\n setKeyboardNavigation(true);\n\n switch (action) {\n case 'First':\n first();\n break;\n case 'Next':\n next(activeOption);\n break;\n case 'Previous':\n previous(activeOption);\n break;\n case 'PageDown':\n pageDown();\n break;\n case 'PageUp':\n pageUp();\n break;\n case 'Open':\n setOpen(e, true);\n break;\n case 'Close':\n // stop propagation for escape key to avoid dismissing any parent popups\n e.stopPropagation();\n setOpen(e, false);\n break;\n case 'CloseSelect':\n !multiselect && !activeOption?.disabled && setOpen(e, false);\n // fallthrough\n case 'Select':\n activeOption && selectOption(e, activeOption);\n break;\n case 'Tab':\n !multiselect && activeOption && selectOption(e, activeOption);\n break;\n }\n });\n}\n"],"names":["React","useSetKeyboardNavigation","mergeCallbacks","slot","useEventCallback","useMergedRefs","getDropdownActionFromKey","useTriggerSlot","triggerSlotFromProp","ref","options","state","open","setOpen","setHasFocus","defaultProps","elementType","activeDescendantController","trigger","always","type","role","triggerRef","useRef","onBlur","event","onFocus","target","currentTarget","onClick","onKeyDown","useTriggerKeydown","getOptionById","selectOption","multiselect","getActiveOption","useCallback","activeOptionId","active","undefined","first","next","activeOption","previous","prev","pageUp","i","pageDown","setKeyboardNavigation","e","action","preventDefault","stopPropagation","disabled"],"mappings":"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"}
|
|
@@ -10,22 +10,26 @@ Object.defineProperty(exports, "renderCombobox_unstable", {
|
|
|
10
10
|
});
|
|
11
11
|
const _jsxruntime = require("@fluentui/react-jsx-runtime/jsx-runtime");
|
|
12
12
|
const _reactportal = require("@fluentui/react-portal");
|
|
13
|
+
const _reactaria = require("@fluentui/react-aria");
|
|
13
14
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
14
15
|
const _ComboboxContext = require("../../contexts/ComboboxContext");
|
|
15
16
|
const renderCombobox_unstable = (state, contextValues)=>{
|
|
16
17
|
(0, _reactutilities.assertSlots)(state);
|
|
17
18
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(state.root, {
|
|
18
|
-
children: /*#__PURE__*/ (0, _jsxruntime.
|
|
19
|
-
value: contextValues.
|
|
20
|
-
children:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactaria.ActiveDescendantContextProvider, {
|
|
20
|
+
value: contextValues.activeDescendant,
|
|
21
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_ComboboxContext.ComboboxContext.Provider, {
|
|
22
|
+
value: contextValues.combobox,
|
|
23
|
+
children: [
|
|
24
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(state.input, {}),
|
|
25
|
+
state.clearIcon && /*#__PURE__*/ (0, _jsxruntime.jsx)(state.clearIcon, {}),
|
|
26
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(state.expandIcon, {}),
|
|
27
|
+
state.listbox && (state.inlinePopup ? /*#__PURE__*/ (0, _jsxruntime.jsx)(state.listbox, {}) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactportal.Portal, {
|
|
28
|
+
mountNode: state.mountNode,
|
|
29
|
+
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(state.listbox, {})
|
|
30
|
+
}))
|
|
31
|
+
]
|
|
32
|
+
})
|
|
29
33
|
})
|
|
30
34
|
});
|
|
31
35
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["renderCombobox.js"],"sourcesContent":[" import { jsx as _jsx, jsxs as _jsxs } from \"@fluentui/react-jsx-runtime/jsx-runtime\";\nimport { Portal } from '@fluentui/react-portal';\nimport { assertSlots } from '@fluentui/react-utilities';\nimport { ComboboxContext } from '../../contexts/ComboboxContext';\n/**\n * Render the final JSX of Combobox\n */ export const renderCombobox_unstable = (state, contextValues)=>{\n assertSlots(state);\n return /*#__PURE__*/ _jsx(state.root, {\n children: /*#__PURE__*/ _jsxs(ComboboxContext.Provider, {\n
|
|
1
|
+
{"version":3,"sources":["renderCombobox.js"],"sourcesContent":[" import { jsx as _jsx, jsxs as _jsxs } from \"@fluentui/react-jsx-runtime/jsx-runtime\";\nimport { Portal } from '@fluentui/react-portal';\nimport { ActiveDescendantContextProvider } from '@fluentui/react-aria';\nimport { assertSlots } from '@fluentui/react-utilities';\nimport { ComboboxContext } from '../../contexts/ComboboxContext';\n/**\n * Render the final JSX of Combobox\n */ export const renderCombobox_unstable = (state, contextValues)=>{\n assertSlots(state);\n return /*#__PURE__*/ _jsx(state.root, {\n children: /*#__PURE__*/ _jsx(ActiveDescendantContextProvider, {\n value: contextValues.activeDescendant,\n children: /*#__PURE__*/ _jsxs(ComboboxContext.Provider, {\n value: contextValues.combobox,\n children: [\n /*#__PURE__*/ _jsx(state.input, {}),\n state.clearIcon && /*#__PURE__*/ _jsx(state.clearIcon, {}),\n /*#__PURE__*/ _jsx(state.expandIcon, {}),\n state.listbox && (state.inlinePopup ? /*#__PURE__*/ _jsx(state.listbox, {}) : /*#__PURE__*/ _jsx(Portal, {\n mountNode: state.mountNode,\n children: /*#__PURE__*/ _jsx(state.listbox, {})\n }))\n ]\n })\n })\n });\n};\n"],"names":["renderCombobox_unstable","state","contextValues","assertSlots","_jsx","root","children","ActiveDescendantContextProvider","value","activeDescendant","_jsxs","ComboboxContext","Provider","combobox","input","clearIcon","expandIcon","listbox","inlinePopup","Portal","mountNode"],"mappings":";;;;+BAOiBA;;;eAAAA;;;4BAP4B;6BACtB;2BACyB;gCACpB;iCACI;AAGrB,MAAMA,0BAA0B,CAACC,OAAOC;IAC/CC,IAAAA,2BAAW,EAACF;IACZ,OAAO,WAAW,GAAGG,IAAAA,eAAI,EAACH,MAAMI,IAAI,EAAE;QAClCC,UAAU,WAAW,GAAGF,IAAAA,eAAI,EAACG,0CAA+B,EAAE;YAC1DC,OAAON,cAAcO,gBAAgB;YACrCH,UAAU,WAAW,GAAGI,IAAAA,gBAAK,EAACC,gCAAe,CAACC,QAAQ,EAAE;gBACpDJ,OAAON,cAAcW,QAAQ;gBAC7BP,UAAU;oBACN,WAAW,GAAGF,IAAAA,eAAI,EAACH,MAAMa,KAAK,EAAE,CAAC;oBACjCb,MAAMc,SAAS,IAAI,WAAW,GAAGX,IAAAA,eAAI,EAACH,MAAMc,SAAS,EAAE,CAAC;oBACxD,WAAW,GAAGX,IAAAA,eAAI,EAACH,MAAMe,UAAU,EAAE,CAAC;oBACtCf,MAAMgB,OAAO,IAAKhB,CAAAA,MAAMiB,WAAW,GAAG,WAAW,GAAGd,IAAAA,eAAI,EAACH,MAAMgB,OAAO,EAAE,CAAC,KAAK,WAAW,GAAGb,IAAAA,eAAI,EAACe,mBAAM,EAAE;wBACrGC,WAAWnB,MAAMmB,SAAS;wBAC1Bd,UAAU,WAAW,GAAGF,IAAAA,eAAI,EAACH,MAAMgB,OAAO,EAAE,CAAC;oBACjD,EAAC;iBACJ;YACL;QACJ;IACJ;AACJ"}
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "useCombobox_unstable", {
|
|
|
10
10
|
});
|
|
11
11
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
12
12
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
13
|
+
const _reactaria = require("@fluentui/react-aria");
|
|
13
14
|
const _reactfield = require("@fluentui/react-field");
|
|
14
15
|
const _reacticons = require("@fluentui/react-icons");
|
|
15
16
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
@@ -18,6 +19,7 @@ const _useComboboxPositioning = require("../../utils/useComboboxPositioning");
|
|
|
18
19
|
const _Listbox = require("../Listbox/Listbox");
|
|
19
20
|
const _useListboxSlot = require("../../utils/useListboxSlot");
|
|
20
21
|
const _useInputTriggerSlot = require("./useInputTriggerSlot");
|
|
22
|
+
const _useOptionStylesstyles = require("../Option/useOptionStyles.styles");
|
|
21
23
|
const useCombobox_unstable = (props, ref)=>{
|
|
22
24
|
var _state_clearIcon, _state_clearIcon1;
|
|
23
25
|
// Merge props from surrounding <Field>, if any
|
|
@@ -26,9 +28,13 @@ const useCombobox_unstable = (props, ref)=>{
|
|
|
26
28
|
supportsRequired: true,
|
|
27
29
|
supportsSize: true
|
|
28
30
|
});
|
|
31
|
+
const { listboxRef: activeDescendantListboxRef, activeParentRef, controller: activeDescendantController } = (0, _reactaria.useActiveDescendant)({
|
|
32
|
+
matchOption: (el)=>el.classList.contains(_useOptionStylesstyles.optionClassNames.root)
|
|
33
|
+
});
|
|
29
34
|
const baseState = (0, _useComboboxBaseState.useComboboxBaseState)({
|
|
30
35
|
...props,
|
|
31
|
-
editable: true
|
|
36
|
+
editable: true,
|
|
37
|
+
activeDescendantController
|
|
32
38
|
});
|
|
33
39
|
const { clearable, clearSelection, multiselect, open, selectedOptions, selectOption, setOpen, setValue, value, hasFocus } = baseState;
|
|
34
40
|
const [comboboxPopupRef, comboboxTargetRef] = (0, _useComboboxPositioning.useComboboxPositioning)(props);
|
|
@@ -57,7 +63,7 @@ const useCombobox_unstable = (props, ref)=>{
|
|
|
57
63
|
setOpen(ev, newState);
|
|
58
64
|
};
|
|
59
65
|
const triggerRef = _react.useRef(null);
|
|
60
|
-
const listbox = (0, _useListboxSlot.useListboxSlot)(props.listbox, comboboxPopupRef, {
|
|
66
|
+
const listbox = (0, _useListboxSlot.useListboxSlot)(props.listbox, (0, _reactutilities.useMergedRefs)(comboboxPopupRef, activeDescendantListboxRef), {
|
|
61
67
|
state: baseState,
|
|
62
68
|
triggerRef,
|
|
63
69
|
defaultProps: {
|
|
@@ -65,7 +71,7 @@ const useCombobox_unstable = (props, ref)=>{
|
|
|
65
71
|
}
|
|
66
72
|
});
|
|
67
73
|
var _props_input;
|
|
68
|
-
const triggerSlot = (0, _useInputTriggerSlot.useInputTriggerSlot)((_props_input = props.input) !== null && _props_input !== void 0 ? _props_input : {}, (0, _reactutilities.useMergedRefs)(triggerRef, ref), {
|
|
74
|
+
const triggerSlot = (0, _useInputTriggerSlot.useInputTriggerSlot)((_props_input = props.input) !== null && _props_input !== void 0 ? _props_input : {}, (0, _reactutilities.useMergedRefs)(triggerRef, activeParentRef, ref), {
|
|
69
75
|
state: baseState,
|
|
70
76
|
freeform,
|
|
71
77
|
defaultProps: {
|
|
@@ -73,7 +79,8 @@ const useCombobox_unstable = (props, ref)=>{
|
|
|
73
79
|
value: value !== null && value !== void 0 ? value : '',
|
|
74
80
|
'aria-controls': open ? listbox === null || listbox === void 0 ? void 0 : listbox.id : undefined,
|
|
75
81
|
...triggerNativeProps
|
|
76
|
-
}
|
|
82
|
+
},
|
|
83
|
+
activeDescendantController
|
|
77
84
|
});
|
|
78
85
|
const rootSlot = _reactutilities.slot.always(props.root, {
|
|
79
86
|
defaultProps: {
|
|
@@ -113,6 +120,7 @@ const useCombobox_unstable = (props, ref)=>{
|
|
|
113
120
|
elementType: 'span'
|
|
114
121
|
}),
|
|
115
122
|
showClearIcon,
|
|
123
|
+
activeDescendantController,
|
|
116
124
|
...baseState
|
|
117
125
|
};
|
|
118
126
|
/* handle open/close + focus change when clicking expandIcon */ const { onMouseDown: onIconMouseDown } = state.expandIcon || {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["useCombobox.js"],"sourcesContent":["import * as React from 'react';\nimport { useFieldControlProps_unstable } from '@fluentui/react-field';\nimport { ChevronDownRegular as ChevronDownIcon, DismissRegular as DismissIcon } from '@fluentui/react-icons';\nimport { getPartitionedNativeProps, mergeCallbacks, useEventCallback, useId, useMergedRefs, slot } from '@fluentui/react-utilities';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPositioning } from '../../utils/useComboboxPositioning';\nimport { Listbox } from '../Listbox/Listbox';\nimport { useListboxSlot } from '../../utils/useListboxSlot';\nimport { useInputTriggerSlot } from './useInputTriggerSlot';\n/**\n * Create the state required to render Combobox.\n *\n * The returned state can be modified with hooks such as useComboboxStyles_unstable,\n * before being passed to renderCombobox_unstable.\n *\n * @param props - props from this instance of Combobox\n * @param ref - reference to root HTMLElement of Combobox\n */ export const useCombobox_unstable = (props, ref)=>{\n var _state_clearIcon, _state_clearIcon1;\n // Merge props from surrounding <Field>, if any\n props = useFieldControlProps_unstable(props, {\n supportsLabelFor: true,\n supportsRequired: true,\n supportsSize: true\n });\n const baseState = useComboboxBaseState({\n ...props,\n editable: true\n });\n const { clearable, clearSelection, multiselect, open, selectedOptions, selectOption, setOpen, setValue, value, hasFocus } = baseState;\n const [comboboxPopupRef, comboboxTargetRef] = useComboboxPositioning(props);\n const { disabled, freeform, inlinePopup } = props;\n const comboId = useId('combobox-');\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'input',\n excludedPropNames: [\n 'children',\n 'size'\n ]\n });\n // reset any typed value when an option is selected\n baseState.selectOption = (ev, option)=>{\n setValue(undefined);\n selectOption(ev, option);\n };\n baseState.setOpen = (ev, newState)=>{\n if (disabled) {\n return;\n }\n if (!newState && !freeform) {\n setValue(undefined);\n }\n setOpen(ev, newState);\n };\n const triggerRef = React.useRef(null);\n const listbox = useListboxSlot(props.listbox, comboboxPopupRef, {\n state: baseState,\n triggerRef,\n defaultProps: {\n children: props.children\n }\n });\n var _props_input;\n const triggerSlot = useInputTriggerSlot((_props_input = props.input) !== null && _props_input !== void 0 ? _props_input : {}, useMergedRefs(triggerRef, ref), {\n state: baseState,\n freeform,\n defaultProps: {\n type: 'text',\n value: value !== null && value !== void 0 ? value : '',\n 'aria-controls': open ? listbox === null || listbox === void 0 ? void 0 : listbox.id : undefined,\n ...triggerNativeProps\n }\n });\n const rootSlot = slot.always(props.root, {\n defaultProps: {\n 'aria-owns': !inlinePopup && open ? listbox === null || listbox === void 0 ? void 0 : listbox.id : undefined,\n ...rootNativeProps\n },\n elementType: 'div'\n });\n rootSlot.ref = useMergedRefs(rootSlot.ref, comboboxTargetRef);\n const showClearIcon = selectedOptions.length > 0 && clearable && !multiselect;\n const state = {\n components: {\n root: 'div',\n input: 'input',\n expandIcon: 'span',\n listbox: Listbox,\n clearIcon: 'span'\n },\n root: rootSlot,\n input: triggerSlot,\n listbox: open || hasFocus ? listbox : undefined,\n clearIcon: slot.optional(props.clearIcon, {\n defaultProps: {\n 'aria-hidden': 'true',\n children: /*#__PURE__*/ React.createElement(DismissIcon, null)\n },\n elementType: 'span',\n renderByDefault: true\n }),\n expandIcon: slot.optional(props.expandIcon, {\n renderByDefault: true,\n defaultProps: {\n 'aria-expanded': open,\n children: /*#__PURE__*/ React.createElement(ChevronDownIcon, null),\n role: 'button'\n },\n elementType: 'span'\n }),\n showClearIcon,\n ...baseState\n };\n /* handle open/close + focus change when clicking expandIcon */ const { onMouseDown: onIconMouseDown } = state.expandIcon || {};\n const onExpandIconMouseDown = useEventCallback(mergeCallbacks(onIconMouseDown, (event)=>{\n var _triggerRef_current;\n event.preventDefault();\n state.setOpen(event, !state.open);\n (_triggerRef_current = triggerRef.current) === null || _triggerRef_current === void 0 ? void 0 : _triggerRef_current.focus();\n }));\n if (state.expandIcon) {\n state.expandIcon.onMouseDown = onExpandIconMouseDown;\n // If there is no explicit aria-label, calculate default accName attribute for expandIcon button,\n // using the following steps:\n // 1. If there is an aria-label, it is \"Open [aria-label]\"\n // 2. If there is an aria-labelledby, it is \"Open [aria-labelledby target]\" (using aria-labelledby + ids)\n // 3. If there is no aria-label/ledby attr, it falls back to \"Open\"\n // We can't fall back to a label/htmlFor name because of https://github.com/w3c/accname/issues/179\n const hasExpandLabel = state.expandIcon['aria-label'] || state.expandIcon['aria-labelledby'];\n const defaultOpenString = 'Open'; // this is english-only since it is the fallback\n if (!hasExpandLabel) {\n if (props['aria-labelledby']) {\n var _state_expandIcon_id;\n const chevronId = (_state_expandIcon_id = state.expandIcon.id) !== null && _state_expandIcon_id !== void 0 ? _state_expandIcon_id : `${comboId}-chevron`;\n const chevronLabelledBy = `${chevronId} ${state.input['aria-labelledby']}`;\n state.expandIcon['aria-label'] = defaultOpenString;\n state.expandIcon.id = chevronId;\n state.expandIcon['aria-labelledby'] = chevronLabelledBy;\n } else if (props['aria-label']) {\n state.expandIcon['aria-label'] = `${defaultOpenString} ${props['aria-label']}`;\n } else {\n state.expandIcon['aria-label'] = defaultOpenString;\n }\n }\n }\n const onClearIconMouseDown = useEventCallback(mergeCallbacks((_state_clearIcon = state.clearIcon) === null || _state_clearIcon === void 0 ? void 0 : _state_clearIcon.onMouseDown, (ev)=>{\n ev.preventDefault();\n }));\n const onClearIconClick = useEventCallback(mergeCallbacks((_state_clearIcon1 = state.clearIcon) === null || _state_clearIcon1 === void 0 ? void 0 : _state_clearIcon1.onClick, (ev)=>{\n clearSelection(ev);\n }));\n if (state.clearIcon) {\n state.clearIcon.onMouseDown = onClearIconMouseDown;\n state.clearIcon.onClick = onClearIconClick;\n }\n // Heads up! We don't support \"clearable\" in multiselect mode, so we should never display a slot\n if (multiselect) {\n state.clearIcon = undefined;\n }\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks -- \"process.env\" does not change in runtime\n React.useEffect(()=>{\n if (clearable && multiselect) {\n // eslint-disable-next-line no-console\n console.error(`[@fluentui/react-combobox] \"clearable\" prop is not supported in multiselect mode.`);\n }\n }, [\n clearable,\n multiselect\n ]);\n }\n return state;\n};\n"],"names":["useCombobox_unstable","props","ref","_state_clearIcon","_state_clearIcon1","useFieldControlProps_unstable","supportsLabelFor","supportsRequired","supportsSize","baseState","useComboboxBaseState","editable","clearable","clearSelection","multiselect","open","selectedOptions","selectOption","setOpen","setValue","value","hasFocus","comboboxPopupRef","comboboxTargetRef","useComboboxPositioning","disabled","freeform","inlinePopup","comboId","useId","primary","triggerNativeProps","root","rootNativeProps","getPartitionedNativeProps","primarySlotTagName","excludedPropNames","ev","option","undefined","newState","triggerRef","React","useRef","listbox","useListboxSlot","state","defaultProps","children","_props_input","triggerSlot","useInputTriggerSlot","input","useMergedRefs","type","id","rootSlot","slot","always","elementType","showClearIcon","length","components","expandIcon","Listbox","clearIcon","optional","createElement","DismissIcon","renderByDefault","ChevronDownIcon","role","onMouseDown","onIconMouseDown","onExpandIconMouseDown","useEventCallback","mergeCallbacks","event","_triggerRef_current","preventDefault","current","focus","hasExpandLabel","defaultOpenString","_state_expandIcon_id","chevronId","chevronLabelledBy","onClearIconMouseDown","onClearIconClick","onClick","process","env","NODE_ENV","useEffect","console","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["useCombobox.js"],"sourcesContent":["import * as React from 'react';\nimport { useActiveDescendant } from '@fluentui/react-aria';\nimport { useFieldControlProps_unstable } from '@fluentui/react-field';\nimport { ChevronDownRegular as ChevronDownIcon, DismissRegular as DismissIcon } from '@fluentui/react-icons';\nimport { getPartitionedNativeProps, mergeCallbacks, useEventCallback, useId, useMergedRefs, slot } from '@fluentui/react-utilities';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPositioning } from '../../utils/useComboboxPositioning';\nimport { Listbox } from '../Listbox/Listbox';\nimport { useListboxSlot } from '../../utils/useListboxSlot';\nimport { useInputTriggerSlot } from './useInputTriggerSlot';\nimport { optionClassNames } from '../Option/useOptionStyles.styles';\n/**\n * Create the state required to render Combobox.\n *\n * The returned state can be modified with hooks such as useComboboxStyles_unstable,\n * before being passed to renderCombobox_unstable.\n *\n * @param props - props from this instance of Combobox\n * @param ref - reference to root HTMLElement of Combobox\n */ export const useCombobox_unstable = (props, ref)=>{\n var _state_clearIcon, _state_clearIcon1;\n // Merge props from surrounding <Field>, if any\n props = useFieldControlProps_unstable(props, {\n supportsLabelFor: true,\n supportsRequired: true,\n supportsSize: true\n });\n const { listboxRef: activeDescendantListboxRef, activeParentRef, controller: activeDescendantController } = useActiveDescendant({\n matchOption: (el)=>el.classList.contains(optionClassNames.root)\n });\n const baseState = useComboboxBaseState({\n ...props,\n editable: true,\n activeDescendantController\n });\n const { clearable, clearSelection, multiselect, open, selectedOptions, selectOption, setOpen, setValue, value, hasFocus } = baseState;\n const [comboboxPopupRef, comboboxTargetRef] = useComboboxPositioning(props);\n const { disabled, freeform, inlinePopup } = props;\n const comboId = useId('combobox-');\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'input',\n excludedPropNames: [\n 'children',\n 'size'\n ]\n });\n // reset any typed value when an option is selected\n baseState.selectOption = (ev, option)=>{\n setValue(undefined);\n selectOption(ev, option);\n };\n baseState.setOpen = (ev, newState)=>{\n if (disabled) {\n return;\n }\n if (!newState && !freeform) {\n setValue(undefined);\n }\n setOpen(ev, newState);\n };\n const triggerRef = React.useRef(null);\n const listbox = useListboxSlot(props.listbox, useMergedRefs(comboboxPopupRef, activeDescendantListboxRef), {\n state: baseState,\n triggerRef,\n defaultProps: {\n children: props.children\n }\n });\n var _props_input;\n const triggerSlot = useInputTriggerSlot((_props_input = props.input) !== null && _props_input !== void 0 ? _props_input : {}, useMergedRefs(triggerRef, activeParentRef, ref), {\n state: baseState,\n freeform,\n defaultProps: {\n type: 'text',\n value: value !== null && value !== void 0 ? value : '',\n 'aria-controls': open ? listbox === null || listbox === void 0 ? void 0 : listbox.id : undefined,\n ...triggerNativeProps\n },\n activeDescendantController\n });\n const rootSlot = slot.always(props.root, {\n defaultProps: {\n 'aria-owns': !inlinePopup && open ? listbox === null || listbox === void 0 ? void 0 : listbox.id : undefined,\n ...rootNativeProps\n },\n elementType: 'div'\n });\n rootSlot.ref = useMergedRefs(rootSlot.ref, comboboxTargetRef);\n const showClearIcon = selectedOptions.length > 0 && clearable && !multiselect;\n const state = {\n components: {\n root: 'div',\n input: 'input',\n expandIcon: 'span',\n listbox: Listbox,\n clearIcon: 'span'\n },\n root: rootSlot,\n input: triggerSlot,\n listbox: open || hasFocus ? listbox : undefined,\n clearIcon: slot.optional(props.clearIcon, {\n defaultProps: {\n 'aria-hidden': 'true',\n children: /*#__PURE__*/ React.createElement(DismissIcon, null)\n },\n elementType: 'span',\n renderByDefault: true\n }),\n expandIcon: slot.optional(props.expandIcon, {\n renderByDefault: true,\n defaultProps: {\n 'aria-expanded': open,\n children: /*#__PURE__*/ React.createElement(ChevronDownIcon, null),\n role: 'button'\n },\n elementType: 'span'\n }),\n showClearIcon,\n activeDescendantController,\n ...baseState\n };\n /* handle open/close + focus change when clicking expandIcon */ const { onMouseDown: onIconMouseDown } = state.expandIcon || {};\n const onExpandIconMouseDown = useEventCallback(mergeCallbacks(onIconMouseDown, (event)=>{\n var _triggerRef_current;\n event.preventDefault();\n state.setOpen(event, !state.open);\n (_triggerRef_current = triggerRef.current) === null || _triggerRef_current === void 0 ? void 0 : _triggerRef_current.focus();\n }));\n if (state.expandIcon) {\n state.expandIcon.onMouseDown = onExpandIconMouseDown;\n // If there is no explicit aria-label, calculate default accName attribute for expandIcon button,\n // using the following steps:\n // 1. If there is an aria-label, it is \"Open [aria-label]\"\n // 2. If there is an aria-labelledby, it is \"Open [aria-labelledby target]\" (using aria-labelledby + ids)\n // 3. If there is no aria-label/ledby attr, it falls back to \"Open\"\n // We can't fall back to a label/htmlFor name because of https://github.com/w3c/accname/issues/179\n const hasExpandLabel = state.expandIcon['aria-label'] || state.expandIcon['aria-labelledby'];\n const defaultOpenString = 'Open'; // this is english-only since it is the fallback\n if (!hasExpandLabel) {\n if (props['aria-labelledby']) {\n var _state_expandIcon_id;\n const chevronId = (_state_expandIcon_id = state.expandIcon.id) !== null && _state_expandIcon_id !== void 0 ? _state_expandIcon_id : `${comboId}-chevron`;\n const chevronLabelledBy = `${chevronId} ${state.input['aria-labelledby']}`;\n state.expandIcon['aria-label'] = defaultOpenString;\n state.expandIcon.id = chevronId;\n state.expandIcon['aria-labelledby'] = chevronLabelledBy;\n } else if (props['aria-label']) {\n state.expandIcon['aria-label'] = `${defaultOpenString} ${props['aria-label']}`;\n } else {\n state.expandIcon['aria-label'] = defaultOpenString;\n }\n }\n }\n const onClearIconMouseDown = useEventCallback(mergeCallbacks((_state_clearIcon = state.clearIcon) === null || _state_clearIcon === void 0 ? void 0 : _state_clearIcon.onMouseDown, (ev)=>{\n ev.preventDefault();\n }));\n const onClearIconClick = useEventCallback(mergeCallbacks((_state_clearIcon1 = state.clearIcon) === null || _state_clearIcon1 === void 0 ? void 0 : _state_clearIcon1.onClick, (ev)=>{\n clearSelection(ev);\n }));\n if (state.clearIcon) {\n state.clearIcon.onMouseDown = onClearIconMouseDown;\n state.clearIcon.onClick = onClearIconClick;\n }\n // Heads up! We don't support \"clearable\" in multiselect mode, so we should never display a slot\n if (multiselect) {\n state.clearIcon = undefined;\n }\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks -- \"process.env\" does not change in runtime\n React.useEffect(()=>{\n if (clearable && multiselect) {\n // eslint-disable-next-line no-console\n console.error(`[@fluentui/react-combobox] \"clearable\" prop is not supported in multiselect mode.`);\n }\n }, [\n clearable,\n multiselect\n ]);\n }\n return state;\n};\n"],"names":["useCombobox_unstable","props","ref","_state_clearIcon","_state_clearIcon1","useFieldControlProps_unstable","supportsLabelFor","supportsRequired","supportsSize","listboxRef","activeDescendantListboxRef","activeParentRef","controller","activeDescendantController","useActiveDescendant","matchOption","el","classList","contains","optionClassNames","root","baseState","useComboboxBaseState","editable","clearable","clearSelection","multiselect","open","selectedOptions","selectOption","setOpen","setValue","value","hasFocus","comboboxPopupRef","comboboxTargetRef","useComboboxPositioning","disabled","freeform","inlinePopup","comboId","useId","primary","triggerNativeProps","rootNativeProps","getPartitionedNativeProps","primarySlotTagName","excludedPropNames","ev","option","undefined","newState","triggerRef","React","useRef","listbox","useListboxSlot","useMergedRefs","state","defaultProps","children","_props_input","triggerSlot","useInputTriggerSlot","input","type","id","rootSlot","slot","always","elementType","showClearIcon","length","components","expandIcon","Listbox","clearIcon","optional","createElement","DismissIcon","renderByDefault","ChevronDownIcon","role","onMouseDown","onIconMouseDown","onExpandIconMouseDown","useEventCallback","mergeCallbacks","event","_triggerRef_current","preventDefault","current","focus","hasExpandLabel","defaultOpenString","_state_expandIcon_id","chevronId","chevronLabelledBy","onClearIconMouseDown","onClearIconClick","onClick","process","env","NODE_ENV","useEffect","console","error"],"mappings":"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"}
|
|
@@ -15,10 +15,12 @@ const _keyboardkeys = require("@fluentui/keyboard-keys");
|
|
|
15
15
|
const _useTriggerSlot = require("../../utils/useTriggerSlot");
|
|
16
16
|
const _dropdownKeyActions = require("../../utils/dropdownKeyActions");
|
|
17
17
|
function useInputTriggerSlot(triggerFromProps, ref, options) {
|
|
18
|
-
const { state: { open, value,
|
|
18
|
+
const { state: { open, value, selectOption, setValue, multiselect, selectedOptions, clearSelection, getOptionById, setOpen }, freeform, defaultProps, activeDescendantController } = options;
|
|
19
19
|
const onBlur = (ev)=>{
|
|
20
20
|
// handle selection and updating value if freeform is false
|
|
21
21
|
if (!open && !freeform) {
|
|
22
|
+
const activeOptionId = activeDescendantController.active();
|
|
23
|
+
const activeOption = activeOptionId ? getOptionById(activeOptionId) : null;
|
|
22
24
|
// select matching option, if the value fully matches
|
|
23
25
|
if (value && activeOption && value.trim().toLowerCase() === (activeOption === null || activeOption === void 0 ? void 0 : activeOption.text.toLowerCase())) {
|
|
24
26
|
selectOption(ev, activeOption);
|
|
@@ -30,18 +32,19 @@ function useInputTriggerSlot(triggerFromProps, ref, options) {
|
|
|
30
32
|
const getOptionFromInput = (inputValue)=>{
|
|
31
33
|
const searchString = inputValue === null || inputValue === void 0 ? void 0 : inputValue.trim().toLowerCase();
|
|
32
34
|
if (!searchString || searchString.length === 0) {
|
|
35
|
+
activeDescendantController.blur();
|
|
33
36
|
return;
|
|
34
37
|
}
|
|
35
38
|
const matcher = (optionText)=>optionText.toLowerCase().indexOf(searchString) === 0;
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
const match = activeDescendantController.find((id)=>{
|
|
40
|
+
const option = getOptionById(id);
|
|
41
|
+
return !!option && matcher(option.text);
|
|
42
|
+
});
|
|
43
|
+
if (!match) {
|
|
44
|
+
activeDescendantController.blur();
|
|
45
|
+
return undefined;
|
|
42
46
|
}
|
|
43
|
-
|
|
44
|
-
return (_matches_ = matches[0]) !== null && _matches_ !== void 0 ? _matches_ : undefined;
|
|
47
|
+
return getOptionById(match);
|
|
45
48
|
};
|
|
46
49
|
// update value and active option based on input
|
|
47
50
|
const onChange = (ev)=>{
|
|
@@ -50,8 +53,6 @@ function useInputTriggerSlot(triggerFromProps, ref, options) {
|
|
|
50
53
|
setValue(inputValue);
|
|
51
54
|
// handle updating active option based on input
|
|
52
55
|
const matchingOption = getOptionFromInput(inputValue);
|
|
53
|
-
setActiveOption(matchingOption);
|
|
54
|
-
setFocusVisible(true);
|
|
55
56
|
// clear selection for single-select if the input value no longer matches the selection
|
|
56
57
|
if (!multiselect && selectedOptions.length === 1 && (inputValue.length < 1 || !matchingOption)) {
|
|
57
58
|
clearSelection(ev);
|
|
@@ -60,7 +61,8 @@ function useInputTriggerSlot(triggerFromProps, ref, options) {
|
|
|
60
61
|
const trigger = (0, _useTriggerSlot.useTriggerSlot)(triggerFromProps, ref, {
|
|
61
62
|
state: options.state,
|
|
62
63
|
defaultProps,
|
|
63
|
-
elementType: 'input'
|
|
64
|
+
elementType: 'input',
|
|
65
|
+
activeDescendantController
|
|
64
66
|
});
|
|
65
67
|
trigger.onChange = (0, _reactutilities.mergeCallbacks)(trigger.onChange, onChange);
|
|
66
68
|
trigger.onBlur = (0, _reactutilities.mergeCallbacks)(trigger.onBlur, onBlur);
|