@sproutsocial/seeds-react-menu 0.2.1 → 0.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/.eslintrc.js +2 -6
- package/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +7 -0
- package/dist/esm/index.js +11 -11
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +6 -10
- package/dist/index.js.map +1 -1
- package/package.json +3 -5
- package/src/ActionMenu/ActionMenu.tsx +2 -3
- package/src/MenuContent/MenuContentTypes.ts +2 -1
- package/src/MenuContext.tsx +6 -1
- package/src/MenuGroup/MenuGroupTypes.ts +0 -1
- package/src/MenuGroup/__tests__/MenuGroup.test.tsx +0 -1
- package/src/MenuHeader/__tests__/MenuHeader.typetest.tsx +0 -1
- package/src/MenuItem/MenuItem.tsx +0 -4
- package/src/MenuItem/styles.tsx +1 -1
- package/src/MenuItem/useOptionProps.tsx +0 -1
- package/src/MenuRoot/MenuRoot.tsx +2 -2
- package/src/MenuRoot/__tests__/MenuRoot.test.tsx +1 -2
- package/src/MultiSelectMenu/MultiSelectMenu.tsx +0 -1
- package/src/MultiSelectMenu/__tests__/MultiSelectMenu.test.tsx +7 -2
- package/src/SingleSelectMenu/SingleSelectMenu.tsx +0 -1
- package/src/hooks/useItemsFromChildren.tsx +7 -5
- package/src/index.ts +1 -0
- package/src/types.ts +2 -5
- package/tsconfig.json +1 -1
- package/.eslintignore +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-menu",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Seeds React Menu",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
"clean:modules": "rm -rf node_modules",
|
|
15
15
|
"typecheck": "tsc --noEmit",
|
|
16
16
|
"test": "jest",
|
|
17
|
-
"test:watch": "jest --watch --coverage=false"
|
|
18
|
-
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
|
19
|
-
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix"
|
|
17
|
+
"test:watch": "jest --watch --coverage=false"
|
|
20
18
|
},
|
|
21
19
|
"dependencies": {
|
|
22
20
|
"@sproutsocial/seeds-react-box": "*",
|
|
@@ -32,7 +30,7 @@
|
|
|
32
30
|
"motion": "^11.11.17"
|
|
33
31
|
},
|
|
34
32
|
"devDependencies": {
|
|
35
|
-
"eslint-config-seeds": "*",
|
|
33
|
+
"@sproutsocial/eslint-config-seeds": "*",
|
|
36
34
|
"@sproutsocial/seeds-react-testing-library": "*",
|
|
37
35
|
"@sproutsocial/seeds-testing": "*",
|
|
38
36
|
"@types/react": "^18.0.0",
|
|
@@ -49,7 +49,7 @@ const handleStateChange = (
|
|
|
49
49
|
if (!selectedItem) return;
|
|
50
50
|
|
|
51
51
|
// if selectedItem is disabled, do nothing
|
|
52
|
-
if (selectedItem.
|
|
52
|
+
if (selectedItem.disabled) {
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -58,7 +58,7 @@ const handleStateChange = (
|
|
|
58
58
|
changes.type === useSelect.stateChangeTypes.ToggleButtonKeyDownEnter;
|
|
59
59
|
|
|
60
60
|
// selectedItem props
|
|
61
|
-
const selectedItemProps = selectedItem.
|
|
61
|
+
const selectedItemProps = selectedItem.menuItemProps;
|
|
62
62
|
|
|
63
63
|
if (selectedItemProps?.onClick) {
|
|
64
64
|
// Create a synthetic event to pass into the onClick
|
|
@@ -111,7 +111,6 @@ export const ActionMenu = ({
|
|
|
111
111
|
onStateChange: (changes) => handleStateChange(changes, currentSelectedItem),
|
|
112
112
|
stateReducer: (state, actionAndChanges) => {
|
|
113
113
|
let newState: Partial<UseSelectState<TypeDefaultItemProps>>;
|
|
114
|
-
// eslint-disable-next-line prefer-const, react-hooks/rules-of-hooks
|
|
115
114
|
newState = useSelectStateReducer(state, actionAndChanges);
|
|
116
115
|
return externalStateReducer
|
|
117
116
|
? externalStateReducer(state, {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import { type HTMLMotionProps } from "motion/react";
|
|
2
|
-
import type { ReactNode } from "react";
|
|
3
|
+
import type { ReactNode, RefObject } from "react";
|
|
3
4
|
|
|
4
5
|
export interface TypeMenuContentProps extends HTMLMotionProps<"ul"> {
|
|
5
6
|
children: ReactNode;
|
package/src/MenuContext.tsx
CHANGED
|
@@ -44,7 +44,6 @@ describe("MenuGroup", () => {
|
|
|
44
44
|
const menuGroup = screen.getByRole("group", { name: menuTitle });
|
|
45
45
|
expect(menuGroup).toBeInTheDocument();
|
|
46
46
|
expect(
|
|
47
|
-
// eslint-disable-next-line testing-library/prefer-presence-queries
|
|
48
47
|
screen.queryByRole("heading", { name: menuTitle })
|
|
49
48
|
).toBeInTheDocument();
|
|
50
49
|
});
|
|
@@ -6,7 +6,6 @@ export const MenuHeaderTypeTest = () => (
|
|
|
6
6
|
title="Menu Header"
|
|
7
7
|
leftAction={<div>left action</div>}
|
|
8
8
|
rightAction={<div>right action</div>}
|
|
9
|
-
// eslint-disable-next-line react/no-children-prop
|
|
10
9
|
children={<div>children</div>}
|
|
11
10
|
/>
|
|
12
11
|
{/* left and right action accept strings */}
|
|
@@ -17,12 +17,9 @@ export const MenuItem = ({
|
|
|
17
17
|
children,
|
|
18
18
|
onClick,
|
|
19
19
|
onKeyDown,
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
21
20
|
disabled = false,
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
23
21
|
ref,
|
|
24
22
|
href,
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
23
|
color,
|
|
27
24
|
...props
|
|
28
25
|
}: TypeMenuItemProps) => {
|
|
@@ -53,7 +50,6 @@ export const MenuItem = ({
|
|
|
53
50
|
// use anchor tag if href is provided and button for menuitem
|
|
54
51
|
as={isListbox ? undefined : href ? "a" : "button"}
|
|
55
52
|
href={href}
|
|
56
|
-
// eslint-disable-next-line react/no-children-prop
|
|
57
53
|
children={children}
|
|
58
54
|
{...optionProps}
|
|
59
55
|
{...props}
|
package/src/MenuItem/styles.tsx
CHANGED
|
@@ -23,7 +23,6 @@ export const MenuItemContainer = styled.li`
|
|
|
23
23
|
list-style-type: none;
|
|
24
24
|
margin-left: ${({ theme }) => theme.space[300]};
|
|
25
25
|
margin-right: ${({ theme }) => theme.space[300]};
|
|
26
|
-
transition: all ${({ theme }) => theme.duration["fast"]};
|
|
27
26
|
|
|
28
27
|
&:first-child {
|
|
29
28
|
margin-top: ${({ theme }) => theme.space[300]};
|
|
@@ -49,6 +48,7 @@ export const StyledMenuItem = styled.div<{ $highlighted: boolean }>`
|
|
|
49
48
|
padding: ${({ theme }) => theme.space[300]};
|
|
50
49
|
outline: 0;
|
|
51
50
|
${({ theme }) => theme.typography[200]};
|
|
51
|
+
transition: all ${({ theme }) => theme.duration["fast"]};
|
|
52
52
|
|
|
53
53
|
/* Highlighted */
|
|
54
54
|
${({ $highlighted }) => $highlighted && highlightedStyles}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import React, { useCallback } from "react";
|
|
1
|
+
import React, { useCallback, useRef } from "react";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
import { Popout, type TypePopoutProps } from "@sproutsocial/seeds-react-popout";
|
|
4
4
|
|
|
5
5
|
import { MenuProvider, type TypeMenuProviderProps } from "../MenuContext";
|
|
6
6
|
|
|
7
7
|
export interface TypeMenuRootOwnProps {
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
8
|
menuToggleElement: React.ReactElement<any>;
|
|
10
9
|
popoutProps?: Partial<
|
|
11
10
|
Omit<TypePopoutProps, "isOpen" | "setIsOpen" | "content" | "children">
|
|
@@ -46,6 +45,7 @@ export const MenuRoot = ({
|
|
|
46
45
|
return (
|
|
47
46
|
<MenuProvider {...contextProps}>
|
|
48
47
|
<Popout
|
|
48
|
+
menuPopout
|
|
49
49
|
isOpen={!!isOpen}
|
|
50
50
|
setIsOpen={setIsOpen}
|
|
51
51
|
content={
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
screen,
|
|
6
6
|
waitFor,
|
|
7
7
|
} from "@sproutsocial/seeds-react-testing-library";
|
|
8
|
+
import { Box } from "@sproutsocial/seeds-react-box";
|
|
8
9
|
import { Button } from "@sproutsocial/seeds-react-button";
|
|
9
10
|
import {
|
|
10
11
|
MenuRoot,
|
|
@@ -17,7 +18,6 @@ import {
|
|
|
17
18
|
type TypeMenuContextProps,
|
|
18
19
|
} from "../../index";
|
|
19
20
|
|
|
20
|
-
// eslint-disable-next-line react/display-name
|
|
21
21
|
jest.mock("@sproutsocial/seeds-react-portal", () => ({ children }) => (
|
|
22
22
|
<div>{children}</div>
|
|
23
23
|
));
|
|
@@ -197,7 +197,6 @@ describe("MenuRoot", () => {
|
|
|
197
197
|
const { user } = render(
|
|
198
198
|
<MenuRoot
|
|
199
199
|
menuToggleElement={<CustomToggleElement />}
|
|
200
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
201
200
|
// @ts-ignore - mock contextProps may be imperfect
|
|
202
201
|
getToggleButtonProps={() => ({ onClick: mockToggleClick })}
|
|
203
202
|
>
|
|
@@ -82,7 +82,6 @@ export const MultiSelectMenu = ({
|
|
|
82
82
|
defaultHighlightedIndex: 0,
|
|
83
83
|
stateReducer: (state, actionAndChanges) => {
|
|
84
84
|
let newState: Partial<UseSelectState<TypeDefaultItemProps>>;
|
|
85
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
86
85
|
newState = useSelectStateReducer(state, actionAndChanges);
|
|
87
86
|
newState = selectReducerForMultiSelect(state, {
|
|
88
87
|
...actionAndChanges,
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable testing-library/prefer-find-by */
|
|
2
|
-
/* eslint-disable testing-library/no-wait-for-multiple-assertions */
|
|
3
1
|
/* eslint-disable testing-library/no-unnecessary-act */
|
|
4
2
|
import {
|
|
5
3
|
MultiSelectMenu,
|
|
@@ -11,6 +9,9 @@ import {
|
|
|
11
9
|
import {
|
|
12
10
|
render,
|
|
13
11
|
screen,
|
|
12
|
+
fireEvent,
|
|
13
|
+
act,
|
|
14
|
+
cleanup,
|
|
14
15
|
waitFor,
|
|
15
16
|
} from "@sproutsocial/seeds-react-testing-library";
|
|
16
17
|
|
|
@@ -22,6 +23,10 @@ const menuItems = [
|
|
|
22
23
|
];
|
|
23
24
|
|
|
24
25
|
describe("MultiSelectMenu", () => {
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
cleanup();
|
|
28
|
+
});
|
|
29
|
+
|
|
25
30
|
it("should render the MenuItems when provided as children", async () => {
|
|
26
31
|
const { user } = render(
|
|
27
32
|
<MultiSelectMenu
|
|
@@ -36,7 +36,6 @@ export const SingleSelectMenu = ({
|
|
|
36
36
|
itemToString,
|
|
37
37
|
stateReducer: (state, actionAndChanges) => {
|
|
38
38
|
let newState: Partial<UseSelectState<TypeDefaultItemProps>>;
|
|
39
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks, prefer-const
|
|
40
39
|
newState = useSelectStateReducer(state, actionAndChanges);
|
|
41
40
|
return externalStateReducer
|
|
42
41
|
? externalStateReducer(state, {
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import React, { type ReactNode, useMemo } from "react";
|
|
2
|
-
import type {
|
|
2
|
+
import type { TypeMenuItemProps } from "../MenuItem";
|
|
3
3
|
import type { TypeMenuContext } from "../MenuContext";
|
|
4
4
|
|
|
5
5
|
export interface TypeUseItemsFromChildrenProps {
|
|
6
6
|
children: ReactNode;
|
|
7
7
|
}
|
|
8
|
+
export interface TypeItemElements {
|
|
9
|
+
element: React.ReactElement<TypeMenuItemProps>;
|
|
10
|
+
parents: readonly React.ReactNode[];
|
|
11
|
+
}
|
|
8
12
|
|
|
9
13
|
// https://stackoverflow.com/questions/69119016/find-specific-children-components-regardless-of-depth-in-react
|
|
10
14
|
const walkAllChildren = (
|
|
@@ -16,7 +20,6 @@ const walkAllChildren = (
|
|
|
16
20
|
// console.log("element", element);
|
|
17
21
|
callback(element, parents);
|
|
18
22
|
const newParents = [...parents, element];
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
23
|
const children = (element as any).props?.children;
|
|
21
24
|
React.Children.toArray(children).forEach((child) => {
|
|
22
25
|
walk(child, newParents);
|
|
@@ -60,13 +63,12 @@ export const useItemsFromChildren = ({
|
|
|
60
63
|
const allMenuItemElements = getAllMenuItems(children);
|
|
61
64
|
const menuItemsMap: TypeMenuContext["itemsMap"] = {};
|
|
62
65
|
const allMenuItems: TypeMenuContext["items"] = allMenuItemElements.map(
|
|
63
|
-
({ element
|
|
66
|
+
({ element }, index) => {
|
|
64
67
|
const item = {
|
|
65
68
|
id: element.props.id,
|
|
66
69
|
disabled: element.props.disabled,
|
|
67
70
|
index,
|
|
68
|
-
element,
|
|
69
|
-
parents,
|
|
71
|
+
menuItemProps: element.props,
|
|
70
72
|
};
|
|
71
73
|
menuItemsMap[`${item.id}`] = item;
|
|
72
74
|
return item;
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import type { TypeMenuItemProps } from "./MenuItem";
|
|
2
2
|
|
|
3
|
-
export interface
|
|
4
|
-
element: React.ReactElement<TypeMenuItemProps>;
|
|
5
|
-
parents: readonly React.ReactNode[];
|
|
6
|
-
}
|
|
7
|
-
export interface TypeDefaultItemProps extends Partial<TypeItemElements> {
|
|
3
|
+
export interface TypeDefaultItemProps {
|
|
8
4
|
id: string;
|
|
9
5
|
index: number;
|
|
10
6
|
disabled?: boolean;
|
|
7
|
+
menuItemProps?: TypeMenuItemProps;
|
|
11
8
|
}
|
|
12
9
|
|
|
13
10
|
export type TypeNotEmptyChildren =
|
package/tsconfig.json
CHANGED