@sproutsocial/seeds-react-menu 0.5.0 → 0.6.0

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