@sproutsocial/seeds-react-menu 0.4.1 → 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 (105) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +32 -0
  3. package/dist/esm/index.js +1553 -423
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/index.d.mts +303 -122
  6. package/dist/index.d.ts +303 -122
  7. package/dist/index.js +1561 -405
  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 +30 -26
  12. package/src/ActionMenu/ActionMenuTypes.ts +13 -8
  13. package/src/ActionMenu/__tests__/ActionMenu.test.tsx +17 -30
  14. package/src/ActionMenu/__tests__/ActionMenu.typetest.tsx +32 -3
  15. package/src/Autocomplete/Autocomplete.stories.tsx +61 -2
  16. package/src/Autocomplete/Autocomplete.tsx +15 -74
  17. package/src/Autocomplete/AutocompleteInput.tsx +18 -27
  18. package/src/Autocomplete/AutocompleteTokenInput.tsx +50 -0
  19. package/src/Autocomplete/AutocompleteTypes.ts +27 -11
  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 +116 -3
  24. package/src/MenuContent/MenuContent.stories.tsx +164 -0
  25. package/src/MenuContent/MenuContent.tsx +35 -8
  26. package/src/MenuContent/MenuContentTypes.ts +7 -5
  27. package/src/MenuContent/__tests__/MenuContent.typetest.tsx +18 -2
  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 +21 -21
  32. package/src/MenuGroup/MenuGroup.stories.tsx +248 -0
  33. package/src/MenuGroup/MenuGroup.tsx +9 -7
  34. package/src/MenuGroup/MenuGroupTypes.ts +8 -6
  35. package/src/MenuGroup/__tests__/MenuGroup.test.tsx +6 -6
  36. package/src/MenuGroup/__tests__/MenuGroup.typetest.tsx +23 -4
  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 -9
  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 +44 -67
  65. package/src/MultiSelectMenu/MultiSelectMenuTypes.ts +9 -5
  66. package/src/MultiSelectMenu/__tests__/MultiSelectMenu.test.tsx +46 -60
  67. package/src/MultiSelectMenu/__tests__/MultiSelectMenu.typetest.tsx +29 -2
  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 +29 -25
  81. package/src/SingleSelectMenu/SingleSelectMenuTypes.ts +9 -5
  82. package/src/SingleSelectMenu/__tests__/SingleSelectMenu.typetest.tsx +32 -2
  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/__tests__/Menu.test.tsx +38 -0
  91. package/src/hooks/useDownshiftDefaults.tsx +107 -0
  92. package/src/hooks/useItemFiltering.tsx +66 -0
  93. package/src/hooks/useMenuChildren.tsx +279 -0
  94. package/src/index.ts +7 -1
  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 -5
  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/hooks/useItemsFromChildren.tsx +0 -131
  105. package/src/utils/itemToString.ts +0 -5
package/dist/esm/index.js CHANGED
@@ -94,27 +94,37 @@ var require_object_assign = __commonJS({
94
94
  }
95
95
  });
96
96
 
97
- // src/MenuItem/MenuItem.tsx
98
- import "react";
99
-
100
97
  // src/MenuContext.tsx
101
- import {
102
- createContext,
103
- useMemo,
104
- useContext
105
- } from "react";
98
+ import React, { createContext, useMemo, useContext } from "react";
106
99
  import { jsx } from "react/jsx-runtime";
