@sproutsocial/seeds-react-menu 0.5.0 → 0.6.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 (103) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +15 -0
  3. package/dist/esm/index.js +1486 -440
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/index.d.mts +248 -92
  6. package/dist/index.d.ts +248 -92
  7. package/dist/index.js +1500 -429
  8. package/dist/index.js.map +1 -1
  9. package/package.json +4 -1
  10. package/src/ActionMenu/ActionMenu.stories.tsx +426 -0
  11. package/src/ActionMenu/ActionMenu.tsx +24 -27
  12. package/src/ActionMenu/ActionMenuTypes.ts +8 -7
  13. package/src/ActionMenu/__tests__/ActionMenu.test.tsx +17 -8
  14. package/src/ActionMenu/__tests__/ActionMenu.typetest.tsx +8 -8
  15. package/src/Autocomplete/Autocomplete.stories.tsx +38 -3
  16. package/src/Autocomplete/Autocomplete.tsx +15 -80
  17. package/src/Autocomplete/AutocompleteInput.tsx +18 -27
  18. package/src/Autocomplete/AutocompleteTokenInput.tsx +50 -0
  19. package/src/Autocomplete/AutocompleteTypes.ts +25 -12
  20. package/src/Autocomplete/MultiAutocomplete.tsx +189 -0
  21. package/src/Autocomplete/SingleAutocomplete.tsx +74 -0
  22. package/src/Autocomplete/__tests__/Autocomplete.test.tsx +171 -3
  23. package/src/Autocomplete/__tests__/Autocomplete.typetest.tsx +90 -8
  24. package/src/MenuContent/MenuContent.stories.tsx +164 -0
  25. package/src/MenuContent/MenuContent.tsx +26 -12
  26. package/src/MenuContent/MenuContentTypes.ts +6 -4
  27. package/src/MenuContent/__tests__/MenuContent.typetest.tsx +8 -8
  28. package/src/MenuContext.tsx +191 -37
  29. package/src/MenuFooter/MenuFooter.stories.tsx +202 -0
  30. package/src/MenuFooter/__tests__/MenuFooter.test.tsx +16 -11
  31. package/src/MenuGroup/MenuGroup.feature +16 -16
  32. package/src/MenuGroup/MenuGroup.stories.tsx +248 -0
  33. package/src/MenuGroup/MenuGroup.tsx +8 -7
  34. package/src/MenuGroup/MenuGroupTypes.ts +6 -2
  35. package/src/MenuGroup/__tests__/MenuGroup.test.tsx +6 -6
  36. package/src/MenuGroup/__tests__/MenuGroup.typetest.tsx +7 -7
  37. package/src/MenuGroup/styles.tsx +4 -2
  38. package/src/MenuHeader/MenuHeader.stories.tsx +276 -0
  39. package/src/MenuHeader/MenuHeader.tsx +3 -1
  40. package/src/MenuHeader/__tests__/MenuHeader.test.tsx +23 -13
  41. package/src/MenuHeader/styles.tsx +18 -14
  42. package/src/MenuItem/MenuItem.stories.tsx +507 -0
  43. package/src/MenuItem/MenuItem.tsx +18 -8
  44. package/src/MenuItem/MenuItemTypes.ts +9 -4
  45. package/src/MenuItem/__tests__/MenuItem.test.tsx +6 -6
  46. package/src/MenuItem/styles.tsx +21 -5
  47. package/src/MenuItem/useOptionProps.tsx +10 -8
  48. package/src/MenuLabel.tsx +2 -2
  49. package/src/MenuRoot/MenuRoot.tsx +37 -23
  50. package/src/MenuRoot/__tests__/MenuRoot.test.tsx +59 -32
  51. package/src/MenuSearchInput/MenuSearchInput.tsx +63 -0
  52. package/src/MenuSearchInput/__tests__/MenuSearchInput.test.tsx +157 -0
  53. package/src/MenuSearchInput/__tests__/MenuSearchInput.typetest.tsx +31 -0
  54. package/src/MenuSearchInput/index.ts +1 -0
  55. package/src/MenuSearchTokenInput/MenuSearchTokenInput.tsx +98 -0
  56. package/src/MenuSearchTokenInput/__tests__/MenuSearchTokenInput.test.tsx +247 -0
  57. package/src/MenuSearchTokenInput/__tests__/MenuSearchTokenInput.typetest.tsx +33 -0
  58. package/src/MenuSearchTokenInput/index.ts +1 -0
  59. package/src/MenuToggleButton/MenuToggleButton.stories.tsx +72 -0
  60. package/src/{MenuToggleButton.tsx → MenuToggleButton/MenuToggleButton.tsx} +6 -5
  61. package/src/MenuToggleButton/index.ts +1 -0
  62. package/src/MenuTokenInput.tsx +104 -0
  63. package/src/MultiSelectMenu/MultiSelectMenu.stories.tsx +214 -0
  64. package/src/MultiSelectMenu/MultiSelectMenu.tsx +38 -68
  65. package/src/MultiSelectMenu/MultiSelectMenuTypes.ts +8 -6
  66. package/src/MultiSelectMenu/__tests__/MultiSelectMenu.test.tsx +46 -17
  67. package/src/MultiSelectMenu/__tests__/MultiSelectMenu.typetest.tsx +6 -6
  68. package/src/NestedMenu/NestedMenu.feature +109 -0
  69. package/src/NestedMenu/NestedMenu.stories.tsx +157 -0
  70. package/src/NestedMenu/NestedMenu.tsx +102 -0
  71. package/src/NestedMenu/NestedMenuContent.tsx +71 -0
  72. package/src/NestedMenu/NestedMenuContext.tsx +56 -0
  73. package/src/NestedMenu/NestedMenuHeader.tsx +25 -0
  74. package/src/NestedMenu/NestedMenuItem.tsx +37 -0
  75. package/src/NestedMenu/NestedMenuTypes.ts +47 -0
  76. package/src/NestedMenu/__tests__/NestedMenu.test.tsx +31 -0
  77. package/src/NestedMenu/__tests__/NestedMenu.typetest.tsx +134 -0
  78. package/src/NestedMenu/index.ts +5 -0
  79. package/src/SingleSelectMenu/SingleSelectMenu.stories.tsx +227 -0
  80. package/src/SingleSelectMenu/SingleSelectMenu.tsx +23 -26
  81. package/src/SingleSelectMenu/SingleSelectMenuTypes.ts +7 -5
  82. package/src/SingleSelectMenu/__tests__/SingleSelectMenu.typetest.tsx +6 -6
  83. package/src/SubmenuItem/SubmenuItem.feature +82 -0
  84. package/src/SubmenuItem/SubmenuItem.stories.tsx +163 -0
  85. package/src/SubmenuItem/SubmenuItem.tsx +254 -0
  86. package/src/SubmenuItem/SubmenuItemTypes.ts +24 -0
  87. package/src/SubmenuItem/__tests__/SubmenuItem.test.tsx +3 -0
  88. package/src/SubmenuItem/__tests__/SubmenuItem.typetest.tsx +112 -0
  89. package/src/SubmenuItem/index.ts +2 -0
  90. package/src/hooks/useDownshiftDefaults.tsx +107 -0
  91. package/src/hooks/useItemFiltering.tsx +66 -0
  92. package/src/hooks/useMenuChildren.tsx +197 -128
  93. package/src/index.ts +6 -0
  94. package/src/menuTestingUtils.tsx +21 -10
  95. package/src/reducers/nestedMenuStateReducer.tsx +23 -0
  96. package/src/reducers/useComboboxStateReducer.tsx +26 -8
  97. package/src/reducers/useSelectStateReducer.tsx +24 -6
  98. package/src/storybookUtilities/menu-storybook-components.tsx +5 -3
  99. package/src/types.ts +38 -30
  100. package/src/utils/downshiftDefaults.ts +9 -0
  101. package/src/utils/getMultiSelectOverrides.ts +21 -0
  102. package/src/utils/reduceReducers.ts +19 -0
  103. package/src/utils/itemToString.ts +0 -5
package/dist/index.js CHANGED
@@ -108,48 +108,85 @@ __export(index_exports, {
108
108
  AutocompleteInput: () => AutocompleteInput,
109
109
  INPUT_TYPES: () => INPUT_TYPES,
110
110
  MenuContent: () => MenuContent,
111
- MenuContext: () => MenuContext,
111
+ MenuContentContext: () => MenuContentContext,
112
+ MenuContentProvider: () => MenuContentProvider,
112
113
  MenuFooter: () => MenuFooter,
113
114
  MenuGroup: () => MenuGroup,
114
115
  MenuHeader: () => MenuHeader,
115
116
  MenuItem: () => MenuItem,
116
117
  MenuItemAction: () => MenuItemAction,
118
+ MenuItemActionLeft: () => MenuItemActionLeft,
119
+ MenuItemActionRight: () => MenuItemActionRight,
117
120
  MenuItemContainer: () => MenuItemContainer,
118
121
  MenuItemRow: () => MenuItemRow,
119
122
  MenuItemText: () => MenuItemText,
120
123
  MenuLabel: () => MenuLabel,
121
- MenuProvider: () => MenuProvider,
122
124
  MenuRoot: () => MenuRoot,
125
+ MenuSearchInput: () => MenuSearchInput,
126
+ MenuSearchTokenInput: () => MenuSearchTokenInput,
123
127
  MenuToggleButton: () => MenuToggleButton,
128
+ MenuToggleContext: () => MenuToggleContext,
129
+ MenuToggleProvider: () => MenuToggleProvider,
130
+ MenuTokenInput: () => MenuTokenInput,
124
131
  MultiSelectMenu: () => MultiSelectMenu,
132
+ NestedMenu: () => NestedMenu,
133
+ NestedMenuContent: () => NestedMenuContent,
134
+ NestedMenuContext: () => NestedMenuContext,
135
+ NestedMenuHeader: () => NestedMenuHeader,
136
+ NestedMenuItem: () => NestedMenuItem,
137
+ NestedMenuProvider: () => NestedMenuProvider,
125
138
  SingleSelectMenu: () => SingleSelectMenu,
126
139
  StyledMenuGroup: () => StyledMenuGroup,
127
140
  StyledMenuGroupUl: () => StyledMenuGroupUl,
128
141
  StyledMenuItem: () => StyledMenuItem,
129
142
  StyledTitle: () => StyledTitle,
130
- defaultUseSelectProps: () => defaultUseSelectProps,
143
+ SubmenuItem: () => SubmenuItem,
144
+ checkIfItemSelected: () => checkIfItemSelected,
145
+ defaultMenuContext: () => defaultMenuContext,
146
+ getChildrenFromMenuItems: () => getChildrenFromMenuItems,
147
+ getSelectedItemIds: () => getSelectedItemIds,
131
148
  mapMenuItems: () => mapMenuItems,
132
149
  useMenu: () => useMenu,
133
150
  useMenuChildren: () => useMenuChildren,
134
- useMenuContext: () => useMenuContext,
135
- useSelectStateReducer: () => useSelectStateReducer
151
+ useMenuContentContext: () => useMenuContentContext,
152
+ useMenuToggleContext: () => useMenuToggleContext,
153
+ useNestedMenuContext: () => useNestedMenuContext,
154
+ useSelectStateReducer: () => useSelectStateReducer,
155
+ useSelectStateReducerForMulti: () => useSelectStateReducerForMulti
136
156
  });
137
157
  module.exports = __toCommonJS(index_exports);
138
158
 
139
159
  // src/MenuContext.tsx
140
- var import_react = require("react");
160
+ var import_react = __toESM(require("react"));
141
161
  var import_jsx_runtime = require("react/jsx-runtime");
