@ringcentral/spring-ui 1.9.2 → 1.9.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/NestedMenuContext.js +1 -1
- package/SubMenu.js +20 -30
- package/chunks/useMenuItemSelect.js +6 -2
- package/package.json +4 -4
- package/src/NestedMenuContext/NestedMenuContext.d.ts +4 -1
- package/src/NestedMenuContext/SubMenuTriggerNestedIdContext.d.ts +2 -0
- package/src/NestedMenuContext/useNestedChildMenu.d.ts +2 -1
package/NestedMenuContext.js
CHANGED
|
@@ -8,7 +8,7 @@ const useNestedChildMenu = (props) => {
|
|
|
8
8
|
const { open, closeMenu, id } = props;
|
|
9
9
|
const context = useNestedMenuContext();
|
|
10
10
|
const { registOpenedSubMenu } = context ?? {};
|
|
11
|
-
const closeMenuMemo = useEventCallback(() => closeMenu());
|
|
11
|
+
const closeMenuMemo = useEventCallback((options) => closeMenu(options));
|
|
12
12
|
useEffect(() => {
|
|
13
13
|
if (open) {
|
|
14
14
|
return registOpenedSubMenu?.({
|
package/SubMenu.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Popper } from './Popper.js';
|
|
|
6
6
|
import { CaretRightMd } from '@ringcentral/spring-icon';
|
|
7
7
|
import { useThemeProps } from '@ringcentral/spring-theme';
|
|
8
8
|
import { I as Icon } from './chunks/Icon.js';
|
|
9
|
-
import { M as MenuItem } from './chunks/useMenuItemSelect.js';
|
|
9
|
+
import { S as SubMenuTriggerNestedIdContext, M as MenuItem } from './chunks/useMenuItemSelect.js';
|
|
10
10
|
import 'tabbable';
|
|
11
11
|
import './chunks/useListNavigation.js';
|
|
12
12
|
import './chunks/Menu.js';
|
|
@@ -49,7 +49,9 @@ const SubMenu = forwardRef((inProps, ref) => {
|
|
|
49
49
|
const itemRef = useRef(null);
|
|
50
50
|
const handleRef = useForkRef(itemRef, ref);
|
|
51
51
|
const open = Boolean(anchor);
|
|
52
|
-
const
|
|
52
|
+
const restoreFocusOnCloseRef = useRef(false);
|
|
53
|
+
const closeSubMenu = (options) => {
|
|
54
|
+
restoreFocusOnCloseRef.current = options?.restoreFocus === true;
|
|
53
55
|
setAnchor(null);
|
|
54
56
|
};
|
|
55
57
|
const { hover: anchorHover, hoverHandlers: anchorHoverHandlers } = useHover({
|
|
@@ -74,38 +76,28 @@ const SubMenu = forwardRef((inProps, ref) => {
|
|
|
74
76
|
useNestedMenuItem({ hovered: anchorHover, id });
|
|
75
77
|
useNestedChildMenu({
|
|
76
78
|
open,
|
|
77
|
-
closeMenu: () =>
|
|
78
|
-
closeSubMenu();
|
|
79
|
-
},
|
|
79
|
+
closeMenu: (options) => closeSubMenu(options),
|
|
80
80
|
id,
|
|
81
81
|
});
|
|
82
82
|
const shouldKeepMenu = (() => {
|
|
83
83
|
if (!open)
|
|
84
84
|
return false;
|
|
85
|
-
if (
|
|
85
|
+
if (!menuMounted)
|
|
86
86
|
return true;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
if ((!menuHover && menuHoverEverRef.current) ||
|
|
92
|
-
(!anchorHover && anchorHoverEverRef.current)) {
|
|
93
|
-
shouldKeepMenu = false;
|
|
94
|
-
}
|
|
95
|
-
if (menuHover || anchorHover) {
|
|
96
|
-
shouldKeepMenu = true;
|
|
97
|
-
}
|
|
98
|
-
return shouldKeepMenu;
|
|
87
|
+
if (focusVisibleWithin)
|
|
88
|
+
return true;
|
|
89
|
+
return menuHover || anchorHover;
|
|
99
90
|
})();
|
|
100
91
|
useEffect(() => {
|
|
101
92
|
if (!shouldKeepMenu) {
|
|
102
93
|
closeSubMenu();
|
|
103
94
|
}
|
|
104
|
-
return undefined;
|
|
105
95
|
}, [shouldKeepMenu]);
|
|
106
96
|
useOnLayoutReRender(() => {
|
|
97
|
+
const restoreFocus = restoreFocusOnCloseRef.current;
|
|
107
98
|
if (!open) {
|
|
108
|
-
itemRef.current?.focus();
|
|
99
|
+
restoreFocus && itemRef.current?.focus();
|
|
100
|
+
restoreFocusOnCloseRef.current = false;
|
|
109
101
|
}
|
|
110
102
|
}, [open]);
|
|
111
103
|
useEffect(() => {
|
|
@@ -115,21 +107,19 @@ const SubMenu = forwardRef((inProps, ref) => {
|
|
|
115
107
|
anchorHoverEverRef.current = false;
|
|
116
108
|
}
|
|
117
109
|
}, [open]);
|
|
118
|
-
return (jsxs(Fragment, { children: [jsxs(MenuItem, { autoClose: false, ...rest, onKeyDown: (e) => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
return (jsxs(Fragment, { children: [jsx(SubMenuTriggerNestedIdContext.Provider, { value: id, children: jsxs(MenuItem, { autoClose: false, ...rest, onKeyDown: (e) => {
|
|
111
|
+
onKeyDownProp?.(e);
|
|
112
|
+
if (e.key === 'ArrowRight') {
|
|
113
|
+
setAnchor(e.currentTarget);
|
|
114
|
+
}
|
|
115
|
+
}, ...anchorHoverHandlers, ref: handleRef, children: [typeof itemContent === 'string' ? (jsx(MenuItemText, { children: itemContent })) : (itemContent), jsx(Icon, { symbol: CaretRightMd })] }) }), open && (jsx(PopperMenu, { anchorEl: anchor, placement: "right-start", offset: -4, whileElementsMounted: () => {
|
|
124
116
|
setMenuMounted(true);
|
|
125
117
|
return () => { };
|
|
126
118
|
}, onKeyDown: (e) => {
|
|
127
119
|
if ((e.key === 'ArrowLeft' || e.key === 'Escape') &&
|
|
128
120
|
e.currentTarget.contains(e.target)) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
closeSubMenu();
|
|
121
|
+
e.stopPropagation();
|
|
122
|
+
closeSubMenu({ restoreFocus: true });
|
|
133
123
|
}
|
|
134
124
|
}, ...menuHoverHandlers, ...focusVisibleHandlers, children: children }))] }));
|
|
135
125
|
});
|
|
@@ -15,6 +15,8 @@ const MenuListContext = createContext({
|
|
|
15
15
|
});
|
|
16
16
|
const useMenuListContext = () => useContext(MenuListContext);
|
|
17
17
|
|
|
18
|
+
const SubMenuTriggerNestedIdContext = createContext(null);
|
|
19
|
+
|
|
18
20
|
const MenuItemSelectContext = createContext(null);
|
|
19
21
|
const useMenuItemSelectContext = () => useContext(MenuItemSelectContext);
|
|
20
22
|
|
|
@@ -128,7 +130,9 @@ const MenuItem = forwardRef((inProps, ref) => {
|
|
|
128
130
|
const selectMode = selectContextValue
|
|
129
131
|
? selectContextValue.selectMode
|
|
130
132
|
: 'single';
|
|
131
|
-
const
|
|
133
|
+
const subMenuTriggerNestedId = useContext(SubMenuTriggerNestedIdContext);
|
|
134
|
+
const generatedId = useId();
|
|
135
|
+
const id = subMenuTriggerNestedId ?? generatedId;
|
|
132
136
|
const { hover, hoverHandlers } = useHover({ onMouseEnter, onMouseLeave });
|
|
133
137
|
useNestedMenuItem({ hovered: hover, id });
|
|
134
138
|
useLayoutEffect(() => {
|
|
@@ -236,4 +240,4 @@ const useMenuItemSelect = (props) => {
|
|
|
236
240
|
};
|
|
237
241
|
};
|
|
238
242
|
|
|
239
|
-
export { Action as A, MenuItem as M, MenuItemSelectContext as a, useMenuItem as b, useMenuItemSelect as c, useVirtualizedMenuItem as d, MenuListContext as e, useMenuListContext as f, useMenuItemSelectContext as u };
|
|
243
|
+
export { Action as A, MenuItem as M, SubMenuTriggerNestedIdContext as S, MenuItemSelectContext as a, useMenuItem as b, useMenuItemSelect as c, useVirtualizedMenuItem as d, MenuListContext as e, useMenuListContext as f, useMenuItemSelectContext as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ringcentral/spring-ui",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"author": "RingCentral",
|
|
5
5
|
"description": "A comprehensive React component library built with Tailwind CSS, featuring production-ready components",
|
|
6
6
|
"main": "./index.js",
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
"@floating-ui/react-dom": "2.1.1",
|
|
16
16
|
"@juggle/resize-observer": "3.4.0",
|
|
17
17
|
"@mui/base": "5.0.0-beta.40",
|
|
18
|
-
"@ringcentral/spring-base": "^1.9.
|
|
19
|
-
"@ringcentral/spring-icon": "^1.9.
|
|
20
|
-
"@ringcentral/spring-theme": "^1.9.
|
|
18
|
+
"@ringcentral/spring-base": "^1.9.3",
|
|
19
|
+
"@ringcentral/spring-icon": "^1.9.3",
|
|
20
|
+
"@ringcentral/spring-theme": "^1.9.3",
|
|
21
21
|
"@types/lodash": "^4.14.182",
|
|
22
22
|
"@use-gesture/react": "10.3.1",
|
|
23
23
|
"clsx": "^1.2.1",
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
+
export declare type CloseSubMenuOptions = {
|
|
3
|
+
restoreFocus?: boolean;
|
|
4
|
+
};
|
|
2
5
|
export declare type SubMenuItemSymbol = {
|
|
3
6
|
anchorId: string;
|
|
4
|
-
closeSubMenu: () => void;
|
|
7
|
+
closeSubMenu: (options?: CloseSubMenuOptions) => void;
|
|
5
8
|
};
|
|
6
9
|
export declare type NestedMenuContextValue = {
|
|
7
10
|
registHoveredItem: (menuItemId: string) => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { CloseSubMenuOptions } from './NestedMenuContext';
|
|
1
2
|
export declare type UseNestedChildMenuProps = {
|
|
2
3
|
open: boolean;
|
|
3
4
|
id: string;
|
|
4
|
-
closeMenu: () => void;
|
|
5
|
+
closeMenu: (options?: CloseSubMenuOptions) => void;
|
|
5
6
|
};
|
|
6
7
|
export declare const useNestedChildMenu: (props: UseNestedChildMenuProps) => void;
|