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