107
100
  var defaultMenuContext = {
108
101
  items: [],
109
- itemsMap: {}
110
- };
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;
111
115
  var useMenu = ({
112
116
  items = [],
113
117
  isListbox = false,
114
118
  isOpen = false,
115
119
  itemsMap: itemsMapFromProps,
120
+ selectedItemIds: selectedItemIdsFromProps,
121
+ selectedItem,
122
+ selectedItems,
123
+ getInputProps,
124
+ contentRef: contentRefFromProps,
116
125
  ...rest
117
126
  } = {}) => {
127
+ const contentRef = contentRefFromProps || React.createRef();
118
128
  const menuProps = useMemo(() => ({ ...rest }), [rest]);
119
129
  const itemsMap = useMemo(
120
130
  () => itemsMapFromProps || items.reduce((map, item) => {
@@ -125,27 +135,90 @@ var useMenu = ({
125
135
  }, {}),
126
136
  [items, itemsMapFromProps]
127
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
+ );
128
179
  return {
129
180
  isOpen,
130
181
  isListbox,
131
182
  items,
132
183
  itemsMap,
184
+ selectedItem,
185
+ selectedItems,
186
+ selectedItemIds,
187
+ isItemSelected,
188
+ getInputProps,
189
+ getInputComponentProps,
190
+ contentRef,
133
191
  ...menuProps
134
192
  };
135
193
  };
136
- var MenuContext = createContext(defaultMenuContext);
137
- var MenuProvider = ({
194
+ var MenuToggleContext = createContext(defaultMenuContext);
195
+ var MenuToggleProvider = ({
138
196
  children,
139
- menuProps
197
+ menuContext
140
198
  }) => {
141
- const filterContext = useMenu(menuProps);
142
- return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { ...filterContext }, children });
199
+ return /* @__PURE__ */ jsx(MenuToggleContext.Provider, { value: { ...menuContext }, children });
143
200
  };
144
- var useMenuContext = () => {
145
- const menuContextValue = useContext(MenuContext);
201
+ var useMenuToggleContext = () => {
202
+ const menuContextValue = useContext(MenuToggleContext);
146
203
  if (menuContextValue === null) {
147
204
  throw new Error(
148
- "useMenuContext must be used within a <MenuContext.Provider />"
205
+ "useMenuToggleContext must be used within a <MenuToggleContext.Provider />"
206
+ );
207
+ }
208
+ return menuContextValue;
209
+ };
210
+ var MenuContentContext = createContext(defaultMenuContext);
211
+ var MenuContentProvider = ({
212
+ children,
213
+ menuContext
214
+ }) => {
215
+ return /* @__PURE__ */ jsx(MenuContentContext.Provider, { value: { ...menuContext }, children });
216
+ };
217
+ var useMenuContentContext = () => {
218
+ const menuContextValue = useContext(MenuContentContext);
219
+ if (menuContextValue === null) {
220
+ throw new Error(
221
+ "useMenuContentContext must be used within a <MenuContentContext.Provider />"
149
222
  );
150
223
  }
151
224
  return menuContextValue;
@@ -1695,6 +1768,10 @@ var highlightedStyles = css4`
1695
1768
  color: ${({ theme: theme2 }) => theme2.colors.text.body};
1696
1769
  text-decoration: none;
1697
1770
  `;
1771
+ var activeStyles = css4`
1772
+ background-color: ${({ theme: theme2 }) => theme2.colors.listItem.background.active};
1773
+ color: ${({ theme: theme2 }) => theme2.colors.text.inverse};
1774
+ `;
1698
1775
  var MenuItemContainer = styled.li`
1699
1776
  box-sizing: border-box;
1700
1777
  list-style-type: none;
@@ -1709,7 +1786,7 @@ var MenuItemContainer = styled.li`
1709
1786
  margin-bottom: ${({ theme: theme2 }) => theme2.space[300]};
1710
1787
  }
1711
1788
  `;
1712
- var StyledMenuItem = styled.div`
1789
+ var StyledMenuItem = styled.button`
1713
1790
  display: block;
1714
1791
  box-sizing: border-box;
1715
1792
  width: 100%;
@@ -1748,10 +1825,12 @@ var StyledMenuItem = styled.div`
1748
1825
  ${focusRing}
1749
1826
  }
1750
1827
 
1828
+ /* Active */
1829
+ ${({ $active }) => $active && activeStyles}
1830
+
1751
1831
  /* Pressed state*/
1752
1832
  &:active {
1753
- background-color: ${({ theme: theme2 }) => theme2.colors.listItem.background.active};
1754
- color: ${({ theme: theme2 }) => theme2.colors.text.inverse};
1833
+ ${activeStyles}
1755
1834
  }
1756
1835
 
1757
1836
  &[aria-disabled="true"] {
@@ -1772,12 +1851,17 @@ var MenuItemRow = styled.div`
1772
1851
  pointer-events: none;
1773
1852
  `;
1774
1853
  var MenuItemAction = styled.div`
1775
- margin-right: ${({ theme: theme2 }) => theme2.space[300]};
1776
1854
  display: flex;
1777
1855
  align-items: center;
1778
1856
  justify-content: center;
1779
1857
  flex-shrink: 0;
1780
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
+ `;
1781
1865
  var MenuItemText = styled.div`
1782
1866
  word-break: break-word;
1783
1867
  flex-grow: 1;
@@ -1785,7 +1869,7 @@ var MenuItemText = styled.div`
1785
1869
  `;
1786
1870
 
1787
1871
  // src/MenuItem/useOptionProps.tsx
1788
- import { useContext as useContext2, useMemo as useMemo2 } from "react";
1872
+ import { useMemo as useMemo2 } from "react";
1789
1873
  import { Icon } from "@sproutsocial/seeds-react-icon";
1790
1874
  import { Checkbox } from "@sproutsocial/seeds-react-checkbox";
1791
1875
  import { Switch } from "@sproutsocial/seeds-react-switch";
@@ -1808,6 +1892,7 @@ var SelectionIndicator = ({
1808
1892
  return /* @__PURE__ */ jsx2(
1809
1893
  Checkbox,
1810
1894
  {
1895
+ tabIndex: -1,
1811
1896
  onChange: () => {
1812
1897
  },
1813
1898
  checked: selected,
@@ -1819,6 +1904,7 @@ var SelectionIndicator = ({
1819
1904
  return /* @__PURE__ */ jsx2(
1820
1905
  Switch,
1821
1906
  {
1907
+ tabIndex: -1,
1822
1908
  onClick: inputStub,
1823
1909
  checked: !!selected,
1824
1910
  "aria-labelledby": labeledBy,
@@ -1829,6 +1915,7 @@ var SelectionIndicator = ({
1829
1915
  return /* @__PURE__ */ jsx2(
1830
1916
  Radio,
1831
1917
  {
1918
+ tabIndex: -1,
1832
1919
  checked: selected,
1833
1920
  id: `MenuItem-${inputType}-${id}`,
1834
1921
  name: `MenuItem-${inputType}`,
@@ -1852,9 +1939,9 @@ var useOptionProps = ({
1852
1939
  inputLabelId,
1853
1940
  ...props
1854
1941
  }) => {
1855
- const { selectedItem, selectedItems, isListbox } = useContext2(MenuContext);
1942
+ const { selectedItem, selectedItems, isListbox, isItemSelected } = useMenuContentContext();
1856
1943
  const selected = useMemo2(
1857
- () => selectedItem?.id === id || !!selectedItems?.find((item) => item?.id === id),
1944
+ () => isItemSelected(id),
1858
1945
  [selectedItem, selectedItems]
1859
1946
  );
1860
1947
  const label = inputLabelId || `menu-item-child-${id}`;
@@ -1862,7 +1949,7 @@ var useOptionProps = ({
1862
1949
  active: selected,
1863
1950
  ["aria-selected"]: selected,
1864
1951
  children: /* @__PURE__ */ jsxs(MenuItemRow, { children: [
1865
- /* @__PURE__ */ jsx2(MenuItemAction, { children: /* @__PURE__ */ jsx2(
1952
+ /* @__PURE__ */ jsx2(MenuItemActionLeft, { children: /* @__PURE__ */ jsx2(
1866
1953
  SelectionIndicator,
1867
1954
  {
1868
1955
  id,
@@ -1885,12 +1972,19 @@ var MenuItem = ({
1885
1972
  onClick,
1886
1973
  onKeyDown,
1887
1974
  disabled: disabled2 = false,
1888
- ref,
1975
+ active,
1976
+ innerRef,
1889
1977
  href,
1890
1978
  color: color2,
1891
1979
  ...props
1892
1980
  }) => {
1893
- const { getItemProps, itemsMap, highlightedIndex, isListbox } = useMenuContext();
1981
+ const {
1982
+ getItemProps,
1983
+ itemsMap,
1984
+ highlightedIndex,
1985
+ isListbox,
1986
+ hiddenItemsMap = {}
1987
+ } = useMenuContentContext();
1894
1988
  const { ...optionProps } = useOptionProps({
1895
1989
  id,
1896
1990
  children,
@@ -1898,23 +1992,26 @@ var MenuItem = ({
1898
1992
  });
1899
1993
  const item = itemsMap[id] || { index: 0, id };
1900
1994
  const highlighted = highlightedIndex === item?.index;
1901
- 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(
1902
1996
  StyledMenuItem,
1903
1997
  {
1904
1998
  id,
1905
1999
  $highlighted: highlighted,
2000
+ $active: active,
1906
2001
  ...getItemProps?.({
1907
2002
  ...isListbox ? {} : { role: "menuitem" },
1908
2003
  item,
1909
2004
  index: item.index,
1910
- // This prop no longer supported in downshift
2005
+ // The disabled prop no longer supported in downshift. Use isItemDisabled instead.
1911
2006
  // disabled,
1912
2007
  onClick,
1913
- onKeyDown
2008
+ onKeyDown,
2009
+ ref: innerRef
1914
2010
  }),
1915
2011
  as: isListbox ? void 0 : href ? "a" : "button",
1916
2012
  href,
1917
2013
  children,
2014
+ tabIndex: -1,
1918
2015
  ...optionProps,
1919
2016
  ...props
1920
2017
  }
@@ -1957,14 +2054,13 @@ var MenuTitleText = styled2.h3`
1957
2054
  color: ${({ theme: theme2 }) => theme2.colors.text.headline};
1958
2055
  font-weight: ${({ theme: theme2 }) => theme2.fontWeights.bold};
1959
2056
  margin: 0px;
1960
- flex-grow: 2;
1961
- justify-self: start;
2057
+ flex-grow: 1;
1962
2058
 
1963
2059
  ${({ theme: theme2 }) => theme2.typography[200]}
1964
2060
 
1965
2061
  ${({ $leftAction, theme: theme2 }) => $leftAction && `
1966
- padding-left: ${theme2.space[350]};
1967
- `}
2062
+ padding-left: ${theme2.space[350]};
2063
+ `}
1968
2064
  `;
1969
2065
  var MenuChildrenContainer = styled2.div`
1970
2066
  grid-column: 1 / -1;
@@ -1972,19 +2068,24 @@ var MenuChildrenContainer = styled2.div`
1972
2068
  `;
1973
2069
  var MenuHeaderFeatures = styled2.div`
1974
2070
  display: flex;
2071
+ align-items: center;
2072
+ justify-content: space-between;
2073
+ width: 100%;
1975
2074
 
1976
- > a {
1977
- white-space: nowrap;
1978
- }
1979
-
1980
- &:first-child {
1981
- flex-grow: 1;
1982
- 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;
1983
2082
  }
1984
2083
 
1985
- &:last-child {
1986
- flex-grow: 1;
1987
- justify-self: end;
2084
+ > a,
2085
+ > button {
2086
+ display: flex;
2087
+ align-items: center;
2088
+ word-break: break-word;
1988
2089
  }
1989
2090
  `;
1990
2091
 
@@ -2001,7 +2102,7 @@ var MenuHeader = ({
2001
2102
  /* @__PURE__ */ jsxs2(MenuHeaderFeatures, { $leftAction: !!leftAction, children: [
2002
2103
  leftAction && leftAction,
2003
2104
  title && /* @__PURE__ */ jsx4(MenuTitleText, { $leftAction: !!leftAction, children: title }),
2004
- rightAction && rightAction
2105
+ rightAction && /* @__PURE__ */ jsx4("div", { className: "right-action", children: rightAction })
2005
2106
  ] }),
2006
2107
  children && /* @__PURE__ */ jsx4(MenuChildrenContainer, { children })
2007
2108
  ] }) });
@@ -2015,25 +2116,216 @@ var StyledMenuContent = styled3(motion.ul)`
2015
2116
  padding: 0;
2016
2117
  `;
2017
2118
 
2119
+ // src/hooks/useMenuChildren.tsx
2120
+ import React4, { useMemo as useMemo3 } from "react";
2121
+ import { Fragment as Fragment3, jsx as jsx5 } from "react/jsx-runtime";
2122
+ var walkAllChildren = (children, callback) => {
2123
+ const walk = (element, parents2) => {
2124
+ if (element === null || element === void 0) return;
2125
+ callback(element, parents2);
2126
+ const newParents = [...parents2, element];
2127
+ const children2 = element.props?.children;
2128
+ React4.Children.toArray(children2).forEach((child) => {
2129
+ walk(child, newParents);
2130
+ });
2131
+ };
2132
+ const parents = [];
2133
+ React4.Children.toArray(children).forEach((child) => {
2134
+ walk(child, parents);
2135
+ });
2136
+ };
2137
+ var getComponentName = (element) => {
2138
+ if (element && typeof element === "object" && "type" in element && typeof element.type !== "string" && typeof element.type.name === "string") {
2139
+ return element.type.name;
2140
+ }
2141
+ };
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
+ }) => {
2217
+ walkAllChildren(children, (element) => {
2218
+ switch (getComponentName(element)) {
2219
+ case "MenuItem":
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
2232
+ });
2233
+ break;
2234
+ case "MenuGroup":
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
2240
+ });
2241
+ break;
2242
+ case "MenuContent":
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
2249
+ });
2250
+ break;
2251
+ default:
2252
+ break;
2253
+ }
2254
+ });
2255
+ };
2256
+ var mapMenuItems = ({
2257
+ menuItems,
2258
+ MenuItemComponent = MenuItem
2259
+ }) => {
2260
+ return /* @__PURE__ */ jsx5(Fragment3, { children: menuItems.map((menuItemProps) => /* @__PURE__ */ jsx5(MenuItemComponent, { ...menuItemProps }, menuItemProps.id)) });
2261
+ };
2262
+ var getChildrenFromMenuItems = ({
2263
+ menuItems,
2264
+ MenuItemComponent
2265
+ }) => /* @__PURE__ */ jsx5(MenuContent, { menuItems, MenuItemComponent });
2266
+ var useMenuChildren = ({
2267
+ children: childrenProp,
2268
+ menuItems,
2269
+ MenuItemComponent
2270
+ }) => {
2271
+ const { allMenuItems, menuItemsMap, children } = useMemo3(() => {
2272
+ let children2 = /* @__PURE__ */ jsx5(Fragment3, {});
2273
+ const menuItemsMap2 = {};
2274
+ const allMenuItems2 = [];
2275
+ if (menuItems && menuItems.length) {
2276
+ menuItems.forEach((menuItem) => {
2277
+ addMenuItem({ itemProps: menuItem, allMenuItems: allMenuItems2, menuItemsMap: menuItemsMap2 });
2278
+ });
2279
+ children2 = getChildrenFromMenuItems({ menuItems, MenuItemComponent });
2280
+ } else if (childrenProp) {
2281
+ children2 = childrenProp;
2282
+ setMenuItemsFromChildren({
2283
+ children: childrenProp,
2284
+ allMenuItems: allMenuItems2,
2285
+ menuItemsMap: menuItemsMap2
2286
+ });
2287
+ }
2288
+ return { allMenuItems: allMenuItems2, menuItemsMap: menuItemsMap2, children: children2 };
2289
+ }, [childrenProp, menuItems, MenuItemComponent]);
2290
+ return { allMenuItems, menuItemsMap, children };
2291
+ };
2292
+
2018
2293
  // src/MenuContent/MenuContent.tsx
2019
- import { jsx as jsx5 } from "react/jsx-runtime";
2294
+ import { useCallback } from "react";
2295
+ import { jsx as jsx6 } from "react/jsx-runtime";
2020
2296
  var MenuContent = ({
2021
2297
  id = "menu_content",
2022
- children,
2298
+ children: childrenProp,
2299
+ menuItems,
2300
+ MenuItemComponent,
2301
+ onKeyDown,
2302
+ innerRef = null,
2023
2303
  ...rest
2024
2304
  }) => {
2025
- const { getToggleButtonProps, getMenuProps, isListbox } = useMenuContext();
2026
- return /* @__PURE__ */ jsx5(
2305
+ const { getToggleButtonProps, getMenuProps, isListbox } = useMenuContentContext();
2306
+ const toggleButtonProps = getToggleButtonProps?.();
2307
+ const children = childrenProp || !menuItems || !menuItems.length ? childrenProp : mapMenuItems({ menuItems, MenuItemComponent });
2308
+ if (!children) {
2309
+ return null;
2310
+ }
2311
+ const handleKeyDown = useCallback(
2312
+ (e) => {
2313
+ toggleButtonProps?.["onKeyDown"]?.(e);
2314
+ onKeyDown?.(e);
2315
+ },
2316
+ [onKeyDown, toggleButtonProps?.["onKeyDown"]]
2317
+ );
2318
+ return /* @__PURE__ */ jsx6(
2027
2319
  StyledMenuContent,
2028
2320
  {
2029
2321
  autoFocus: true,
2030
2322
  id,
2031
2323
  tabIndex: 0,
2032
- onKeyDown: getToggleButtonProps?.()["onKeyDown"] || void 0,
2033
- "aria-activedescendant": getToggleButtonProps?.()["aria-activedescendant"],
2324
+ onKeyDown: handleKeyDown,
2325
+ "aria-activedescendant": toggleButtonProps?.["aria-activedescendant"],
2034
2326
  ...getMenuProps?.(
2035
2327
  {
2036
- ...isListbox ? {} : { role: "menu" }
2328
+ ...isListbox ? { ref: innerRef } : { ref: innerRef, role: "menu" }
2037
2329
  },
2038
2330
  // Suppress ref error for now
2039
2331
  { suppressRefError: true }
@@ -2056,9 +2348,9 @@ var StyledMenuFooterBox = styled4(Box2)`
2056
2348
  `;
2057
2349
 
2058
2350
  // src/MenuFooter/MenuFooter.tsx
2059
- import { jsx as jsx6 } from "react/jsx-runtime";
2351
+ import { jsx as jsx7 } from "react/jsx-runtime";
2060
2352
  var MenuFooter = ({ children, ...rest }) => {
2061
- return /* @__PURE__ */ jsx6(StyledMenuFooterBox, { ...rest, children });
2353
+ return /* @__PURE__ */ jsx7(StyledMenuFooterBox, { ...rest, children });
2062
2354
  };
2063
2355
 
2064
2356
  // src/MenuGroup/MenuGroup.tsx
@@ -2078,7 +2370,7 @@ import {
2078
2370
  GRID,
2079
2371
  TYPOGRAPHY
2080
2372
  } from "@sproutsocial/seeds-react-system-props";
2081
- import { jsx as jsx7 } from "react/jsx-runtime";
2373
+ import { jsx as jsx8 } from "react/jsx-runtime";
2082
2374
  import "react";
2083
2375
  var Container = styled5.span`
2084
2376
  margin: 0;
@@ -2139,7 +2431,7 @@ var SmallBodyCopy = styled22(styles_default)`
2139
2431
  `;
2140
2432
  var Text = ({ fontSize: fontSize2, children, qa, color: color2, ...rest }) => {
2141
2433
  const qaText = typeof children === "string" ? children : void 0;
2142
- return /* @__PURE__ */ jsx7(
2434
+ return /* @__PURE__ */ jsx8(
2143
2435
  styles_default,
2144
2436
  {
2145
2437
  typeScale: fontSize2,
@@ -2154,7 +2446,7 @@ var Text = ({ fontSize: fontSize2, children, qa, color: color2, ...rest }) => {
2154
2446
  var withTextLogic = (Component) => {
2155
2447
  return ({ children, ...props }) => {
2156
2448
  const qaText = typeof children === "string" ? children : void 0;
2157
- return /* @__PURE__ */ jsx7(Component, { "data-qa-text": qaText, ...props, children });
2449
+ return /* @__PURE__ */ jsx8(Component, { "data-qa-text": qaText, ...props, children });
2158
2450
  };
2159
2451
  };
2160
2452
  var HeadlineWithLogic = withTextLogic(Headline);
@@ -2199,6 +2491,7 @@ var StyledMenuGroup = styled6.li`
2199
2491
  ${space}
2200
2492
  `;
2201
2493
  var StyledTitle = styled6(index_default.SmallSubHeadline)`
2494
+ font-size: ${({ theme: theme2 }) => theme2.typography[200].fontSize};
2202
2495
  margin: ${({ theme: theme2 }) => theme2.space[400]} ${({ theme: theme2 }) => theme2.space[400]}
2203
2496
  0px ${({ theme: theme2 }) => theme2.space[400]};
2204
2497
  `;
@@ -2208,7 +2501,7 @@ var StyledMenuGroupUl = styled6.ul`
2208
2501
  `;
2209
2502
 
2210
2503
  // src/MenuGroup/MenuGroup.tsx
2211
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
2504
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
2212
2505
  var MenuGroup = ({
2213
2506
  titleAs = "h3",
2214
2507
  children: childrenProp,
@@ -2216,12 +2509,12 @@ var MenuGroup = ({
2216
2509
  color: color2,
2217
2510
  isSingleSelect,
2218
2511
  id,
2219
- items,
2220
- MenuItemComponent = MenuItem,
2512
+ menuItems,
2513
+ MenuItemComponent,
2221
2514
  ...rest
2222
2515
  }) => {
2223
2516
  const titleId = `menu-group-title-${Math.random().toString(36).slice(2, 11)}`;
2224
- const children = childrenProp || !items || !items.length ? childrenProp : items.map((item) => /* @__PURE__ */ jsx8(MenuItemComponent, { ...item }, item.id));
2517
+ const children = childrenProp || !menuItems || !menuItems.length ? childrenProp : mapMenuItems({ menuItems, MenuItemComponent });
2225
2518
  if (!children) {
2226
2519
  return null;
2227
2520
  }
@@ -2235,18 +2528,18 @@ var MenuGroup = ({
2235
2528
  color: color2,
2236
2529
  ...rest,
2237
2530
  children: [
2238
- title && /* @__PURE__ */ jsx8(StyledTitle, { role: "heading", as: titleAs, id: titleId, children: title }),
2239
- /* @__PURE__ */ jsx8(StyledMenuGroupUl, { children })
2531
+ title && /* @__PURE__ */ jsx9(StyledTitle, { role: "heading", as: titleAs, id: titleId, children: title }),
2532
+ /* @__PURE__ */ jsx9(StyledMenuGroupUl, { children })
2240
2533
  ]
2241
2534
  }
2242
2535
  );
2243
2536
  };
2244
2537
 
2245
2538
  // src/MenuRoot/MenuRoot.tsx
2246
- import { useCallback } from "react";
2539
+ import { useCallback as useCallback2 } from "react";
2247
2540
  import styled7 from "styled-components";
2248
2541
  import { Popout } from "@sproutsocial/seeds-react-popout";
2249
- import { jsx as jsx9 } from "react/jsx-runtime";
2542
+ import { jsx as jsx10 } from "react/jsx-runtime";
2250
2543
  var CustomPopoutContent = styled7(Popout.Content)`
2251
2544
  padding: 0;
2252
2545
  margin-left: 0;
@@ -2255,24 +2548,26 @@ var CustomPopoutContent = styled7(Popout.Content)`
2255
2548
  var MenuRoot = ({
2256
2549
  children,
2257
2550
  menuToggleElement,
2258
- popoutProps: { focusLockProps, ...popoutProps } = {},
2551
+ popoutProps: { placement = "bottom", focusLockProps, ...popoutProps } = {},
2259
2552
  width: width2 = "300px",
2260
2553
  ...contextProps
2261
2554
  }) => {
2262
2555
  const { isOpen, openMenu, closeMenu } = contextProps;
2263
- const setIsOpen = useCallback(
2556
+ const setIsOpen = useCallback2(
2264
2557
  (newIsOpen) => {
2265
2558
  newIsOpen ? openMenu?.() : closeMenu?.();
2266
2559
  },
2267
2560
  [openMenu, closeMenu]
2268
2561
  );
2269
- return /* @__PURE__ */ jsx9(MenuProvider, { menuProps: contextProps, children: /* @__PURE__ */ jsx9(
2562
+ const menuContext = useMenu(contextProps);
2563
+ return /* @__PURE__ */ jsx10(
2270
2564
  Popout,
2271
2565
  {
2272
2566
  menuPopout: true,
2567
+ placement,
2273
2568
  isOpen: !!isOpen,
2274
2569
  setIsOpen,
2275
- content: /* @__PURE__ */ jsx9(CustomPopoutContent, { width: width2, children }),
2570
+ content: /* @__PURE__ */ jsx10(MenuContentProvider, { menuContext, children: /* @__PURE__ */ jsx10(CustomPopoutContent, { width: width2, children }) }),
2276
2571
  focusLockProps: {
2277
2572
  // correct jerking motion when scrolling while the Popout is open
2278
2573
  // returnFocus: false,
@@ -2281,37 +2576,38 @@ var MenuRoot = ({
2281
2576
  },
2282
2577
  disableWrapperAria: true,
2283
2578
  ...popoutProps,
2284
- children: menuToggleElement
2579
+ children: (toggleProps) => /* @__PURE__ */ jsx10(MenuToggleProvider, { menuContext: { ...menuContext, ...toggleProps }, children: menuToggleElement })
2285
2580
  }
2286
- ) });
2581
+ );
2287
2582
  };
2288
2583
 
2289
2584
  // src/MenuLabel.tsx
2290
2585
  import "react";
2291
2586
  import { Label } from "@sproutsocial/seeds-react-label";
2292
- import { jsx as jsx10 } from "react/jsx-runtime";
2587
+ import { jsx as jsx11 } from "react/jsx-runtime";
2293
2588
  var MenuLabel = ({ children, ...rest }) => {
2294
- const { getLabelProps } = useMenuContext();
2295
- return /* @__PURE__ */ jsx10(Label, { htmlFor: "fallback_menu_label", ...getLabelProps?.(), ...rest, children });
2589
+ const { getLabelProps } = useMenuToggleContext();
2590
+ return /* @__PURE__ */ jsx11(Label, { htmlFor: "fallback_menu_label", ...getLabelProps?.(), ...rest, children });
2296
2591
  };
2297
2592
 
2298
- // src/MenuToggleButton.tsx
2299
- import { useContext as useContext3 } from "react";
2593
+ // src/MenuToggleButton/MenuToggleButton.tsx
2594
+ import "react";
2300
2595
  import { Button } from "@sproutsocial/seeds-react-button";
2301
- import { jsx as jsx11 } from "react/jsx-runtime";
2596
+ import { jsx as jsx12 } from "react/jsx-runtime";
2302
2597
  var MenuToggleButton = ({
2303
2598
  children,
2304
2599
  ...rest
2305
2600
  }) => {
2306
- const { getToggleButtonProps, isListbox, getDropdownProps } = useContext3(MenuContext);
2307
- return /* @__PURE__ */ jsx11(
2601
+ const { getToggleButtonProps, isListbox, getDropdownProps, ref, ariaProps } = useMenuToggleContext();
2602
+ return /* @__PURE__ */ jsx12(
2308
2603
  Button,
2309
2604
  {
2310
2605
  appearance: "secondary",
2311
2606
  ...getToggleButtonProps?.({
2312
2607
  // Decide if we want the preventKeyAction stuff. Maybe create a prop to allow for this to be overriden.
2313
- ...getDropdownProps?.({ preventKeyAction: true }),
2608
+ ...getDropdownProps?.({ ref, preventKeyAction: true }) || { ref },
2314
2609
  refKey: "innerRef",
2610
+ ...ariaProps,
2315
2611
  ...isListbox ? {} : { role: "button", "aria-haspopup": "menu" }
2316
2612
  }),
2317
2613
  ...rest,
@@ -2320,235 +2616,705 @@ var MenuToggleButton = ({
2320
2616
  );
2321
2617
  };
2322
2618
 
2323
- // src/ActionMenu/ActionMenu.tsx
2324
- import React10, { useEffect } from "react";
2325
- import {
2326
- useSelect as useSelect2
2327
- } from "downshift";
2328
-
2329
- // src/hooks/useItemsFromChildren.tsx
2330
- import React9, { useMemo as useMemo4 } from "react";
2331
- var walkAllChildren = (children, callback) => {
2332
- const walk = (element, parents2) => {
2333
- if (element === null || element === void 0) return;
2334
- callback(element, parents2);
2335
- const newParents = [...parents2, element];
2336
- const children2 = element.props?.children;
2337
- React9.Children.toArray(children2).forEach((child) => {
2338
- walk(child, newParents);
2339
- });
2340
- };
2341
- const parents = [];
2342
- React9.Children.toArray(children).forEach((child) => {
2343
- walk(child, parents);
2344
- });
2345
- };
2346
- var checkIfIsElement = (element, name) => {
2347
- return !!(element && typeof element === "object" && "type" in element && typeof element.type !== "string" && typeof element.type.name === "string" && element.type.name === name);
2348
- };
2349
- var getAllMenuItems = (children) => {
2350
- const orderedElements = [];
2351
- walkAllChildren(children, (element) => {
2352
- if (checkIfIsElement(element, "MenuItem")) {
2353
- orderedElements.push({
2354
- type: "item",
2355
- element
2356
- });
2357
- } else if (checkIfIsElement(element, "MenuGroup")) {
2358
- orderedElements.push({
2359
- type: "group",
2360
- element
2361
- });
2362
- }
2363
- });
2364
- return { orderedElements };
2365
- };
2366
- var useItemsFromChildren = ({
2367
- children
2368
- }) => {
2369
- const { allMenuItems, menuItemsMap } = useMemo4(() => {
2370
- const { orderedElements } = getAllMenuItems(children);
2371
- const menuItemsMap2 = {};
2372
- const allMenuItems2 = [];
2373
- let index = 0;
2374
- orderedElements.forEach(({ type, element }) => {
2375
- if (type === "group") {
2376
- const menuGroup = element;
2377
- const items = menuGroup.props.items;
2378
- if (items) {
2379
- items.forEach((menuItem) => {
2380
- const item = {
2381
- id: menuItem.id,
2382
- index: index++,
2383
- disabled: menuItem.disabled,
2384
- menuItemProps: menuItem,
2385
- menuGroupProps: element.props
2386
- };
2387
- allMenuItems2.push(item);
2388
- menuItemsMap2[`${item.id}`] = item;
2389
- });
2390
- } else if (menuGroup.props.children) {
2391
- let children2 = menuGroup.props.children;
2392
- if (!Array.isArray(children2)) {
2393
- children2 = [children2];
2394
- }
2395
- children2.forEach((menuItem) => {
2396
- const item = {
2397
- id: menuItem.props.id,
2398
- index: index++,
2399
- disabled: menuItem.props.disabled,
2400
- menuItemProps: menuItem.props,
2401
- menuGroupProps: element.props
2402
- };
2403
- allMenuItems2.push(item);
2404
- menuItemsMap2[`${item.id}`] = item;
2405
- });
2406
- }
2407
- } else {
2408
- if (menuItemsMap2[`${element.props.id}`]) return;
2409
- const menuItem = element;
2410
- const item = {
2411
- id: menuItem.props.id,
2412
- index: index++,
2413
- disabled: menuItem.props.disabled,
2414
- menuItemProps: menuItem.props
2415
- };
2416
- allMenuItems2.push(item);
2417
- menuItemsMap2[`${item.id}`] = item;
2418
- }
2419
- });
2420
- return { allMenuItems: allMenuItems2, menuItemsMap: menuItemsMap2 };
2421
- }, [children]);
2422
- return { allMenuItems, menuItemsMap };
2423
- };
2619
+ // src/MenuSearchInput/MenuSearchInput.tsx
2620
+ import React11 from "react";
2621
+ import { Input } from "@sproutsocial/seeds-react-input";
2424
2622
 
2425
- // src/reducers/useSelectStateReducer.tsx
2426
- import { useSelect } from "downshift";
2427
- var useSelectStateReducer = (state, actionAndChanges) => {
2428
- const { type, changes } = actionAndChanges;
2429
- switch (type) {
2430
- /** If downshift is blurred by tabbing within the menu, stay open */
2431
- case useSelect.stateChangeTypes.ToggleButtonBlur:
2432
- return {
2433
- ...changes,
2434
- // keep menu open on blur
2435
- isOpen: true
2436
- };
2437
- /** Return standard change payload */
2438
- default:
2439
- return changes;
2440
- }
2441
- };
2442
- var defaultUseSelectProps = {
2443
- stateReducer: useSelectStateReducer,
2444
- isItemDisabled: (item) => !!item.disabled
2445
- };
2623
+ // src/hooks/useItemFiltering.tsx
2624
+ import React10 from "react";
2446
2625
 
2447
- // src/utils/itemToString.ts
2626
+ // src/utils/downshiftDefaults.ts
2448
2627
  var itemToString = (item) => {
2449
2628
  return item ? item.id : "";
2450
2629
  };
2451
-
2452
- // src/ActionMenu/ActionMenu.tsx
2453
- import { jsx as jsx12 } from "react/jsx-runtime";
2454
- var handleStateChange = (changes, currentSelectedItem) => {
2455
- if (!(changes.type === useSelect2.stateChangeTypes.ToggleButtonKeyDownEnter || changes.type === useSelect2.stateChangeTypes.ToggleButtonKeyDownSpaceButton)) {
2456
- return;
2457
- }
2458
- const selectedItem = changes.selectedItem || currentSelectedItem;
2459
- if (!selectedItem) return;
2460
- if (selectedItem.disabled) {
2461
- return;
2462
- }
2463
- const isEnterKeyDown = changes.type === useSelect2.stateChangeTypes.ToggleButtonKeyDownEnter;
2464
- const selectedItemProps = selectedItem.menuItemProps;
2465
- if (selectedItemProps?.onClick) {
2466
- const syntheticKeyboardEvent = new KeyboardEvent("keydown", {
2467
- key: isEnterKeyDown ? "Enter" : " ",
2468
- code: isEnterKeyDown ? "Enter" : "Space",
2469
- bubbles: true,
2470
- cancelable: true,
2471
- view: window
2472
- });
2473
- selectedItemProps?.onClick?.(
2474
- syntheticKeyboardEvent
2475
- );
2476
- }
2477
- if (selectedItemProps?.href) {
2478
- if (selectedItemProps.target) {
2479
- window.open(selectedItemProps.href, selectedItemProps.target);
2480
- } else {
2481
- window.location.href = selectedItemProps?.href;
2482
- }
2483
- }
2630
+ var itemToKey = (item) => {
2631
+ return item ? item.id : "";
2484
2632
  };
2485
- var ActionMenu = ({
2486
- children,
2487
- stateReducer: externalStateReducer,
2488
- ...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
2489
2643
  }) => {
2490
- const { allMenuItems, menuItemsMap } = useItemsFromChildren({ children });
2491
- const [currentSelectedItem, setCurrentSelectedItem] = React10.useState(null);
2492
- const { isOpen, ...useSelectReturnProps } = useSelect2({
2493
- ...defaultUseSelectProps,
2494
- items: allMenuItems,
2495
- itemToString,
2496
- onStateChange: (changes) => handleStateChange(changes, currentSelectedItem),
2497
- stateReducer: (state, actionAndChanges) => {
2498
- let newState;
2499
- newState = useSelectStateReducer(state, actionAndChanges);
2500
- return externalStateReducer ? externalStateReducer(state, {
2501
- ...actionAndChanges,
2502
- changes: newState
2503
- }) : 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);
2504
2653
  },
2505
- ...useSelectProps
2506
- });
2507
- useEffect(() => {
2508
- setCurrentSelectedItem(useSelectReturnProps.selectedItem);
2509
- }, [useSelectReturnProps.selectedItem]);
2510
- return /* @__PURE__ */ jsx12(
2511
- MenuRoot,
2512
- {
2513
- ...{
2514
- isListbox: false,
2515
- items: allMenuItems,
2516
- itemsMap: menuItemsMap,
2517
- itemToString,
2518
- isOpen,
2519
- ...useSelectProps,
2520
- ...useSelectReturnProps
2521
- },
2522
- children
2523
- }
2654
+ [allMenuItems, getIsItemVisible, getShouldFilter]
2524
2655
  );
2656
+ return {
2657
+ getIsItemVisible,
2658
+ updateFilteredItems
2659
+ };
2525
2660
  };
2526
2661
 
2527
- // src/SingleSelectMenu/SingleSelectMenu.tsx
2528
- import "react";
2529
- import { useSelect as useSelect3 } from "downshift";
2662
+ // src/MenuSearchInput/MenuSearchInput.tsx
2530
2663
  import { jsx as jsx13 } from "react/jsx-runtime";
2531
- var SingleSelectMenu = ({
2532
- children,
2533
- stateReducer: externalStateReducer,
2534
- ...useSelectProps
2664
+ var MenuSearchInput = ({
2665
+ getIsItemVisible,
2666
+ ...inputProps
2535
2667
  }) => {
2536
- const { allMenuItems, menuItemsMap } = useItemsFromChildren({ children });
2537
- const { isOpen, ...useSelectReturnProps } = useSelect3({
2538
- ...defaultUseSelectProps,
2539
- items: allMenuItems,
2540
- itemToString,
2541
- stateReducer: (state, actionAndChanges) => {
2542
- let newState;
2543
- newState = useSelectStateReducer(state, actionAndChanges);
2544
- return externalStateReducer ? externalStateReducer(state, {
2545
- ...actionAndChanges,
2546
- changes: newState
2547
- }) : newState;
2668
+ const {
2669
+ items,
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
2680
+ });
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);
2688
+ },
2689
+ [getToggleButtonProps]
2690
+ );
2691
+ return /* @__PURE__ */ jsx13(
2692
+ Input,
2693
+ {
2694
+ onChange: (e, value) => {
2695
+ updateFilteredItems({ inputValue: value });
2696
+ },
2697
+ onKeyDown: handleKeyDown,
2698
+ autoComplete: false,
2699
+ ...inputProps
2700
+ }
2701
+ );
2702
+ };
2703
+
2704
+ // src/MenuTokenInput.tsx
2705
+ import React12 from "react";
2706
+ import styled8 from "styled-components";
2707
+ import {
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;
2714
+ }
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
2733
+ }) => {
2734
+ const {
2735
+ itemToString: itemToString2,
2736
+ getSelectedItemProps,
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);
2548
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
+ ),
2549
3265
  ...useSelectProps
2550
3266
  });
2551
- return /* @__PURE__ */ jsx13(
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(
2552
3318
  MenuRoot,
2553
3319
  {
2554
3320
  ...{
@@ -2558,7 +3324,8 @@ var SingleSelectMenu = ({
2558
3324
  itemToString,
2559
3325
  isOpen,
2560
3326
  ...useSelectProps,
2561
- ...useSelectReturnProps
3327
+ ...useSelectReturnProps,
3328
+ ...restDefaults
2562
3329
  },
2563
3330
  children
2564
3331
  }
@@ -2567,47 +3334,35 @@ var SingleSelectMenu = ({
2567
3334
 
2568
3335
  // src/MultiSelectMenu/MultiSelectMenu.tsx
2569
3336
  import "react";
2570
- import {
2571
- useSelect as useSelect4,
2572
- useMultipleSelection
2573
- } from "downshift";
2574
- import { jsx as jsx14 } from "react/jsx-runtime";
2575
- var selectReducerForMultiSelect = (state, actionAndChanges) => {
2576
- const { changes, type } = actionAndChanges;
2577
- switch (type) {
2578
- case useSelect4.stateChangeTypes.ToggleButtonKeyDownEnter:
2579
- case useSelect4.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
2580
- case useSelect4.stateChangeTypes.ItemClick:
2581
- return {
2582
- ...changes,
2583
- isOpen: true,
2584
- // keep the menu open after selection.
2585
- // TODO: Confirm that keeping highlightedIndex the same is the desired UX
2586
- // highlightedIndex: 0, // with the first option highlighted.
2587
- highlightedIndex: state.highlightedIndex
2588
- // keep highlightedIndex the same instead of returning to 0
2589
- };
2590
- }
2591
- return changes;
2592
- };
3337
+ import { useSelect as useSelect4, useMultipleSelection } from "downshift";
3338
+ import { jsx as jsx19 } from "react/jsx-runtime";
2593
3339
  var MultiSelectMenu = ({
2594
- children,
3340
+ children: childrenProp,
3341
+ menuItems,
3342
+ MenuItemComponent,
3343
+ onSelectedItemChange: externalOnSelectedItemChange,
2595
3344
  stateReducer: externalStateReducer,
2596
3345
  getA11yMultiStatusMessage,
2597
3346
  onMultiSelectStateChange,
2598
3347
  multiSelectStateReducer,
2599
3348
  ...useSelectProps
2600
3349
  }) => {
2601
- const { allMenuItems, menuItemsMap } = useItemsFromChildren({ children });
2602
- const multiSelectOverrides = Object.entries({
2603
- ...useSelectProps,
2604
- getA11yStatusMessage: getA11yMultiStatusMessage,
2605
- onStateChange: onMultiSelectStateChange,
2606
- stateReducer: multiSelectStateReducer
2607
- }).reduce(
2608
- (a, [k, v]) => v ? (a[k] = v, a) : a,
2609
- {}
2610
- );
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
+ });
2611
3366
  const {
2612
3367
  getSelectedItemProps,
2613
3368
  addSelectedItem,
@@ -2615,26 +3370,19 @@ var MultiSelectMenu = ({
2615
3370
  selectedItems,
2616
3371
  getDropdownProps,
2617
3372
  ...useMultipleSelectionReturnProps
2618
- } = useMultipleSelection(multiSelectOverrides);
3373
+ } = useMultipleSelection(defaultDownshiftProps.multi);
2619
3374
  const { isOpen, ...useSelectReturnProps } = useSelect4({
2620
- ...defaultUseSelectProps,
3375
+ ...defaultDownshiftProps.select,
2621
3376
  items: allMenuItems,
2622
3377
  itemToString,
2623
3378
  selectedItem: null,
2624
3379
  defaultHighlightedIndex: 0,
2625
- stateReducer: (state, actionAndChanges) => {
2626
- let newState;
2627
- newState = useSelectStateReducer(state, actionAndChanges);
2628
- newState = selectReducerForMultiSelect(state, {
2629
- ...actionAndChanges,
2630
- changes: newState
2631
- });
2632
- return externalStateReducer ? externalStateReducer(state, {
2633
- ...actionAndChanges,
2634
- changes: newState
2635
- }) : newState;
2636
- },
2637
- onStateChange: ({ type, selectedItem: newSelectedItem }) => {
3380
+ stateReducer: reduceReducers(
3381
+ defaultDownshiftProps.select.stateReducer,
3382
+ externalStateReducer
3383
+ ),
3384
+ onSelectedItemChange: (changes) => {
3385
+ const { type, selectedItem: newSelectedItem } = changes;
2638
3386
  switch (type) {
2639
3387
  case useSelect4.stateChangeTypes.ToggleButtonKeyDownEnter:
2640
3388
  case useSelect4.stateChangeTypes.ToggleButtonKeyDownSpaceButton:
@@ -2655,10 +3403,11 @@ var MultiSelectMenu = ({
2655
3403
  default:
2656
3404
  break;
2657
3405
  }
3406
+ externalOnSelectedItemChange?.(changes);
2658
3407
  },
2659
3408
  ...useSelectProps
2660
3409
  });
2661
- return /* @__PURE__ */ jsx14(
3410
+ return /* @__PURE__ */ jsx19(
2662
3411
  MenuRoot,
2663
3412
  {
2664
3413
  ...{
@@ -2677,7 +3426,8 @@ var MultiSelectMenu = ({
2677
3426
  multiSelectStateReducer,
2678
3427
  ...useSelectProps,
2679
3428
  ...useSelectReturnProps,
2680
- ...useMultipleSelectionReturnProps
3429
+ ...useMultipleSelectionReturnProps,
3430
+ ...restDefaults
2681
3431
  },
2682
3432
  children
2683
3433
  }
@@ -2685,77 +3435,191 @@ var MultiSelectMenu = ({
2685
3435
  };
2686
3436
 
2687
3437
  // src/Autocomplete/Autocomplete.tsx
2688
- import React13 from "react";
2689
- import { useCombobox as useCombobox2 } from "downshift";
2690
-
2691
- // src/reducers/useComboboxStateReducer.tsx
2692
- import { useCombobox } from "downshift";
2693
- var useComboboxStateReducer = (state, actionAndChanges) => {
2694
- const { type, changes } = actionAndChanges;
2695
- switch (type) {
2696
- /** If downshift is blurred by tabbing within the menu, stay open */
2697
- case useCombobox.stateChangeTypes.InputBlur:
2698
- return {
2699
- ...changes,
2700
- // keep menu open on blur
2701
- isOpen: true
2702
- };
2703
- /** Return standard change payload */
2704
- default:
2705
- return changes;
2706
- }
2707
- };
2708
- var defaultUseComboboxProps = {
2709
- // disabling while item.hidden so that hidden items are ignored by downshift
2710
- isItemDisabled: (item) => Boolean(item.disabled || item.hidden)
2711
- };
3438
+ import "react";
2712
3439
 
2713
- // src/Autocomplete/Autocomplete.tsx
2714
- import { jsx as jsx15 } from "react/jsx-runtime";
2715
- var Autocomplete = ({
2716
- children,
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 = ({
3445
+ children: childrenProp,
2717
3446
  stateReducer: externalStateReducer,
3447
+ menuItems,
3448
+ MenuItemComponent,
2718
3449
  itemToString: itemToString2 = itemToString,
2719
- getIsItemVisible = (item, inputValue) => itemToString2(item).toLowerCase().startsWith(inputValue.toLowerCase()),
3450
+ getIsItemVisible,
2720
3451
  ...useComboboxProps
2721
3452
  }) => {
2722
- const { allMenuItems } = useItemsFromChildren({ children });
2723
- const [items, setItems] = React13.useState(allMenuItems);
3453
+ const { allMenuItems, children } = useMenuChildren({
3454
+ children: childrenProp,
3455
+ menuItems,
3456
+ MenuItemComponent
3457
+ });
3458
+ const { setHiddenItemsMap, defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({ isCombobox: true });
3459
+ const { updateFilteredItems } = useItemFiltering({
3460
+ allMenuItems,
3461
+ itemToString: itemToString2,
3462
+ getIsItemVisible,
3463
+ setHiddenItemsMap
3464
+ });
2724
3465
  const { isOpen, ...useComboboxReturnProps } = useCombobox2({
2725
- ...defaultUseComboboxProps,
2726
- items,
3466
+ ...defaultDownshiftProps.combobox,
3467
+ items: allMenuItems,
2727
3468
  itemToString: itemToString2,
2728
- onInputValueChange({ inputValue }) {
2729
- setItems(
2730
- inputValue ? allMenuItems.reduce(
2731
- (items2, item) => [
2732
- ...items2,
2733
- { ...item, hidden: !getIsItemVisible(item, inputValue) }
2734
- ],
2735
- []
2736
- ) : allMenuItems
2737
- );
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);
2738
3528
  },
2739
- stateReducer: (state, actionAndChanges) => {
2740
- let newState;
2741
- newState = useComboboxStateReducer(state, actionAndChanges);
2742
- return externalStateReducer ? externalStateReducer(state, {
2743
- ...actionAndChanges,
2744
- changes: newState
2745
- }) : 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);
2746
3601
  },
2747
3602
  ...useComboboxProps
2748
3603
  });
2749
- return /* @__PURE__ */ jsx15(
3604
+ return /* @__PURE__ */ jsx21(
2750
3605
  MenuRoot,
2751
3606
  {
2752
3607
  ...{
2753
3608
  isListbox: true,
2754
- items,
3609
+ items: allMenuItems,
2755
3610
  itemToString: itemToString2,
2756
3611
  isOpen,
3612
+ initialSelectedItems,
3613
+ onStateChange,
3614
+ onSelectedItemsChange,
3615
+ getA11yMultiStatusMessage,
3616
+ onMultiSelectStateChange,
3617
+ multiSelectStateReducer,
3618
+ setHiddenItemsMap,
2757
3619
  ...useComboboxProps,
2758
- ...useComboboxReturnProps
3620
+ ...useComboboxReturnProps,
3621
+ ...useMultipleSelectionReturnProps,
3622
+ ...restDefaults
2759
3623
  },
2760
3624
  popoutProps: {
2761
3625
  focusOnContent: false
@@ -2765,10 +3629,22 @@ var Autocomplete = ({
2765
3629
  );
2766
3630
  };
2767
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
+
2768
3644
  // src/Autocomplete/AutocompleteInput.tsx
2769
- import { useContext as useContext4 } from "react";
2770
- import { Input } from "@sproutsocial/seeds-react-input";
2771
- import { jsx as jsx16 } 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";
2772
3648
  var AutocompleteInput = ({
2773
3649
  onKeyDown,
2774
3650
  onChange,
@@ -2778,60 +3654,314 @@ var AutocompleteInput = ({
2778
3654
  inputProps,
2779
3655
  ...rest
2780
3656
  }) => {
2781
- const { getInputProps, inputValue } = useContext4(MenuContext);
2782
- return /* @__PURE__ */ jsx16(
2783
- Input,
3657
+ const { getInputComponentProps, inputValue, ref, ariaProps } = useMenuToggleContext();
3658
+ return /* @__PURE__ */ jsx23(
3659
+ Input2,
2784
3660
  {
2785
3661
  id: "autocomplete_input",
2786
3662
  name: "autocomplete_input",
2787
- inputProps: {
2788
- ...getInputProps?.({
2789
- // refKey: "innerRef",
2790
- onKeyDown,
2791
- onChange,
2792
- onInput,
2793
- onBlur,
2794
- onClick,
2795
- value: inputValue
2796
- }),
2797
- ...inputProps
2798
- },
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
+ }),
2799
3675
  autoComplete: false,
2800
3676
  value: inputValue,
2801
3677
  ...rest
2802
3678
  }
2803
3679
  );
2804
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
+ };
2805
3914
  export {
2806
3915
  ActionMenu,
2807
3916
  Autocomplete,
2808
3917
  AutocompleteInput,
2809
3918
  INPUT_TYPES,
2810
3919
  MenuContent,
2811
- MenuContext,
3920
+ MenuContentContext,
3921
+ MenuContentProvider,
2812
3922
  MenuFooter,
2813
3923
  MenuGroup,
2814
3924
  MenuHeader,
2815
3925
  MenuItem,
2816
3926
  MenuItemAction,
3927
+ MenuItemActionLeft,
3928
+ MenuItemActionRight,
2817
3929
  MenuItemContainer,
2818
3930
  MenuItemRow,
2819
3931
  MenuItemText,
2820
3932
  MenuLabel,
2821
- MenuProvider,
2822
3933
  MenuRoot,
3934
+ MenuSearchInput,
3935
+ MenuSearchTokenInput,
2823
3936
  MenuToggleButton,
3937
+ MenuToggleContext,
3938
+ MenuToggleProvider,
3939
+ MenuTokenInput,
2824
3940
  MultiSelectMenu,
3941
+ NestedMenu,
3942
+ NestedMenuContent,
3943
+ NestedMenuContext,
3944
+ NestedMenuHeader,
3945
+ NestedMenuItem,
3946
+ NestedMenuProvider,
2825
3947
  SingleSelectMenu,
2826
3948
  StyledMenuGroup,
2827
3949
  StyledMenuGroupUl,
2828
3950
  StyledMenuItem,
2829
3951
  StyledTitle,
2830
- defaultUseSelectProps,
2831
- useItemsFromChildren,
3952
+ SubmenuItem,
3953
+ checkIfItemSelected,
3954
+ defaultMenuContext,
3955
+ getChildrenFromMenuItems,
3956
+ getSelectedItemIds,
3957
+ mapMenuItems,
2832
3958
  useMenu,
2833
- useMenuContext,
2834
- useSelectStateReducer
3959
+ useMenuChildren,
3960
+ useMenuContentContext,
3961
+ useMenuToggleContext,
3962
+ useNestedMenuContext,
3963
+ useSelectStateReducer,
3964
+ useSelectStateReducerForMulti
2835
3965
  };
2836
3966
  /*! Bundled license information:
2837
3967