@sproutsocial/seeds-react-menu 1.2.1 → 1.2.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-menu",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Seeds React Menu",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -78,8 +78,8 @@ const handleStateChange = (
78
78
  * @description An ActionMenu contains a list of clickable items like buttons or links. ActionMenus do not hold a selection.
79
79
  *
80
80
  * **To select menu items:**
81
- * @see {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/SingleSelectMenu | SingleSelectMenu}
82
- * @see {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MultiSelectMenu | MultiSelectMenu}
81
+ * @see {@link https://seeds.sproutsocial.com/components/single-select-menu SingleSelectMenu}
82
+ * @see {@link https://seeds.sproutsocial.com/components/multi-select-menu MultiSelectMenu}
83
83
  */
84
84
  export const ActionMenu = <I extends TypeMenuItemProps = TypeMenuItemProps>({
85
85
  children: childrenProp,
@@ -52,9 +52,7 @@ export const AutocompleteTextInputExample: Story = {
52
52
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
53
53
  menuToggleElement={
54
54
  <>
55
- <MenuLabel htmlFor="my-combobox" mb={300}>
56
- Choose a book
57
- </MenuLabel>
55
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
58
56
  <AutocompleteInput />
59
57
  </>
60
58
  }
@@ -80,9 +78,7 @@ export const AutocompleteWithItemsAsProps: Story = {
80
78
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
81
79
  menuToggleElement={
82
80
  <>
83
- <MenuLabel htmlFor="my-combobox" mb={300}>
84
- Choose a book
85
- </MenuLabel>
81
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
86
82
  <AutocompleteInput />
87
83
  </>
88
84
  }
@@ -104,9 +100,7 @@ export const AutocompleteTextWithButtonExample: Story = {
104
100
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
105
101
  menuToggleElement={
106
102
  <>
107
- <MenuLabel htmlFor="my-combobox" mb={300}>
108
- Choose a book
109
- </MenuLabel>
103
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
110
104
  <Box display="flex" alignItems="center" gap={200}>
111
105
  <AutocompleteInput style={{ flex: 2 }} />
112
106
  <MenuToggleButton>
@@ -137,9 +131,7 @@ export const AutocompleteTokenInputExample: Story = {
137
131
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
138
132
  menuToggleElement={
139
133
  <>
140
- <MenuLabel htmlFor="my-combobox" mb={300}>
141
- Choose a book
142
- </MenuLabel>
134
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
143
135
  <AutocompleteTokenInput />
144
136
  <MenuToggleButton mt={200} width="100%" p="0">
145
137
  <Icon name="chevron-down" aria-label="Open Menu" />
@@ -170,9 +162,7 @@ export const AutocompleteSelectExample: Story = {
170
162
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
171
163
  menuToggleElement={
172
164
  <>
173
- <MenuLabel htmlFor="my-combobox" mb={300}>
174
- Choose a book
175
- </MenuLabel>
165
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
176
166
  <AutocompleteSelect />
177
167
  </>
178
168
  }
@@ -247,9 +237,7 @@ const TestControlledMultiAutocomplete = (args: CustomAutocompleteArgs) => {
247
237
  itemToString={(item) => (item ? TEST_BOOKS[item.index].title : "")}
248
238
  menuToggleElement={
249
239
  <>
250
- <MenuLabel htmlFor="my-combobox" mb={300}>
251
- Choose a book
252
- </MenuLabel>
240
+ <MenuLabel mb={300}>Choose a book</MenuLabel>
253
241
  <AutocompleteTokenInput />
254
242
  <MenuToggleButton mt={200} width="100%" p="0">
255
243
  <Icon name="chevron-down" aria-label="Open Menu" />
@@ -1,7 +1,6 @@
1
1
  import React from "react";
2
2
 
3
3
  import type { TypeMenuItemProps } from "../MenuItem";
4
- import type { TypeMenuRootProps } from "../MenuRoot";
5
4
  import type { TypeAutocompleteProps } from "./AutocompleteTypes";
6
5
  import { SingleAutocomplete } from "./SingleAutocomplete";
7
6
  import { MultiAutocomplete } from "./MultiAutocomplete";
@@ -9,11 +8,11 @@ import { MultiAutocomplete } from "./MultiAutocomplete";
9
8
  /**
10
9
  * @link https://seeds.sproutsocial.com/components/autocomplete/
11
10
  *
12
- * @description A Autocomplete allows selecting a {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems} to be selected from a list or groups of lists to populate an input.
11
+ * @description A Autocomplete allows selecting {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems} from a list or groups of lists to populate an input.
13
12
  *
14
13
  */
15
14
  export const Autocomplete = <I extends TypeMenuItemProps = TypeMenuItemProps>({
16
- multiSelect,
15
+ multiSelect = false,
17
16
  ...rest
18
17
  }: TypeAutocompleteProps<I>) => {
19
18
  if (multiSelect) {
@@ -1,34 +1,38 @@
1
- import type { TypeMenuRootOwnProps } from "../MenuRoot";
2
1
  import type {
3
2
  TypeDownshiftComboboxProps,
4
3
  TypeDownshiftMultiSelectProps,
5
4
  } from "../MenuContext";
6
5
  import type { TypeGetIsItemVisibleFn } from "../hooks/useItemFiltering";
7
- import type { TypeMenuRootProps } from "../MenuRoot";
8
6
  import type { TypeMenuItemProps } from "../MenuItem";
9
7
  import type {
10
8
  TypeChildrenOrItems,
11
9
  TypeHigherOrderComponentProps,
12
10
  } from "../types";
13
11
 
14
- export type TypeSingleAutocompleteProps<
15
- I extends TypeMenuItemProps = TypeMenuItemProps
16
- > = TypeHigherOrderComponentProps &
17
- TypeChildrenOrItems<I> &
12
+ export type TypeBaseAutocompleteProps = TypeHigherOrderComponentProps &
18
13
  TypeDownshiftComboboxProps & {
14
+ /** A function that can be passed to override the default filtering logic */
19
15
  getIsItemVisible?: TypeGetIsItemVisibleFn;
16
+ /** Set multiSelect to true to allow multiple selections.
17
+ * Default: false*/
18
+ multiSelect?: boolean;
20
19
  };
21
20
 
21
+ export type TypeSingleAutocompleteProps<
22
+ I extends TypeMenuItemProps = TypeMenuItemProps
23
+ > = TypeBaseAutocompleteProps & {
24
+ multiSelect?: false;
25
+ } & TypeChildrenOrItems<I>;
26
+
22
27
  export type TypeMultiAutocompleteProps<
23
28
  I extends TypeMenuItemProps = TypeMenuItemProps
24
- > = TypeSingleAutocompleteProps<I> &
29
+ > = TypeBaseAutocompleteProps &
25
30
  TypeDownshiftMultiSelectProps & {
26
- /* Determine whether or not the combobox should display selected items in the dropdown */
31
+ multiSelect?: true;
32
+ /** Determines whether a multiselect autocomplete will display selected items in the dropdown */
27
33
  showSelectedItemsInDropdown?: boolean;
28
- };
34
+ } & TypeChildrenOrItems<I>;
29
35
 
30
36
  export type TypeAutocompleteProps<
31
37
  I extends TypeMenuItemProps = TypeMenuItemProps
32
- > =
33
- | (TypeSingleAutocompleteProps<I> & { multiSelect?: false })
34
- | (TypeMultiAutocompleteProps<I> & { multiSelect: true });
38
+ > = TypeSingleAutocompleteProps<I> | TypeMultiAutocompleteProps<I>;
@@ -74,18 +74,20 @@ export const MultiAutocomplete = <
74
74
  [selectedItemIds, showSelectedItemsInDropdown, getIsItemVisible]
75
75
  );
76
76
 
77
- const { setHiddenItemsMap, defaultDownshiftProps, ...restDefaults } =
78
- useDownshiftDefaults({
79
- isCombobox: true,
80
- isMulti: true,
81
- // handles the prop name mapping for multi select
82
- multiSelectProps: {
83
- getA11yMultiStatusMessage,
84
- onMultiSelectStateChange,
85
- multiSelectStateReducer,
86
- ...useComboboxProps,
87
- },
88
- });
77
+ const downshiftDefaults = useDownshiftDefaults({
78
+ isCombobox: true,
79
+ isMulti: true,
80
+ // handles the prop name mapping for multi select
81
+ multiSelectProps: {
82
+ getA11yMultiStatusMessage,
83
+ onMultiSelectStateChange,
84
+ multiSelectStateReducer,
85
+ ...useComboboxProps,
86
+ },
87
+ });
88
+
89
+ const { setHiddenItemsMap, defaultDownshiftProps, hiddenItemsCount } =
90
+ downshiftDefaults;
89
91
 
90
92
  // used to handle filtering of items
91
93
  const { updateFilteredItems } = useItemFiltering({
@@ -118,9 +120,8 @@ export const MultiAutocomplete = <
118
120
  /**
119
121
  * Destructure Downshift props and call the core useCombobox with items and state handler
120
122
  */
121
- const { isOpen, ...useComboboxReturnProps } = useCombobox<
122
- (typeof allMenuItems)[number]
123
- >({
123
+
124
+ const useComboboxReturnProps = useCombobox<(typeof allMenuItems)[number]>({
124
125
  ...defaultDownshiftProps.combobox,
125
126
  items: allMenuItems,
126
127
  itemToString,
@@ -160,24 +161,31 @@ export const MultiAutocomplete = <
160
161
  ...useComboboxProps,
161
162
  });
162
163
 
164
+ const { isOpen, closeMenu, inputValue } = useComboboxReturnProps;
165
+
166
+ React.useEffect(() => {
167
+ if (!inputValue) return;
168
+ if (allMenuItems && hiddenItemsCount >= allMenuItems.length && isOpen) {
169
+ closeMenu?.();
170
+ }
171
+ }, [hiddenItemsCount, allMenuItems?.length, isOpen, inputValue]);
172
+
163
173
  return (
164
174
  <MenuRootComponent
165
175
  {...{
166
176
  isListbox: true,
167
177
  items: allMenuItems,
168
178
  itemToString,
169
- isOpen,
170
179
  initialSelectedItems,
171
180
  onStateChange,
172
181
  onSelectedItemsChange,
173
182
  getA11yMultiStatusMessage,
174
183
  onMultiSelectStateChange,
175
184
  multiSelectStateReducer,
176
- setHiddenItemsMap,
177
185
  ...useComboboxProps,
178
186
  ...useComboboxReturnProps,
179
187
  ...useMultipleSelectionReturnProps,
180
- ...restDefaults,
188
+ ...downshiftDefaults,
181
189
  }}
182
190
  popoutProps={{
183
191
  focusOnContent: false,
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from "react";
1
+ import React from "react";
2
2
  import { useCombobox } from "downshift";
3
3
  import { useMenuChildren } from "../hooks/useMenuChildren";
4
4
  import { itemToString as defaultItemToString } from "../utils/downshiftDefaults";
@@ -8,7 +8,7 @@ import { useItemFiltering } from "../hooks/useItemFiltering";
8
8
  import { MenuRoot } from "../MenuRoot";
9
9
 
10
10
  import type { TypeMenuItemProps } from "../MenuItem";
11
- import type { TypeAutocompleteProps } from "./AutocompleteTypes";
11
+ import type { TypeSingleAutocompleteProps } from "./AutocompleteTypes";
12
12
 
13
13
  export const SingleAutocomplete = <
14
14
  I extends TypeMenuItemProps = TypeMenuItemProps
@@ -21,15 +21,19 @@ export const SingleAutocomplete = <
21
21
  itemToString = defaultItemToString,
22
22
  getIsItemVisible,
23
23
  ...useComboboxProps
24
- }: TypeAutocompleteProps<I>) => {
24
+ }: TypeSingleAutocompleteProps<I>) => {
25
25
  /** Get a list of menuItems and children */
26
26
  const { allMenuItems, children } = useMenuChildren({
27
27
  children: childrenProp,
28
28
  menuItems,
29
29
  MenuItemComponent,
30
30
  });
31
- const { setHiddenItemsMap, defaultDownshiftProps, ...restDefaults } =
32
- useDownshiftDefaults({ isCombobox: true });
31
+
32
+ const downshiftDefaults = useDownshiftDefaults({ isCombobox: true });
33
+
34
+ const { setHiddenItemsMap, defaultDownshiftProps, hiddenItemsCount } =
35
+ downshiftDefaults;
36
+
33
37
  const { updateFilteredItems } = useItemFiltering({
34
38
  allMenuItems,
35
39
  itemToString,
@@ -40,7 +44,7 @@ export const SingleAutocomplete = <
40
44
  /**
41
45
  * Destructure Downshift props and call the core useCombobox with items and state handler
42
46
  */
43
- const { isOpen, ...useComboboxReturnProps } = useCombobox({
47
+ const useComboboxReturnProps = useCombobox({
44
48
  ...defaultDownshiftProps.combobox,
45
49
  items: allMenuItems,
46
50
  itemToString,
@@ -52,17 +56,24 @@ export const SingleAutocomplete = <
52
56
  ...useComboboxProps,
53
57
  });
54
58
 
59
+ const { isOpen, closeMenu, inputValue } = useComboboxReturnProps;
60
+
61
+ React.useEffect(() => {
62
+ if (!inputValue) return;
63
+ if (allMenuItems && hiddenItemsCount >= allMenuItems.length && isOpen) {
64
+ closeMenu?.();
65
+ }
66
+ }, [hiddenItemsCount, allMenuItems?.length, isOpen, inputValue]);
67
+
55
68
  return (
56
69
  <MenuRootComponent
57
70
  {...{
58
71
  isListbox: true,
59
72
  items: allMenuItems,
60
73
  itemToString,
61
- isOpen,
62
- setHiddenItemsMap,
63
74
  ...useComboboxProps,
64
75
  ...useComboboxReturnProps,
65
- ...restDefaults,
76
+ ...downshiftDefaults,
66
77
  }}
67
78
  popoutProps={{
68
79
  focusOnContent: false,
@@ -6,9 +6,9 @@ import { useCallback } from "react";
6
6
  import type { TypeMenuItemProps } from "../MenuItem";
7
7
 
8
8
  /**
9
- * @link https://seeds.sproutsocial.com/components/menu-content/
9
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menucontent
10
10
  *
11
- * @description MenuContent is used to contain lists or grouped lists of {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems}.
11
+ * @description MenuContent is used to contain lists or grouped lists of {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems}.
12
12
  *
13
13
  * @example
14
14
  * <ActionMenu>
@@ -24,8 +24,8 @@ import type { TypeMenuItemProps } from "../MenuItem";
24
24
  * <MenuFooter>Footer</MenuFooter>
25
25
  * </ActionMenu>
26
26
  *
27
- * @see {@link https://seeds.sproutsocial.com/components/menu-item/ | MenuItem}
28
- * @see {@link https://seeds.sproutsocial.com/components/menu-group/ | MenuGroup}
27
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItem}
28
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup MenuGroup}
29
29
  */
30
30
 
31
31
  const MenuContent = <I extends TypeMenuItemProps = TypeMenuItemProps>({
@@ -28,8 +28,11 @@ export interface TypeDownshiftMultiSelectProps
28
28
  >
29
29
  > {
30
30
  // Multi Select Props with conflicting useSelect prop names
31
+ /** Optional override to the built-in getA11yStatusMessage function for multiple selection*/
31
32
  getA11yMultiStatusMessage?: UseMultipleSelectionProps<TypeInternalItemProps>["getA11yStatusMessage"];
33
+ /** Optional override to the built-in onStateChange function for multiple selection*/
32
34
  onMultiSelectStateChange?: UseMultipleSelectionProps<TypeInternalItemProps>["onStateChange"];
35
+ /** Optional override to the built-in stateReducer function for multiple selection*/
33
36
  multiSelectStateReducer?: UseMultipleSelectionProps<TypeInternalItemProps>["stateReducer"];
34
37
  }
35
38
 
@@ -3,11 +3,11 @@ import type { TypeMenuFooterProps } from "./MenuFooterTypes";
3
3
  import { StyledMenuFooterBox } from "./styles";
4
4
 
5
5
  /**
6
- * @link https://seeds.sproutsocial.com/components/menu-footer/
6
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menufooter
7
7
  *
8
8
  * @description MenuFooter is a container used to hold footer content within a Menu.
9
9
  *
10
- * @see {@link https://seeds.sproutsocial.com/components/menu-header/ | MenuHeader}
10
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
11
11
  */
12
12
 
13
13
  export const MenuFooter = ({ children, ...rest }: TypeMenuFooterProps) => {
@@ -1,14 +1,13 @@
1
1
  import React from "react";
2
2
  import type { TypeMenuItemProps } from "../MenuItem";
3
- import type { TypeMenuRootProps } from "../MenuRoot";
4
3
  import type { TypeMenuGroupProps } from "./MenuGroupTypes";
5
4
  import { StyledMenuGroup, StyledTitle, StyledMenuGroupUl } from "./styles";
6
5
  import { mapMenuItems } from "../hooks/useMenuChildren";
7
6
 
8
7
  /**
9
- * @link https://seeds.sproutsocial.com/components/menu-group/
8
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup
10
9
  *
11
- * @description MenuGroup is used to group lists of {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems}.
10
+ * @description MenuGroup is used to group lists of {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems}.
12
11
  *
13
12
  * @example
14
13
  * <ActionMenu>
@@ -22,7 +21,8 @@ import { mapMenuItems } from "../hooks/useMenuChildren";
22
21
  * </MenuContent>
23
22
  * </ActionMenu>
24
23
  *
25
- * @see {@link https://seeds.sproutsocial.com/components/menu-item/ | MenuItem}
24
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItem}
25
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menucontent MenuContent}
26
26
  */
27
27
 
28
28
  const MenuGroup = <I extends TypeMenuItemProps = TypeMenuItemProps>({
@@ -8,11 +8,13 @@ import {
8
8
  import type { TypeMenuHeaderProps } from "./MenuHeaderTypes";
9
9
 
10
10
  /**
11
- * @link https://seeds.sproutsocial.com/components/menu-header/
11
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader
12
12
  *
13
13
  * @description MenuHeader is a container used to hold header content within a Menu.
14
14
  *
15
- * @see {@link https://seeds.sproutsocial.com/components/menu-footer/ | MenuFooter}
15
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menufooter MenuFooter}
16
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
17
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
16
18
  */
17
19
 
18
20
  const MenuHeader = ({
package/src/MenuLabel.tsx CHANGED
@@ -2,10 +2,40 @@ import React from "react";
2
2
  import { Label, type TypeLabelProps } from "@sproutsocial/seeds-react-label";
3
3
  import { useMenuToggleContext } from "./MenuContext";
4
4
 
5
- export const MenuLabel = ({ children, ...rest }: Partial<TypeLabelProps>) => {
5
+ export interface TypeMenuLabelProps extends Omit<TypeLabelProps, "htmlFor"> {
6
+ // The children and required types are redundant, but they power the MenuLabel PropTable.
7
+ children: React.ReactNode;
8
+ /** Whether making a selection in the associated menu is required. */
9
+ required?: boolean;
10
+ /** ID of the associated form element. This prop is never valid to pass into MenuLabel
11
+ * because MenuLabel passes its own htmlFor prop to the underlying Label component.*/
12
+ htmlFor?: never;
13
+ }
14
+
15
+ /**
16
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menulabel
17
+ *
18
+ * @description MenuLabel extends Label to create an accessible label for a Menu's toggle element.
19
+ * A MenuLabel will automatically be associated with the corresponding menuToggleElement,
20
+ * so an `htmlFor` prop is not necessary or allowed.
21
+ *
22
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menutogglebutton MenuToggleButton}
23
+ * @see {@link https://seeds.sproutsocial.com/components/label/ Label}
24
+ */
25
+ export const MenuLabel = ({
26
+ children,
27
+ required = false,
28
+ ...rest
29
+ }: TypeMenuLabelProps) => {
6
30
  const { getLabelProps } = useMenuToggleContext();
7
31
  return (
8
- <Label htmlFor="fallback_menu_label" {...getLabelProps?.()} {...rest}>
32
+ // This fallback id should never be used, but it is here to satisfy TypeScript since getLabelProps could be undefined.
33
+ <Label
34
+ htmlFor="fallback_menu_label"
35
+ required={required}
36
+ {...getLabelProps?.()}
37
+ {...rest}
38
+ >
9
39
  {children}
10
40
  </Label>
11
41
  );
@@ -18,10 +18,16 @@ import {
18
18
  import { MOTION_DURATION_FAST } from "@sproutsocial/seeds-motion/unitless";
19
19
 
20
20
  export interface TypeMenuRootOwnProps {
21
+ /** The element that is or contains an element that will toggle the menu when clicked.
22
+ * May contain labels, buttons, inputs or other content as needed. */
21
23
  menuToggleElement: React.ReactElement<any>;
24
+ /** Props to pass through to the underlying Popout.
25
+ * Any Popout prop is valid except those explicitly omitted. */
22
26
  popoutProps?: Partial<
23
27
  Omit<TypePopoutProps, "isOpen" | "setIsOpen" | "content" | "children">
24
28
  >;
29
+ /** The width of the Popout content.
30
+ * Defaults to 200px or the width of the toggle element, whichever is greater.*/
25
31
  width?: TypePopoutProps["width"];
26
32
  }
27
33
  export interface TypeMenuRootProps
@@ -108,9 +114,7 @@ export const MenuPopout = ({
108
114
  };
109
115
 
110
116
  /**
111
- * @link https://seeds.sproutsocial.com/components/menu-root/
112
- *
113
- * @description MenuRoot is a utility component used to handle {@link https://github.com/sproutsocial/seeds/blob/dev/seeds-react/seeds-react-menu/src/MenuContext.tsx | MenuContext}. This component should rarely, if ever, be used directly unless building a custom menu type.
117
+ * @description MenuRoot is a utility component used to handle React Context for our Menus. This component should rarely, if ever, be used directly unless building a custom menu type.
114
118
  */
115
119
 
116
120
  export const MenuRoot = ({
@@ -146,13 +150,6 @@ export const MenuRoot = ({
146
150
  }
147
151
  }, [width, toggleElementRef.current?.offsetWidth]);
148
152
 
149
- useEffect(() => {
150
- if (!inputValue) return;
151
- if (items && hiddenItemsCount >= items.length && isOpen) {
152
- closeMenu?.();
153
- }
154
- }, [hiddenItemsCount, items?.length, isOpen, inputValue]);
155
-
156
153
  const menuContext = useMenu(contextProps);
157
154
 
158
155
  // Hack to suppress error: "downshift: You forgot to call the getMenuProps getter function on your component / element."
@@ -189,17 +186,3 @@ export const MenuRoot = ({
189
186
  </MenuPopout>
190
187
  );
191
188
  };
192
-
193
- export const MenuRootNoPopout = ({
194
- children,
195
- menuToggleElement,
196
- ...contextProps
197
- }: TypeMenuRootProps) => {
198
- const menuContext = useMenu(contextProps);
199
-
200
- return (
201
- <MenuContentProvider menuContext={menuContext}>
202
- {children}
203
- </MenuContentProvider>
204
- );
205
- };
@@ -10,23 +10,17 @@ import {
10
10
  } from "../MenuContext";
11
11
 
12
12
  export interface TypeMenuSearchInputProps extends TypeInputProps {
13
- /* A function that can be passed to override the default filtering logic */
13
+ /** A function that can be passed to override the default filtering logic */
14
14
  getIsItemVisible?: TypeGetIsItemVisibleFn;
15
15
  }
16
16
 
17
17
  /**
18
- * <input
19
- * aria-activedescendant=""
20
- * aria-autocomplete="list"
21
- * aria-controls="downshift-:r1:-menu"
22
- * aria-expanded="true"
23
- * />
24
- */
25
-
26
- /**
27
- * @link https://seeds.sproutsocial.com/components/menu-header/
18
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput
28
19
  *
29
20
  * @description MenuSearchInput is search input that can be added to the MenuHeader to filter the items.
21
+ *
22
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
23
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
30
24
  */
31
25
  export const MenuSearchInput = ({
32
26
  getIsItemVisible,
@@ -14,14 +14,17 @@ import {
14
14
  } from "../MenuTokenInput";
15
15
 
16
16
  export interface TypeMenuSearchTokenInputProps extends TypeMenuTokenInputProps {
17
- /* A function that can be passed to override the default filtering logic */
17
+ /** A function that can be passed to override the default filtering logic */
18
18
  getIsItemVisible?: TypeGetIsItemVisibleFn;
19
19
  }
20
20
 
21
21
  /**
22
- * @link https://seeds.sproutsocial.com/components/menu-search-token-input/
22
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput
23
23
  *
24
- * @description MenuSearchTokenInput is search token input that can be added to the MenuHeader to filter the items.
24
+ * @description MenuSearchTokenInput is a token input that can be added to the MenuHeader to filter the items.
25
+ *
26
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuheader MenuHeader}
27
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
25
28
  */
26
29
  export const MenuSearchTokenInput = ({
27
30
  getIsItemVisible,
@@ -1,15 +1,16 @@
1
- import React, { type ReactNode } from "react";
2
1
  import { Button, type TypeButtonProps } from "@sproutsocial/seeds-react-button";
3
2
  import { useMenuToggleContext } from "../MenuContext";
4
3
 
5
- export interface TypeMenuToggleButtonProps extends Partial<TypeButtonProps> {
6
- children: ReactNode;
7
- }
4
+ export interface TypeMenuToggleButtonProps extends TypeButtonProps {}
8
5
 
9
- export const MenuToggleButton = ({
10
- children,
11
- ...rest
12
- }: TypeMenuToggleButtonProps) => {
6
+ /**
7
+ * @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menutogglebutton
8
+ * @param props - MenuToggleButton accepts all the same props as Button.
9
+ * @description MenuToggleButton extends the Button component to create a toggle for a menu.
10
+ * @see {@link https://seeds.sproutsocial.com/components/button/ Button}
11
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menulabel MenuLabel}
12
+ */
13
+ export const MenuToggleButton = (props: TypeMenuToggleButtonProps) => {
13
14
  const { getToggleButtonProps, isListbox, getDropdownProps, ref, ariaProps } =
14
15
  useMenuToggleContext();
15
16
  return (
@@ -22,9 +23,7 @@ export const MenuToggleButton = ({
22
23
  ...ariaProps,
23
24
  ...(isListbox ? {} : { role: "button", "aria-haspopup": "menu" }),
24
25
  })}
25
- {...rest}
26
- >
27
- {children}
28
- </Button>
26
+ {...props}
27
+ />
29
28
  );
30
29
  };
@@ -26,13 +26,19 @@ const StyledTokenInputWrapper = styled.div`
26
26
  `;
27
27
 
28
28
  export interface TypeMenuTokenInputProps extends TypeTokenInputProps {
29
- /* A function that can be passed to override the default token props */
30
- getTokenProps?: (
31
- itemId: TypeInternalItemProps["id"]
32
- ) => Partial<TypeTokenSpec>;
29
+ /** A function that can be passed to override the default token props */
30
+ getTokenProps?: (itemId: string) => Partial<TypeTokenSpec>;
31
+ /** Specify the menu context to use. MenuToggleContext is the default.
32
+ * This prop is only needed for specialized use cases. */
33
33
  MenuContext?: typeof MenuToggleContext | typeof MenuContentContext;
34
34
  }
35
35
 
36
+ /**
37
+ * @description MenuTokenInput is the basis of the MenuSearchTokenInput and AutocompleteTokenInput components
38
+ *
39
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchinput MenuSearchInput}
40
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput MenuSearchTokenInput}
41
+ */
36
42
  export const MenuTokenInput = ({
37
43
  inputProps = {},
38
44
  getTokenProps,
@@ -10,11 +10,12 @@ import type { TypeMultiSelectMenuProps } from "./MultiSelectMenuTypes";
10
10
  import type { TypeInternalItemProps } from "../types";
11
11
 
12
12
  /**
13
- * @link https://seeds.sproutsocial.com/components/multiselect-menu/
13
+ * @link https://seeds.sproutsocial.com/components/multi-select-menu/
14
14
  *
15
- * @description A MultiSelectMenu allows multiple {@link https://github.com/sproutsocial/seeds/tree/dev/seeds-react/seeds-react-menu/src/MenuItem | MenuItems} to be selected from a list or groups of lists.
15
+ * @description A MultiSelectMenu allows multiple {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItems} to be selected from a list or groups of lists.
16
16
  *
17
- * @see {@link https://seeds.sproutsocial.com/components/menu-group/ | MenuGroup}
17
+ * @see {@link https://seeds.sproutsocial.com/components/single-select-menu/ SingleSelectMenu}
18
+ * @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup MenuGroup}
18
19
  */
19
20
 
20
21
  export const MultiSelectMenu = <