@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.
Files changed (78) hide show
  1. package/CHANGELOG.md +41 -9
  2. package/dist/index.d.ts +54 -11
  3. package/lib/components/Combobox/Combobox.types.js.map +1 -1
  4. package/lib/components/Combobox/renderCombobox.js +15 -11
  5. package/lib/components/Combobox/renderCombobox.js.map +1 -1
  6. package/lib/components/Combobox/useCombobox.js +12 -4
  7. package/lib/components/Combobox/useCombobox.js.map +1 -1
  8. package/lib/components/Combobox/useInputTriggerSlot.js +14 -12
  9. package/lib/components/Combobox/useInputTriggerSlot.js.map +1 -1
  10. package/lib/components/Dropdown/Dropdown.types.js.map +1 -1
  11. package/lib/components/Dropdown/renderDropdown.js +19 -15
  12. package/lib/components/Dropdown/renderDropdown.js.map +1 -1
  13. package/lib/components/Dropdown/useButtonTriggerSlot.js +51 -31
  14. package/lib/components/Dropdown/useButtonTriggerSlot.js.map +1 -1
  15. package/lib/components/Dropdown/useDropdown.js +14 -4
  16. package/lib/components/Dropdown/useDropdown.js.map +1 -1
  17. package/lib/components/Listbox/Listbox.types.js.map +1 -1
  18. package/lib/components/Listbox/renderListbox.js +7 -3
  19. package/lib/components/Listbox/renderListbox.js.map +1 -1
  20. package/lib/components/Listbox/useListbox.js +43 -35
  21. package/lib/components/Listbox/useListbox.js.map +1 -1
  22. package/lib/components/Option/Option.types.js.map +1 -1
  23. package/lib/components/Option/useOption.js +7 -11
  24. package/lib/components/Option/useOption.js.map +1 -1
  25. package/lib/components/Option/useOptionStyles.styles.js +27 -28
  26. package/lib/components/Option/useOptionStyles.styles.js.map +1 -1
  27. package/lib/contexts/useComboboxContextValues.js +14 -5
  28. package/lib/contexts/useComboboxContextValues.js.map +1 -1
  29. package/lib/contexts/useListboxContextValues.js +12 -5
  30. package/lib/contexts/useListboxContextValues.js.map +1 -1
  31. package/lib/utils/ComboboxBase.types.js.map +1 -1
  32. package/lib/utils/OptionCollection.types.js.map +1 -1
  33. package/lib/utils/Selection.types.js.map +1 -1
  34. package/lib/utils/dropdownKeyActions.js +0 -21
  35. package/lib/utils/dropdownKeyActions.js.map +1 -1
  36. package/lib/utils/useComboboxBaseState.js +52 -14
  37. package/lib/utils/useComboboxBaseState.js.map +1 -1
  38. package/lib/utils/useOptionCollection.js +18 -45
  39. package/lib/utils/useOptionCollection.js.map +1 -1
  40. package/lib/utils/useTriggerSlot.js +86 -33
  41. package/lib/utils/useTriggerSlot.js.map +1 -1
  42. package/lib-commonjs/components/Combobox/renderCombobox.js +15 -11
  43. package/lib-commonjs/components/Combobox/renderCombobox.js.map +1 -1
  44. package/lib-commonjs/components/Combobox/useCombobox.js +12 -4
  45. package/lib-commonjs/components/Combobox/useCombobox.js.map +1 -1
  46. package/lib-commonjs/components/Combobox/useInputTriggerSlot.js +14 -12
  47. package/lib-commonjs/components/Combobox/useInputTriggerSlot.js.map +1 -1
  48. package/lib-commonjs/components/Dropdown/renderDropdown.js +19 -15
  49. package/lib-commonjs/components/Dropdown/renderDropdown.js.map +1 -1
  50. package/lib-commonjs/components/Dropdown/useButtonTriggerSlot.js +51 -31
  51. package/lib-commonjs/components/Dropdown/useButtonTriggerSlot.js.map +1 -1
  52. package/lib-commonjs/components/Dropdown/useDropdown.js +14 -4
  53. package/lib-commonjs/components/Dropdown/useDropdown.js.map +1 -1
  54. package/lib-commonjs/components/Listbox/renderListbox.js +7 -3
  55. package/lib-commonjs/components/Listbox/renderListbox.js.map +1 -1
  56. package/lib-commonjs/components/Listbox/useListbox.js +42 -34
  57. package/lib-commonjs/components/Listbox/useListbox.js.map +1 -1
  58. package/lib-commonjs/components/Option/useOption.js +7 -11
  59. package/lib-commonjs/components/Option/useOption.js.map +1 -1
  60. package/lib-commonjs/components/Option/useOptionStyles.styles.js +85 -85
  61. package/lib-commonjs/components/Option/useOptionStyles.styles.js.map +1 -1
  62. package/lib-commonjs/contexts/useComboboxContextValues.js +13 -5
  63. package/lib-commonjs/contexts/useComboboxContextValues.js.map +1 -1
  64. package/lib-commonjs/contexts/useListboxContextValues.js +13 -5
  65. package/lib-commonjs/contexts/useListboxContextValues.js.map +1 -1
  66. package/lib-commonjs/utils/dropdownKeyActions.js +3 -30
  67. package/lib-commonjs/utils/dropdownKeyActions.js.map +1 -1
  68. package/lib-commonjs/utils/useComboboxBaseState.js +52 -14
  69. package/lib-commonjs/utils/useComboboxBaseState.js.map +1 -1
  70. package/lib-commonjs/utils/useOptionCollection.js +18 -45
  71. package/lib-commonjs/utils/useOptionCollection.js.map +1 -1
  72. package/lib-commonjs/utils/useTriggerSlot.js +84 -31
  73. package/lib-commonjs/utils/useTriggerSlot.js.map +1 -1
  74. package/package.json +9 -8
  75. package/lib/utils/useScrollOptionsIntoView.js +0 -29
  76. package/lib/utils/useScrollOptionsIntoView.js.map +0 -1
  77. package/lib-commonjs/utils/useScrollOptionsIntoView.js +0 -40
  78. 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 nodes = React.useRef([]);