142
162
  var defaultMenuContext = {
143
163
  items: [],
144
- itemsMap: {}
145
- };
164
+ itemsMap: {},
165
+ isItemSelected: () => false,
166
+ getInputComponentProps: () => ({})
167
+ };
168
+ var getSelectedItemIds = (selectedItems) => selectedItems?.reduce(
169
+ (selected, item) => ({ ...selected, [item.id]: true }),
170
+ {}
171
+ );
172
+ var checkIfItemSelected = ({
173
+ id,
174
+ selectedItem,
175
+ selectedItemIds
176
+ }) => selectedItemIds ? !!selectedItemIds[id] : selectedItem?.id === id;
146
177
  var useMenu = ({
147
178
  items = [],
148
179
  isListbox = false,
149
180
  isOpen = false,
150
181
  itemsMap: itemsMapFromProps,
182
+ selectedItemIds: selectedItemIdsFromProps,
183
+ selectedItem,
184
+ selectedItems,
185
+ getInputProps,
186
+ contentRef: contentRefFromProps,
151
187
  ...rest
152
188
  } = {}) => {
189
+ const contentRef = contentRefFromProps || import_react.default.createRef();
153
190
  const menuProps = (0, import_react.useMemo)(() => ({ ...rest }), [rest]);
154
191
  const itemsMap = (0, import_react.useMemo)(
155
192
  () => itemsMapFromProps || items.reduce((map, item) => {
@@ -160,27 +197,90 @@ var useMenu = ({
160
197
  }, {}),
161
198
  [items, itemsMapFromProps]
162
199
  );
200
+ const selectedItemIds = (0, import_react.useMemo)(
201
+ () => selectedItemIdsFromProps || getSelectedItemIds(selectedItems),
202
+ [selectedItems, selectedItemIdsFromProps]
203
+ );
204
+ const isItemSelected = import_react.default.useCallback(
205
+ (id) => checkIfItemSelected({ id, selectedItem, selectedItemIds }),
206
+ [selectedItem, selectedItemIds]
207
+ );
208
+ const getInputComponentProps = import_react.default.useCallback(
209
+ ({ inputProps, ...props }) => {
210
+ if (!getInputProps) return {};
211
+ const {
212
+ ["aria-activedescendant"]: activedescendant,
213
+ ["aria-autocomplete"]: autocomplete,
214
+ ["aria-controls"]: controls,
215
+ ["aria-expanded"]: expanded,
216
+ ["aria-labelledby"]: labelledby,
217
+ role,
218
+ autoComplete,
219
+ onClick,
220
+ value,
221
+ ...restProps
222
+ } = getInputProps(props);
223
+ return {
224
+ ...restProps,
225
+ inputProps: {
226
+ ["aria-activedescendant"]: activedescendant,
227
+ ["aria-autocomplete"]: autocomplete,
228
+ ["aria-controls"]: controls,
229
+ ["aria-expanded"]: expanded,
230
+ ["aria-labelledby"]: labelledby,
231
+ role,
232
+ autoComplete,
233
+ onClick,
234
+ value,
235
+ ...inputProps
236
+ }
237
+ };
238
+ },
239
+ [getInputProps]
240
+ );
163
241
  return {
164
242
  isOpen,
165
243
  isListbox,
166
244
  items,
167
245
  itemsMap,
246
+ selectedItem,
247
+ selectedItems,
248
+ selectedItemIds,
249
+ isItemSelected,
250
+ getInputProps,
251
+ getInputComponentProps,
252
+ contentRef,
168
253
  ...menuProps
169
254
  };
170
255
  };
171
- var MenuContext = (0, import_react.createContext)(defaultMenuContext);
172
- var MenuProvider = ({
256
+ var MenuToggleContext = (0, import_react.createContext)(defaultMenuContext);
257
+ var MenuToggleProvider = ({
258
+ children,
259
+ menuContext
260
+ }) => {
261
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuToggleContext.Provider, { value: { ...menuContext }, children });
262
+ };
263
+ var useMenuToggleContext = () => {
264
+ const menuContextValue = (0, import_react.useContext)(MenuToggleContext);
265
+ if (menuContextValue === null) {
266
+ throw new Error(
267
+ "useMenuToggleContext must be used within a <MenuToggleContext.Provider />"
268
+ );
269
+ }
270
+ return menuContextValue;
271
+ };
272
+ var MenuContentContext = (0, import_react.createContext)(defaultMenuContext);
273
+ var MenuContentProvider = ({
173
274
  children,
174
- menuProps
275
+ menuContext
175
276
  }) => {
176
- const filterContext = useMenu(menuProps);
177
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuContext.Provider, { value: { ...filterContext }, children });
277
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MenuContentContext.Provider, { value: { ...menuContext }, children });
178
278
  };
179
- var useMenuContext = () => {
180
- const menuContextValue = (0, import_react.useContext)(MenuContext);
279
+ var useMenuContentContext = () => {
280
+ const menuContextValue = (0, import_react.useContext)(MenuContentContext);
181
281
  if (menuContextValue === null) {
182
282
  throw new Error(
183
- "useMenuContext must be used within a <MenuContext.Provider />"
283
+ "useMenuContentContext must be used within a <MenuContentContext.Provider />"
184
284
  );
185
285
  }
186
286
  return menuContextValue;
@@ -1723,6 +1823,10 @@ var highlightedStyles = import_styled_components2.css`
1723
1823
  color: ${({ theme: theme2 }) => theme2.colors.text.body};
1724
1824
  text-decoration: none;
1725
1825
  `;
1826
+ var activeStyles = import_styled_components2.css`
1827
+ background-color: ${({ theme: theme2 }) => theme2.colors.listItem.background.active};
1828
+ color: ${({ theme: theme2 }) => theme2.colors.text.inverse};
1829
+ `;
1726
1830
  var MenuItemContainer = import_styled_components2.default.li`
1727
1831
  box-sizing: border-box;
1728
1832
  list-style-type: none;
@@ -1737,7 +1841,7 @@ var MenuItemContainer = import_styled_components2.default.li`
1737
1841
  margin-bottom: ${({ theme: theme2 }) => theme2.space[300]};
1738
1842
  }
1739
1843
  `;
1740
- var StyledMenuItem = import_styled_components2.default.div`
1844
+ var StyledMenuItem = import_styled_components2.default.button`
1741
1845
  display: block;
1742
1846
  box-sizing: border-box;
1743
1847
  width: 100%;
@@ -1776,10 +1880,12 @@ var StyledMenuItem = import_styled_components2.default.div`
1776
1880
  ${focusRing}
1777
1881
  }
1778
1882
 
1883
+ /* Active */
1884
+ ${({ $active }) => $active && activeStyles}
1885
+
1779
1886
  /* Pressed state*/
1780
1887
  &:active {
1781
- background-color: ${({ theme: theme2 }) => theme2.colors.listItem.background.active};
1782
- color: ${({ theme: theme2 }) => theme2.colors.text.inverse};
1888
+ ${activeStyles}
1783
1889
  }
1784
1890
 
1785
1891
  &[aria-disabled="true"] {
@@ -1800,12 +1906,17 @@ var MenuItemRow = import_styled_components2.default.div`
1800
1906
  pointer-events: none;
1801
1907
  `;
1802
1908
  var MenuItemAction = import_styled_components2.default.div`
1803
- margin-right: ${({ theme: theme2 }) => theme2.space[300]};
1804
1909
  display: flex;
1805
1910
  align-items: center;
1806
1911
  justify-content: center;
1807
1912
  flex-shrink: 0;
1808
1913
  `;
1914
+ var MenuItemActionLeft = (0, import_styled_components2.default)(MenuItemAction)`
1915
+ margin-right: ${({ theme: theme2 }) => theme2.space[300]};
1916
+ `;
1917
+ var MenuItemActionRight = (0, import_styled_components2.default)(MenuItemAction)`
1918
+ margin-left: ${({ theme: theme2 }) => theme2.space[300]};
1919
+ `;
1809
1920
  var MenuItemText = import_styled_components2.default.div`
1810
1921
  word-break: break-word;
1811
1922
  flex-grow: 1;
@@ -1836,6 +1947,7 @@ var SelectionIndicator = ({
1836
1947
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1837
1948
  import_seeds_react_checkbox2.Checkbox,
1838
1949
  {
1950
+ tabIndex: -1,
1839
1951
  onChange: () => {
1840
1952
  },
1841
1953
  checked: selected,
@@ -1847,6 +1959,7 @@ var SelectionIndicator = ({
1847
1959
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1848
1960
  import_seeds_react_switch.Switch,
1849
1961
  {
1962
+ tabIndex: -1,
1850
1963
  onClick: inputStub,
1851
1964
  checked: !!selected,
1852
1965
  "aria-labelledby": labeledBy,
@@ -1857,6 +1970,7 @@ var SelectionIndicator = ({
1857
1970
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1858
1971
  import_seeds_react_radio.Radio,
1859
1972
  {
1973
+ tabIndex: -1,
1860
1974
  checked: selected,
1861
1975
  id: `MenuItem-${inputType}-${id}`,
1862
1976
  name: `MenuItem-${inputType}`,
@@ -1880,9 +1994,9 @@ var useOptionProps = ({
1880
1994
  inputLabelId,
1881
1995
  ...props
1882
1996
  }) => {
1883
- const { selectedItem, selectedItems, isListbox } = (0, import_react2.useContext)(MenuContext);
1997
+ const { selectedItem, selectedItems, isListbox, isItemSelected } = useMenuContentContext();
1884
1998
  const selected = (0, import_react2.useMemo)(
1885
- () => selectedItem?.id === id || !!selectedItems?.find((item) => item?.id === id),
1999
+ () => isItemSelected(id),
1886
2000
  [selectedItem, selectedItems]
1887
2001
  );
1888
2002
  const label = inputLabelId || `menu-item-child-${id}`;
@@ -1890,7 +2004,7 @@ var useOptionProps = ({
1890
2004
  active: selected,
1891
2005
  ["aria-selected"]: selected,
1892
2006
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(MenuItemRow, { children: [
1893
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MenuItemAction, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2007
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MenuItemActionLeft, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1894
2008
  SelectionIndicator,
1895
2009
  {
1896
2010
  id,
@@ -1913,12 +2027,19 @@ var MenuItem = ({
1913
2027
  onClick,
1914
2028
  onKeyDown,
1915
2029
  disabled: disabled2 = false,
1916
- ref,
2030
+ active,
2031
+ innerRef,
1917
2032
  href,
1918
2033
  color: color2,
1919
2034
  ...props
1920
2035
  }) => {
1921
- const { getItemProps, itemsMap, highlightedIndex, isListbox } = useMenuContext();
2036
+ const {
2037
+ getItemProps,
2038
+ itemsMap,
2039
+ highlightedIndex,
2040
+ isListbox,
2041
+ hiddenItemsMap = {}
2042
+ } = useMenuContentContext();
1922
2043
  const { ...optionProps } = useOptionProps({
1923
2044
  id,
1924
2045
  children,
@@ -1926,23 +2047,26 @@ var MenuItem = ({
1926
2047
  });
1927
2048
  const item = itemsMap[id] || { index: 0, id };
1928
2049
  const highlighted = highlightedIndex === item?.index;
1929
- return item.hidden ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuItemContainer, { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2050
+ return hiddenItemsMap[item.id] ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MenuItemContainer, { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1930
2051
  StyledMenuItem,
1931
2052
  {
1932
2053
  id,
1933
2054
  $highlighted: highlighted,
2055
+ $active: active,
1934
2056
  ...getItemProps?.({
1935
2057
  ...isListbox ? {} : { role: "menuitem" },
1936
2058
  item,
1937
2059
  index: item.index,
1938
- // This prop no longer supported in downshift
2060
+ // The disabled prop no longer supported in downshift. Use isItemDisabled instead.
1939
2061
  // disabled,
1940
2062
  onClick,
1941
- onKeyDown
2063
+ onKeyDown,
2064
+ ref: innerRef
1942
2065
  }),
1943
2066
  as: isListbox ? void 0 : href ? "a" : "button",
1944
2067
  href,
1945
2068
  children,
2069
+ tabIndex: -1,
1946
2070
  ...optionProps,
1947
2071
  ...props
1948
2072
  }
@@ -1985,14 +2109,13 @@ var MenuTitleText = import_styled_components4.default.h3`
1985
2109
  color: ${({ theme: theme2 }) => theme2.colors.text.headline};
1986
2110
  font-weight: ${({ theme: theme2 }) => theme2.fontWeights.bold};
1987
2111
  margin: 0px;
1988
- flex-grow: 2;
1989
- justify-self: start;
2112
+ flex-grow: 1;
1990
2113
 
1991
2114
  ${({ theme: theme2 }) => theme2.typography[200]}
1992
2115
 
1993
2116
  ${({ $leftAction, theme: theme2 }) => $leftAction && `
1994
- padding-left: ${theme2.space[350]};
1995
- `}
2117
+ padding-left: ${theme2.space[350]};
2118
+ `}
1996
2119
  `;
1997
2120
  var MenuChildrenContainer = import_styled_components4.default.div`
1998
2121
  grid-column: 1 / -1;
@@ -2000,19 +2123,24 @@ var MenuChildrenContainer = import_styled_components4.default.div`
2000
2123
  `;
2001
2124
  var MenuHeaderFeatures = import_styled_components4.default.div`
2002
2125
  display: flex;
2126
+ align-items: center;
2127
+ justify-content: space-between;
2128
+ width: 100%;
2003
2129
 
2004
- > a {
2005
- white-space: nowrap;
2006
- }
2007
-
2008
- &:first-child {
2009
- flex-grow: 1;
2010
- justify-self: start;
2130
+ .right-action {
2131
+ margin-left: auto; /* Pushes the right action to the right */
2132
+ display: flex;
2133
+ justify-content: flex-end;
2134
+ flex-shrink: 0; /* Prevents it from shrinking */
2135
+ max-width: 40%; /* Prevents it from taking too much space */
2136
+ text-align: right;
2011
2137
  }
2012
2138
 
2013
- &:last-child {
2014
- flex-grow: 1;
2015
- justify-self: end;
2139
+ > a,
2140
+ > button {
2141
+ display: flex;
2142
+ align-items: center;
2143
+ word-break: break-word;
2016
2144
  }
2017
2145
  `;
2018
2146
 
@@ -2029,7 +2157,7 @@ var MenuHeader = ({
2029
2157
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuHeaderFeatures, { $leftAction: !!leftAction, children: [
2030
2158
  leftAction && leftAction,
2031
2159
  title && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuTitleText, { $leftAction: !!leftAction, children: title }),
2032
- rightAction && rightAction
2160
+ rightAction && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "right-action", children: rightAction })
2033
2161
  ] }),
2034
2162
  children && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MenuChildrenContainer, { children })
2035
2163
  ] }) });
@@ -2066,160 +2194,193 @@ var getComponentName = (element) => {
2066
2194
  return element.type.name;
2067
2195
  }
2068
2196
  };
2069
- var getAllMenuItems = (children) => {
2070
- const orderedElements = [];
2197
+ var addMenuItem = ({
2198
+ itemProps,
2199
+ allMenuItems,
2200
+ menuItemsMap
2201
+ }) => {
2202
+ const item = {
2203
+ ...itemProps,
2204
+ index: allMenuItems.length
2205
+ };
2206
+ allMenuItems.push(item);
2207
+ menuItemsMap[`${item.id}`] = item;
2208
+ };
2209
+ var addItemsFromGroup = ({
2210
+ groupElement: menuGroup,
2211
+ allMenuItems,
2212
+ menuItemsMap
2213
+ }) => {
2214
+ const menuItems = menuGroup.props.menuItems;
2215
+ if (menuItems) {
2216
+ menuItems.forEach((menuItem) => {
2217
+ addMenuItem({
2218
+ itemProps: {
2219
+ id: menuItem.id,
2220
+ disabled: menuItem.disabled,
2221
+ menuItemProps: menuItem,
2222
+ menuGroupProps: menuGroup.props
2223
+ },
2224
+ allMenuItems,
2225
+ menuItemsMap
2226
+ });
2227
+ });
2228
+ } else if (menuGroup.props.children) {
2229
+ let children = menuGroup.props.children;
2230
+ if (!Array.isArray(children)) {
2231
+ children = [children];
2232
+ }
2233
+ children.forEach((menuItem) => {
2234
+ addMenuItem({
2235
+ itemProps: {
2236
+ id: menuItem.props.id,
2237
+ disabled: menuItem.props.disabled,
2238
+ menuItemProps: menuItem.props,
2239
+ menuGroupProps: menuGroup.props
2240
+ },
2241
+ allMenuItems,
2242
+ menuItemsMap
2243
+ });
2244
+ });
2245
+ }
2246
+ };
2247
+ var addItemsFromContent = ({
2248
+ contentElement: menuContent,
2249
+ allMenuItems,
2250
+ menuItemsMap
2251
+ }) => {
2252
+ if (!("menuItems" in menuContent.props)) return;
2253
+ if (menuContent.props.menuItems) {
2254
+ menuContent.props.menuItems.forEach((menuItem) => {
2255
+ addMenuItem({
2256
+ itemProps: {
2257
+ id: menuItem.id,
2258
+ disabled: menuItem.disabled,
2259
+ menuItemProps: menuItem
2260
+ },
2261
+ allMenuItems,
2262
+ menuItemsMap
2263
+ });
2264
+ });
2265
+ }
2266
+ };
2267
+ var setMenuItemsFromChildren = ({
2268
+ children,
2269
+ allMenuItems,
2270
+ menuItemsMap
2271
+ }) => {
2071
2272
  walkAllChildren(children, (element) => {
2072
2273
  switch (getComponentName(element)) {
2073
2274
  case "MenuItem":
2074
- orderedElements.push({
2075
- type: "item",
2076
- element
2275
+ case "SubmenuItem":
2276
+ case "NestedMenuItem":
2277
+ const menuItem = element;
2278
+ if (menuItemsMap[`${menuItem.props.id}`]) return;
2279
+ addMenuItem({
2280
+ itemProps: {
2281
+ id: menuItem.props.id,
2282
+ disabled: menuItem.props.disabled,
2283
+ menuItemProps: menuItem.props
2284
+ },
2285
+ allMenuItems,
2286
+ menuItemsMap
2077
2287
  });
2078
2288
  break;
2079
2289
  case "MenuGroup":
2080
- orderedElements.push({
2081
- type: "group",
2082
- element
2290
+ addItemsFromGroup({
2291
+ // Cast element to the TypeMenuGroupElement since we know it's a group and is needed for addItemsFromGroup.
2292
+ groupElement: element,
2293
+ allMenuItems,
2294
+ menuItemsMap
2083
2295
  });
2084
2296
  break;
2085
2297
  case "MenuContent":
2086
- orderedElements.push({
2087
- type: "content",
2088
- element
2298
+ case "NestedMenuContent":
2299
+ addItemsFromContent({
2300
+ // Cast element to the TypeMenuContentElement since we know it's a content and is needed for addItemsFromContent.
2301
+ contentElement: element,
2302
+ allMenuItems,
2303
+ menuItemsMap
2089
2304
  });
2090
2305
  break;
2091
2306
  default:
2092
2307
  break;
2093
2308
  }
2094
2309
  });
2095
- return { orderedElements };
2096
2310
  };
2097
2311
  var mapMenuItems = ({
2098
- items,
2099
- MenuItemComponent
2312
+ menuItems,
2313
+ MenuItemComponent = MenuItem
2100
2314
  }) => {
2101
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: items.map((menuItem) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuItemComponent, { ...menuItem }, menuItem.id)) });
2315
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: menuItems.map((menuItemProps) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuItemComponent, { ...menuItemProps }, menuItemProps.id)) });
2102
2316
  };
2317
+ var getChildrenFromMenuItems = ({
2318
+ menuItems,
2319
+ MenuItemComponent
2320
+ }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuContent, { menuItems, MenuItemComponent });
2103
2321
  var useMenuChildren = ({
2104
2322
  children: childrenProp,
2105
- items,
2106
- MenuItemComponent = MenuItem
2323
+ menuItems,
2324
+ MenuItemComponent
2107
2325
  }) => {
2108
2326
  const { allMenuItems, menuItemsMap, children } = (0, import_react5.useMemo)(() => {
2109
2327
  let children2 = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, {});
2110
- let index = 0;
2111
2328
  const menuItemsMap2 = {};
2112
2329
  const allMenuItems2 = [];
2113
- if (items && items.length) {
2114
- items.forEach((menuItem) => {
2115
- const item = {
2116
- id: menuItem.id,
2117
- index: index++,
2118
- disabled: menuItem.disabled,
2119
- menuItemProps: menuItem
2120
- };
2121
- allMenuItems2.push(item);
2122
- menuItemsMap2[`${item.id}`] = item;
2330
+ if (menuItems && menuItems.length) {
2331
+ menuItems.forEach((menuItem) => {
2332
+ addMenuItem({ itemProps: menuItem, allMenuItems: allMenuItems2, menuItemsMap: menuItemsMap2 });
2123
2333
  });
2124
- children2 = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MenuContent, { children: mapMenuItems({ items, MenuItemComponent }) });
2334
+ children2 = getChildrenFromMenuItems({ menuItems, MenuItemComponent });
2125
2335
  } else if (childrenProp) {
2126
2336
  children2 = childrenProp;
2127
- const { orderedElements } = getAllMenuItems(childrenProp);
2128
- orderedElements.forEach(({ type, element }) => {
2129
- if (type === "content") {
2130
- const menuContent = element;
2131
- const items2 = menuContent.props.items;
2132
- if (items2) {
2133
- items2.forEach((menuItem) => {
2134
- const item = {
2135
- id: menuItem.id,
2136
- index: index++,
2137
- children: menuItem.children,
2138
- disabled: menuItem.disabled,
2139
- menuItemProps: menuItem
2140
- };
2141
- allMenuItems2.push(item);
2142
- menuItemsMap2[`${item.id}`] = item;
2143
- });
2144
- }
2145
- } else if (type === "group") {
2146
- const menuGroup = element;
2147
- const items2 = menuGroup.props.items;
2148
- if (items2) {
2149
- items2.forEach((menuItem) => {
2150
- const item = {
2151
- id: menuItem.id,
2152
- index: index++,
2153
- children: menuItem.children,
2154
- disabled: menuItem.disabled,
2155
- menuItemProps: menuItem,
2156
- menuGroupProps: element.props
2157
- };
2158
- allMenuItems2.push(item);
2159
- menuItemsMap2[`${item.id}`] = item;
2160
- });
2161
- } else if (menuGroup.props.children) {
2162
- let children3 = menuGroup.props.children;
2163
- if (!Array.isArray(children3)) {
2164
- children3 = [children3];
2165
- }
2166
- children3.forEach((menuItem) => {
2167
- const item = {
2168
- id: menuItem.props.id,
2169
- index: index++,
2170
- children: menuItem.props.children,
2171
- disabled: menuItem.props.disabled,
2172
- menuItemProps: menuItem.props,
2173
- menuGroupProps: element.props
2174
- };
2175
- allMenuItems2.push(item);
2176
- menuItemsMap2[`${item.id}`] = item;
2177
- });
2178
- }
2179
- } else {
2180
- if (menuItemsMap2[`${element.props.id}`]) return;
2181
- const menuItem = element;
2182
- const item = {
2183
- id: menuItem.props.id,
2184
- index: index++,
2185
- disabled: menuItem.props.disabled,
2186
- menuItemProps: menuItem.props
2187
- };
2188
- allMenuItems2.push(item);
2189
- menuItemsMap2[`${item.id}`] = item;
2190
- }
2337
+ setMenuItemsFromChildren({
2338
+ children: childrenProp,
2339
+ allMenuItems: allMenuItems2,
2340
+ menuItemsMap: menuItemsMap2
2191
2341
  });
2192
2342
  }
2193
2343
  return { allMenuItems: allMenuItems2, menuItemsMap: menuItemsMap2, children: children2 };
2194
- }, [childrenProp, items, MenuItemComponent]);
2344
+ }, [childrenProp, menuItems, MenuItemComponent]);
2195
2345
  return { allMenuItems, menuItemsMap, children };
2196
2346
  };
2197
2347
 
2198
2348
  // src/MenuContent/MenuContent.tsx
2349
+ var import_react6 = require("react");
2199
2350
  var import_jsx_runtime6 = require("react/jsx-runtime");
2200
2351
  var MenuContent = ({
2201
2352
  id = "menu_content",
2202
2353
  children: childrenProp,
2203
- items,
2204
- MenuItemComponent = MenuItem,
2354
+ menuItems,
2355
+ MenuItemComponent,
2356
+ onKeyDown,
2357
+ innerRef = null,
2205
2358
  ...rest
2206
2359
  }) => {
2207
- const { getToggleButtonProps, getMenuProps, isListbox } = useMenuContext();
2208
- const children = childrenProp || !items || !items.length ? childrenProp : mapMenuItems({ items, MenuItemComponent });
2360
+ const { getToggleButtonProps, getMenuProps, isListbox } = useMenuContentContext();
2361
+ const toggleButtonProps = getToggleButtonProps?.();
2362
+ const children = childrenProp || !menuItems || !menuItems.length ? childrenProp : mapMenuItems({ menuItems, MenuItemComponent });
2209
2363
  if (!children) {
2210
2364
  return null;
2211
2365
  }
2366
+ const handleKeyDown = (0, import_react6.useCallback)(
2367
+ (e) => {
2368
+ toggleButtonProps?.["onKeyDown"]?.(e);
2369
+ onKeyDown?.(e);
2370
+ },
2371
+ [onKeyDown, toggleButtonProps?.["onKeyDown"]]
2372
+ );
2212
2373
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2213
2374
  StyledMenuContent,
2214
2375
  {
2215
2376
  autoFocus: true,
2216
2377
  id,
2217
2378
  tabIndex: 0,
2218
- onKeyDown: getToggleButtonProps?.()["onKeyDown"] || void 0,
2219
- "aria-activedescendant": getToggleButtonProps?.()["aria-activedescendant"],
2379
+ onKeyDown: handleKeyDown,
2380
+ "aria-activedescendant": toggleButtonProps?.["aria-activedescendant"],
2220
2381
  ...getMenuProps?.(
2221
2382
  {
2222
- ...isListbox ? {} : { role: "menu" }
2383
+ ...isListbox ? { ref: innerRef } : { ref: innerRef, role: "menu" }
2223
2384
  },
2224
2385
  // Suppress ref error for now
2225
2386
  { suppressRefError: true }
@@ -2231,7 +2392,7 @@ var MenuContent = ({
2231
2392
  };
2232
2393
 
2233
2394
  // src/MenuFooter/MenuFooter.tsx
2234
- var import_react6 = require("react");
2395
+ var import_react7 = require("react");
2235
2396
 
2236
2397
  // src/MenuFooter/styles.tsx
2237
2398
  var import_styled_components6 = __toESM(require("styled-components"));
@@ -2248,18 +2409,18 @@ var MenuFooter = ({ children, ...rest }) => {
2248
2409
  };
2249
2410
 
2250
2411
  // src/MenuGroup/MenuGroup.tsx
2251
- var import_react9 = require("react");
2412
+ var import_react10 = require("react");
2252
2413
 
2253
2414
  // src/MenuGroup/styles.tsx
2254
2415
  var import_styled_components9 = __toESM(require("styled-components"));
2255
2416
 
2256
2417
  // ../seeds-react-text/dist/esm/index.js
2257
- var import_react7 = require("react");
2418
+ var import_react8 = require("react");
2258
2419
  var import_styled_components7 = __toESM(require("styled-components"));
2259
2420
  var import_styled_components8 = __toESM(require("styled-components"));
2260
2421
  var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
2261
2422
  var import_jsx_runtime8 = require("react/jsx-runtime");
2262
- var import_react8 = require("react");
2423
+ var import_react9 = require("react");
2263
2424
  var Container = import_styled_components8.default.span`
2264
2425
  margin: 0;
2265
2426
  padding-left: 0;
@@ -2379,6 +2540,7 @@ var StyledMenuGroup = import_styled_components9.default.li`
2379
2540
  ${space}
2380
2541
  `;
2381
2542
  var StyledTitle = (0, import_styled_components9.default)(index_default.SmallSubHeadline)`
2543
+ font-size: ${({ theme: theme2 }) => theme2.typography[200].fontSize};
2382
2544
  margin: ${({ theme: theme2 }) => theme2.space[400]} ${({ theme: theme2 }) => theme2.space[400]}
2383
2545
  0px ${({ theme: theme2 }) => theme2.space[400]};
2384
2546
  `;
@@ -2396,12 +2558,12 @@ var MenuGroup = ({
2396
2558
  color: color2,
2397
2559
  isSingleSelect,
2398
2560
  id,
2399
- items,
2400
- MenuItemComponent = MenuItem,
2561
+ menuItems,
2562
+ MenuItemComponent,
2401
2563
  ...rest
2402
2564
  }) => {
2403
2565
  const titleId = `menu-group-title-${Math.random().toString(36).slice(2, 11)}`;
2404
- const children = childrenProp || !items || !items.length ? childrenProp : mapMenuItems({ items, MenuItemComponent });
2566
+ const children = childrenProp || !menuItems || !menuItems.length ? childrenProp : mapMenuItems({ menuItems, MenuItemComponent });
2405
2567
  if (!children) {
2406
2568
  return null;
2407
2569
  }
@@ -2423,7 +2585,7 @@ var MenuGroup = ({
2423
2585
  };
2424
2586
 
2425
2587
  // src/MenuRoot/MenuRoot.tsx
2426
- var import_react10 = require("react");
2588
+ var import_react11 = require("react");
2427
2589
  var import_styled_components10 = __toESM(require("styled-components"));
2428
2590
  var import_seeds_react_popout = require("@sproutsocial/seeds-react-popout");
2429
2591
  var import_jsx_runtime10 = require("react/jsx-runtime");
@@ -2435,24 +2597,26 @@ var CustomPopoutContent = (0, import_styled_components10.default)(import_seeds_r
2435
2597
  var MenuRoot = ({
2436
2598
  children,
2437
2599
  menuToggleElement,
2438
- popoutProps: { focusLockProps, ...popoutProps } = {},
2600
+ popoutProps: { placement = "bottom", focusLockProps, ...popoutProps } = {},
2439
2601
  width: width2 = "300px",
2440
2602
  ...contextProps
2441
2603
  }) => {
2442
2604
  const { isOpen, openMenu, closeMenu } = contextProps;
2443
- const setIsOpen = (0, import_react10.useCallback)(
2605
+ const setIsOpen = (0, import_react11.useCallback)(
2444
2606
  (newIsOpen) => {
2445
2607
  newIsOpen ? openMenu?.() : closeMenu?.();
2446
2608
  },
2447
2609
  [openMenu, closeMenu]
2448
2610
  );
2449
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MenuProvider, { menuProps: contextProps, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2611
+ const menuContext = useMenu(contextProps);
2612
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2450
2613
  import_seeds_react_popout.Popout,
2451
2614
  {
2452
2615
  menuPopout: true,
2616
+ placement,
2453
2617
  isOpen: !!isOpen,
2454
2618
  setIsOpen,
2455
- content: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CustomPopoutContent, { width: width2, children }),
2619
+ content: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MenuContentProvider, { menuContext, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CustomPopoutContent, { width: width2, children }) }),
2456
2620
  focusLockProps: {
2457
2621
  // correct jerking motion when scrolling while the Popout is open
2458
2622
  // returnFocus: false,
@@ -2461,37 +2625,38 @@ var MenuRoot = ({
2461
2625
  },
2462
2626
  disableWrapperAria: true,
2463
2627
  ...popoutProps,
2464
- children: menuToggleElement
2628
+ children: (toggleProps) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(MenuToggleProvider, { menuContext: { ...menuContext, ...toggleProps }, children: menuToggleElement })
2465
2629
  }
2466
- ) });
2630
+ );
2467
2631
  };
2468
2632
 
2469
2633
  // src/MenuLabel.tsx
2470
- var import_react11 = require("react");
2634
+ var import_react12 = require("react");
2471
2635
  var import_seeds_react_label = require("@sproutsocial/seeds-react-label");
2472
2636
  var import_jsx_runtime11 = require("react/jsx-runtime");
2473
2637
  var MenuLabel = ({ children, ...rest }) => {
2474
- const { getLabelProps } = useMenuContext();
2638
+ const { getLabelProps } = useMenuToggleContext();
2475
2639
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_seeds_react_label.Label, { htmlFor: "fallback_menu_label", ...getLabelProps?.(), ...rest, children });
2476
2640
  };
2477
2641
 
2478
- // src/MenuToggleButton.tsx
2479
- var import_react12 = require("react");
2642
+ // src/MenuToggleButton/MenuToggleButton.tsx
2643
+ var import_react13 = require("react");
2480
2644
  var import_seeds_react_button = require("@sproutsocial/seeds-react-button");
2481
2645
  var import_jsx_runtime12 = require("react/jsx-runtime");
2482
2646
  var MenuToggleButton = ({
2483
2647
  children,
2484
2648
  ...rest
2485
2649
  }) => {
2486
- const { getToggleButtonProps, isListbox, getDropdownProps } = (0, import_react12.useContext)(MenuContext);
2650
+ const { getToggleButtonProps, isListbox, getDropdownProps, ref, ariaProps } = useMenuToggleContext();
2487
2651
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2488
2652
  import_seeds_react_button.Button,
2489
2653
  {
2490
2654
  appearance: "secondary",
2491
2655
  ...getToggleButtonProps?.({
2492
2656
  // Decide if we want the preventKeyAction stuff. Maybe create a prop to allow for this to be overriden.
2493
- ...getDropdownProps?.({ preventKeyAction: true }),
2657
+ ...getDropdownProps?.({ ref, preventKeyAction: true }) || { ref },
2494
2658
  refKey: "innerRef",
2659
+ ...ariaProps,
2495
2660
  ...isListbox ? {} : { role: "button", "aria-haspopup": "menu" }
2496
2661
  }),
2497
2662
  ...rest,
@@ -2500,191 +2665,727 @@ var MenuToggleButton = ({
2500
2665
  );
2501
2666
  };
2502
2667
 
2503
- // src/ActionMenu/ActionMenu.tsx
2504
- var import_react13 = __toESM(require("react"));
2505
- var import_downshift2 = require("downshift");
2668
+ // src/MenuSearchInput/MenuSearchInput.tsx
2669
+ var import_react15 = __toESM(require("react"));
2670
+ var import_seeds_react_input = require("@sproutsocial/seeds-react-input");
2506
2671
 
2507
- // src/reducers/useSelectStateReducer.tsx
2508
- var import_downshift = require("downshift");
2509
- var useSelectStateReducer = (state, actionAndChanges) => {
2510
- const { type, changes } = actionAndChanges;
2511
- switch (type) {
2512
- /** If downshift is blurred by tabbing within the menu, stay open */
2513
- case import_downshift.useSelect.stateChangeTypes.ToggleButtonBlur:
2514
- return {
2515
- ...changes,
2516
- // keep menu open on blur
2517
- isOpen: true
2518
- };
2519
- /** Return standard change payload */
2520
- default:
2521
- return changes;
2522
- }
2523
- };
2524
- var defaultUseSelectProps = {
2525
- stateReducer: useSelectStateReducer,
2526
- isItemDisabled: (item) => !!item.disabled
2527
- };
2672
+ // src/hooks/useItemFiltering.tsx
2673
+ var import_react14 = __toESM(require("react"));
2528
2674
 
2529
- // src/utils/itemToString.ts
2675
+ // src/utils/downshiftDefaults.ts
2530
2676
  var itemToString = (item) => {
2531
2677
  return item ? item.id : "";
2532
2678
  };
2679
+ var itemToKey = (item) => {
2680
+ return item ? item.id : "";
2681
+ };
2533
2682
 
2534
- // src/ActionMenu/ActionMenu.tsx
2535
- var import_jsx_runtime13 = require("react/jsx-runtime");
2536
- var handleStateChange = (changes, currentSelectedItem) => {
2537
- if (!(changes.type === import_downshift2.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter || changes.type === import_downshift2.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton)) {
2538
- return;
2539
- }
2540
- const selectedItem = changes.selectedItem || currentSelectedItem;
2541
- if (!selectedItem) return;
2542
- if (selectedItem.disabled) {
2543
- return;
2544
- }
2545
- const isEnterKeyDown = changes.type === import_downshift2.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter;
2546
- const selectedItemProps = selectedItem.menuItemProps;
2547
- if (selectedItemProps?.onClick) {
2548
- const syntheticKeyboardEvent = new KeyboardEvent("keydown", {
2549
- key: isEnterKeyDown ? "Enter" : " ",
2550
- code: isEnterKeyDown ? "Enter" : "Space",
2551
- bubbles: true,
2552
- cancelable: true,
2553
- view: window
2554
- });
2555
- selectedItemProps?.onClick?.(
2556
- syntheticKeyboardEvent
2557
- );
2558
- }
2559
- if (selectedItemProps?.href) {
2560
- if (selectedItemProps.target) {
2561
- window.open(selectedItemProps.href, selectedItemProps.target);
2562
- } else {
2563
- window.location.href = selectedItemProps?.href;
2564
- }
2565
- }
2683
+ // src/hooks/useItemFiltering.tsx
2684
+ var getDefaultGetIsItemVisible = (itemToString2 = itemToString) => (item, inputValue) => itemToString2(item).toLowerCase().includes(inputValue.toLowerCase());
2685
+ var defaultGetShouldFilter = ({ inputValue }) => Boolean(inputValue);
2686
+ var useItemFiltering = ({
2687
+ allMenuItems,
2688
+ itemToString: itemToString2,
2689
+ getIsItemVisible = getDefaultGetIsItemVisible(itemToString2),
2690
+ getShouldFilter = defaultGetShouldFilter,
2691
+ setHiddenItemsMap: setHiddenItemsMapProp
2692
+ }) => {
2693
+ const [hiddenItemsMap, setHiddenItemsMap] = import_react14.default.useState({});
2694
+ const updateFilteredItems = import_react14.default.useCallback(
2695
+ ({ inputValue }) => {
2696
+ const newHiddenItems = getShouldFilter({ inputValue }) ? allMenuItems.reduce((map, item) => {
2697
+ const isItemVisible = getIsItemVisible(item, inputValue);
2698
+ return isItemVisible ? map : { ...map, [item.id]: true };
2699
+ }, {}) : {};
2700
+ setHiddenItemsMap(newHiddenItems);
2701
+ setHiddenItemsMapProp?.(newHiddenItems);
2702
+ },
2703
+ [allMenuItems, getIsItemVisible, getShouldFilter]
2704
+ );
2705
+ return {
2706
+ getIsItemVisible,
2707
+ updateFilteredItems
2708
+ };
2566
2709
  };
2567
- var ActionMenu = ({
2568
- children: childrenProp,
2569
- items,
2570
- MenuItemComponent = MenuItem,
2571
- stateReducer: externalStateReducer,
2572
- ...useSelectProps
2710
+
2711
+ // src/MenuSearchInput/MenuSearchInput.tsx
2712
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2713
+ var MenuSearchInput = ({
2714
+ getIsItemVisible,
2715
+ ...inputProps
2573
2716
  }) => {
2574
- const { allMenuItems, menuItemsMap, children } = useMenuChildren({
2575
- children: childrenProp,
2717
+ const {
2576
2718
  items,
2577
- MenuItemComponent
2719
+ itemToString: itemToString2,
2720
+ setHiddenItemsMap,
2721
+ isOpen,
2722
+ getToggleButtonProps
2723
+ } = useMenuContentContext();
2724
+ const { updateFilteredItems } = useItemFiltering({
2725
+ allMenuItems: items,
2726
+ itemToString: itemToString2,
2727
+ getIsItemVisible,
2728
+ setHiddenItemsMap
2578
2729
  });
2579
- const [currentSelectedItem, setCurrentSelectedItem] = import_react13.default.useState(null);
2580
- const { isOpen, ...useSelectReturnProps } = (0, import_downshift2.useSelect)({
2581
- ...defaultUseSelectProps,
2582
- items: allMenuItems,
2583
- itemToString,
2584
- onStateChange: (changes) => handleStateChange(changes, currentSelectedItem),
2585
- stateReducer: (state, actionAndChanges) => {
2586
- let newState;
2587
- newState = useSelectStateReducer(state, actionAndChanges);
2588
- return externalStateReducer ? externalStateReducer(state, {
2589
- ...actionAndChanges,
2590
- changes: newState
2591
- }) : newState;
2730
+ import_react15.default.useEffect(() => {
2731
+ updateFilteredItems({ inputValue: inputProps.value || "" });
2732
+ }, [isOpen, inputProps.value]);
2733
+ const handleKeyDown = import_react15.default.useCallback(
2734
+ (e) => {
2735
+ if (e.key === " ") return;
2736
+ getToggleButtonProps?.()["onKeyDown"](e);
2592
2737
  },
2593
- ...useSelectProps
2594
- });
2595
- (0, import_react13.useEffect)(() => {
2596
- setCurrentSelectedItem(useSelectReturnProps.selectedItem);
2597
- }, [useSelectReturnProps.selectedItem]);
2738
+ [getToggleButtonProps]
2739
+ );
2598
2740
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2599
- MenuRoot,
2741
+ import_seeds_react_input.Input,
2600
2742
  {
2601
- ...{
2602
- isListbox: false,
2603
- items: allMenuItems,
2604
- itemsMap: menuItemsMap,
2605
- itemToString,
2606
- isOpen,
2607
- ...useSelectProps,
2608
- ...useSelectReturnProps
2743
+ onChange: (e, value) => {
2744
+ updateFilteredItems({ inputValue: value });
2609
2745
  },
2610
- children
2746
+ onKeyDown: handleKeyDown,
2747
+ autoComplete: false,
2748
+ ...inputProps
2611
2749
  }
2612
2750
  );
2613
2751
  };
2614
2752
 
2615
- // src/SingleSelectMenu/SingleSelectMenu.tsx
2616
- var import_react14 = require("react");
2617
- var import_downshift3 = require("downshift");
2753
+ // src/MenuTokenInput.tsx
2754
+ var import_react16 = __toESM(require("react"));
2755
+ var import_styled_components11 = __toESM(require("styled-components"));
2756
+ var import_seeds_react_token_input = require("@sproutsocial/seeds-react-token-input");
2618
2757
  var import_jsx_runtime14 = require("react/jsx-runtime");
2619
- var SingleSelectMenu = ({
2620
- children: childrenProp,
2621
- stateReducer: externalStateReducer,
2622
- items,
2623
- MenuItemComponent = MenuItem,
2624
- ...useSelectProps
2758
+ var StyledTokenInputWrapper = import_styled_components11.default.div`
2759
+ > div {
2760
+ padding: 4px;
2761
+ }
2762
+
2763
+ input {
2764
+ line-height: 21px;
2765
+ margin: 0;
2766
+ padding: 2px 4px;
2767
+ }
2768
+
2769
+ .TokenInput-token button {
2770
+ margin-top: 0;
2771
+ padding: 1px 4px;
2772
+ }
2773
+ `;
2774
+ var MenuTokenInput = ({
2775
+ inputProps = {},
2776
+ getTokenProps,
2777
+ onKeyDown,
2778
+ MenuContext = MenuToggleContext,
2779
+ ...tokenInputProps
2625
2780
  }) => {
2626
- const { allMenuItems, menuItemsMap, children } = useMenuChildren({
2627
- children: childrenProp,
2628
- items,
2629
- MenuItemComponent
2630
- });
2631
- const { isOpen, ...useSelectReturnProps } = (0, import_downshift3.useSelect)({
2632
- ...defaultUseSelectProps,
2633
- items: allMenuItems,
2634
- itemToString,
2635
- stateReducer: (state, actionAndChanges) => {
2636
- let newState;
2637
- newState = useSelectStateReducer(state, actionAndChanges);
2638
- return externalStateReducer ? externalStateReducer(state, {
2639
- ...actionAndChanges,
2640
- changes: newState
2641
- }) : newState;
2642
- },
2643
- ...useSelectProps
2644
- });
2645
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2646
- MenuRoot,
2781
+ const {
2782
+ itemToString: itemToString2,
2783
+ getSelectedItemProps,
2784
+ removeSelectedItem,
2785
+ setActiveIndex,
2786
+ selectedItems = []
2787
+ } = import_react16.default.useContext(MenuContext);
2788
+ const removeToken = (tokenId) => {
2789
+ const tokenToRemove = selectedItems?.find((item) => item.id === tokenId);
2790
+ tokenToRemove && removeSelectedItem?.(tokenToRemove);
2791
+ };
2792
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(StyledTokenInputWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2793
+ import_seeds_react_token_input.TokenInput,
2647
2794
  {
2648
- ...{
2649
- isListbox: true,
2650
- items: allMenuItems,
2651
- itemsMap: menuItemsMap,
2652
- itemToString,
2653
- isOpen,
2654
- ...useSelectProps,
2655
- ...useSelectReturnProps
2795
+ onKeyDown: (e, value) => {
2796
+ if (e.key === "ArrowLeft" && !value && selectedItems.length) {
2797
+ setActiveIndex?.(selectedItems.length - 1);
2798
+ }
2799
+ onKeyDown?.(e, value);
2656
2800
  },
2657
- children
2801
+ inputProps: {
2802
+ autoComplete: "off",
2803
+ type: "search",
2804
+ ...inputProps
2805
+ },
2806
+ tokens: selectedItems.map((item, index) => {
2807
+ const {
2808
+ tokenProps: { ref, onKeyDown: onKeyDown2, ...restTokenProps } = {
2809
+ ref: void 0,
2810
+ onKeyDown: void 0
2811
+ },
2812
+ ...rest
2813
+ } = getTokenProps?.(item.id) || {};
2814
+ return {
2815
+ id: item.id,
2816
+ value: itemToString2?.(item) || item.id,
2817
+ tokenProps: {
2818
+ ...getSelectedItemProps?.({
2819
+ selectedItem: item,
2820
+ index,
2821
+ ref,
2822
+ refKey: "innerRef",
2823
+ onKeyDown: onKeyDown2
2824
+ }),
2825
+ // nullify the onclick provided from downshift
2826
+ // TokenInput deletes the token on click
2827
+ onClick: void 0,
2828
+ tabIndex: 0,
2829
+ ...restTokenProps
2830
+ },
2831
+ ...rest
2832
+ };
2833
+ }),
2834
+ onRemoveToken: removeToken,
2835
+ ...tokenInputProps
2658
2836
  }
2659
- );
2837
+ ) });
2660
2838
  };
2661
2839
 
2662
- // src/MultiSelectMenu/MultiSelectMenu.tsx
2663
- var import_react15 = require("react");
2664
- var import_downshift4 = require("downshift");
2840
+ // src/MenuSearchTokenInput/MenuSearchTokenInput.tsx
2841
+ var import_react17 = __toESM(require("react"));
2665
2842
  var import_jsx_runtime15 = require("react/jsx-runtime");
2666
- var selectReducerForMultiSelect = (state, actionAndChanges) => {
2667
- const { changes, type } = actionAndChanges;
2668
- switch (type) {
2669
- case import_downshift4.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
2670
- case import_downshift4.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
2671
- case import_downshift4.useSelect.stateChangeTypes.ItemClick:
2672
- return {
2673
- ...changes,
2674
- isOpen: true,
2675
- // keep the menu open after selection.
2676
- // TODO: Confirm that keeping highlightedIndex the same is the desired UX
2677
- // highlightedIndex: 0, // with the first option highlighted.
2678
- highlightedIndex: state.highlightedIndex
2679
- // keep highlightedIndex the same instead of returning to 0
2680
- };
2681
- }
2682
- return changes;
2683
- };
2843
+ var MenuSearchTokenInput = ({
2844
+ getIsItemVisible,
2845
+ getTokenProps,
2846
+ onChange,
2847
+ inputProps: { value: inputPropsValue, ...inputProps } = {},
2848
+ value,
2849
+ ...tokenInputProps
2850
+ }) => {
2851
+ const {
2852
+ items,
2853
+ itemToString: itemToString2,
2854
+ setHiddenItemsMap,
2855
+ isOpen,
2856
+ getToggleButtonProps
2857
+ } = useMenuContentContext();
2858
+ const { updateFilteredItems } = useItemFiltering({
2859
+ allMenuItems: items,
2860
+ itemToString: itemToString2,
2861
+ getIsItemVisible,
2862
+ setHiddenItemsMap
2863
+ });
2864
+ const controlledValue = value || inputPropsValue !== void 0 ? `${inputPropsValue}` : void 0;
2865
+ const [internalValue, setInternalValue] = import_react17.default.useState(
2866
+ controlledValue || ""
2867
+ );
2868
+ const updateFilteredState = import_react17.default.useCallback(
2869
+ // defaults to an empty string if no value is passed
2870
+ (value2 = "") => {
2871
+ setInternalValue(value2);
2872
+ updateFilteredItems({ inputValue: value2 });
2873
+ },
2874
+ [updateFilteredItems]
2875
+ );
2876
+ import_react17.default.useEffect(() => {
2877
+ updateFilteredState(controlledValue);
2878
+ }, [controlledValue]);
2879
+ import_react17.default.useEffect(() => {
2880
+ updateFilteredState(controlledValue);
2881
+ }, [isOpen]);
2882
+ const handleKeyDown = import_react17.default.useCallback(
2883
+ (e) => {
2884
+ if (e.key === " ") return;
2885
+ getToggleButtonProps?.()["onKeyDown"](e);
2886
+ },
2887
+ [getToggleButtonProps]
2888
+ );
2889
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2890
+ MenuTokenInput,
2891
+ {
2892
+ onChange: (e, value2) => {
2893
+ updateFilteredState(value2);
2894
+ onChange?.(e, value2);
2895
+ },
2896
+ onKeyDown: handleKeyDown,
2897
+ inputProps: {
2898
+ value: internalValue,
2899
+ ...inputProps
2900
+ },
2901
+ MenuContext: MenuContentContext,
2902
+ ...tokenInputProps
2903
+ }
2904
+ );
2905
+ };
2906
+
2907
+ // src/SubmenuItem/SubmenuItem.tsx
2908
+ var import_react18 = __toESM(require("react"));
2909
+ var import_seeds_react_icon2 = require("@sproutsocial/seeds-react-icon");
2910
+ var import_seeds_react_box3 = require("@sproutsocial/seeds-react-box");
2911
+ var import_seeds_react_utilities = require("@sproutsocial/seeds-react-utilities");
2912
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2913
+ var SubmenuItemTrigger = ({
2914
+ id,
2915
+ children,
2916
+ innerRef,
2917
+ ...rest
2918
+ }) => {
2919
+ const { getToggleButtonProps, getDropdownProps, ref, ariaProps } = useMenuToggleContext();
2920
+ const toggleRef = ref && innerRef ? (0, import_seeds_react_utilities.mergeRefs)([ref, innerRef].filter(Boolean)) : ref || innerRef;
2921
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2922
+ MenuItem,
2923
+ {
2924
+ ...rest,
2925
+ ...getToggleButtonProps?.(
2926
+ {
2927
+ ...getDropdownProps?.({
2928
+ ref: toggleRef,
2929
+ preventKeyAction: true
2930
+ }) || { ref: toggleRef },
2931
+ refKey: "innerRef",
2932
+ role: "menuitem",
2933
+ ...ariaProps
2934
+ },
2935
+ { suppressRefError: true }
2936
+ ),
2937
+ id,
2938
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_seeds_react_box3.Box, { display: "flex", justifyContent: "space-between", children: [
2939
+ children,
2940
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MenuItemActionRight, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_seeds_react_icon2.Icon, { name: "chevron-right-outline" }) })
2941
+ ] })
2942
+ }
2943
+ );
2944
+ };
2945
+ var doesRefContainEventTarget = (ref, event) => {
2946
+ return ref.current && event.target instanceof Node && ref.current.contains(event.target);
2947
+ };
2948
+ var SubmenuItem = ({
2949
+ MenuComponent,
2950
+ menuProps: {
2951
+ children: menuChildren,
2952
+ menuItems,
2953
+ MenuItemComponent,
2954
+ popoutProps: { popperProps, ...popoutProps } = {},
2955
+ onStateChange,
2956
+ ...menuProps
2957
+ },
2958
+ // isOpen,
2959
+ // onToggleSubmenu,
2960
+ id,
2961
+ children,
2962
+ ...rest
2963
+ }) => {
2964
+ const {
2965
+ highlightedIndex,
2966
+ setHighlightedIndex,
2967
+ itemsMap,
2968
+ isOpen: parentIsOpen
2969
+ } = useMenuContentContext();
2970
+ const [submenuIsFocused, setSubmenuIsFocused] = import_react18.default.useState(false);
2971
+ const [submenuIsOpen, setSubmenuIsOpen] = import_react18.default.useState(false);
2972
+ const [submenuIsActive, setSubmenuIsActive] = import_react18.default.useState(false);
2973
+ const submenuItemRef = import_react18.default.useRef(null);
2974
+ const submenuRef = import_react18.default.useRef(null);
2975
+ const menuContent = menuItems ? getChildrenFromMenuItems({ menuItems, MenuItemComponent }) : menuChildren;
2976
+ const item = itemsMap[id] || {
2977
+ index: 0,
2978
+ id
2979
+ };
2980
+ import_react18.default.useEffect(() => {
2981
+ if (highlightedIndex === item.index) {
2982
+ !submenuIsOpen && setSubmenuIsOpen(true);
2983
+ } else if (submenuIsOpen && highlightedIndex !== -1) {
2984
+ setSubmenuIsOpen(false);
2985
+ setSubmenuIsActive(false);
2986
+ }
2987
+ }, [highlightedIndex, item.index, submenuIsOpen, setSubmenuIsOpen]);
2988
+ const onSubmenuStateChange = import_react18.default.useCallback(
2989
+ (state) => {
2990
+ if (state.isOpen !== void 0) {
2991
+ setSubmenuIsOpen(state.isOpen);
2992
+ if (!state.isOpen) {
2993
+ setSubmenuIsFocused(false);
2994
+ setHighlightedIndex?.(-1);
2995
+ }
2996
+ }
2997
+ onStateChange?.(state);
2998
+ },
2999
+ [onStateChange, setSubmenuIsOpen]
3000
+ );
3001
+ const onSubmenuKeydown = (e) => {
3002
+ switch (e.key) {
3003
+ case "ArrowRight":
3004
+ case " ":
3005
+ case "Enter":
3006
+ if (!submenuIsFocused && submenuIsOpen) {
3007
+ e.stopPropagation();
3008
+ setSubmenuIsFocused(true);
3009
+ }
3010
+ break;
3011
+ case "ArrowLeft":
3012
+ if (submenuIsFocused) {
3013
+ e.stopPropagation();
3014
+ setSubmenuIsFocused(false);
3015
+ }
3016
+ break;
3017
+ default:
3018
+ break;
3019
+ }
3020
+ };
3021
+ const onMenuItemClick = () => {
3022
+ const newIsActive = !submenuIsActive;
3023
+ setSubmenuIsActive(newIsActive);
3024
+ setSubmenuIsOpen(newIsActive);
3025
+ };
3026
+ const onBodyClick = (e) => {
3027
+ if (doesRefContainEventTarget(submenuItemRef, e)) {
3028
+ e.stopPropagation();
3029
+ onMenuItemClick();
3030
+ }
3031
+ };
3032
+ import_react18.default.useEffect(() => {
3033
+ if (document && document.body) {
3034
+ document.body.addEventListener("click", onBodyClick, {
3035
+ capture: true
3036
+ });
3037
+ document.body.addEventListener("keydown", onSubmenuKeydown, {
3038
+ capture: true
3039
+ });
3040
+ return () => {
3041
+ document.body.removeEventListener("click", onBodyClick, {
3042
+ capture: true
3043
+ });
3044
+ document.body.removeEventListener("keydown", onSubmenuKeydown, {
3045
+ capture: true
3046
+ });
3047
+ };
3048
+ }
3049
+ }, [document, onSubmenuKeydown]);
3050
+ const subMenuContent = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3051
+ "div",
3052
+ {
3053
+ ref: submenuRef,
3054
+ onKeyDown: (e) => {
3055
+ e.stopPropagation();
3056
+ },
3057
+ tabIndex: -1,
3058
+ children: menuContent
3059
+ }
3060
+ );
3061
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3062
+ MenuComponent,
3063
+ {
3064
+ ...{
3065
+ ...menuProps,
3066
+ children: subMenuContent,
3067
+ menuToggleElement: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3068
+ SubmenuItemTrigger,
3069
+ {
3070
+ innerRef: submenuItemRef,
3071
+ id,
3072
+ children,
3073
+ active: submenuIsActive,
3074
+ ...rest
3075
+ }
3076
+ ),
3077
+ isOpen: submenuIsOpen,
3078
+ onStateChange: onSubmenuStateChange,
3079
+ popoutProps: {
3080
+ placement: "right",
3081
+ popperProps: {
3082
+ modifiers: {
3083
+ offset: {
3084
+ offset: "0,18"
3085
+ }
3086
+ },
3087
+ ...popperProps
3088
+ },
3089
+ focusOnContent: submenuIsFocused,
3090
+ ...popoutProps
3091
+ }
3092
+ }
3093
+ }
3094
+ );
3095
+ };
3096
+
3097
+ // src/ActionMenu/ActionMenu.tsx
3098
+ var import_react20 = __toESM(require("react"));
3099
+ var import_downshift3 = require("downshift");
3100
+
3101
+ // src/hooks/useDownshiftDefaults.tsx
3102
+ var import_react19 = __toESM(require("react"));
3103
+
3104
+ // src/reducers/useComboboxStateReducer.tsx
3105
+ var import_downshift = require("downshift");
3106
+
3107
+ // src/utils/reduceReducers.ts
3108
+ var reduceReducers = (...reducers) => (state, action) => reducers.reduce(
3109
+ (changes, nextReducer) => nextReducer ? nextReducer(state, {
3110
+ ...action,
3111
+ changes
3112
+ }) : changes,
3113
+ action.changes
3114
+ );
3115
+
3116
+ // src/reducers/useComboboxStateReducer.tsx
3117
+ var useComboboxStateReducer = (state, actionAndChanges) => {
3118
+ const { type, changes } = actionAndChanges;
3119
+ switch (type) {
3120
+ /** If downshift is blurred by tabbing within the menu, stay open */
3121
+ case import_downshift.useCombobox.stateChangeTypes.InputBlur:
3122
+ return {
3123
+ ...changes,
3124
+ // keep menu open on blur
3125
+ isOpen: true
3126
+ };
3127
+ /** Return standard change payload */
3128
+ default:
3129
+ return changes;
3130
+ }
3131
+ };
3132
+ var useComboboxStateReducerForMulti = reduceReducers(
3133
+ useComboboxStateReducer,
3134
+ (state, actionAndChanges) => {
3135
+ const { changes, type } = actionAndChanges;
3136
+ switch (type) {
3137
+ case import_downshift.useCombobox.stateChangeTypes.InputKeyDownEnter:
3138
+ case import_downshift.useCombobox.stateChangeTypes.ItemClick:
3139
+ case import_downshift.useCombobox.stateChangeTypes.InputBlur:
3140
+ return {
3141
+ ...changes,
3142
+ ...changes.selectedItem && {
3143
+ inputValue: ""
3144
+ }
3145
+ };
3146
+ default:
3147
+ return changes;
3148
+ }
3149
+ }
3150
+ );
3151
+
3152
+ // src/reducers/useSelectStateReducer.tsx
3153
+ var import_downshift2 = require("downshift");
3154
+ var useSelectStateReducer = (state, actionAndChanges) => {
3155
+ const { type, changes } = actionAndChanges;
3156
+ switch (type) {
3157
+ /** If downshift is blurred by tabbing within the menu, stay open */
3158
+ case import_downshift2.useSelect.stateChangeTypes.ToggleButtonBlur:
3159
+ return {
3160
+ ...changes,
3161
+ // keep menu open on blur
3162
+ isOpen: true
3163
+ };
3164
+ /** Return standard change payload */
3165
+ default:
3166
+ return changes;
3167
+ }
3168
+ };
3169
+ var useSelectStateReducerForMulti = reduceReducers(
3170
+ useSelectStateReducer,
3171
+ (state, actionAndChanges) => {
3172
+ const { changes, type } = actionAndChanges;
3173
+ switch (type) {
3174
+ case import_downshift2.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
3175
+ case import_downshift2.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
3176
+ case import_downshift2.useSelect.stateChangeTypes.ItemClick:
3177
+ return {
3178
+ ...changes,
3179
+ isOpen: true,
3180
+ // keep the menu open after selection.
3181
+ // TODO: Confirm that keeping highlightedIndex the same is the desired UX
3182
+ // highlightedIndex: 0, // with the first option highlighted.
3183
+ highlightedIndex: state.highlightedIndex
3184
+ // keep highlightedIndex the same instead of returning to 0
3185
+ };
3186
+ }
3187
+ return changes;
3188
+ }
3189
+ );
3190
+
3191
+ // src/utils/getMultiSelectOverrides.ts
3192
+ var getMultiSelectOverrides = ({
3193
+ getA11yMultiStatusMessage,
3194
+ onMultiSelectStateChange,
3195
+ multiSelectStateReducer,
3196
+ ...useSelectProps
3197
+ }) => Object.entries({
3198
+ ...useSelectProps,
3199
+ getA11yStatusMessage: getA11yMultiStatusMessage,
3200
+ onStateChange: onMultiSelectStateChange,
3201
+ stateReducer: multiSelectStateReducer
3202
+ }).reduce(
3203
+ (a, [k, v]) => v ? (a[k] = v, a) : a,
3204
+ {}
3205
+ );
3206
+
3207
+ // src/hooks/useDownshiftDefaults.tsx
3208
+ var defaultUseSelectProps = {
3209
+ stateReducer: useSelectStateReducer
3210
+ };
3211
+ var defaultUseComboboxProps = {
3212
+ stateReducer: useComboboxStateReducer
3213
+ };
3214
+ var defaultUseSelectPropsForMulti = {
3215
+ stateReducer: useSelectStateReducerForMulti
3216
+ };
3217
+ var defaultUseComboboxPropsForMulti = {
3218
+ stateReducer: useComboboxStateReducerForMulti
3219
+ };
3220
+ var useDownshiftDefaults = ({
3221
+ isCombobox = false,
3222
+ isMulti = false,
3223
+ multiSelectProps = {}
3224
+ } = {}) => {
3225
+ const [hiddenItemsMap, setHiddenItemsMap] = import_react19.default.useState({});
3226
+ const isItemDisabled = import_react19.default.useCallback(
3227
+ (item) => Boolean(item.disabled || hiddenItemsMap[item.id]),
3228
+ [hiddenItemsMap]
3229
+ );
3230
+ return {
3231
+ hiddenItemsMap,
3232
+ setHiddenItemsMap,
3233
+ defaultDownshiftProps: {
3234
+ select: !isCombobox ? {
3235
+ // disabling while item.hidden so that hidden items are ignored by downshift
3236
+ isItemDisabled,
3237
+ ...isMulti ? defaultUseSelectPropsForMulti : defaultUseSelectProps
3238
+ } : {},
3239
+ combobox: isCombobox ? {
3240
+ // disabling while item.hidden so that hidden items are ignored by downshift
3241
+ isItemDisabled,
3242
+ ...isMulti ? defaultUseComboboxPropsForMulti : defaultUseComboboxProps
3243
+ } : {},
3244
+ multi: isMulti ? {
3245
+ // handles the prop name mapping for multi select
3246
+ ...getMultiSelectOverrides(multiSelectProps)
3247
+ } : {}
3248
+ }
3249
+ };
3250
+ };
3251
+
3252
+ // src/ActionMenu/ActionMenu.tsx
3253
+ var import_jsx_runtime17 = require("react/jsx-runtime");
3254
+ var handleStateChange = (changes, currentSelectedItem) => {
3255
+ if (!(changes.type === import_downshift3.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter || changes.type === import_downshift3.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton)) {
3256
+ return;
3257
+ }
3258
+ const selectedItem = changes.selectedItem || currentSelectedItem;
3259
+ if (!selectedItem) return;
3260
+ if (selectedItem.disabled) {
3261
+ return;
3262
+ }
3263
+ const isEnterKeyDown = changes.type === import_downshift3.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter;
3264
+ const selectedItemProps = selectedItem.menuItemProps;
3265
+ if (selectedItemProps?.onClick) {
3266
+ const syntheticKeyboardEvent = new KeyboardEvent("keydown", {
3267
+ key: isEnterKeyDown ? "Enter" : " ",
3268
+ code: isEnterKeyDown ? "Enter" : "Space",
3269
+ bubbles: true,
3270
+ cancelable: true,
3271
+ view: window
3272
+ });
3273
+ selectedItemProps?.onClick?.(
3274
+ syntheticKeyboardEvent
3275
+ );
3276
+ }
3277
+ if (selectedItemProps?.href) {
3278
+ if (selectedItemProps.target) {
3279
+ window.open(selectedItemProps.href, selectedItemProps.target);
3280
+ } else {
3281
+ window.location.href = selectedItemProps?.href;
3282
+ }
3283
+ }
3284
+ };
3285
+ var ActionMenu = ({
3286
+ children: childrenProp,
3287
+ menuItems,
3288
+ MenuItemComponent,
3289
+ stateReducer: externalStateReducer,
3290
+ ...useSelectProps
3291
+ }) => {
3292
+ const { allMenuItems, menuItemsMap, children } = useMenuChildren({
3293
+ children: childrenProp,
3294
+ menuItems,
3295
+ MenuItemComponent
3296
+ });
3297
+ const { defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({
3298
+ isCombobox: false
3299
+ });
3300
+ const [currentSelectedItem, setCurrentSelectedItem] = import_react20.default.useState(null);
3301
+ const { isOpen, ...useSelectReturnProps } = (0, import_downshift3.useSelect)({
3302
+ ...defaultDownshiftProps.select,
3303
+ items: allMenuItems,
3304
+ itemToString,
3305
+ onStateChange: (changes) => handleStateChange(changes, currentSelectedItem),
3306
+ stateReducer: reduceReducers(
3307
+ defaultDownshiftProps.select.stateReducer,
3308
+ externalStateReducer
3309
+ ),
3310
+ ...useSelectProps
3311
+ });
3312
+ (0, import_react20.useEffect)(() => {
3313
+ setCurrentSelectedItem(useSelectReturnProps.selectedItem);
3314
+ }, [useSelectReturnProps.selectedItem]);
3315
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3316
+ MenuRoot,
3317
+ {
3318
+ ...{
3319
+ isListbox: false,
3320
+ items: allMenuItems,
3321
+ itemsMap: menuItemsMap,
3322
+ itemToString,
3323
+ isOpen,
3324
+ ...useSelectProps,
3325
+ ...useSelectReturnProps,
3326
+ ...restDefaults
3327
+ },
3328
+ children
3329
+ }
3330
+ );
3331
+ };
3332
+
3333
+ // src/SingleSelectMenu/SingleSelectMenu.tsx
3334
+ var import_react21 = require("react");
3335
+ var import_downshift4 = require("downshift");
3336
+ var import_jsx_runtime18 = require("react/jsx-runtime");
3337
+ var SingleSelectMenu = ({
3338
+ children: childrenProp,
3339
+ stateReducer: externalStateReducer,
3340
+ menuItems,
3341
+ MenuItemComponent,
3342
+ ...useSelectProps
3343
+ }) => {
3344
+ const { allMenuItems, menuItemsMap, children } = useMenuChildren({
3345
+ children: childrenProp,
3346
+ menuItems,
3347
+ MenuItemComponent
3348
+ });
3349
+ const { defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({
3350
+ isCombobox: false
3351
+ });
3352
+ const { isOpen, ...useSelectReturnProps } = (0, import_downshift4.useSelect)({
3353
+ ...defaultDownshiftProps.select,
3354
+ items: allMenuItems,
3355
+ itemToString,
3356
+ stateReducer: reduceReducers(
3357
+ defaultDownshiftProps.select.stateReducer,
3358
+ externalStateReducer
3359
+ ),
3360
+ ...useSelectProps
3361
+ });
3362
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
3363
+ MenuRoot,
3364
+ {
3365
+ ...{
3366
+ isListbox: true,
3367
+ items: allMenuItems,
3368
+ itemsMap: menuItemsMap,
3369
+ itemToString,
3370
+ isOpen,
3371
+ ...useSelectProps,
3372
+ ...useSelectReturnProps,
3373
+ ...restDefaults
3374
+ },
3375
+ children
3376
+ }
3377
+ );
3378
+ };
3379
+
3380
+ // src/MultiSelectMenu/MultiSelectMenu.tsx
3381
+ var import_react22 = require("react");
3382
+ var import_downshift5 = require("downshift");
3383
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2684
3384
  var MultiSelectMenu = ({
2685
3385
  children: childrenProp,
2686
- items,
2687
- MenuItemComponent = MenuItem,
3386
+ menuItems,
3387
+ MenuItemComponent,
3388
+ onSelectedItemChange: externalOnSelectedItemChange,
2688
3389
  stateReducer: externalStateReducer,
2689
3390
  getA11yMultiStatusMessage,
2690
3391
  onMultiSelectStateChange,
@@ -2693,18 +3394,20 @@ var MultiSelectMenu = ({
2693
3394
  }) => {
2694
3395
  const { allMenuItems, menuItemsMap, children } = useMenuChildren({
2695
3396
  children: childrenProp,
2696
- items,
3397
+ menuItems,
2697
3398
  MenuItemComponent
2698
3399
  });
2699
- const multiSelectOverrides = Object.entries({
2700
- ...useSelectProps,
2701
- getA11yStatusMessage: getA11yMultiStatusMessage,
2702
- onStateChange: onMultiSelectStateChange,
2703
- stateReducer: multiSelectStateReducer
2704
- }).reduce(
2705
- (a, [k, v]) => v ? (a[k] = v, a) : a,
2706
- {}
2707
- );
3400
+ const { defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({
3401
+ isCombobox: false,
3402
+ isMulti: true,
3403
+ // handles the prop name mapping for multi select
3404
+ multiSelectProps: {
3405
+ getA11yMultiStatusMessage,
3406
+ onMultiSelectStateChange,
3407
+ multiSelectStateReducer,
3408
+ ...useSelectProps
3409
+ }
3410
+ });
2708
3411
  const {
2709
3412
  getSelectedItemProps,
2710
3413
  addSelectedItem,
@@ -2712,30 +3415,23 @@ var MultiSelectMenu = ({
2712
3415
  selectedItems,
2713
3416
  getDropdownProps,
2714
3417
  ...useMultipleSelectionReturnProps
2715
- } = (0, import_downshift4.useMultipleSelection)(multiSelectOverrides);
2716
- const { isOpen, ...useSelectReturnProps } = (0, import_downshift4.useSelect)({
2717
- ...defaultUseSelectProps,
3418
+ } = (0, import_downshift5.useMultipleSelection)(defaultDownshiftProps.multi);
3419
+ const { isOpen, ...useSelectReturnProps } = (0, import_downshift5.useSelect)({
3420
+ ...defaultDownshiftProps.select,
2718
3421
  items: allMenuItems,
2719
3422
  itemToString,
2720
3423
  selectedItem: null,
2721
3424
  defaultHighlightedIndex: 0,
2722
- stateReducer: (state, actionAndChanges) => {
2723
- let newState;
2724
- newState = useSelectStateReducer(state, actionAndChanges);
2725
- newState = selectReducerForMultiSelect(state, {
2726
- ...actionAndChanges,
2727
- changes: newState
2728
- });
2729
- return externalStateReducer ? externalStateReducer(state, {
2730
- ...actionAndChanges,
2731
- changes: newState
2732
- }) : newState;
2733
- },
2734
- onStateChange: ({ type, selectedItem: newSelectedItem }) => {
3425
+ stateReducer: reduceReducers(
3426
+ defaultDownshiftProps.select.stateReducer,
3427
+ externalStateReducer
3428
+ ),
3429
+ onSelectedItemChange: (changes) => {
3430
+ const { type, selectedItem: newSelectedItem } = changes;
2735
3431
  switch (type) {
2736
- case import_downshift4.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
2737
- case import_downshift4.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
2738
- case import_downshift4.useSelect.stateChangeTypes.ItemClick:
3432
+ case import_downshift5.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
3433
+ case import_downshift5.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
3434
+ case import_downshift5.useSelect.stateChangeTypes.ItemClick:
2739
3435
  if (!newSelectedItem) break;
2740
3436
  if (selectedItems?.find((item) => item?.id === newSelectedItem.id)) {
2741
3437
  removeSelectedItem(newSelectedItem);
@@ -2752,10 +3448,11 @@ var MultiSelectMenu = ({
2752
3448
  default:
2753
3449
  break;
2754
3450
  }
3451
+ externalOnSelectedItemChange?.(changes);
2755
3452
  },
2756
3453
  ...useSelectProps
2757
3454
  });
2758
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
3455
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2759
3456
  MenuRoot,
2760
3457
  {
2761
3458
  ...{
@@ -2774,7 +3471,8 @@ var MultiSelectMenu = ({
2774
3471
  multiSelectStateReducer,
2775
3472
  ...useSelectProps,
2776
3473
  ...useSelectReturnProps,
2777
- ...useMultipleSelectionReturnProps
3474
+ ...useMultipleSelectionReturnProps,
3475
+ ...restDefaults
2778
3476
  },
2779
3477
  children
2780
3478
  }
@@ -2782,83 +3480,191 @@ var MultiSelectMenu = ({
2782
3480
  };
2783
3481
 
2784
3482
  // src/Autocomplete/Autocomplete.tsx
2785
- var import_react16 = __toESM(require("react"));
2786
- var import_downshift6 = require("downshift");
2787
-
2788
- // src/reducers/useComboboxStateReducer.tsx
2789
- var import_downshift5 = require("downshift");
2790
- var useComboboxStateReducer = (state, actionAndChanges) => {
2791
- const { type, changes } = actionAndChanges;
2792
- switch (type) {
2793
- /** If downshift is blurred by tabbing within the menu, stay open */
2794
- case import_downshift5.useCombobox.stateChangeTypes.InputBlur:
2795
- return {
2796
- ...changes,
2797
- // keep menu open on blur
2798
- isOpen: true
2799
- };
2800
- /** Return standard change payload */
2801
- default:
2802
- return changes;
2803
- }
2804
- };
2805
- var defaultUseComboboxProps = {
2806
- // disabling while item.hidden so that hidden items are ignored by downshift
2807
- isItemDisabled: (item) => Boolean(item.disabled || item.hidden)
2808
- };
3483
+ var import_react25 = require("react");
2809
3484
 
2810
- // src/Autocomplete/Autocomplete.tsx
2811
- var import_jsx_runtime16 = require("react/jsx-runtime");
2812
- var Autocomplete = ({
3485
+ // src/Autocomplete/SingleAutocomplete.tsx
3486
+ var import_react23 = require("react");
3487
+ var import_downshift6 = require("downshift");
3488
+ var import_jsx_runtime20 = require("react/jsx-runtime");
3489
+ var SingleAutocomplete = ({
2813
3490
  children: childrenProp,
2814
3491
  stateReducer: externalStateReducer,
2815
- items: itemsProp,
2816
- MenuItemComponent = MenuItem,
3492
+ menuItems,
3493
+ MenuItemComponent,
2817
3494
  itemToString: itemToString2 = itemToString,
2818
- getIsItemVisible = (item, inputValue) => itemToString2(item).toLowerCase().startsWith(inputValue.toLowerCase()),
3495
+ getIsItemVisible,
2819
3496
  ...useComboboxProps
2820
3497
  }) => {
2821
3498
  const { allMenuItems, children } = useMenuChildren({
2822
3499
  children: childrenProp,
2823
- items: itemsProp,
3500
+ menuItems,
2824
3501
  MenuItemComponent
2825
3502
  });
2826
- const [items, setItems] = import_react16.default.useState(allMenuItems);
3503
+ const { setHiddenItemsMap, defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({ isCombobox: true });
3504
+ const { updateFilteredItems } = useItemFiltering({
3505
+ allMenuItems,
3506
+ itemToString: itemToString2,
3507
+ getIsItemVisible,
3508
+ setHiddenItemsMap
3509
+ });
2827
3510
  const { isOpen, ...useComboboxReturnProps } = (0, import_downshift6.useCombobox)({
2828
- ...defaultUseComboboxProps,
2829
- items,
3511
+ ...defaultDownshiftProps.combobox,
3512
+ items: allMenuItems,
2830
3513
  itemToString: itemToString2,
2831
- onInputValueChange({ inputValue }) {
2832
- setItems(
2833
- inputValue ? allMenuItems.reduce(
2834
- (items2, item) => [
2835
- ...items2,
2836
- { ...item, hidden: !getIsItemVisible(item, inputValue) }
2837
- ],
2838
- []
2839
- ) : allMenuItems
2840
- );
3514
+ onInputValueChange: updateFilteredItems,
3515
+ stateReducer: reduceReducers(
3516
+ defaultDownshiftProps.combobox.stateReducer,
3517
+ externalStateReducer
3518
+ ),
3519
+ ...useComboboxProps
3520
+ });
3521
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
3522
+ MenuRoot,
3523
+ {
3524
+ ...{
3525
+ isListbox: true,
3526
+ items: allMenuItems,
3527
+ itemToString: itemToString2,
3528
+ isOpen,
3529
+ setHiddenItemsMap,
3530
+ ...useComboboxProps,
3531
+ ...useComboboxReturnProps,
3532
+ ...restDefaults
3533
+ },
3534
+ popoutProps: {
3535
+ focusOnContent: false
3536
+ },
3537
+ children
3538
+ }
3539
+ );
3540
+ };
3541
+
3542
+ // src/Autocomplete/MultiAutocomplete.tsx
3543
+ var import_react24 = __toESM(require("react"));
3544
+ var import_downshift7 = require("downshift");
3545
+ var import_jsx_runtime21 = require("react/jsx-runtime");
3546
+ var MultiAutocomplete = ({
3547
+ children: childrenProp,
3548
+ stateReducer: externalStateReducer,
3549
+ menuItems,
3550
+ MenuItemComponent,
3551
+ itemToString: itemToString2 = itemToString,
3552
+ itemToKey: itemToKey2 = itemToKey,
3553
+ getIsItemVisible = getDefaultGetIsItemVisible(itemToString2),
3554
+ showSelectedItemsInDropdown = false,
3555
+ initialSelectedItems = [],
3556
+ onStateChange,
3557
+ onSelectedItemsChange,
3558
+ getA11yMultiStatusMessage,
3559
+ onMultiSelectStateChange,
3560
+ multiSelectStateReducer,
3561
+ ...useComboboxProps
3562
+ }) => {
3563
+ const { allMenuItems, children } = useMenuChildren({
3564
+ children: childrenProp,
3565
+ menuItems,
3566
+ MenuItemComponent
3567
+ });
3568
+ const [selectedItems, setSelectedItems] = import_react24.default.useState(initialSelectedItems);
3569
+ const [selectedItemIds, setSelectedItemIds] = import_react24.default.useState(getSelectedItemIds(initialSelectedItems));
3570
+ const getIsItemVisibleMulti = import_react24.default.useCallback(
3571
+ (item, inputValue) => {
3572
+ return (showSelectedItemsInDropdown || !selectedItemIds[item.id]) && getIsItemVisible(item, inputValue);
2841
3573
  },
2842
- stateReducer: (state, actionAndChanges) => {
2843
- let newState;
2844
- newState = useComboboxStateReducer(state, actionAndChanges);
2845
- return externalStateReducer ? externalStateReducer(state, {
2846
- ...actionAndChanges,
2847
- changes: newState
2848
- }) : newState;
3574
+ [selectedItemIds, showSelectedItemsInDropdown, getIsItemVisible]
3575
+ );
3576
+ const getShouldFilterMulti = import_react24.default.useCallback(
3577
+ (args) => {
3578
+ return !showSelectedItemsInDropdown && Object.keys(selectedItemIds).length > 0 || defaultGetShouldFilter(args);
3579
+ },
3580
+ [selectedItemIds, showSelectedItemsInDropdown, getIsItemVisible]
3581
+ );
3582
+ const { setHiddenItemsMap, defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({
3583
+ isCombobox: true,
3584
+ isMulti: true,
3585
+ // handles the prop name mapping for multi select
3586
+ multiSelectProps: {
3587
+ getA11yMultiStatusMessage,
3588
+ onMultiSelectStateChange,
3589
+ multiSelectStateReducer,
3590
+ ...useComboboxProps
3591
+ }
3592
+ });
3593
+ const { updateFilteredItems } = useItemFiltering({
3594
+ allMenuItems,
3595
+ itemToString: itemToString2,
3596
+ getIsItemVisible: getIsItemVisibleMulti,
3597
+ getShouldFilter: getShouldFilterMulti,
3598
+ setHiddenItemsMap
3599
+ });
3600
+ import_react24.default.useEffect(() => {
3601
+ updateFilteredItems({ inputValue: "" });
3602
+ }, [selectedItemIds]);
3603
+ const useMultipleSelectionReturnProps = (0, import_downshift7.useMultipleSelection)({
3604
+ ...defaultDownshiftProps.multi,
3605
+ itemToKey: itemToKey2,
3606
+ selectedItems,
3607
+ onSelectedItemsChange: ({ selectedItems: selectedItems2, ...changes }) => {
3608
+ setSelectedItems(selectedItems2);
3609
+ setSelectedItemIds(getSelectedItemIds(selectedItems2));
3610
+ onSelectedItemsChange && onSelectedItemsChange({ selectedItems: selectedItems2, ...changes });
3611
+ }
3612
+ });
3613
+ const { isOpen, ...useComboboxReturnProps } = (0, import_downshift7.useCombobox)({
3614
+ ...defaultDownshiftProps.combobox,
3615
+ items: allMenuItems,
3616
+ itemToString: itemToString2,
3617
+ itemToKey: itemToKey2,
3618
+ stateReducer: reduceReducers(
3619
+ defaultDownshiftProps.combobox.stateReducer,
3620
+ externalStateReducer
3621
+ ),
3622
+ onStateChange(changes) {
3623
+ const { type, selectedItem: newSelectedItem, inputValue } = changes;
3624
+ switch (type) {
3625
+ // Add the selected item to the selected items list
3626
+ case import_downshift7.useCombobox.stateChangeTypes.InputKeyDownEnter:
3627
+ case import_downshift7.useCombobox.stateChangeTypes.ItemClick:
3628
+ if (newSelectedItem) {
3629
+ const newSelectedItems = [...selectedItems, newSelectedItem];
3630
+ setSelectedItems(newSelectedItems);
3631
+ setSelectedItemIds({
3632
+ ...selectedItemIds,
3633
+ [newSelectedItem.id]: true
3634
+ });
3635
+ onSelectedItemsChange && onSelectedItemsChange({
3636
+ selectedItems: newSelectedItems,
3637
+ type: import_downshift7.useMultipleSelection.stateChangeTypes.FunctionSetSelectedItems
3638
+ });
3639
+ }
3640
+ break;
3641
+ default:
3642
+ break;
3643
+ }
3644
+ if (inputValue !== void 0) updateFilteredItems({ inputValue });
3645
+ onStateChange && onStateChange(changes);
2849
3646
  },
2850
3647
  ...useComboboxProps
2851
3648
  });
2852
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3649
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2853
3650
  MenuRoot,
2854
3651
  {
2855
3652
  ...{
2856
3653
  isListbox: true,
2857
- items,
3654
+ items: allMenuItems,
2858
3655
  itemToString: itemToString2,
2859
3656
  isOpen,
3657
+ initialSelectedItems,
3658
+ onStateChange,
3659
+ onSelectedItemsChange,
3660
+ getA11yMultiStatusMessage,
3661
+ onMultiSelectStateChange,
3662
+ multiSelectStateReducer,
3663
+ setHiddenItemsMap,
2860
3664
  ...useComboboxProps,
2861
- ...useComboboxReturnProps
3665
+ ...useComboboxReturnProps,
3666
+ ...useMultipleSelectionReturnProps,
3667
+ ...restDefaults
2862
3668
  },
2863
3669
  popoutProps: {
2864
3670
  focusOnContent: false
@@ -2868,10 +3674,22 @@ var Autocomplete = ({
2868
3674
  );
2869
3675
  };
2870
3676
 
3677
+ // src/Autocomplete/Autocomplete.tsx
3678
+ var import_jsx_runtime22 = require("react/jsx-runtime");
3679
+ var Autocomplete = ({
3680
+ multiSelect,
3681
+ ...rest
3682
+ }) => {
3683
+ if (multiSelect) {
3684
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(MultiAutocomplete, { ...rest });
3685
+ }
3686
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SingleAutocomplete, { ...rest });
3687
+ };
3688
+
2871
3689
  // src/Autocomplete/AutocompleteInput.tsx
2872
- var import_react17 = require("react");
2873
- var import_seeds_react_input = require("@sproutsocial/seeds-react-input");
2874
- var import_jsx_runtime17 = require("react/jsx-runtime");
3690
+ var import_react26 = require("react");
3691
+ var import_seeds_react_input2 = require("@sproutsocial/seeds-react-input");
3692
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2875
3693
  var AutocompleteInput = ({
2876
3694
  onKeyDown,
2877
3695
  onChange,
@@ -2881,30 +3699,263 @@ var AutocompleteInput = ({
2881
3699
  inputProps,
2882
3700
  ...rest
2883
3701
  }) => {
2884
- const { getInputProps, inputValue } = (0, import_react17.useContext)(MenuContext);
2885
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2886
- import_seeds_react_input.Input,
3702
+ const { getInputComponentProps, inputValue, ref, ariaProps } = useMenuToggleContext();
3703
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3704
+ import_seeds_react_input2.Input,
2887
3705
  {
2888
3706
  id: "autocomplete_input",
2889
3707
  name: "autocomplete_input",
2890
- inputProps: {
2891
- ...getInputProps?.({
2892
- // refKey: "innerRef",
2893
- onKeyDown,
2894
- onChange,
2895
- onInput,
2896
- onBlur,
2897
- onClick,
2898
- value: inputValue
2899
- }),
2900
- ...inputProps
2901
- },
3708
+ ...getInputComponentProps({
3709
+ onKeyDown,
3710
+ onChange,
3711
+ onInput,
3712
+ onBlur,
3713
+ onClick,
3714
+ value: inputValue,
3715
+ ref,
3716
+ refKey: "innerRef",
3717
+ inputProps,
3718
+ ...ariaProps
3719
+ }),
2902
3720
  autoComplete: false,
2903
3721
  value: inputValue,
2904
3722
  ...rest
2905
3723
  }
2906
3724
  );
2907
3725
  };
3726
+
3727
+ // src/NestedMenu/NestedMenu.tsx
3728
+ var import_react29 = require("react");
3729
+
3730
+ // src/NestedMenu/NestedMenuContext.tsx
3731
+ var import_react27 = require("react");
3732
+ var import_jsx_runtime24 = require("react/jsx-runtime");
3733
+ var defaultNestedMenuContext = {
3734
+ selectedMenuPath: [],
3735
+ setSelectedMenuId: () => {
3736
+ },
3737
+ setSelectedMenuPath: () => {
3738
+ },
3739
+ goBack: () => {
3740
+ }
3741
+ };
3742
+ var NestedMenuContext = (0, import_react27.createContext)(
3743
+ defaultNestedMenuContext
3744
+ );
3745
+ var NestedMenuProvider = ({
3746
+ children,
3747
+ ...nestedMenuProps
3748
+ }) => {
3749
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NestedMenuContext.Provider, { value: nestedMenuProps, children });
3750
+ };
3751
+ var useNestedMenuContext = () => {
3752
+ const nestedMenuContextValue = (0, import_react27.useContext)(NestedMenuContext);
3753
+ if (nestedMenuContextValue === null) {
3754
+ throw new Error(
3755
+ "useNestedMenuContext must be used within a <NestedMenuContext.Provider />"
3756
+ );
3757
+ }
3758
+ return nestedMenuContextValue;
3759
+ };
3760
+
3761
+ // src/NestedMenu/NestedMenuHeader.tsx
3762
+ var import_seeds_react_button2 = require("@sproutsocial/seeds-react-button");
3763
+ var import_seeds_react_icon3 = require("@sproutsocial/seeds-react-icon");
3764
+ var import_jsx_runtime25 = require("react/jsx-runtime");
3765
+ var NestedMenuHeader = ({
3766
+ backArrowLabel,
3767
+ ...props
3768
+ }) => {
3769
+ const { goBack, selectedMenuPath } = useNestedMenuContext();
3770
+ const showBackArrow = selectedMenuPath.length > 1;
3771
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3772
+ MenuHeader,
3773
+ {
3774
+ leftAction: showBackArrow ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_seeds_react_button2.Button, { onClick: goBack, ariaLabel: backArrowLabel, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_seeds_react_icon3.Icon, { name: "arrow-left" }) }) : void 0,
3775
+ ...props
3776
+ }
3777
+ );
3778
+ };
3779
+
3780
+ // src/reducers/nestedMenuStateReducer.tsx
3781
+ var import_downshift8 = require("downshift");
3782
+ var nestedMenuStateReducer = (_state, actionAndChanges) => {
3783
+ const { type, changes } = actionAndChanges;
3784
+ const hasChildMenu = !!changes?.selectedItem?.menuItemProps?.childMenuId;
3785
+ if (!hasChildMenu) {
3786
+ return changes;
3787
+ }
3788
+ switch (type) {
3789
+ case import_downshift8.useSelect.stateChangeTypes.ToggleButtonBlur:
3790
+ case import_downshift8.useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
3791
+ case import_downshift8.useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
3792
+ case import_downshift8.useSelect.stateChangeTypes.ItemClick:
3793
+ case import_downshift8.useCombobox.stateChangeTypes.ItemClick:
3794
+ return {
3795
+ ...changes,
3796
+ isOpen: true,
3797
+ highlightedIndex: 0
3798
+ };
3799
+ default:
3800
+ return changes;
3801
+ }
3802
+ };
3803
+
3804
+ // src/NestedMenu/NestedMenuContent.tsx
3805
+ var import_react28 = require("react");
3806
+ var import_src = require("@sproutsocial/seeds-react-utilities/src/index");
3807
+
3808
+ // src/NestedMenu/NestedMenuItem.tsx
3809
+ var import_seeds_react_icon4 = require("@sproutsocial/seeds-react-icon");
3810
+ var import_seeds_react_box4 = require("@sproutsocial/seeds-react-box");
3811
+ var import_jsx_runtime26 = require("react/jsx-runtime");
3812
+ var NestedMenuItem = ({
3813
+ children,
3814
+ childMenuId,
3815
+ onClick: onClickProp,
3816
+ ...rest
3817
+ }) => {
3818
+ const { setSelectedMenuId } = useNestedMenuContext();
3819
+ const onClickProps = childMenuId ? {
3820
+ onClick: (e) => {
3821
+ onClickProp?.(e);
3822
+ setSelectedMenuId?.(childMenuId);
3823
+ }
3824
+ } : {};
3825
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MenuItem, { ...onClickProps, ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_seeds_react_box4.Box, { display: "flex", justifyContent: "space-between", children: [
3826
+ children,
3827
+ childMenuId && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MenuItemActionRight, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_seeds_react_icon4.Icon, { name: "arrow-right-outline" }) })
3828
+ ] }) });
3829
+ };
3830
+
3831
+ // src/NestedMenu/NestedMenuContent.tsx
3832
+ var import_jsx_runtime27 = require("react/jsx-runtime");
3833
+ var NestedMenuContent = ({
3834
+ innerRef: innerRefProp = null,
3835
+ onKeyDown: onKeyDownProp,
3836
+ children,
3837
+ menuItems,
3838
+ MenuItemComponent = NestedMenuItem,
3839
+ ...props
3840
+ }) => {
3841
+ const { highlightedIndex, items } = useMenuContentContext();
3842
+ const { setSelectedMenuId, selectedMenuPath, goBack } = useNestedMenuContext();
3843
+ const internalRef = (0, import_react28.useRef)(null);
3844
+ const innerRef = (0, import_src.mergeRefs)(internalRef, innerRefProp);
3845
+ const contentProps = children ? { children } : { menuItems, MenuItemComponent };
3846
+ (0, import_react28.useEffect)(() => {
3847
+ internalRef?.current?.focus();
3848
+ }, []);
3849
+ const onKeyDown = (e) => {
3850
+ onKeyDownProp?.(e);
3851
+ switch (e.key) {
3852
+ case "ArrowRight":
3853
+ case " ":
3854
+ case "Enter":
3855
+ if (highlightedIndex !== void 0 && highlightedIndex !== -1) {
3856
+ const item = items[highlightedIndex];
3857
+ if (item?.menuItemProps?.childMenuId !== void 0) {
3858
+ setSelectedMenuId?.(item?.menuItemProps?.childMenuId);
3859
+ }
3860
+ }
3861
+ break;
3862
+ case "ArrowLeft":
3863
+ if (selectedMenuPath.length > 1) {
3864
+ goBack?.();
3865
+ }
3866
+ break;
3867
+ }
3868
+ };
3869
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
3870
+ MenuContent,
3871
+ {
3872
+ onKeyDown,
3873
+ innerRef,
3874
+ ...contentProps,
3875
+ ...props
3876
+ }
3877
+ );
3878
+ };
3879
+
3880
+ // src/NestedMenu/NestedMenu.tsx
3881
+ var import_jsx_runtime28 = require("react/jsx-runtime");
3882
+ var NestedMenu = ({
3883
+ initialMenuId,
3884
+ menus,
3885
+ onBackButtonClick,
3886
+ backArrowLabel,
3887
+ menuToggleElement
3888
+ }) => {
3889
+ const [selectedMenuPath, setSelectedMenuPath] = (0, import_react29.useState)([initialMenuId]);
3890
+ const selectedMenuId = selectedMenuPath[selectedMenuPath.length - 1];
3891
+ const setSelectedMenuId = (id) => {
3892
+ setSelectedMenuPath((currentPath) => [...currentPath, id]);
3893
+ };
3894
+ const goBack = () => {
3895
+ setSelectedMenuPath((currentPath) => currentPath.slice(0, -1));
3896
+ onBackButtonClick?.(selectedMenuId);
3897
+ };
3898
+ const {
3899
+ MenuComponent,
3900
+ menuProps,
3901
+ MenuHeaderComponent = NestedMenuHeader,
3902
+ menuHeaderProps = {}
3903
+ } = menus[selectedMenuId] || {};
3904
+ const {
3905
+ children,
3906
+ menuItems,
3907
+ MenuItemComponent,
3908
+ stateReducer: externalStateReducer,
3909
+ onStateChange: externalOnStateChange,
3910
+ ...props
3911
+ } = menuProps || {};
3912
+ const stateReducer = reduceReducers(
3913
+ nestedMenuStateReducer,
3914
+ externalStateReducer
3915
+ );
3916
+ const onStateChange = (changes) => {
3917
+ externalOnStateChange?.(changes);
3918
+ if (changes.isOpen === false) {
3919
+ setTimeout(() => {
3920
+ setSelectedMenuPath([initialMenuId]);
3921
+ }, 100);
3922
+ }
3923
+ };
3924
+ const nestedMenuProps = {
3925
+ menuToggleElement,
3926
+ stateReducer,
3927
+ onStateChange,
3928
+ initialIsOpen: selectedMenuPath.length > 1,
3929
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
3930
+ MenuHeaderComponent && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3931
+ MenuHeaderComponent,
3932
+ {
3933
+ backArrowLabel,
3934
+ ...menuHeaderProps
3935
+ }
3936
+ ),
3937
+ children && children,
3938
+ menuItems && !children && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3939
+ NestedMenuContent,
3940
+ {
3941
+ menuItems,
3942
+ MenuItemComponent: MenuItemComponent ?? NestedMenuItem
3943
+ }
3944
+ )
3945
+ ] }),
3946
+ ...props
3947
+ };
3948
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3949
+ NestedMenuProvider,
3950
+ {
3951
+ selectedMenuPath,
3952
+ setSelectedMenuPath,
3953
+ setSelectedMenuId,
3954
+ goBack,
3955
+ children: MenuComponent && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MenuComponent, { ...nestedMenuProps })
3956
+ }
3957
+ );
3958
+ };
2908
3959
  // Annotate the CommonJS export names for ESM import in node:
2909
3960
  0 && (module.exports = {
2910
3961
  ActionMenu,
@@ -2912,31 +3963,51 @@ var AutocompleteInput = ({
2912
3963
  AutocompleteInput,
2913
3964
  INPUT_TYPES,
2914
3965
  MenuContent,
2915
- MenuContext,
3966
+ MenuContentContext,
3967
+ MenuContentProvider,
2916
3968
  MenuFooter,
2917
3969
  MenuGroup,
2918
3970
  MenuHeader,
2919
3971
  MenuItem,
2920
3972
  MenuItemAction,
3973
+ MenuItemActionLeft,
3974
+ MenuItemActionRight,
2921
3975
  MenuItemContainer,
2922
3976
  MenuItemRow,
2923
3977
  MenuItemText,
2924
3978
  MenuLabel,
2925
- MenuProvider,
2926
3979
  MenuRoot,
3980
+ MenuSearchInput,
3981
+ MenuSearchTokenInput,
2927
3982
  MenuToggleButton,
3983
+ MenuToggleContext,
3984
+ MenuToggleProvider,
3985
+ MenuTokenInput,
2928
3986
  MultiSelectMenu,
3987
+ NestedMenu,
3988
+ NestedMenuContent,
3989
+ NestedMenuContext,
3990
+ NestedMenuHeader,
3991
+ NestedMenuItem,
3992
+ NestedMenuProvider,
2929
3993
  SingleSelectMenu,
2930
3994
  StyledMenuGroup,
2931
3995
  StyledMenuGroupUl,
2932
3996
  StyledMenuItem,
2933
3997
  StyledTitle,
2934
- defaultUseSelectProps,
3998
+ SubmenuItem,
3999
+ checkIfItemSelected,
4000
+ defaultMenuContext,
4001
+ getChildrenFromMenuItems,
4002
+ getSelectedItemIds,
2935
4003
  mapMenuItems,
2936
4004
  useMenu,
2937
4005
  useMenuChildren,
2938
- useMenuContext,
2939
- useSelectStateReducer
4006
+ useMenuContentContext,
4007
+ useMenuToggleContext,
4008
+ useNestedMenuContext,
4009
+ useSelectStateReducer,
4010
+ useSelectStateReducerForMulti
2940
4011
  });
2941
4012
  /*! Bundled license information:
2942
4013