@fluentui/react-combobox 9.0.0 → 9.1.1
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.json +72 -6
- package/CHANGELOG.md +31 -7
- package/dist/index.d.ts +8 -1
- package/lib/components/Combobox/useCombobox.js +2 -2
- package/lib/components/Combobox/useCombobox.js.map +1 -1
- package/lib/components/Dropdown/useDropdown.js +2 -2
- package/lib/components/Dropdown/useDropdown.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/useComboboxBaseState.js +12 -5
- package/lib/utils/useComboboxBaseState.js.map +1 -1
- package/lib/utils/useOptionCollection.js +5 -1
- package/lib/utils/useOptionCollection.js.map +1 -1
- package/lib-amd/components/Combobox/useCombobox.js +2 -4
- package/lib-amd/components/Combobox/useCombobox.js.map +1 -1
- package/lib-amd/components/Dropdown/useDropdown.js +2 -2
- package/lib-amd/components/Dropdown/useDropdown.js.map +1 -1
- package/lib-amd/utils/OptionCollection.types.js.map +1 -1
- package/lib-amd/utils/Selection.types.js.map +1 -1
- package/lib-amd/utils/useComboboxBaseState.js +12 -5
- package/lib-amd/utils/useComboboxBaseState.js.map +1 -1
- package/lib-amd/utils/useOptionCollection.js +4 -0
- package/lib-amd/utils/useOptionCollection.js.map +1 -1
- package/lib-commonjs/components/Combobox/useCombobox.js +2 -2
- package/lib-commonjs/components/Combobox/useCombobox.js.map +1 -1
- package/lib-commonjs/components/Dropdown/useDropdown.js +2 -2
- package/lib-commonjs/components/Dropdown/useDropdown.js.map +1 -1
- package/lib-commonjs/utils/useComboboxBaseState.js +12 -5
- package/lib-commonjs/utils/useComboboxBaseState.js.map +1 -1
- package/lib-commonjs/utils/useOptionCollection.js +5 -1
- package/lib-commonjs/utils/useOptionCollection.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,73 @@
|
|
|
2
2
|
"name": "@fluentui/react-combobox",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Fri, 10 Feb 2023 08:46:47 GMT",
|
|
6
|
+
"tag": "@fluentui/react-combobox_v9.1.1",
|
|
7
|
+
"version": "9.1.1",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "beachball",
|
|
12
|
+
"package": "@fluentui/react-combobox",
|
|
13
|
+
"comment": "Bump @fluentui/react-context-selector to v9.1.8",
|
|
14
|
+
"commit": "cc62f050f8231e8f21a2cf7dddf33003e0ba3931"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"author": "beachball",
|
|
18
|
+
"package": "@fluentui/react-combobox",
|
|
19
|
+
"comment": "Bump @fluentui/react-field to v9.0.0-alpha.19",
|
|
20
|
+
"commit": "cc62f050f8231e8f21a2cf7dddf33003e0ba3931"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"author": "beachball",
|
|
24
|
+
"package": "@fluentui/react-combobox",
|
|
25
|
+
"comment": "Bump @fluentui/react-portal to v9.1.7",
|
|
26
|
+
"commit": "cc62f050f8231e8f21a2cf7dddf33003e0ba3931"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"author": "beachball",
|
|
30
|
+
"package": "@fluentui/react-combobox",
|
|
31
|
+
"comment": "Bump @fluentui/react-positioning to v9.4.0",
|
|
32
|
+
"commit": "cc62f050f8231e8f21a2cf7dddf33003e0ba3931"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"author": "beachball",
|
|
36
|
+
"package": "@fluentui/react-combobox",
|
|
37
|
+
"comment": "Bump @fluentui/react-utilities to v9.5.2",
|
|
38
|
+
"commit": "cc62f050f8231e8f21a2cf7dddf33003e0ba3931"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"date": "Tue, 07 Feb 2023 14:13:09 GMT",
|
|
45
|
+
"tag": "@fluentui/react-combobox_v9.1.0",
|
|
46
|
+
"version": "9.1.0",
|
|
47
|
+
"comments": {
|
|
48
|
+
"minor": [
|
|
49
|
+
{
|
|
50
|
+
"author": "sarah.higley@microsoft.com",
|
|
51
|
+
"package": "@fluentui/react-combobox",
|
|
52
|
+
"commit": "22ecddb787ec8626605eb9cd79d8905d93ed179f",
|
|
53
|
+
"comment": "fix: update Combobox and Dropdown to never use the Option value string as a display value; input value must be set if selectedOptions or defaultSelectOptions is set\""
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"author": "beachball",
|
|
57
|
+
"package": "@fluentui/react-combobox",
|
|
58
|
+
"comment": "Bump @fluentui/react-portal to v9.1.6",
|
|
59
|
+
"commit": "8a1405562b3328c408f15e3bf511d3eb6a0c0e66"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"author": "beachball",
|
|
63
|
+
"package": "@fluentui/react-combobox",
|
|
64
|
+
"comment": "Bump @fluentui/react-positioning to v9.3.11",
|
|
65
|
+
"commit": "8a1405562b3328c408f15e3bf511d3eb6a0c0e66"
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"date": "Tue, 31 Jan 2023 19:53:53 GMT",
|
|
6
72
|
"tag": "@fluentui/react-combobox_v9.0.0",
|
|
7
73
|
"version": "9.0.0",
|
|
8
74
|
"comments": {
|
|
@@ -17,31 +83,31 @@
|
|
|
17
83
|
"author": "beachball",
|
|
18
84
|
"package": "@fluentui/react-combobox",
|
|
19
85
|
"comment": "Bump @fluentui/react-context-selector to v9.1.7",
|
|
20
|
-
"commit": "
|
|
86
|
+
"commit": "794d9e845cb952f597ba786e70cd8d248be62746"
|
|
21
87
|
},
|
|
22
88
|
{
|
|
23
89
|
"author": "beachball",
|
|
24
90
|
"package": "@fluentui/react-combobox",
|
|
25
91
|
"comment": "Bump @fluentui/react-field to v9.0.0-alpha.18",
|
|
26
|
-
"commit": "
|
|
92
|
+
"commit": "794d9e845cb952f597ba786e70cd8d248be62746"
|
|
27
93
|
},
|
|
28
94
|
{
|
|
29
95
|
"author": "beachball",
|
|
30
96
|
"package": "@fluentui/react-combobox",
|
|
31
97
|
"comment": "Bump @fluentui/react-portal to v9.1.5",
|
|
32
|
-
"commit": "
|
|
98
|
+
"commit": "794d9e845cb952f597ba786e70cd8d248be62746"
|
|
33
99
|
},
|
|
34
100
|
{
|
|
35
101
|
"author": "beachball",
|
|
36
102
|
"package": "@fluentui/react-combobox",
|
|
37
103
|
"comment": "Bump @fluentui/react-positioning to v9.3.10",
|
|
38
|
-
"commit": "
|
|
104
|
+
"commit": "794d9e845cb952f597ba786e70cd8d248be62746"
|
|
39
105
|
},
|
|
40
106
|
{
|
|
41
107
|
"author": "beachball",
|
|
42
108
|
"package": "@fluentui/react-combobox",
|
|
43
109
|
"comment": "Bump @fluentui/react-utilities to v9.5.1",
|
|
44
|
-
"commit": "
|
|
110
|
+
"commit": "794d9e845cb952f597ba786e70cd8d248be62746"
|
|
45
111
|
}
|
|
46
112
|
]
|
|
47
113
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,22 +1,46 @@
|
|
|
1
1
|
# Change Log - @fluentui/react-combobox
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Fri, 10 Feb 2023 08:46:47 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## [9.1.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.1.1)
|
|
8
|
+
|
|
9
|
+
Fri, 10 Feb 2023 08:46:47 GMT
|
|
10
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-combobox_v9.1.0..@fluentui/react-combobox_v9.1.1)
|
|
11
|
+
|
|
12
|
+
### Patches
|
|
13
|
+
|
|
14
|
+
- Bump @fluentui/react-context-selector to v9.1.8 ([commit](https://github.com/microsoft/fluentui/commit/cc62f050f8231e8f21a2cf7dddf33003e0ba3931) by beachball)
|
|
15
|
+
- Bump @fluentui/react-field to v9.0.0-alpha.19 ([commit](https://github.com/microsoft/fluentui/commit/cc62f050f8231e8f21a2cf7dddf33003e0ba3931) by beachball)
|
|
16
|
+
- Bump @fluentui/react-portal to v9.1.7 ([commit](https://github.com/microsoft/fluentui/commit/cc62f050f8231e8f21a2cf7dddf33003e0ba3931) by beachball)
|
|
17
|
+
- Bump @fluentui/react-positioning to v9.4.0 ([commit](https://github.com/microsoft/fluentui/commit/cc62f050f8231e8f21a2cf7dddf33003e0ba3931) by beachball)
|
|
18
|
+
- Bump @fluentui/react-utilities to v9.5.2 ([commit](https://github.com/microsoft/fluentui/commit/cc62f050f8231e8f21a2cf7dddf33003e0ba3931) by beachball)
|
|
19
|
+
|
|
20
|
+
## [9.1.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.1.0)
|
|
21
|
+
|
|
22
|
+
Tue, 07 Feb 2023 14:13:09 GMT
|
|
23
|
+
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-combobox_v9.0.0..@fluentui/react-combobox_v9.1.0)
|
|
24
|
+
|
|
25
|
+
### Minor changes
|
|
26
|
+
|
|
27
|
+
- fix: update Combobox and Dropdown to never use the Option value string as a display value; input value must be set if selectedOptions or defaultSelectOptions is set" ([PR #26617](https://github.com/microsoft/fluentui/pull/26617) by sarah.higley@microsoft.com)
|
|
28
|
+
- Bump @fluentui/react-portal to v9.1.6 ([PR #26732](https://github.com/microsoft/fluentui/pull/26732) by beachball)
|
|
29
|
+
- Bump @fluentui/react-positioning to v9.3.11 ([PR #26732](https://github.com/microsoft/fluentui/pull/26732) by beachball)
|
|
30
|
+
|
|
7
31
|
## [9.0.0](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.0.0)
|
|
8
32
|
|
|
9
|
-
Tue, 31 Jan 2023 19:
|
|
33
|
+
Tue, 31 Jan 2023 19:53:53 GMT
|
|
10
34
|
[Compare changes](https://github.com/microsoft/fluentui/compare/@fluentui/react-combobox_v9.0.0-beta.26..@fluentui/react-combobox_v9.0.0)
|
|
11
35
|
|
|
12
36
|
### Patches
|
|
13
37
|
|
|
14
38
|
- feat: release Combobox and Dropdown as stable components ([PR #26518](https://github.com/microsoft/fluentui/pull/26518) by sarah.higley@microsoft.com)
|
|
15
|
-
- Bump @fluentui/react-context-selector to v9.1.7 ([PR #
|
|
16
|
-
- Bump @fluentui/react-field to v9.0.0-alpha.18 ([PR #
|
|
17
|
-
- Bump @fluentui/react-portal to v9.1.5 ([PR #
|
|
18
|
-
- Bump @fluentui/react-positioning to v9.3.10 ([PR #
|
|
19
|
-
- Bump @fluentui/react-utilities to v9.5.1 ([PR #
|
|
39
|
+
- Bump @fluentui/react-context-selector to v9.1.7 ([PR #26557](https://github.com/microsoft/fluentui/pull/26557) by beachball)
|
|
40
|
+
- Bump @fluentui/react-field to v9.0.0-alpha.18 ([PR #26557](https://github.com/microsoft/fluentui/pull/26557) by beachball)
|
|
41
|
+
- Bump @fluentui/react-portal to v9.1.5 ([PR #26557](https://github.com/microsoft/fluentui/pull/26557) by beachball)
|
|
42
|
+
- Bump @fluentui/react-positioning to v9.3.10 ([PR #26557](https://github.com/microsoft/fluentui/pull/26557) by beachball)
|
|
43
|
+
- Bump @fluentui/react-utilities to v9.5.1 ([PR #26557](https://github.com/microsoft/fluentui/pull/26557) by beachball)
|
|
20
44
|
|
|
21
45
|
## [9.0.0-beta.26](https://github.com/microsoft/fluentui/tree/@fluentui/react-combobox_v9.0.0-beta.26)
|
|
22
46
|
|
package/dist/index.d.ts
CHANGED
|
@@ -237,7 +237,9 @@ declare type OptionCollectionState = {
|
|
|
237
237
|
/** Returns the option data by key. */
|
|
238
238
|
getOptionById(id: string): OptionValue | undefined;
|
|
239
239
|
/** Returns an array of options filtered by a value matching function against the option's text string. */
|
|
240
|
-
getOptionsMatchingText(matcher: (
|
|
240
|
+
getOptionsMatchingText(matcher: (text: string) => boolean): OptionValue[];
|
|
241
|
+
/** Returns an array of options filtered by a value matching function against the option's value string. */
|
|
242
|
+
getOptionsMatchingValue(matcher: (value: string) => boolean): OptionValue[];
|
|
241
243
|
/** The unordered option data. */
|
|
242
244
|
options: OptionValue[];
|
|
243
245
|
registerOption: (option: OptionValue, element: HTMLElement) => () => void;
|
|
@@ -354,6 +356,10 @@ export declare const renderOptionGroup_unstable: (state: OptionGroupState) => JS
|
|
|
354
356
|
declare type SelectionEvents = React_2.ChangeEvent<HTMLElement> | React_2.KeyboardEvent<HTMLElement> | React_2.MouseEvent<HTMLElement>;
|
|
355
357
|
|
|
356
358
|
declare type SelectionProps = {
|
|
359
|
+
/**
|
|
360
|
+
* For an uncontrolled component, sets the initial selection.
|
|
361
|
+
* If this is set, the `defaultValue` prop MUST also be set.
|
|
362
|
+
*/
|
|
357
363
|
defaultSelectedOptions?: string[];
|
|
358
364
|
/**
|
|
359
365
|
* Sets the selection type to multiselect.
|
|
@@ -366,6 +372,7 @@ declare type SelectionProps = {
|
|
|
366
372
|
/**
|
|
367
373
|
* An array of selected option keys.
|
|
368
374
|
* Use this with `onOptionSelect` to directly control the selected option(s)
|
|
375
|
+
* If this is set, the `value` prop MUST also be controlled.
|
|
369
376
|
*/
|
|
370
377
|
selectedOptions?: string[];
|
|
371
378
|
};
|
|
@@ -99,7 +99,7 @@ export const useCombobox_unstable = (props, ref) => {
|
|
|
99
99
|
// handle selection and updating value if freeform is false
|
|
100
100
|
if (!baseState.open && !freeform) {
|
|
101
101
|
// select matching option, if the value fully matches
|
|
102
|
-
if (value && activeOption && value.trim().toLowerCase() === (activeOption === null || activeOption === void 0 ? void 0 : activeOption.
|
|
102
|
+
if (value && activeOption && value.trim().toLowerCase() === (activeOption === null || activeOption === void 0 ? void 0 : activeOption.text.toLowerCase())) {
|
|
103
103
|
baseState.selectOption(ev, activeOption);
|
|
104
104
|
}
|
|
105
105
|
// reset typed value when the input loses focus while collapsed, unless freeform is true
|
|
@@ -125,7 +125,7 @@ export const useCombobox_unstable = (props, ref) => {
|
|
|
125
125
|
setActiveOption(matchingOption);
|
|
126
126
|
setFocusVisible(true);
|
|
127
127
|
// clear selection for single-select if the input value no longer matches the selection
|
|
128
|
-
if (!multiselect && selectedOptions.length === 1 && (inputValue.length < 1 ||
|
|
128
|
+
if (!multiselect && selectedOptions.length === 1 && (inputValue.length < 1 || !matchingOption)) {
|
|
129
129
|
clearSelection(ev);
|
|
130
130
|
}
|
|
131
131
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":["React","ArrowLeft","ArrowRight","ChevronDownRegular","ChevronDownIcon","getPartitionedNativeProps","resolveShorthand","mergeCallbacks","useEventCallback","useId","useMergedRefs","getDropdownActionFromKey","useComboboxBaseState","useComboboxPopup","useTriggerListboxSlots","Listbox","useCombobox_unstable","props","ref","baseState","editable","activeOption","clearSelection","getIndexOfId","getOptionsMatchingText","hasFocus","open","selectOption","selectedOptions","setActiveOption","setFocusVisible","setOpen","setValue","value","disabled","freeform","inlinePopup","multiselect","comboId","primary","triggerNativeProps","root","rootNativeProps","primarySlotTagName","excludedPropNames","rootRef","useRef","triggerRef","hideActiveDescendant","setHideActiveDescendant","useState","popupDimensions","setPopupDimensions","useEffect","width","current","clientWidth","getOptionFromInput","inputValue","searchString","trim","toLowerCase","length","matcher","optionText","indexOf","matches","startIndex","id","nextMatch","find","option","undefined","ev","onTriggerBlur","newState","onTriggerChange","target","matchingOption","onTriggerKeyDown","key","triggerSlot","listboxSlot","input","required","defaultProps","type","onChange","onBlur","onKeyDown","listbox","children","style","state","components","expandIcon","role","onMouseDown","onIconMouseDown","onClick","onIconClick","onExpandIconMouseDown","ignoreNextBlur","onExpandIconClick","event","focus","hasExpandLabel","defaultOpenString","chevronId","chevronLabelledBy"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/components/Combobox/useCombobox.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ArrowLeft, ArrowRight } from '@fluentui/keyboard-keys';\nimport { ChevronDownRegular as ChevronDownIcon } from '@fluentui/react-icons';\nimport {\n getPartitionedNativeProps,\n resolveShorthand,\n mergeCallbacks,\n useEventCallback,\n useId,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey } from '../../utils/dropdownKeyActions';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPopup } from '../../utils/useComboboxPopup';\nimport { useTriggerListboxSlots } from '../../utils/useTriggerListboxSlots';\nimport { Listbox } from '../Listbox/Listbox';\nimport type { Slot } from '@fluentui/react-utilities';\nimport type { SelectionEvents } from '../../utils/Selection.types';\nimport type { OptionValue } from '../../utils/OptionCollection.types';\nimport type { ComboboxProps, ComboboxState } from './Combobox.types';\n\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 */\nexport const useCombobox_unstable = (props: ComboboxProps, ref: React.Ref<HTMLInputElement>): ComboboxState => {\n const baseState = useComboboxBaseState({ ...props, editable: true });\n const {\n activeOption,\n clearSelection,\n getIndexOfId,\n getOptionsMatchingText,\n hasFocus,\n open,\n selectOption,\n selectedOptions,\n setActiveOption,\n setFocusVisible,\n setOpen,\n setValue,\n value,\n } = baseState;\n const { disabled, freeform, inlinePopup, multiselect } = props;\n const comboId = useId('combobox-');\n\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'input',\n excludedPropNames: ['children', 'size'],\n });\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLInputElement>(null);\n\n // NVDA and JAWS have bugs that suppress reading the input value text when aria-activedescendant is set\n // To prevent this, we clear the HTML attribute (but save the state) when a user presses left/right arrows\n // ref: https://github.com/microsoft/fluentui/issues/26359#issuecomment-1397759888\n const [hideActiveDescendant, setHideActiveDescendant] = React.useState(false);\n\n // calculate listbox width style based on trigger width\n const [popupDimensions, setPopupDimensions] = React.useState<{ width: string }>();\n React.useEffect(() => {\n // only recalculate width when opening\n if (open) {\n const width = `${rootRef.current?.clientWidth}px`;\n if (width !== popupDimensions?.width) {\n setPopupDimensions({ width });\n }\n }\n }, [open, popupDimensions]);\n\n // set active option and selection based on typing\n const getOptionFromInput = (inputValue: string): OptionValue | undefined => {\n const searchString = inputValue?.trim().toLowerCase();\n\n if (!searchString || searchString.length === 0) {\n return;\n }\n\n const matcher = (optionText: string) => optionText.toLowerCase().indexOf(searchString) === 0;\n const matches = getOptionsMatchingText(matcher);\n\n // return first matching option after the current active option, looping back to the top\n if (matches.length > 1 && activeOption) {\n const startIndex = getIndexOfId(activeOption.id);\n const nextMatch = matches.find(option => getIndexOfId(option.id) >= startIndex);\n return nextMatch ?? matches[0];\n }\n\n return matches[0] ?? undefined;\n };\n\n /* Handle typed input */\n\n // reset any typed value when an option is selected\n baseState.selectOption = (ev: SelectionEvents, option: OptionValue) => {\n setValue(undefined);\n selectOption(ev, option);\n };\n\n const onTriggerBlur = (ev: React.FocusEvent<HTMLInputElement>) => {\n // handle selection and updating value if freeform is false\n if (!baseState.open && !freeform) {\n // select matching option, if the value fully matches\n if (value && activeOption && value.trim().toLowerCase() === activeOption?.value.toLowerCase()) {\n baseState.selectOption(ev, activeOption);\n }\n\n // reset typed value when the input loses focus while collapsed, unless freeform is true\n setValue(undefined);\n }\n };\n\n baseState.setOpen = (ev, newState: boolean) => {\n if (disabled) {\n return;\n }\n\n if (!newState && !freeform) {\n setValue(undefined);\n }\n\n setOpen(ev, newState);\n };\n\n // update value and active option based on input\n const onTriggerChange = (ev: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = ev.target.value;\n // update uncontrolled value\n baseState.setValue(inputValue);\n\n // handle updating active option based on input\n const matchingOption = getOptionFromInput(inputValue);\n setActiveOption(matchingOption);\n\n setFocusVisible(true);\n\n // clear selection for single-select if the input value no longer matches the selection\n if (\n !multiselect &&\n selectedOptions.length === 1 &&\n (inputValue.length < 1 || selectedOptions[0].indexOf(inputValue) !== 0)\n ) {\n clearSelection(ev);\n }\n };\n\n // open Combobox when typing\n const onTriggerKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {\n if (!open && getDropdownActionFromKey(ev) === 'Type') {\n baseState.setOpen(ev, true);\n }\n\n // clear activedescendant when moving the text insertion cursor\n if (ev.key === ArrowLeft || ev.key === ArrowRight) {\n setHideActiveDescendant(true);\n } else {\n setHideActiveDescendant(false);\n }\n };\n\n // resolve input and listbox slot props\n let triggerSlot: Slot<'input'>;\n let listboxSlot: Slot<typeof Listbox> | undefined;\n\n triggerSlot = resolveShorthand(props.input, {\n required: true,\n defaultProps: {\n ref: useMergedRefs(props.input?.ref, triggerRef),\n type: 'text',\n value: value ?? '',\n ...triggerNativeProps,\n },\n });\n\n triggerSlot.onChange = mergeCallbacks(triggerSlot.onChange, onTriggerChange);\n triggerSlot.onBlur = mergeCallbacks(triggerSlot.onBlur, onTriggerBlur);\n triggerSlot.onKeyDown = mergeCallbacks(triggerSlot.onKeyDown, onTriggerKeyDown);\n\n // only resolve listbox slot if needed\n listboxSlot =\n open || hasFocus\n ? resolveShorthand(props.listbox, {\n required: true,\n defaultProps: {\n children: props.children,\n style: popupDimensions,\n },\n })\n : undefined;\n\n [triggerSlot, listboxSlot] = useComboboxPopup(props, triggerSlot, listboxSlot);\n [triggerSlot, listboxSlot] = useTriggerListboxSlots(props, baseState, ref, triggerSlot, listboxSlot);\n\n if (hideActiveDescendant) {\n triggerSlot['aria-activedescendant'] = undefined;\n }\n\n const state: ComboboxState = {\n components: {\n root: 'div',\n input: 'input',\n expandIcon: 'span',\n listbox: Listbox,\n },\n root: resolveShorthand(props.root, {\n required: true,\n defaultProps: {\n 'aria-owns': !inlinePopup ? listboxSlot?.id : undefined,\n ...rootNativeProps,\n },\n }),\n input: triggerSlot,\n listbox: listboxSlot,\n expandIcon: resolveShorthand(props.expandIcon, {\n required: true,\n defaultProps: {\n 'aria-expanded': open,\n children: <ChevronDownIcon />,\n role: 'button',\n },\n }),\n ...baseState,\n };\n\n state.root.ref = useMergedRefs(state.root.ref, rootRef);\n\n /* handle open/close + focus change when clicking expandIcon */\n const { onMouseDown: onIconMouseDown, onClick: onIconClick } = state.expandIcon || {};\n const onExpandIconMouseDown = useEventCallback(\n mergeCallbacks(onIconMouseDown, () => {\n // do not dismiss on blur when closing via clicking the icon\n if (open) {\n baseState.ignoreNextBlur.current = true;\n }\n }),\n );\n\n const onExpandIconClick = useEventCallback(\n mergeCallbacks(onIconClick, (event: React.MouseEvent<HTMLSpanElement>) => {\n // open and set focus\n state.setOpen(event, !state.open);\n triggerRef.current?.focus();\n\n // set focus visible=false, since this can only be done with the mouse/pointer\n setFocusVisible(false);\n }),\n );\n\n if (state.expandIcon) {\n state.expandIcon.onMouseDown = onExpandIconMouseDown;\n state.expandIcon.onClick = onExpandIconClick;\n\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 const chevronId = state.expandIcon.id ?? `${comboId}-chevron`;\n const chevronLabelledBy = `${chevronId} ${state.input['aria-labelledby']}`;\n\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\n return state;\n};\n"]}
|
|
1
|
+
{"version":3,"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,SAAS,EAAEC,UAAU,QAAQ,yBAAyB;AAC/D,SAASC,kBAAkB,IAAIC,eAAe,QAAQ,uBAAuB;AAC7E,SACEC,yBAAyB,EACzBC,gBAAgB,EAChBC,cAAc,EACdC,gBAAgB,EAChBC,KAAK,EACLC,aAAa,QACR,2BAA2B;AAClC,SAASC,wBAAwB,QAAQ,gCAAgC;AACzE,SAASC,oBAAoB,QAAQ,kCAAkC;AACvE,SAASC,gBAAgB,QAAQ,8BAA8B;AAC/D,SAASC,sBAAsB,QAAQ,oCAAoC;AAC3E,SAASC,OAAO,QAAQ,oBAAoB;AAM5C;;;;;;;;;AASA,OAAO,MAAMC,oBAAoB,GAAG,CAACC,KAAoB,EAAEC,GAAgC,KAAmB;;EAC5G,MAAMC,SAAS,GAAGP,oBAAoB,CAAC;IAAE,GAAGK,KAAK;IAAEG,QAAQ,EAAE;EAAI,CAAE,CAAC;EACpE,MAAM;IACJC,YAAY;IACZC,cAAc;IACdC,YAAY;IACZC,sBAAsB;IACtBC,QAAQ;IACRC,IAAI;IACJC,YAAY;IACZC,eAAe;IACfC,eAAe;IACfC,eAAe;IACfC,OAAO;IACPC,QAAQ;IACRC;EAAK,CACN,GAAGd,SAAS;EACb,MAAM;IAAEe,QAAQ;IAAEC,QAAQ;IAAEC,WAAW;IAAEC;EAAW,CAAE,GAAGpB,KAAK;EAC9D,MAAMqB,OAAO,GAAG7B,KAAK,CAAC,WAAW,CAAC;EAElC,MAAM;IAAE8B,OAAO,EAAEC,kBAAkB;IAAEC,IAAI,EAAEC;EAAe,CAAE,GAAGrC,yBAAyB,CAAC;IACvFY,KAAK;IACL0B,kBAAkB,EAAE,OAAO;IAC3BC,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM;GACvC,CAAC;EAEF,MAAMC,OAAO,GAAG7C,KAAK,CAAC8C,MAAM,CAAiB,IAAI,CAAC;EAClD,MAAMC,UAAU,GAAG/C,KAAK,CAAC8C,MAAM,CAAmB,IAAI,CAAC;EAEvD;EACA;EACA;EACA,MAAM,CAACE,oBAAoB,EAAEC,uBAAuB,CAAC,GAAGjD,KAAK,CAACkD,QAAQ,CAAC,KAAK,CAAC;EAE7E;EACA,MAAM,CAACC,eAAe,EAAEC,kBAAkB,CAAC,GAAGpD,KAAK,CAACkD,QAAQ,EAAqB;EACjFlD,KAAK,CAACqD,SAAS,CAAC,MAAK;;IACnB;IACA,IAAI3B,IAAI,EAAE;MACR,MAAM4B,KAAK,GAAG,GAAG,aAAO,CAACC,OAAO,0CAAEC,WAAW,IAAI;MACjD,IAAIF,KAAK,MAAKH,eAAe,aAAfA,eAAe,uBAAfA,eAAe,CAAEG,KAAK,GAAE;QACpCF,kBAAkB,CAAC;UAAEE;QAAK,CAAE,CAAC;;;EAGnC,CAAC,EAAE,CAAC5B,IAAI,EAAEyB,eAAe,CAAC,CAAC;EAE3B;EACA,MAAMM,kBAAkB,GAAIC,UAAkB,IAA6B;;IACzE,MAAMC,YAAY,GAAGD,UAAU,aAAVA,UAAU,uBAAVA,UAAU,CAAEE,IAAI,GAAGC,WAAW,EAAE;IAErD,IAAI,CAACF,YAAY,IAAIA,YAAY,CAACG,MAAM,KAAK,CAAC,EAAE;MAC9C;;IAGF,MAAMC,OAAO,GAAIC,UAAkB,IAAKA,UAAU,CAACH,WAAW,EAAE,CAACI,OAAO,CAACN,YAAY,CAAC,KAAK,CAAC;IAC5F,MAAMO,OAAO,GAAG1C,sBAAsB,CAACuC,OAAO,CAAC;IAE/C;IACA,IAAIG,OAAO,CAACJ,MAAM,GAAG,CAAC,IAAIzC,YAAY,EAAE;MACtC,MAAM8C,UAAU,GAAG5C,YAAY,CAACF,YAAY,CAAC+C,EAAE,CAAC;MAChD,MAAMC,SAAS,GAAGH,OAAO,CAACI,IAAI,CAACC,MAAM,IAAIhD,YAAY,CAACgD,MAAM,CAACH,EAAE,CAAC,IAAID,UAAU,CAAC;MAC/E,OAAOE,SAAS,aAATA,SAAS,cAATA,SAAS,GAAIH,OAAO,CAAC,CAAC,CAAC;;IAGhC,OAAO,aAAO,CAAC,CAAC,CAAC,mCAAIM,SAAS;EAChC,CAAC;EAED;EAEA;EACArD,SAAS,CAACQ,YAAY,GAAG,CAAC8C,EAAmB,EAAEF,MAAmB,KAAI;IACpEvC,QAAQ,CAACwC,SAAS,CAAC;IACnB7C,YAAY,CAAC8C,EAAE,EAAEF,MAAM,CAAC;EAC1B,CAAC;EAED,MAAMG,aAAa,GAAID,EAAsC,IAAI;IAC/D;IACA,IAAI,CAACtD,SAAS,CAACO,IAAI,IAAI,CAACS,QAAQ,EAAE;MAChC;MACA,IAAIF,KAAK,IAAIZ,YAAY,IAAIY,KAAK,CAAC2B,IAAI,EAAE,CAACC,WAAW,EAAE,MAAKxC,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CAAEsD,IAAI,CAACd,WAAW,EAAE,GAAE;QAC5F1C,SAAS,CAACQ,YAAY,CAAC8C,EAAE,EAAEpD,YAAY,CAAC;;MAG1C;MACAW,QAAQ,CAACwC,SAAS,CAAC;;EAEvB,CAAC;EAEDrD,SAAS,CAACY,OAAO,GAAG,CAAC0C,EAAE,EAAEG,QAAiB,KAAI;IAC5C,IAAI1C,QAAQ,EAAE;MACZ;;IAGF,IAAI,CAAC0C,QAAQ,IAAI,CAACzC,QAAQ,EAAE;MAC1BH,QAAQ,CAACwC,SAAS,CAAC;;IAGrBzC,OAAO,CAAC0C,EAAE,EAAEG,QAAQ,CAAC;EACvB,CAAC;EAED;EACA,MAAMC,eAAe,GAAIJ,EAAuC,IAAI;IAClE,MAAMf,UAAU,GAAGe,EAAE,CAACK,MAAM,CAAC7C,KAAK;IAClC;IACAd,SAAS,CAACa,QAAQ,CAAC0B,UAAU,CAAC;IAE9B;IACA,MAAMqB,cAAc,GAAGtB,kBAAkB,CAACC,UAAU,CAAC;IACrD7B,eAAe,CAACkD,cAAc,CAAC;IAE/BjD,eAAe,CAAC,IAAI,CAAC;IAErB;IACA,IAAI,CAACO,WAAW,IAAIT,eAAe,CAACkC,MAAM,KAAK,CAAC,KAAKJ,UAAU,CAACI,MAAM,GAAG,CAAC,IAAI,CAACiB,cAAc,CAAC,EAAE;MAC9FzD,cAAc,CAACmD,EAAE,CAAC;;EAEtB,CAAC;EAED;EACA,MAAMO,gBAAgB,GAAIP,EAAyC,IAAI;IACrE,IAAI,CAAC/C,IAAI,IAAIf,wBAAwB,CAAC8D,EAAE,CAAC,KAAK,MAAM,EAAE;MACpDtD,SAAS,CAACY,OAAO,CAAC0C,EAAE,EAAE,IAAI,CAAC;;IAG7B;IACA,IAAIA,EAAE,CAACQ,GAAG,KAAKhF,SAAS,IAAIwE,EAAE,CAACQ,GAAG,KAAK/E,UAAU,EAAE;MACjD+C,uBAAuB,CAAC,IAAI,CAAC;KAC9B,MAAM;MACLA,uBAAuB,CAAC,KAAK,CAAC;;EAElC,CAAC;EAED;EACA,IAAIiC,WAA0B;EAC9B,IAAIC,WAA6C;EAEjDD,WAAW,GAAG5E,gBAAgB,CAACW,KAAK,CAACmE,KAAK,EAAE;IAC1CC,QAAQ,EAAE,IAAI;IACdC,YAAY,EAAE;MACZpE,GAAG,EAAER,aAAa,CAAC,WAAK,CAAC0E,KAAK,0CAAElE,GAAG,EAAE6B,UAAU,CAAC;MAChDwC,IAAI,EAAE,MAAM;MACZtD,KAAK,EAAEA,KAAK,aAALA,KAAK,cAALA,KAAK,GAAI,EAAE;MAClB,GAAGO;;GAEN,CAAC;EAEF0C,WAAW,CAACM,QAAQ,GAAGjF,cAAc,CAAC2E,WAAW,CAACM,QAAQ,EAAEX,eAAe,CAAC;EAC5EK,WAAW,CAACO,MAAM,GAAGlF,cAAc,CAAC2E,WAAW,CAACO,MAAM,EAAEf,aAAa,CAAC;EACtEQ,WAAW,CAACQ,SAAS,GAAGnF,cAAc,CAAC2E,WAAW,CAACQ,SAAS,EAAEV,gBAAgB,CAAC;EAE/E;EACAG,WAAW,GACTzD,IAAI,IAAID,QAAQ,GACZnB,gBAAgB,CAACW,KAAK,CAAC0E,OAAO,EAAE;IAC9BN,QAAQ,EAAE,IAAI;IACdC,YAAY,EAAE;MACZM,QAAQ,EAAE3E,KAAK,CAAC2E,QAAQ;MACxBC,KAAK,EAAE1C;;GAEV,CAAC,GACFqB,SAAS;EAEf,CAACU,WAAW,EAAEC,WAAW,CAAC,GAAGtE,gBAAgB,CAACI,KAAK,EAAEiE,WAAW,EAAEC,WAAW,CAAC;EAC9E,CAACD,WAAW,EAAEC,WAAW,CAAC,GAAGrE,sBAAsB,CAACG,KAAK,EAAEE,SAAS,EAAED,GAAG,EAAEgE,WAAW,EAAEC,WAAW,CAAC;EAEpG,IAAInC,oBAAoB,EAAE;IACxBkC,WAAW,CAAC,uBAAuB,CAAC,GAAGV,SAAS;;EAGlD,MAAMsB,KAAK,GAAkB;IAC3BC,UAAU,EAAE;MACVtD,IAAI,EAAE,KAAK;MACX2C,KAAK,EAAE,OAAO;MACdY,UAAU,EAAE,MAAM;MAClBL,OAAO,EAAE5E;KACV;IACD0B,IAAI,EAAEnC,gBAAgB,CAACW,KAAK,CAACwB,IAAI,EAAE;MACjC4C,QAAQ,EAAE,IAAI;MACdC,YAAY,EAAE;QACZ,WAAW,EAAE,CAAClD,WAAW,GAAG+C,WAAW,aAAXA,WAAW,uBAAXA,WAAW,CAAEf,EAAE,GAAGI,SAAS;QACvD,GAAG9B;;KAEN,CAAC;IACF0C,KAAK,EAAEF,WAAW;IAClBS,OAAO,EAAER,WAAW;IACpBa,UAAU,EAAE1F,gBAAgB,CAACW,KAAK,CAAC+E,UAAU,EAAE;MAC7CX,QAAQ,EAAE,IAAI;MACdC,YAAY,EAAE;QACZ,eAAe,EAAE5D,IAAI;QACrBkE,QAAQ,eAAE5F,oBAACI,eAAe,OAAG;QAC7B6F,IAAI,EAAE;;KAET,CAAC;IACF,GAAG9E;GACJ;EAED2E,KAAK,CAACrD,IAAI,CAACvB,GAAG,GAAGR,aAAa,CAACoF,KAAK,CAACrD,IAAI,CAACvB,GAAG,EAAE2B,OAAO,CAAC;EAEvD;EACA,MAAM;IAAEqD,WAAW,EAAEC,eAAe;IAAEC,OAAO,EAAEC;EAAW,CAAE,GAAGP,KAAK,CAACE,UAAU,IAAI,EAAE;EACrF,MAAMM,qBAAqB,GAAG9F,gBAAgB,CAC5CD,cAAc,CAAC4F,eAAe,EAAE,MAAK;IACnC;IACA,IAAIzE,IAAI,EAAE;MACRP,SAAS,CAACoF,cAAc,CAAChD,OAAO,GAAG,IAAI;;EAE3C,CAAC,CAAC,CACH;EAED,MAAMiD,iBAAiB,GAAGhG,gBAAgB,CACxCD,cAAc,CAAC8F,WAAW,EAAGI,KAAwC,IAAI;;IACvE;IACAX,KAAK,CAAC/D,OAAO,CAAC0E,KAAK,EAAE,CAACX,KAAK,CAACpE,IAAI,CAAC;IACjC,gBAAU,CAAC6B,OAAO,0CAAEmD,KAAK,EAAE;IAE3B;IACA5E,eAAe,CAAC,KAAK,CAAC;EACxB,CAAC,CAAC,CACH;EAED,IAAIgE,KAAK,CAACE,UAAU,EAAE;IACpBF,KAAK,CAACE,UAAU,CAACE,WAAW,GAAGI,qBAAqB;IACpDR,KAAK,CAACE,UAAU,CAACI,OAAO,GAAGI,iBAAiB;IAE5C;IACA;IACA;IACA;IACA;IACA;IACA,MAAMG,cAAc,GAAGb,KAAK,CAACE,UAAU,CAAC,YAAY,CAAC,IAAIF,KAAK,CAACE,UAAU,CAAC,iBAAiB,CAAC;IAC5F,MAAMY,iBAAiB,GAAG,MAAM,CAAC,CAAC;IAClC,IAAI,CAACD,cAAc,EAAE;MACnB,IAAI1F,KAAK,CAAC,iBAAiB,CAAC,EAAE;QAC5B,MAAM4F,SAAS,GAAG,WAAK,CAACb,UAAU,CAAC5B,EAAE,mCAAI,GAAG9B,OAAO,UAAU;QAC7D,MAAMwE,iBAAiB,GAAG,GAAGD,SAAS,IAAIf,KAAK,CAACV,KAAK,CAAC,iBAAiB,CAAC,EAAE;QAE1EU,KAAK,CAACE,UAAU,CAAC,YAAY,CAAC,GAAGY,iBAAiB;QAClDd,KAAK,CAACE,UAAU,CAAC5B,EAAE,GAAGyC,SAAS;QAC/Bf,KAAK,CAACE,UAAU,CAAC,iBAAiB,CAAC,GAAGc,iBAAiB;OACxD,MAAM,IAAI7F,KAAK,CAAC,YAAY,CAAC,EAAE;QAC9B6E,KAAK,CAACE,UAAU,CAAC,YAAY,CAAC,GAAG,GAAGY,iBAAiB,IAAI3F,KAAK,CAAC,YAAY,CAAC,EAAE;OAC/E,MAAM;QACL6E,KAAK,CAACE,UAAU,CAAC,YAAY,CAAC,GAAGY,iBAAiB;;;;EAKxD,OAAOd,KAAK;AACd,CAAC","names":["React","ArrowLeft","ArrowRight","ChevronDownRegular","ChevronDownIcon","getPartitionedNativeProps","resolveShorthand","mergeCallbacks","useEventCallback","useId","useMergedRefs","getDropdownActionFromKey","useComboboxBaseState","useComboboxPopup","useTriggerListboxSlots","Listbox","useCombobox_unstable","props","ref","baseState","editable","activeOption","clearSelection","getIndexOfId","getOptionsMatchingText","hasFocus","open","selectOption","selectedOptions","setActiveOption","setFocusVisible","setOpen","setValue","value","disabled","freeform","inlinePopup","multiselect","comboId","primary","triggerNativeProps","root","rootNativeProps","primarySlotTagName","excludedPropNames","rootRef","useRef","triggerRef","hideActiveDescendant","setHideActiveDescendant","useState","popupDimensions","setPopupDimensions","useEffect","width","current","clientWidth","getOptionFromInput","inputValue","searchString","trim","toLowerCase","length","matcher","optionText","indexOf","matches","startIndex","id","nextMatch","find","option","undefined","ev","onTriggerBlur","text","newState","onTriggerChange","target","matchingOption","onTriggerKeyDown","key","triggerSlot","listboxSlot","input","required","defaultProps","type","onChange","onBlur","onKeyDown","listbox","children","style","state","components","expandIcon","role","onMouseDown","onIconMouseDown","onClick","onIconClick","onExpandIconMouseDown","ignoreNextBlur","onExpandIconClick","event","focus","hasExpandLabel","defaultOpenString","chevronId","chevronLabelledBy"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/components/Combobox/useCombobox.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ArrowLeft, ArrowRight } from '@fluentui/keyboard-keys';\nimport { ChevronDownRegular as ChevronDownIcon } from '@fluentui/react-icons';\nimport {\n getPartitionedNativeProps,\n resolveShorthand,\n mergeCallbacks,\n useEventCallback,\n useId,\n useMergedRefs,\n} from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey } from '../../utils/dropdownKeyActions';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPopup } from '../../utils/useComboboxPopup';\nimport { useTriggerListboxSlots } from '../../utils/useTriggerListboxSlots';\nimport { Listbox } from '../Listbox/Listbox';\nimport type { Slot } from '@fluentui/react-utilities';\nimport type { SelectionEvents } from '../../utils/Selection.types';\nimport type { OptionValue } from '../../utils/OptionCollection.types';\nimport type { ComboboxProps, ComboboxState } from './Combobox.types';\n\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 */\nexport const useCombobox_unstable = (props: ComboboxProps, ref: React.Ref<HTMLInputElement>): ComboboxState => {\n const baseState = useComboboxBaseState({ ...props, editable: true });\n const {\n activeOption,\n clearSelection,\n getIndexOfId,\n getOptionsMatchingText,\n hasFocus,\n open,\n selectOption,\n selectedOptions,\n setActiveOption,\n setFocusVisible,\n setOpen,\n setValue,\n value,\n } = baseState;\n const { disabled, freeform, inlinePopup, multiselect } = props;\n const comboId = useId('combobox-');\n\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'input',\n excludedPropNames: ['children', 'size'],\n });\n\n const rootRef = React.useRef<HTMLDivElement>(null);\n const triggerRef = React.useRef<HTMLInputElement>(null);\n\n // NVDA and JAWS have bugs that suppress reading the input value text when aria-activedescendant is set\n // To prevent this, we clear the HTML attribute (but save the state) when a user presses left/right arrows\n // ref: https://github.com/microsoft/fluentui/issues/26359#issuecomment-1397759888\n const [hideActiveDescendant, setHideActiveDescendant] = React.useState(false);\n\n // calculate listbox width style based on trigger width\n const [popupDimensions, setPopupDimensions] = React.useState<{ width: string }>();\n React.useEffect(() => {\n // only recalculate width when opening\n if (open) {\n const width = `${rootRef.current?.clientWidth}px`;\n if (width !== popupDimensions?.width) {\n setPopupDimensions({ width });\n }\n }\n }, [open, popupDimensions]);\n\n // set active option and selection based on typing\n const getOptionFromInput = (inputValue: string): OptionValue | undefined => {\n const searchString = inputValue?.trim().toLowerCase();\n\n if (!searchString || searchString.length === 0) {\n return;\n }\n\n const matcher = (optionText: string) => optionText.toLowerCase().indexOf(searchString) === 0;\n const matches = getOptionsMatchingText(matcher);\n\n // return first matching option after the current active option, looping back to the top\n if (matches.length > 1 && activeOption) {\n const startIndex = getIndexOfId(activeOption.id);\n const nextMatch = matches.find(option => getIndexOfId(option.id) >= startIndex);\n return nextMatch ?? matches[0];\n }\n\n return matches[0] ?? undefined;\n };\n\n /* Handle typed input */\n\n // reset any typed value when an option is selected\n baseState.selectOption = (ev: SelectionEvents, option: OptionValue) => {\n setValue(undefined);\n selectOption(ev, option);\n };\n\n const onTriggerBlur = (ev: React.FocusEvent<HTMLInputElement>) => {\n // handle selection and updating value if freeform is false\n if (!baseState.open && !freeform) {\n // select matching option, if the value fully matches\n if (value && activeOption && value.trim().toLowerCase() === activeOption?.text.toLowerCase()) {\n baseState.selectOption(ev, activeOption);\n }\n\n // reset typed value when the input loses focus while collapsed, unless freeform is true\n setValue(undefined);\n }\n };\n\n baseState.setOpen = (ev, newState: boolean) => {\n if (disabled) {\n return;\n }\n\n if (!newState && !freeform) {\n setValue(undefined);\n }\n\n setOpen(ev, newState);\n };\n\n // update value and active option based on input\n const onTriggerChange = (ev: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = ev.target.value;\n // update uncontrolled value\n baseState.setValue(inputValue);\n\n // handle updating active option based on input\n const matchingOption = getOptionFromInput(inputValue);\n setActiveOption(matchingOption);\n\n setFocusVisible(true);\n\n // clear selection for single-select if the input value no longer matches the selection\n if (!multiselect && selectedOptions.length === 1 && (inputValue.length < 1 || !matchingOption)) {\n clearSelection(ev);\n }\n };\n\n // open Combobox when typing\n const onTriggerKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {\n if (!open && getDropdownActionFromKey(ev) === 'Type') {\n baseState.setOpen(ev, true);\n }\n\n // clear activedescendant when moving the text insertion cursor\n if (ev.key === ArrowLeft || ev.key === ArrowRight) {\n setHideActiveDescendant(true);\n } else {\n setHideActiveDescendant(false);\n }\n };\n\n // resolve input and listbox slot props\n let triggerSlot: Slot<'input'>;\n let listboxSlot: Slot<typeof Listbox> | undefined;\n\n triggerSlot = resolveShorthand(props.input, {\n required: true,\n defaultProps: {\n ref: useMergedRefs(props.input?.ref, triggerRef),\n type: 'text',\n value: value ?? '',\n ...triggerNativeProps,\n },\n });\n\n triggerSlot.onChange = mergeCallbacks(triggerSlot.onChange, onTriggerChange);\n triggerSlot.onBlur = mergeCallbacks(triggerSlot.onBlur, onTriggerBlur);\n triggerSlot.onKeyDown = mergeCallbacks(triggerSlot.onKeyDown, onTriggerKeyDown);\n\n // only resolve listbox slot if needed\n listboxSlot =\n open || hasFocus\n ? resolveShorthand(props.listbox, {\n required: true,\n defaultProps: {\n children: props.children,\n style: popupDimensions,\n },\n })\n : undefined;\n\n [triggerSlot, listboxSlot] = useComboboxPopup(props, triggerSlot, listboxSlot);\n [triggerSlot, listboxSlot] = useTriggerListboxSlots(props, baseState, ref, triggerSlot, listboxSlot);\n\n if (hideActiveDescendant) {\n triggerSlot['aria-activedescendant'] = undefined;\n }\n\n const state: ComboboxState = {\n components: {\n root: 'div',\n input: 'input',\n expandIcon: 'span',\n listbox: Listbox,\n },\n root: resolveShorthand(props.root, {\n required: true,\n defaultProps: {\n 'aria-owns': !inlinePopup ? listboxSlot?.id : undefined,\n ...rootNativeProps,\n },\n }),\n input: triggerSlot,\n listbox: listboxSlot,\n expandIcon: resolveShorthand(props.expandIcon, {\n required: true,\n defaultProps: {\n 'aria-expanded': open,\n children: <ChevronDownIcon />,\n role: 'button',\n },\n }),\n ...baseState,\n };\n\n state.root.ref = useMergedRefs(state.root.ref, rootRef);\n\n /* handle open/close + focus change when clicking expandIcon */\n const { onMouseDown: onIconMouseDown, onClick: onIconClick } = state.expandIcon || {};\n const onExpandIconMouseDown = useEventCallback(\n mergeCallbacks(onIconMouseDown, () => {\n // do not dismiss on blur when closing via clicking the icon\n if (open) {\n baseState.ignoreNextBlur.current = true;\n }\n }),\n );\n\n const onExpandIconClick = useEventCallback(\n mergeCallbacks(onIconClick, (event: React.MouseEvent<HTMLSpanElement>) => {\n // open and set focus\n state.setOpen(event, !state.open);\n triggerRef.current?.focus();\n\n // set focus visible=false, since this can only be done with the mouse/pointer\n setFocusVisible(false);\n }),\n );\n\n if (state.expandIcon) {\n state.expandIcon.onMouseDown = onExpandIconMouseDown;\n state.expandIcon.onClick = onExpandIconClick;\n\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 const chevronId = state.expandIcon.id ?? `${comboId}-chevron`;\n const chevronLabelledBy = `${chevronId} ${state.input['aria-labelledby']}`;\n\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\n return state;\n};\n"]}
|
|
@@ -49,7 +49,7 @@ export const useDropdown_unstable = (props, ref) => {
|
|
|
49
49
|
const getNextMatchingOption = () => {
|
|
50
50
|
var _a;
|
|
51
51
|
// first check for matches for the full searchString
|
|
52
|
-
let matcher =
|
|
52
|
+
let matcher = optionText => optionText.toLowerCase().indexOf(searchString.current) === 0;
|
|
53
53
|
let matches = getOptionsMatchingText(matcher);
|
|
54
54
|
let startIndex = activeOption ? getIndexOfId(activeOption.id) : 0;
|
|
55
55
|
// if the dropdown is already open and the searchstring is a single character,
|
|
@@ -65,7 +65,7 @@ export const useDropdown_unstable = (props, ref) => {
|
|
|
65
65
|
// if the search is all the same letter, cycle through options starting with that letter
|
|
66
66
|
if (allSameLetter) {
|
|
67
67
|
startIndex++;
|
|
68
|
-
matcher =
|
|
68
|
+
matcher = optionText => optionText.toLowerCase().indexOf(letters[0]) === 0;
|
|
69
69
|
matches = getOptionsMatchingText(matcher);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"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","names":["React","ChevronDownRegular","ChevronDownIcon","getPartitionedNativeProps","mergeCallbacks","resolveShorthand","useTimeout","getDropdownActionFromKey","useComboboxBaseState","useComboboxPopup","useTriggerListboxSlots","Listbox","useMergedRefs","useDropdown_unstable","props","ref","baseState","activeOption","getIndexOfId","getOptionsMatchingText","open","setActiveOption","setFocusVisible","setOpen","primary","triggerNativeProps","root","rootNativeProps","primarySlotTagName","excludedPropNames","rootRef","useRef","popupWidth","setPopupWidth","useState","useEffect","width","current","clientWidth","undefined","searchString","setKeyTimeout","clearKeyTimeout","getNextMatchingOption","matcher","optionValue","toLowerCase","indexOf","matches","startIndex","id","length","letters","split","allSameLetter","every","letter","nextMatch","find","option","onTriggerKeyDown","ev","key","nextOption","triggerSlot","listboxSlot","button","required","defaultProps","type","children","value","placeholder","onKeyDown","hasFocus","listbox","style","state","components","expandIcon","inlinePopup","placeholderVisible"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/components/Dropdown/useDropdown.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ChevronDownRegular as ChevronDownIcon } from '@fluentui/react-icons';\nimport { getPartitionedNativeProps, mergeCallbacks, resolveShorthand, useTimeout } from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey } from '../../utils/dropdownKeyActions';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPopup } from '../../utils/useComboboxPopup';\nimport { useTriggerListboxSlots } from '../../utils/useTriggerListboxSlots';\nimport { Listbox } from '../Listbox/Listbox';\nimport type { Slot } from '@fluentui/react-utilities';\nimport type { OptionValue } from '../../utils/OptionCollection.types';\nimport type { DropdownProps, DropdownState } from './Dropdown.types';\nimport { useMergedRefs } from '@fluentui/react-utilities';\n\n/**\n * Create the state required to render Dropdown.\n *\n * The returned state can be modified with hooks such as useDropdownStyles_unstable,\n * before being passed to renderDropdown_unstable.\n *\n * @param props - props from this instance of Dropdown\n * @param ref - reference to root HTMLElement of Dropdown\n */\nexport const useDropdown_unstable = (props: DropdownProps, ref: React.Ref<HTMLButtonElement>): DropdownState => {\n const baseState = useComboboxBaseState(props);\n const {\n activeOption,\n getIndexOfId,\n getOptionsMatchingText,\n open,\n setActiveOption,\n setFocusVisible,\n setOpen,\n } = baseState;\n\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'button',\n excludedPropNames: ['children'],\n });\n\n // set listbox popup width based off the root/trigger width\n const rootRef = React.useRef<HTMLDivElement>(null);\n const [popupWidth, setPopupWidth] = React.useState<string>();\n React.useEffect(() => {\n const width = open ? `${rootRef.current?.clientWidth}px` : undefined;\n setPopupWidth(width);\n }, [open]);\n\n // jump to matching option based on typing\n const searchString = React.useRef('');\n const [setKeyTimeout, clearKeyTimeout] = useTimeout();\n\n const getNextMatchingOption = (): OptionValue | undefined => {\n // first check for matches for the full searchString\n let matcher = (optionValue: string) => optionValue.toLowerCase().indexOf(searchString.current) === 0;\n let matches = getOptionsMatchingText(matcher);\n let startIndex = activeOption ? getIndexOfId(activeOption.id) : 0;\n\n // if the dropdown is already open and the searchstring is a single character,\n // then look after the current activeOption for letters\n // this is so slowly typing the same letter will cycle through matches\n if (open && searchString.current.length === 1) {\n startIndex++;\n }\n\n // if there are no direct matches, check if the search is all the same letter, e.g. \"aaa\"\n if (!matches.length) {\n const letters = searchString.current.split('');\n const allSameLetter = letters.length && letters.every(letter => letter === letters[0]);\n\n // if the search is all the same letter, cycle through options starting with that letter\n if (allSameLetter) {\n startIndex++;\n matcher = (optionValue: string) => optionValue.toLowerCase().indexOf(letters[0]) === 0;\n matches = getOptionsMatchingText(matcher);\n }\n }\n\n // if there is an active option and multiple matches,\n // return first matching option after the current active option, looping back to the top\n if (matches.length > 1 && activeOption) {\n const nextMatch = matches.find(option => getIndexOfId(option.id) >= startIndex);\n return nextMatch ?? matches[0];\n }\n\n return matches[0] ?? undefined;\n };\n\n const onTriggerKeyDown = (ev: React.KeyboardEvent<HTMLButtonElement>) => {\n // clear timeout, if it exists\n clearKeyTimeout();\n\n // if the key was a char key, update search string\n if (getDropdownActionFromKey(ev) === 'Type') {\n // update search string\n searchString.current += ev.key.toLowerCase();\n setKeyTimeout(() => {\n searchString.current = '';\n }, 500);\n\n // update state\n !open && setOpen(ev, true);\n\n const nextOption = getNextMatchingOption();\n setActiveOption(nextOption);\n setFocusVisible(true);\n }\n };\n\n // resolve button and listbox slot props\n let triggerSlot: Slot<'button'>;\n let listboxSlot: Slot<typeof Listbox> | undefined;\n\n triggerSlot = resolveShorthand(props.button, {\n required: true,\n defaultProps: {\n type: 'button',\n children: baseState.value || props.placeholder,\n ...triggerNativeProps,\n },\n });\n\n triggerSlot.onKeyDown = mergeCallbacks(onTriggerKeyDown, triggerSlot.onKeyDown);\n\n listboxSlot =\n baseState.open || baseState.hasFocus\n ? resolveShorthand(props.listbox, {\n required: true,\n defaultProps: {\n children: props.children,\n style: { width: popupWidth },\n },\n })\n : undefined;\n\n [triggerSlot, listboxSlot] = useComboboxPopup(props, triggerSlot, listboxSlot);\n [triggerSlot, listboxSlot] = useTriggerListboxSlots(props, baseState, ref, triggerSlot, listboxSlot);\n\n const state: DropdownState = {\n components: {\n root: 'div',\n button: 'button',\n expandIcon: 'span',\n listbox: Listbox,\n },\n root: resolveShorthand(props.root, {\n required: true,\n defaultProps: {\n 'aria-owns': !props.inlinePopup ? listboxSlot?.id : undefined,\n children: props.children,\n ...rootNativeProps,\n },\n }),\n button: triggerSlot,\n listbox: listboxSlot,\n expandIcon: resolveShorthand(props.expandIcon, {\n required: true,\n defaultProps: {\n children: <ChevronDownIcon />,\n },\n }),\n placeholderVisible: !baseState.value && !!props.placeholder,\n ...baseState,\n };\n\n state.root.ref = useMergedRefs(state.root.ref, rootRef);\n\n return state;\n};\n"]}
|
|
1
|
+
{"version":3,"mappings":"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","names":["React","ChevronDownRegular","ChevronDownIcon","getPartitionedNativeProps","mergeCallbacks","resolveShorthand","useTimeout","getDropdownActionFromKey","useComboboxBaseState","useComboboxPopup","useTriggerListboxSlots","Listbox","useMergedRefs","useDropdown_unstable","props","ref","baseState","activeOption","getIndexOfId","getOptionsMatchingText","open","setActiveOption","setFocusVisible","setOpen","primary","triggerNativeProps","root","rootNativeProps","primarySlotTagName","excludedPropNames","rootRef","useRef","popupWidth","setPopupWidth","useState","useEffect","width","current","clientWidth","undefined","searchString","setKeyTimeout","clearKeyTimeout","getNextMatchingOption","matcher","optionText","toLowerCase","indexOf","matches","startIndex","id","length","letters","split","allSameLetter","every","letter","nextMatch","find","option","onTriggerKeyDown","ev","key","nextOption","triggerSlot","listboxSlot","button","required","defaultProps","type","children","value","placeholder","onKeyDown","hasFocus","listbox","style","state","components","expandIcon","inlinePopup","placeholderVisible"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/components/Dropdown/useDropdown.tsx"],"sourcesContent":["import * as React from 'react';\nimport { ChevronDownRegular as ChevronDownIcon } from '@fluentui/react-icons';\nimport { getPartitionedNativeProps, mergeCallbacks, resolveShorthand, useTimeout } from '@fluentui/react-utilities';\nimport { getDropdownActionFromKey } from '../../utils/dropdownKeyActions';\nimport { useComboboxBaseState } from '../../utils/useComboboxBaseState';\nimport { useComboboxPopup } from '../../utils/useComboboxPopup';\nimport { useTriggerListboxSlots } from '../../utils/useTriggerListboxSlots';\nimport { Listbox } from '../Listbox/Listbox';\nimport type { Slot } from '@fluentui/react-utilities';\nimport type { OptionValue } from '../../utils/OptionCollection.types';\nimport type { DropdownProps, DropdownState } from './Dropdown.types';\nimport { useMergedRefs } from '@fluentui/react-utilities';\n\n/**\n * Create the state required to render Dropdown.\n *\n * The returned state can be modified with hooks such as useDropdownStyles_unstable,\n * before being passed to renderDropdown_unstable.\n *\n * @param props - props from this instance of Dropdown\n * @param ref - reference to root HTMLElement of Dropdown\n */\nexport const useDropdown_unstable = (props: DropdownProps, ref: React.Ref<HTMLButtonElement>): DropdownState => {\n const baseState = useComboboxBaseState(props);\n const {\n activeOption,\n getIndexOfId,\n getOptionsMatchingText,\n open,\n setActiveOption,\n setFocusVisible,\n setOpen,\n } = baseState;\n\n const { primary: triggerNativeProps, root: rootNativeProps } = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'button',\n excludedPropNames: ['children'],\n });\n\n // set listbox popup width based off the root/trigger width\n const rootRef = React.useRef<HTMLDivElement>(null);\n const [popupWidth, setPopupWidth] = React.useState<string>();\n React.useEffect(() => {\n const width = open ? `${rootRef.current?.clientWidth}px` : undefined;\n setPopupWidth(width);\n }, [open]);\n\n // jump to matching option based on typing\n const searchString = React.useRef('');\n const [setKeyTimeout, clearKeyTimeout] = useTimeout();\n\n const getNextMatchingOption = (): OptionValue | undefined => {\n // first check for matches for the full searchString\n let matcher = (optionText: string) => optionText.toLowerCase().indexOf(searchString.current) === 0;\n let matches = getOptionsMatchingText(matcher);\n let startIndex = activeOption ? getIndexOfId(activeOption.id) : 0;\n\n // if the dropdown is already open and the searchstring is a single character,\n // then look after the current activeOption for letters\n // this is so slowly typing the same letter will cycle through matches\n if (open && searchString.current.length === 1) {\n startIndex++;\n }\n\n // if there are no direct matches, check if the search is all the same letter, e.g. \"aaa\"\n if (!matches.length) {\n const letters = searchString.current.split('');\n const allSameLetter = letters.length && letters.every(letter => letter === letters[0]);\n\n // if the search is all the same letter, cycle through options starting with that letter\n if (allSameLetter) {\n startIndex++;\n matcher = (optionText: string) => optionText.toLowerCase().indexOf(letters[0]) === 0;\n matches = getOptionsMatchingText(matcher);\n }\n }\n\n // if there is an active option and multiple matches,\n // return first matching option after the current active option, looping back to the top\n if (matches.length > 1 && activeOption) {\n const nextMatch = matches.find(option => getIndexOfId(option.id) >= startIndex);\n return nextMatch ?? matches[0];\n }\n\n return matches[0] ?? undefined;\n };\n\n const onTriggerKeyDown = (ev: React.KeyboardEvent<HTMLButtonElement>) => {\n // clear timeout, if it exists\n clearKeyTimeout();\n\n // if the key was a char key, update search string\n if (getDropdownActionFromKey(ev) === 'Type') {\n // update search string\n searchString.current += ev.key.toLowerCase();\n setKeyTimeout(() => {\n searchString.current = '';\n }, 500);\n\n // update state\n !open && setOpen(ev, true);\n\n const nextOption = getNextMatchingOption();\n setActiveOption(nextOption);\n setFocusVisible(true);\n }\n };\n\n // resolve button and listbox slot props\n let triggerSlot: Slot<'button'>;\n let listboxSlot: Slot<typeof Listbox> | undefined;\n\n triggerSlot = resolveShorthand(props.button, {\n required: true,\n defaultProps: {\n type: 'button',\n children: baseState.value || props.placeholder,\n ...triggerNativeProps,\n },\n });\n\n triggerSlot.onKeyDown = mergeCallbacks(onTriggerKeyDown, triggerSlot.onKeyDown);\n\n listboxSlot =\n baseState.open || baseState.hasFocus\n ? resolveShorthand(props.listbox, {\n required: true,\n defaultProps: {\n children: props.children,\n style: { width: popupWidth },\n },\n })\n : undefined;\n\n [triggerSlot, listboxSlot] = useComboboxPopup(props, triggerSlot, listboxSlot);\n [triggerSlot, listboxSlot] = useTriggerListboxSlots(props, baseState, ref, triggerSlot, listboxSlot);\n\n const state: DropdownState = {\n components: {\n root: 'div',\n button: 'button',\n expandIcon: 'span',\n listbox: Listbox,\n },\n root: resolveShorthand(props.root, {\n required: true,\n defaultProps: {\n 'aria-owns': !props.inlinePopup ? listboxSlot?.id : undefined,\n children: props.children,\n ...rootNativeProps,\n },\n }),\n button: triggerSlot,\n listbox: listboxSlot,\n expandIcon: resolveShorthand(props.expandIcon, {\n required: true,\n defaultProps: {\n children: <ChevronDownIcon />,\n },\n }),\n placeholderVisible: !baseState.value && !!props.placeholder,\n ...baseState,\n };\n\n state.root.ref = useMergedRefs(state.root.ref, rootRef);\n\n return state;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OptionCollection.types.js","sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/OptionCollection.types.ts"],"names":[],"mappings":"","sourcesContent":["export type OptionValue = {\n /** The disabled state of the option. */\n disabled?: boolean;\n\n /** The `id` attribute of the option. */\n id: string;\n\n /** The `text` string for the option. */\n text: string;\n\n /** The value string of the option. */\n value: string;\n};\n\nexport type OptionCollectionState = {\n /** The total number of options in the collection. */\n getCount: () => number;\n\n /** Returns the index of an option by key. */\n getIndexOfId(id: string): number;\n\n /** Returns the option data for the nth option. */\n getOptionAtIndex(index: number): OptionValue | undefined;\n\n /** Returns the option data by key. */\n getOptionById(id: string): OptionValue | undefined;\n\n /** Returns an array of options filtered by a value matching function against the option's text string. */\n getOptionsMatchingText(matcher: (value: string) => boolean): OptionValue[];\n\n /** The unordered option data. */\n options: OptionValue[];\n\n /* A function that child options call to register their values. Returns a function to unregister the option. */\n registerOption: (option: OptionValue, element: HTMLElement) => () => void;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"OptionCollection.types.js","sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/OptionCollection.types.ts"],"names":[],"mappings":"","sourcesContent":["export type OptionValue = {\n /** The disabled state of the option. */\n disabled?: boolean;\n\n /** The `id` attribute of the option. */\n id: string;\n\n /** The `text` string for the option. */\n text: string;\n\n /** The value string of the option. */\n value: string;\n};\n\nexport type OptionCollectionState = {\n /** The total number of options in the collection. */\n getCount: () => number;\n\n /** Returns the index of an option by key. */\n getIndexOfId(id: string): number;\n\n /** Returns the option data for the nth option. */\n getOptionAtIndex(index: number): OptionValue | undefined;\n\n /** Returns the option data by key. */\n getOptionById(id: string): OptionValue | undefined;\n\n /** Returns an array of options filtered by a value matching function against the option's text string. */\n getOptionsMatchingText(matcher: (text: string) => boolean): OptionValue[];\n\n /** Returns an array of options filtered by a value matching function against the option's value string. */\n getOptionsMatchingValue(matcher: (value: string) => boolean): OptionValue[];\n\n /** The unordered option data. */\n options: OptionValue[];\n\n /* A function that child options call to register their values. Returns a function to unregister the option. */\n registerOption: (option: OptionValue, element: HTMLElement) => () => void;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Selection.types.js","sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/Selection.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport { OptionValue } from './OptionCollection.types';\n\nexport type SelectionProps = {\n
|
|
1
|
+
{"version":3,"file":"Selection.types.js","sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/Selection.types.ts"],"names":[],"mappings":"","sourcesContent":["import * as React from 'react';\nimport { OptionValue } from './OptionCollection.types';\n\nexport type SelectionProps = {\n /**\n * For an uncontrolled component, sets the initial selection.\n * If this is set, the `defaultValue` prop MUST also be set.\n */\n defaultSelectedOptions?: string[];\n\n /**\n * Sets the selection type to multiselect.\n * Set this to true for multiselect, even if fully controlling selection state.\n * This enables styles and accessibility properties to be set.\n * @default false\n */\n multiselect?: boolean;\n\n /* Callback when an option is selected */\n onOptionSelect?: (event: SelectionEvents, data: OptionOnSelectData) => void;\n\n /**\n * An array of selected option keys.\n * Use this with `onOptionSelect` to directly control the selected option(s)\n * If this is set, the `value` prop MUST also be controlled.\n */\n selectedOptions?: string[];\n};\n\n/* Values returned by the useSelection hook */\nexport type SelectionState = {\n clearSelection: (event: SelectionEvents) => void;\n selectedOptions: string[];\n selectOption: (event: SelectionEvents, option: OptionValue) => void;\n};\n\n/*\n * Data for the onOptionSelect callback.\n * `optionValue` and `optionText` will be undefined if multiple options are modified at once.\n */\nexport type OptionOnSelectData = {\n optionValue: string | undefined;\n optionText: string | undefined;\n selectedOptions: string[];\n};\n\n/* Possible event types for onOptionSelect */\nexport type SelectionEvents =\n | React.ChangeEvent<HTMLElement>\n | React.KeyboardEvent<HTMLElement>\n | React.MouseEvent<HTMLElement>;\n"]}
|
|
@@ -18,7 +18,7 @@ export const useComboboxBaseState = props => {
|
|
|
18
18
|
const optionCollection = useOptionCollection();
|
|
19
19
|
const {
|
|
20
20
|
getOptionAtIndex,
|
|
21
|
-
|
|
21
|
+
getOptionsMatchingValue
|
|
22
22
|
} = optionCollection;
|
|
23
23
|
const [activeOption, setActiveOption] = React.useState();
|
|
24
24
|
// track whether keyboard focus outline should be shown
|
|
@@ -46,12 +46,19 @@ export const useComboboxBaseState = props => {
|
|
|
46
46
|
if (isFirstMount && props.defaultValue !== undefined) {
|
|
47
47
|
return props.defaultValue;
|
|
48
48
|
}
|
|
49
|
+
const selectedOptionsText = getOptionsMatchingValue(optionValue => {
|
|
50
|
+
return selectedOptions.includes(optionValue);
|
|
51
|
+
}).map(option => option.text);
|
|
49
52
|
if (multiselect) {
|
|
50
53
|
// editable inputs should not display multiple selected options in the input as text
|
|
51
|
-
return editable ? '' :
|
|
54
|
+
return editable ? '' : selectedOptionsText.join(', ');
|
|
52
55
|
}
|
|
53
|
-
return
|
|
54
|
-
|
|
56
|
+
return selectedOptionsText[0];
|
|
57
|
+
// do not change value after isFirstMount changes,
|
|
58
|
+
// we do not want to accidentally override defaultValue on a second render
|
|
59
|
+
// unless another value is intentionally set
|
|
60
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
61
|
+
}, [controllableValue, editable, getOptionsMatchingValue, multiselect, props.defaultValue, selectedOptions]);
|
|
55
62
|
// Handle open state, which is shared with options in context
|
|
56
63
|
const [open, setOpenState] = useControllableState({
|
|
57
64
|
state: props.open,
|
|
@@ -69,7 +76,7 @@ export const useComboboxBaseState = props => {
|
|
|
69
76
|
if (open && !activeOption) {
|
|
70
77
|
// if it is single-select and there is a selected option, start at the selected option
|
|
71
78
|
if (!multiselect && selectedOptions.length > 0) {
|
|
72
|
-
const selectedOption =
|
|
79
|
+
const selectedOption = getOptionsMatchingValue(v => v === selectedOptions[0]).pop();
|
|
73
80
|
selectedOption && setActiveOption(selectedOption);
|
|
74
81
|
}
|
|
75
82
|
// default to starting at the first option
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,oBAAoB,EAAEC,aAAa,QAAQ,2BAA2B;AAC/E,SAASC,mBAAmB,QAAQ,8BAA8B;AAElE,SAASC,YAAY,QAAQ,uBAAuB;AAGpD;;;AAGA,OAAO,MAAMC,oBAAoB,GAC/BC,KAA6E,IACxD;EACrB,MAAM;IACJC,UAAU,GAAG,SAAS;IACtBC,QAAQ;IACRC,QAAQ,GAAG,KAAK;IAChBC,WAAW,GAAG,KAAK;IACnBC,WAAW;IACXC,YAAY;IACZC,IAAI,GAAG;EAAQ,CAChB,GAAGP,KAAK;EAET,MAAMQ,gBAAgB,GAAGX,mBAAmB,EAAE;EAC9C,MAAM;IAAEY,gBAAgB;IAAEC;
|
|
1
|
+
{"version":3,"mappings":"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","names":["React","useControllableState","useFirstMount","useOptionCollection","useSelection","useComboboxBaseState","props","appearance","children","editable","inlinePopup","multiselect","onOpenChange","size","optionCollection","getOptionAtIndex","getOptionsMatchingValue","activeOption","setActiveOption","useState","focusVisible","setFocusVisible","hasFocus","setHasFocus","ignoreNextBlur","useRef","selectionState","selectedOptions","isFirstMount","controllableValue","setValue","state","value","initialState","undefined","useMemo","defaultValue","selectedOptionsText","optionValue","includes","map","option","text","join","open","setOpenState","defaultState","defaultOpen","setOpen","useCallback","event","newState","useEffect","length","selectedOption","v","pop"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/useComboboxBaseState.ts"],"sourcesContent":["import * as React from 'react';\nimport { useControllableState, useFirstMount } from '@fluentui/react-utilities';\nimport { useOptionCollection } from '../utils/useOptionCollection';\nimport { OptionValue } from '../utils/OptionCollection.types';\nimport { useSelection } from '../utils/useSelection';\nimport type { ComboboxBaseProps, ComboboxBaseOpenEvents, ComboboxBaseState } from './ComboboxBase.types';\n\n/**\n * State shared between Combobox and Dropdown components\n */\nexport const useComboboxBaseState = (\n props: ComboboxBaseProps & { children?: React.ReactNode; editable?: boolean },\n): ComboboxBaseState => {\n const {\n appearance = 'outline',\n children,\n editable = false,\n inlinePopup = false,\n multiselect,\n onOpenChange,\n size = 'medium',\n } = props;\n\n const optionCollection = useOptionCollection();\n const { getOptionAtIndex, getOptionsMatchingValue } = optionCollection;\n\n const [activeOption, setActiveOption] = React.useState<OptionValue | undefined>();\n\n // track whether keyboard focus outline should be shown\n // tabster/keyborg doesn't work here, since the actual keyboard focus target doesn't move\n const [focusVisible, setFocusVisible] = React.useState(false);\n\n // track focused state to conditionally render collapsed listbox\n const [hasFocus, setHasFocus] = React.useState(false);\n\n const ignoreNextBlur = React.useRef(false);\n\n const selectionState = useSelection(props);\n const { selectedOptions } = selectionState;\n\n // calculate value based on props, internal value changes, and selected options\n const isFirstMount = useFirstMount();\n const [controllableValue, setValue] = useControllableState({\n state: props.value,\n initialState: undefined,\n });\n\n const value = React.useMemo(() => {\n // don't compute the value if it is defined through props or setValue,\n if (controllableValue !== undefined) {\n return controllableValue;\n }\n\n // handle defaultValue here, so it is overridden by selection\n if (isFirstMount && props.defaultValue !== undefined) {\n return props.defaultValue;\n }\n\n const selectedOptionsText = getOptionsMatchingValue(optionValue => {\n return selectedOptions.includes(optionValue);\n }).map(option => option.text);\n\n if (multiselect) {\n // editable inputs should not display multiple selected options in the input as text\n return editable ? '' : selectedOptionsText.join(', ');\n }\n\n return selectedOptionsText[0];\n\n // do not change value after isFirstMount changes,\n // we do not want to accidentally override defaultValue on a second render\n // unless another value is intentionally set\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [controllableValue, editable, getOptionsMatchingValue, multiselect, props.defaultValue, selectedOptions]);\n\n // Handle open state, which is shared with options in context\n const [open, setOpenState] = useControllableState({\n state: props.open,\n defaultState: props.defaultOpen,\n initialState: false,\n });\n\n const setOpen = React.useCallback(\n (event: ComboboxBaseOpenEvents, newState: boolean) => {\n onOpenChange?.(event, { open: newState });\n setOpenState(newState);\n },\n [onOpenChange, setOpenState],\n );\n\n // update active option based on change in open state or children\n React.useEffect(() => {\n if (open && !activeOption) {\n // if it is single-select and there is a selected option, start at the selected option\n if (!multiselect && selectedOptions.length > 0) {\n const selectedOption = getOptionsMatchingValue(v => v === selectedOptions[0]).pop();\n selectedOption && setActiveOption(selectedOption);\n }\n // default to starting at the first option\n else {\n setActiveOption(getOptionAtIndex(0));\n }\n } else if (!open) {\n // reset the active option when closing\n setActiveOption(undefined);\n }\n // this should only be run in response to changes in the open state or children\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, children]);\n\n return {\n ...optionCollection,\n ...selectionState,\n activeOption,\n appearance,\n focusVisible,\n hasFocus,\n ignoreNextBlur,\n inlinePopup,\n open,\n setActiveOption,\n setFocusVisible,\n setHasFocus,\n setOpen,\n setValue,\n size,\n value,\n };\n};\n"]}
|
|
@@ -18,12 +18,16 @@ export const useOptionCollection = () => {
|
|
|
18
18
|
const getOptionsMatchingText = matcher => {
|
|
19
19
|
return nodes.current.filter(node => matcher(node.option.text)).map(node => node.option);
|
|
20
20
|
};
|
|
21
|
+
const getOptionsMatchingValue = matcher => {
|
|
22
|
+
return nodes.current.filter(node => matcher(node.option.value)).map(node => node.option);
|
|
23
|
+
};
|
|
21
24
|
return {
|
|
22
25
|
getCount,
|
|
23
26
|
getOptionAtIndex,
|
|
24
27
|
getIndexOfId,
|
|
25
28
|
getOptionById,
|
|
26
|
-
getOptionsMatchingText
|
|
29
|
+
getOptionsMatchingText,
|
|
30
|
+
getOptionsMatchingValue
|
|
27
31
|
};
|
|
28
32
|
}, []);
|
|
29
33
|
const registerOption = React.useCallback((option, element) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":"AAAA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAG9B;;;AAGA,OAAO,MAAMC,mBAAmB,GAAG,MAA4B;EAC7D,MAAMC,KAAK,GAAGF,KAAK,CAACG,MAAM,CAAkD,EAAE,CAAC;EAE/E,MAAMC,aAAa,GAAGJ,KAAK,CAACK,OAAO,CAAC,MAAK;IACvC,MAAMC,QAAQ,GAAG,MAAMJ,KAAK,CAACK,OAAO,CAACC,MAAM;IAC3C,MAAMC,gBAAgB,GAAIC,KAAa,IAAI;MAAA;MAAC,kBAAK,CAACH,OAAO,CAACG,KAAK,CAAC,0CAAEC,MAAM;IAAA;IACxE,MAAMC,YAAY,GAAIC,EAAU,IAAKX,KAAK,CAACK,OAAO,CAACO,SAAS,CAACC,IAAI,IAAIA,IAAI,CAACJ,MAAM,CAACE,EAAE,KAAKA,EAAE,CAAC;IAC3F,MAAMG,aAAa,GAAIH,EAAU,IAAI;MACnC,MAAMI,IAAI,GAAGf,KAAK,CAACK,OAAO,CAACW,IAAI,CAACH,IAAI,IAAIA,IAAI,CAACJ,MAAM,CAACE,EAAE,KAAKA,EAAE,CAAC;MAC9D,OAAOI,IAAI,aAAJA,IAAI,uBAAJA,IAAI,CAAEN,MAAM;IACrB,CAAC;IACD,MAAMQ,sBAAsB,GAAIC,
|
|
1
|
+
{"version":3,"mappings":"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","names":["React","useOptionCollection","nodes","useRef","collectionAPI","useMemo","getCount","current","length","getOptionAtIndex","index","option","getIndexOfId","id","findIndex","node","getOptionById","item","find","getOptionsMatchingText","matcher","filter","text","map","getOptionsMatchingValue","value","registerOption","useCallback","element","compareDocumentPosition","Node","DOCUMENT_POSITION_PRECEDING","newItem","splice","options"],"sourceRoot":"../src/","sources":["packages/react-components/react-combobox/src/utils/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 nodes = React.useRef<{ option: OptionValue; element: HTMLElement }[]>([]);\n\n const collectionAPI = React.useMemo(() => {\n const getCount = () => nodes.current.length;\n const getOptionAtIndex = (index: number) => nodes.current[index]?.option;\n const getIndexOfId = (id: string) => nodes.current.findIndex(node => node.option.id === id);\n const getOptionById = (id: string) => {\n const item = nodes.current.find(node => node.option.id === id);\n return item?.option;\n };\n const getOptionsMatchingText = (matcher: (text: string) => boolean) => {\n return nodes.current.filter(node => matcher(node.option.text)).map(node => node.option);\n };\n const getOptionsMatchingValue = (matcher: (value: string) => boolean) => {\n return nodes.current.filter(node => matcher(node.option.value)).map(node => node.option);\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, element: HTMLElement) => {\n const index = nodes.current.findIndex(node => {\n if (!node.element || !element) {\n return false;\n }\n\n if (node.option.id === option.id) {\n return true;\n }\n\n // use the DOM method compareDocumentPosition to order the current node against registered nodes\n // eslint-disable-next-line no-bitwise\n return node.element.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_PRECEDING;\n });\n\n // do not register the option if it already exists\n if (nodes.current[index]?.option.id !== option.id) {\n const newItem = {\n element,\n option,\n };\n\n // If an index is not found we will push the element to the end.\n if (index === -1) {\n nodes.current = [...nodes.current, newItem];\n } else {\n nodes.current.splice(index, 0, newItem);\n }\n }\n\n // return the unregister function\n return () => {\n nodes.current = nodes.current.filter(node => node.option.id !== option.id);\n };\n }, []);\n\n return {\n ...collectionAPI,\n options: nodes.current.map(node => node.option),\n registerOption,\n };\n};\n"]}
|
|
@@ -68,7 +68,7 @@ define(["require", "exports", "tslib", "react", "@fluentui/keyboard-keys", "@flu
|
|
|
68
68
|
// handle selection and updating value if freeform is false
|
|
69
69
|
if (!baseState.open && !freeform) {
|
|
70
70
|
// select matching option, if the value fully matches
|
|
71
|
-
if (value && activeOption && value.trim().toLowerCase() === (activeOption === null || activeOption === void 0 ? void 0 : activeOption.
|
|
71
|
+
if (value && activeOption && value.trim().toLowerCase() === (activeOption === null || activeOption === void 0 ? void 0 : activeOption.text.toLowerCase())) {
|
|
72
72
|
baseState.selectOption(ev, activeOption);
|
|
73
73
|
}
|
|
74
74
|
// reset typed value when the input loses focus while collapsed, unless freeform is true
|
|
@@ -94,9 +94,7 @@ define(["require", "exports", "tslib", "react", "@fluentui/keyboard-keys", "@flu
|
|
|
94
94
|
setActiveOption(matchingOption);
|
|
95
95
|
setFocusVisible(true);
|
|
96
96
|
// clear selection for single-select if the input value no longer matches the selection
|
|
97
|
-
if (!multiselect &&
|
|
98
|
-
selectedOptions.length === 1 &&
|
|
99
|
-
(inputValue.length < 1 || selectedOptions[0].indexOf(inputValue) !== 0)) {
|
|
97
|
+
if (!multiselect && selectedOptions.length === 1 && (inputValue.length < 1 || !matchingOption)) {
|
|
100
98
|
clearSelection(ev);
|
|
101
99
|
}
|
|
102
100
|
};
|