@sproutsocial/seeds-react-menu 1.2.1 → 1.2.2
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +6 -0
- package/dist/esm/index.js +63 -62
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +119 -59
- package/dist/index.d.ts +119 -59
- package/dist/index.js +91 -91
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/ActionMenu/ActionMenu.tsx +2 -2
- package/src/Autocomplete/Autocomplete.stories.tsx +6 -18
- package/src/Autocomplete/Autocomplete.tsx +2 -3
- package/src/Autocomplete/AutocompleteTypes.ts +16 -12
- package/src/Autocomplete/SingleAutocomplete.tsx +2 -3
- package/src/MenuContent/MenuContent.tsx +4 -4
- package/src/MenuContext.tsx +3 -0
- package/src/MenuFooter/MenuFooter.tsx +2 -2
- package/src/MenuGroup/MenuGroup.tsx +4 -4
- package/src/MenuHeader/MenuHeader.tsx +4 -2
- package/src/MenuLabel.tsx +32 -2
- package/src/MenuRoot/MenuRoot.tsx +7 -17
- package/src/MenuSearchInput/MenuSearchInput.tsx +5 -11
- package/src/MenuSearchTokenInput/MenuSearchTokenInput.tsx +6 -3
- package/src/MenuToggleButton/MenuToggleButton.tsx +11 -12
- package/src/MenuTokenInput.tsx +10 -4
- package/src/MultiSelectMenu/MultiSelectMenu.tsx +4 -3
- package/src/NestedMenu/NestedMenu.feature +2 -2
- package/src/NestedMenu/NestedMenuTypes.ts +3 -0
- package/src/SingleSelectMenu/SingleSelectMenu.tsx +5 -4
- package/src/hooks/useItemFiltering.tsx +2 -1
- package/src/hooks/useMenuChildren.tsx +1 -1
- package/src/types.ts +28 -15
package/package.json
CHANGED
|
@@ -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://
|
|
82
|
-
* @see {@link https://
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
> =
|
|
29
|
+
> = TypeBaseAutocompleteProps &
|
|
25
30
|
TypeDownshiftMultiSelectProps & {
|
|
26
|
-
|
|
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>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
2
1
|
import { useCombobox } from "downshift";
|
|
3
2
|
import { useMenuChildren } from "../hooks/useMenuChildren";
|
|
4
3
|
import { itemToString as defaultItemToString } from "../utils/downshiftDefaults";
|
|
@@ -8,7 +7,7 @@ import { useItemFiltering } from "../hooks/useItemFiltering";
|
|
|
8
7
|
import { MenuRoot } from "../MenuRoot";
|
|
9
8
|
|
|
10
9
|
import type { TypeMenuItemProps } from "../MenuItem";
|
|
11
|
-
import type {
|
|
10
|
+
import type { TypeSingleAutocompleteProps } from "./AutocompleteTypes";
|
|
12
11
|
|
|
13
12
|
export const SingleAutocomplete = <
|
|
14
13
|
I extends TypeMenuItemProps = TypeMenuItemProps
|
|
@@ -21,7 +20,7 @@ export const SingleAutocomplete = <
|
|
|
21
20
|
itemToString = defaultItemToString,
|
|
22
21
|
getIsItemVisible,
|
|
23
22
|
...useComboboxProps
|
|
24
|
-
}:
|
|
23
|
+
}: TypeSingleAutocompleteProps<I>) => {
|
|
25
24
|
/** Get a list of menuItems and children */
|
|
26
25
|
const { allMenuItems, children } = useMenuChildren({
|
|
27
26
|
children: childrenProp,
|
|
@@ -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
|
|
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://
|
|
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
|
|
28
|
-
* @see {@link https://seeds.sproutsocial.com/components/menu
|
|
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>({
|
package/src/MenuContext.tsx
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
8
|
+
* @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup
|
|
10
9
|
*
|
|
11
|
-
* @description MenuGroup is used to group lists of {@link https://
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
* @
|
|
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 = ({
|
|
@@ -189,17 +193,3 @@ export const MenuRoot = ({
|
|
|
189
193
|
</MenuPopout>
|
|
190
194
|
);
|
|
191
195
|
};
|
|
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
|
-
|
|
13
|
+
/** A function that can be passed to override the default filtering logic */
|
|
14
14
|
getIsItemVisible?: TypeGetIsItemVisibleFn;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
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
|
-
|
|
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/
|
|
22
|
+
* @link https://seeds.sproutsocial.com/components/seeds-react-menu/#menusearchtokeninput
|
|
23
23
|
*
|
|
24
|
-
* @description MenuSearchTokenInput is
|
|
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
|
|
6
|
-
children: ReactNode;
|
|
7
|
-
}
|
|
4
|
+
export interface TypeMenuToggleButtonProps extends TypeButtonProps {}
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
{...
|
|
26
|
-
|
|
27
|
-
{children}
|
|
28
|
-
</Button>
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
29
28
|
);
|
|
30
29
|
};
|
package/src/MenuTokenInput.tsx
CHANGED
|
@@ -26,13 +26,19 @@ const StyledTokenInputWrapper = styled.div`
|
|
|
26
26
|
`;
|
|
27
27
|
|
|
28
28
|
export interface TypeMenuTokenInputProps extends TypeTokenInputProps {
|
|
29
|
-
|
|
30
|
-
getTokenProps?: (
|
|
31
|
-
|
|
32
|
-
|
|
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/
|
|
13
|
+
* @link https://seeds.sproutsocial.com/components/multi-select-menu/
|
|
14
14
|
*
|
|
15
|
-
* @description A MultiSelectMenu allows multiple {@link https://
|
|
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
|
|
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 = <
|
|
@@ -30,7 +30,7 @@ Feature: NestedMenu
|
|
|
30
30
|
|
|
31
31
|
Scenario: User can select a child menu without closing the menu
|
|
32
32
|
Given the NestedMenu is open
|
|
33
|
-
When
|
|
33
|
+
When a menu item that triggers a child menu is clicked
|
|
34
34
|
Then the menu will stay open
|
|
35
35
|
And the menu will not use its default open/close behavior
|
|
36
36
|
|
|
@@ -75,7 +75,7 @@ Feature: NestedMenu
|
|
|
75
75
|
|
|
76
76
|
Scenario: A Menu stays open when a menu item with a childMenuId is clicked
|
|
77
77
|
Given the NestedMenu is open
|
|
78
|
-
When
|
|
78
|
+
When a menu item that triggers a child menu is clicked
|
|
79
79
|
Then the menu will stay open
|
|
80
80
|
And the menu will not use its default open/close behavior
|
|
81
81
|
|
|
@@ -27,13 +27,16 @@ export interface TypeNestedMenuHeaderProps extends TypeMenuHeaderProps {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export interface TypeNestedMenuItemProps extends TypeMenuItemProps {
|
|
30
|
+
/** The id of the menu to be displayed when this item is selected. */
|
|
30
31
|
childMenuId?: string;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export interface TypeNestedMenuProps<
|
|
34
35
|
I extends TypeMenuItemProps = TypeNestedMenuItemProps
|
|
35
36
|
> extends Omit<TypeActionMenuBaseProps, "MenuRootComponent"> {
|
|
37
|
+
/** The id of the menu to display when the NestedMenu is opened. */
|
|
36
38
|
initialMenuId: string;
|
|
39
|
+
/** An optional callback to fire when the back button is clicked.*/
|
|
37
40
|
onBackButtonClick?: (menuId: string) => void;
|
|
38
41
|
/** Sets the default localized label for the back arrow in all child menus.
|
|
39
42
|
* This label can be overridden by including backArrowLabel in a menu's menuHeaderProps. */
|
|
@@ -9,12 +9,13 @@ import { MenuRoot, type TypeMenuRootProps } from "../MenuRoot";
|
|
|
9
9
|
import type { TypeSingleSelectMenuProps } from "./SingleSelectMenuTypes";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* @link https://seeds.sproutsocial.com/components/
|
|
12
|
+
* @link https://seeds.sproutsocial.com/components/single-select-menu/
|
|
13
13
|
*
|
|
14
|
-
* @description A SingleSelectMenu allows a single selection of a {@link https://
|
|
14
|
+
* @description A SingleSelectMenu allows a single selection of a {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menuitem MenuItem} from a list or groups or lists.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* @see {@link https://
|
|
16
|
+
* @see {@link https://seeds.sproutsocial.com/components/action-menu/ ActionMenu} for triggering actions from a menu
|
|
17
|
+
* @see {@link https://seeds.sproutsocial.com/components/multi-select-menu/ MultiSelectMenu} for selecting multiple items
|
|
18
|
+
* @see {@link https://seeds.sproutsocial.com/components/seeds-react-menu/#menugroup MenuGroup}'s isSingleSelect prop to create a single select group within a MultiSelectMenu
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
21
|
export const SingleSelectMenu = <
|
|
@@ -3,8 +3,9 @@ import type { TypeMenuContext } from "../MenuContext";
|
|
|
3
3
|
import type { TypeInternalItemProps } from "../types";
|
|
4
4
|
import { itemToString as defaultItemToString } from "../utils/downshiftDefaults";
|
|
5
5
|
|
|
6
|
+
/* Receives the internal Downshift version of the item, which is different from TypeMenuItemProps*/
|
|
6
7
|
export type TypeGetIsItemVisibleFn = (
|
|
7
|
-
item:
|
|
8
|
+
item: TypeInternalItemProps,
|
|
8
9
|
inputValue: string
|
|
9
10
|
) => boolean;
|
|
10
11
|
|
|
@@ -262,7 +262,7 @@ export const useMenuChildren = <
|
|
|
262
262
|
const menuItemsMap: TypeMenuContext["itemsMap"] = {};
|
|
263
263
|
const allMenuItems: TypeMenuContext["items"] = [];
|
|
264
264
|
|
|
265
|
-
// If
|
|
265
|
+
// If a menuItems prop was passed to the Menu, we can bypass the children traversal.
|
|
266
266
|
if (menuItems && menuItems.length) {
|
|
267
267
|
menuItems.forEach((menuItem) => {
|
|
268
268
|
addMenuItem({ itemProps: menuItem, allMenuItems, menuItemsMap });
|
package/src/types.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { TypeMenuItemProps } from "./MenuItem";
|
|
|
3
3
|
import type { TypeMenuGroupBaseProps } from "./MenuGroup";
|
|
4
4
|
import type { TypeMenuRootOwnProps, TypeMenuRootProps } from "./MenuRoot";
|
|
5
5
|
|
|
6
|
-
// The
|
|
6
|
+
// The item object used internally for Menu functionality
|
|
7
7
|
export interface TypeInternalItemProps<Item = TypeMenuItemProps> {
|
|
8
8
|
id: string;
|
|
9
9
|
index: number;
|
|
@@ -13,25 +13,38 @@ export interface TypeInternalItemProps<Item = TypeMenuItemProps> {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface TypeHigherOrderComponentProps extends TypeMenuRootOwnProps {
|
|
16
|
+
/** Overrides the default MenuRoot component. Only necessary for specialized use cases.*/
|
|
16
17
|
MenuRootComponent?: React.ComponentType<TypeMenuRootProps>;
|
|
17
18
|
}
|
|
18
19
|
|
|
20
|
+
// Partial type, for react-docgen. Refined to the two valid configurations below.
|
|
21
|
+
type TypeBaseChildrenOrItems<I extends TypeMenuItemProps = TypeMenuItemProps> =
|
|
22
|
+
{
|
|
23
|
+
/** Allows menu items to be passed in as children. Cannot be used with the menuItems prop.*/
|
|
24
|
+
children?: TypeNotEmptyChildren;
|
|
25
|
+
/** Allows menu items to be passed in as objects. Cannot be used with the children prop.
|
|
26
|
+
* The type of each menu item, I, must be or extend TypeMenuItemProps. */
|
|
27
|
+
menuItems?: I[];
|
|
28
|
+
/** Allows a custom MenuItem component to be used when rendering using the menuItems prop.
|
|
29
|
+
* MenuItemComponent's prop type must match the type of the menuItems, I. */
|
|
30
|
+
MenuItemComponent?: React.ComponentType<I>;
|
|
31
|
+
};
|
|
32
|
+
|
|
19
33
|
export type TypeChildrenOrItems<
|
|
20
34
|
I extends TypeMenuItemProps = TypeMenuItemProps
|
|
21
|
-
> =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
35
|
+
> = TypeBaseChildrenOrItems<I> &
|
|
36
|
+
(
|
|
37
|
+
| {
|
|
38
|
+
children: TypeNotEmptyChildren;
|
|
39
|
+
menuItems?: never;
|
|
40
|
+
MenuItemComponent?: never;
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
children?: never;
|
|
44
|
+
menuItems: I[];
|
|
45
|
+
MenuItemComponent?: React.ComponentType<I>;
|
|
46
|
+
}
|
|
47
|
+
);
|
|
35
48
|
|
|
36
49
|
export type TypeNotEmptyChildren =
|
|
37
50
|
| React.ReactChild
|