5
+ const optionsById = React.useRef(new Map());
6
6
  const collectionAPI = React.useMemo(()=>{
7
- const getCount = ()=>nodes.current.length;
8
- const getOptionAtIndex = (index)=>{
9
- var _nodes_current_index;
10
- return (_nodes_current_index = nodes.current[index]) === null || _nodes_current_index === void 0 ? void 0 : _nodes_current_index.option;
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
- const item = nodes.current.find((node)=>node.option.id === id);
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 nodes.current.filter((node)=>matcher(node.option.text)).map((node)=>node.option);
15
+ return Array.from(optionsById.current.values()).filter(({ text })=>matcher(text));
19
16
  };
20
17
  const getOptionsMatchingValue = (matcher)=>{
21
- return nodes.current.filter((node)=>matcher(node.option.value)).map((node)=>node.option);
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, element)=>{
33
- var _nodes_current_index;
34
- const index = nodes.current.findIndex((node)=>{
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: nodes.current.map((node)=>node.option),
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 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"],"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"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAG/B;;CAEC,GACD,OAAO,MAAMC,sBAAsB;IACjC,MAAMC,QAAQF,MAAMG,MAAM,CAAkD,EAAE;IAE9E,MAAMC,gBAAgBJ,MAAMK,OAAO,CAAC;QAClC,MAAMC,WAAW,IAAMJ,MAAMK,OAAO,CAACC,MAAM;QAC3C,MAAMC,mBAAmB,CAACC;gBAAkBR;oBAAAA,uBAAAA,MAAMK,OAAO,CAACG,MAAM,cAApBR,2CAAAA,qBAAsBS,MAAM;;QACxE,MAAMC,eAAe,CAACC,KAAeX,MAAMK,OAAO,CAACO,SAAS,CAACC,CAAAA,OAAQA,KAAKJ,MAAM,CAACE,EAAE,KAAKA;QACxF,MAAMG,gBAAgB,CAACH;YACrB,MAAMI,OAAOf,MAAMK,OAAO,CAACW,IAAI,CAACH,CAAAA,OAAQA,KAAKJ,MAAM,CAACE,EAAE,KAAKA;YAC3D,OAAOI,iBAAAA,2BAAAA,KAAMN,MAAM;QACrB;QACA,MAAMQ,yBAAyB,CAACC;YAC9B,OAAOlB,MAAMK,OAAO,CAACc,MAAM,CAACN,CAAAA,OAAQK,QAAQL,KAAKJ,MAAM,CAACW,IAAI,GAAGC,GAAG,CAACR,CAAAA,OAAQA,KAAKJ,MAAM;QACxF;QACA,MAAMa,0BAA0B,CAACJ;YAC/B,OAAOlB,MAAMK,OAAO,CAACc,MAAM,CAACN,CAAAA,OAAQK,QAAQL,KAAKJ,MAAM,CAACc,KAAK,GAAGF,GAAG,CAACR,CAAAA,OAAQA,KAAKJ,MAAM;QACzF;QAEA,OAAO;YACLL;YACAG;YACAG;YACAI;YACAG;YACAK;QACF;IACF,GAAG,EAAE;IAEL,MAAME,iBAAiB1B,MAAM2B,WAAW,CAAC,CAAChB,QAAqBiB;YAgBzD1B;QAfJ,MAAMQ,QAAQR,MAAMK,OAAO,CAACO,SAAS,CAACC,CAAAA;YACpC,IAAI,CAACA,KAAKa,OAAO,IAAI,CAACA,SAAS;gBAC7B,OAAO;YACT;YAEA,IAAIb,KAAKJ,MAAM,CAACE,EAAE,KAAKF,OAAOE,EAAE,EAAE;gBAChC,OAAO;YACT;YAEA,gGAAgG;YAChG,sCAAsC;YACtC,OAAOE,KAAKa,OAAO,CAACC,uBAAuB,CAACD,WAAWE,KAAKC,2BAA2B;QACzF;QAEA,kDAAkD;QAClD,IAAI7B,EAAAA,uBAAAA,MAAMK,OAAO,CAACG,MAAM,cAApBR,2CAAAA,qBAAsBS,MAAM,CAACE,EAAE,MAAKF,OAAOE,EAAE,EAAE;YACjD,MAAMmB,UAAU;gBACdJ;gBACAjB;YACF;YAEA,gEAAgE;YAChE,IAAID,UAAU,CAAC,GAAG;gBAChBR,MAAMK,OAAO,GAAG;uBAAIL,MAAMK,OAAO;oBAAEyB;iBAAQ;YAC7C,OAAO;gBACL9B,MAAMK,OAAO,CAAC0B,MAAM,CAACvB,OAAO,GAAGsB;YACjC;QACF;QAEA,iCAAiC;QACjC,OAAO;YACL9B,MAAMK,OAAO,GAAGL,MAAMK,OAAO,CAACc,MAAM,CAACN,CAAAA,OAAQA,KAAKJ,MAAM,CAACE,EAAE,KAAKF,OAAOE,EAAE;QAC3E;IACF,GAAG,EAAE;IAEL,OAAO;QACL,GAAGT,aAAa;QAChB8B,SAAShC,MAAMK,OAAO,CAACgB,GAAG,CAACR,CAAAA,OAAQA,KAAKJ,MAAM;QAC9Ce;IACF;AACF,EAAE"}
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 { mergeCallbacks, slot, useMergedRefs } from '@fluentui/react-utilities';
3
- import { getDropdownActionFromKey, getIndexFromAction } from '../utils/dropdownKeyActions';
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: { activeOption, getCount, getIndexOfId, getOptionAtIndex, open, selectOption, setActiveOption, setFocusVisible, setOpen, multiselect, setHasFocus }, defaultProps, elementType } = options;
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((event)=>{
37
- const action = getDropdownActionFromKey(event, {
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 maxIndex = getCount() - 1;
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
- event.preventDefault();
47
- setFocusVisible(true);
48
- setOpen(event, true);
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
- event.stopPropagation();
53
- event.preventDefault();
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(event, false);
124
+ !multiselect && !(activeOption === null || activeOption === void 0 ? void 0 : activeOption.disabled) && setOpen(e, false);
58
125
  // fallthrough
59
126
  case 'Select':
60
- activeOption && selectOption(event, activeOption);
61
- event.preventDefault();
127
+ activeOption && selectOption(e, activeOption);
62
128
  break;
63
129
  case 'Tab':
64
- !multiselect && activeOption && selectOption(event, activeOption);
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
- }, trigger.onKeyDown);
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, getIndexFromAction } from '../utils/dropdownKeyActions';\nimport type { ComboboxBaseState } from './ComboboxBase.types';\n\nexport type UseTriggerSlotState = Pick<\n ComboboxBaseState,\n | 'activeOption'\n | 'getCount'\n | 'getIndexOfId'\n | 'getOptionAtIndex'\n | 'open'\n | 'selectOption'\n | 'setActiveOption'\n | 'setFocusVisible'\n | 'setOpen'\n | 'multiselect'\n | 'value'\n | 'setHasFocus'\n>;\n\ntype UseTriggerSlotOptions = {\n state: UseTriggerSlotState;\n defaultProps: unknown;\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: {\n activeOption,\n getCount,\n getIndexOfId,\n getOptionAtIndex,\n open,\n selectOption,\n setActiveOption,\n setFocusVisible,\n setOpen,\n multiselect,\n setHasFocus,\n },\n defaultProps,\n elementType,\n } = options;\n\n const trigger = slot.always(triggerSlotFromProp, {\n defaultProps: {\n type: 'text',\n 'aria-expanded': open,\n 'aria-activedescendant': open ? activeOption?.id : undefined,\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 (event: React.KeyboardEvent<HTMLButtonElement> & React.KeyboardEvent<HTMLInputElement>) => {\n const action = getDropdownActionFromKey(event, { open, multiselect });\n const maxIndex = getCount() - 1;\n const activeIndex = activeOption ? getIndexOfId(activeOption.id) : -1;\n let newIndex = activeIndex;\n\n switch (action) {\n case 'Open':\n event.preventDefault();\n setFocusVisible(true);\n setOpen(event, true);\n break;\n case 'Close':\n // stop propagation for escape key to avoid dismissing any parent popups\n event.stopPropagation();\n event.preventDefault();\n setOpen(event, false);\n break;\n case 'CloseSelect':\n !multiselect && !activeOption?.disabled && setOpen(event, false);\n // fallthrough\n case 'Select':\n activeOption && selectOption(event, activeOption);\n event.preventDefault();\n break;\n case 'Tab':\n !multiselect && activeOption && selectOption(event, activeOption);\n break;\n default:\n newIndex = getIndexFromAction(action, activeIndex, maxIndex);\n }\n if (newIndex !== activeIndex) {\n // prevent default page scroll/keyboard action if the index changed\n event.preventDefault();\n setActiveOption(getOptionAtIndex(newIndex));\n setFocusVisible(true);\n }\n },\n trigger.onKeyDown,\n );\n\n trigger.onMouseOver = mergeCallbacks(\n (event: React.MouseEvent<HTMLButtonElement> & React.MouseEvent<HTMLInputElement>) => {\n setFocusVisible(false);\n },\n trigger.onMouseOver,\n );\n\n // TODO fix cast\n return trigger as SlotComponentType<ExtractSlotProps<Slot<'input'>>>;\n}\n"],"names":["React","mergeCallbacks","slot","useMergedRefs","getDropdownActionFromKey","getIndexFromAction","useTriggerSlot","triggerSlotFromProp","ref","options","state","activeOption","getCount","getIndexOfId","getOptionAtIndex","open","selectOption","setActiveOption","setFocusVisible","setOpen","multiselect","setHasFocus","defaultProps","elementType","trigger","always","type","id","undefined","role","triggerRef","useRef","onBlur","event","onFocus","target","currentTarget","onClick","onKeyDown","action","maxIndex","activeIndex","newIndex","preventDefault","stopPropagation","disabled","onMouseOver"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,cAAc,EAAEC,IAAI,EAAEC,aAAa,QAAQ,4BAA4B;AAEhF,SAASC,wBAAwB,EAAEC,kBAAkB,QAAQ,8BAA8B;AAoC3F;;;CAGC,GACD,OAAO,SAASC,eACdC,mBAA6E,EAC7EC,GAA+D,EAC/DC,OAAoE;IAEpE,MAAM,EACJC,OAAO,EACLC,YAAY,EACZC,QAAQ,EACRC,YAAY,EACZC,gBAAgB,EAChBC,IAAI,EACJC,YAAY,EACZC,eAAe,EACfC,eAAe,EACfC,OAAO,EACPC,WAAW,EACXC,WAAW,EACZ,EACDC,YAAY,EACZC,WAAW,EACZ,GAAGd;IAEJ,MAAMe,UAAUtB,KAAKuB,MAAM,CAAClB,qBAAqB;QAC/Ce,cAAc;YACZI,MAAM;YACN,iBAAiBX;YACjB,yBAAyBA,OAAOJ,yBAAAA,mCAAAA,aAAcgB,EAAE,GAAGC;YACnDC,MAAM;YACN,GAAI,OAAOP,iBAAiB,YAAYA,YAAY;QACtD;QACAC;IACF;IAEA,4BAA4B;IAC5B,MAAMO,aAAa9B,MAAM+B,MAAM,CAAuC;IACtEP,QAAQhB,GAAG,GAAGL,cAAc2B,YAAYN,QAAQhB,GAAG,EAAEA;IAErD,2DAA2D;IAC3DgB,QAAQQ,MAAM,GAAG/B,eAAe,CAACgC;QAC/Bd,QAAQc,OAAO;QACfZ,YAAY;IACd,GAAGG,QAAQQ,MAAM;IAEjBR,QAAQU,OAAO,GAAGjC,eAChB,CAACgC;QACC,IAAIA,MAAME,MAAM,KAAKF,MAAMG,aAAa,EAAE;YACxCf,YAAY;QACd;IACF,GACAG,QAAQU,OAAO;IAEjBV,QAAQa,OAAO,GAAGpC,eAChB,CAACgC;QACCd,QAAQc,OAAO,CAAClB;IAClB,GACAS,QAAQa,OAAO;IAGjB,uCAAuC;IACvCb,QAAQc,SAAS,GAAGrC,eAClB,CAACgC;QACC,MAAMM,SAASnC,yBAAyB6B,OAAO;YAAElB;YAAMK;QAAY;QACnE,MAAMoB,WAAW5B,aAAa;QAC9B,MAAM6B,cAAc9B,eAAeE,aAAaF,aAAagB,EAAE,IAAI,CAAC;QACpE,IAAIe,WAAWD;QAEf,OAAQF;YACN,KAAK;gBACHN,MAAMU,cAAc;gBACpBzB,gBAAgB;gBAChBC,QAAQc,OAAO;gBACf;YACF,KAAK;gBACH,wEAAwE;gBACxEA,MAAMW,eAAe;gBACrBX,MAAMU,cAAc;gBACpBxB,QAAQc,OAAO;gBACf;YACF,KAAK;gBACH,CAACb,eAAe,EAACT,yBAAAA,mCAAAA,aAAckC,QAAQ,KAAI1B,QAAQc,OAAO;YAC5D,cAAc;YACd,KAAK;gBACHtB,gBAAgBK,aAAaiB,OAAOtB;gBACpCsB,MAAMU,cAAc;gBACpB;YACF,KAAK;gBACH,CAACvB,eAAeT,gBAAgBK,aAAaiB,OAAOtB;gBACpD;YACF;gBACE+B,WAAWrC,mBAAmBkC,QAAQE,aAAaD;QACvD;QACA,IAAIE,aAAaD,aAAa;YAC5B,mEAAmE;YACnER,MAAMU,cAAc;YACpB1B,gBAAgBH,iBAAiB4B;YACjCxB,gBAAgB;QAClB;IACF,GACAM,QAAQc,SAAS;IAGnBd,QAAQsB,WAAW,GAAG7C,eACpB,CAACgC;QACCf,gBAAgB;IAClB,GACAM,QAAQsB,WAAW;IAGrB,gBAAgB;IAChB,OAAOtB;AACT"}
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.jsxs)(_ComboboxContext.ComboboxContext.Provider, {
19
- value: contextValues.combobox,
20
- children: [
21
- /*#__PURE__*/ (0, _jsxruntime.jsx)(state.input, {}),
22
- state.clearIcon && /*#__PURE__*/ (0, _jsxruntime.jsx)(state.clearIcon, {}),
23
- /*#__PURE__*/ (0, _jsxruntime.jsx)(state.expandIcon, {}),
24
- state.listbox && (state.inlinePopup ? /*#__PURE__*/ (0, _jsxruntime.jsx)(state.listbox, {}) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactportal.Portal, {
25
- mountNode: state.mountNode,
26
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(state.listbox, {})
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 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"],"names":["renderCombobox_unstable","state","contextValues","assertSlots","_jsx","root","children","_jsxs","ComboboxContext","Provider","value","combobox","input","clearIcon","expandIcon","listbox","inlinePopup","Portal","mountNode"],"mappings":";;;;+BAMiBA;;;eAAAA;;;4BAN4B;6BACtB;gCACK;iCACI;AAGrB,MAAMA,0BAA0B,CAACC,OAAOC;IAC/CC,IAAAA,2BAAW,EAACF;IACZ,OAAO,WAAW,GAAGG,IAAAA,eAAI,EAACH,MAAMI,IAAI,EAAE;QAClCC,UAAU,WAAW,GAAGC,IAAAA,gBAAK,EAACC,gCAAe,CAACC,QAAQ,EAAE;YACpDC,OAAOR,cAAcS,QAAQ;YAC7BL,UAAU;gBACN,WAAW,GAAGF,IAAAA,eAAI,EAACH,MAAMW,KAAK,EAAE,CAAC;gBACjCX,MAAMY,SAAS,IAAI,WAAW,GAAGT,IAAAA,eAAI,EAACH,MAAMY,SAAS,EAAE,CAAC;gBACxD,WAAW,GAAGT,IAAAA,eAAI,EAACH,MAAMa,UAAU,EAAE,CAAC;gBACtCb,MAAMc,OAAO,IAAKd,CAAAA,MAAMe,WAAW,GAAG,WAAW,GAAGZ,IAAAA,eAAI,EAACH,MAAMc,OAAO,EAAE,CAAC,KAAK,WAAW,GAAGX,IAAAA,eAAI,EAACa,mBAAM,EAAE;oBACrGC,WAAWjB,MAAMiB,SAAS;oBAC1BZ,UAAU,WAAW,GAAGF,IAAAA,eAAI,EAACH,MAAMc,OAAO,EAAE,CAAC;gBACjD,EAAC;aACJ;QACL;IACJ;AACJ"}
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, activeOption, selectOption, setValue, setActiveOption, setFocusVisible, multiselect, selectedOptions, clearSelection, getOptionsMatchingText, getIndexOfId, setOpen }, freeform, defaultProps } = options;
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 matches = getOptionsMatchingText(matcher);
37
- // return first matching option after the current active option, looping back to the top
38
- if (matches.length > 1 && activeOption) {
39
- const startIndex = getIndexOfId(activeOption.id);
40
- const nextMatch = matches.find((option)=>getIndexOfId(option.id) >= startIndex);
41
- return nextMatch !== null && nextMatch !== void 0 ? nextMatch : matches[0];
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
- var _matches_;
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);