@aurora-ds/components 1.7.19 → 1.7.21
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/dist/cjs/index.js +26 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +26 -9
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -3561,6 +3561,10 @@ const MENU_MIN_WIDTH_PX = 224;
|
|
|
3561
3561
|
*/
|
|
3562
3562
|
const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement = 'bottom', }) => {
|
|
3563
3563
|
const [style, setStyle] = React.useState({});
|
|
3564
|
+
// Stays false until the rAF second pass has run with the real panel dimensions.
|
|
3565
|
+
// Keeps the panel invisible during the initial style={} state and the first
|
|
3566
|
+
// pass (menuHeight = 0) to prevent the position-jump flickering.
|
|
3567
|
+
const [isPositioned, setIsPositioned] = React.useState(false);
|
|
3564
3568
|
const computePosition = React.useCallback(() => {
|
|
3565
3569
|
if (!anchorEl) {
|
|
3566
3570
|
return;
|
|
@@ -3641,14 +3645,19 @@ const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement
|
|
|
3641
3645
|
}
|
|
3642
3646
|
else {
|
|
3643
3647
|
setStyle({});
|
|
3648
|
+
setIsPositioned(false);
|
|
3644
3649
|
}
|
|
3645
3650
|
}, [open, computePosition]);
|
|
3646
|
-
// Second pass: recompute after the panel renders to get actual height/width
|
|
3651
|
+
// Second pass: recompute after the panel renders to get actual height/width,
|
|
3652
|
+
// then mark as positioned so the panel becomes visible.
|
|
3647
3653
|
React.useEffect(() => {
|
|
3648
3654
|
if (!open) {
|
|
3649
3655
|
return;
|
|
3650
3656
|
}
|
|
3651
|
-
const id = requestAnimationFrame(
|
|
3657
|
+
const id = requestAnimationFrame(() => {
|
|
3658
|
+
computePosition();
|
|
3659
|
+
setIsPositioned(true);
|
|
3660
|
+
});
|
|
3652
3661
|
return () => cancelAnimationFrame(id);
|
|
3653
3662
|
}, [open, computePosition]);
|
|
3654
3663
|
// Keep the menu glued to its anchor on scroll (nested containers) and resize.
|
|
@@ -3663,7 +3672,7 @@ const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement
|
|
|
3663
3672
|
window.removeEventListener('resize', computePosition);
|
|
3664
3673
|
};
|
|
3665
3674
|
}, [open, computePosition]);
|
|
3666
|
-
return { style };
|
|
3675
|
+
return { style: { ...style, visibility: isPositioned ? 'visible' : 'hidden' } };
|
|
3667
3676
|
};
|
|
3668
3677
|
|
|
3669
3678
|
/** Custom DOM event fired on a submenu trigger item to request it opens. */
|
|
@@ -3987,7 +3996,7 @@ const HOVER_CLOSE_DELAY_MS = 160;
|
|
|
3987
3996
|
* focus restoration, parent-keyboard pausing and the configurable close-on-click
|
|
3988
3997
|
* behaviour.
|
|
3989
3998
|
*/
|
|
3990
|
-
const useMenuItem = ({ ref, role, hasSubmenu, disabled, onClick, closeOnClick, }) => {
|
|
3999
|
+
const useMenuItem = ({ ref, role, hasSubmenu, disabled, onClick, closeOnClick, submenuTrigger = 'hover', }) => {
|
|
3991
4000
|
const { setChildOpen, closeMenu } = React.useContext(MenuContext);
|
|
3992
4001
|
const liRef = React.useRef(null);
|
|
3993
4002
|
const mergedRef = useMergedRefs(ref, liRef);
|
|
@@ -4047,14 +4056,20 @@ const useMenuItem = ({ ref, role, hasSubmenu, disabled, onClick, closeOnClick, }
|
|
|
4047
4056
|
return;
|
|
4048
4057
|
}
|
|
4049
4058
|
if (hasSubmenu) {
|
|
4050
|
-
|
|
4059
|
+
if (submenuTrigger === 'click') {
|
|
4060
|
+
// Toggle: click again closes the submenu.
|
|
4061
|
+
setSubmenuOpen((prev) => !prev);
|
|
4062
|
+
}
|
|
4063
|
+
else {
|
|
4064
|
+
openSubmenu();
|
|
4065
|
+
}
|
|
4051
4066
|
return;
|
|
4052
4067
|
}
|
|
4053
4068
|
onClick?.(event);
|
|
4054
4069
|
if (shouldCloseOnClick) {
|
|
4055
4070
|
closeMenu?.();
|
|
4056
4071
|
}
|
|
4057
|
-
}, [disabled, hasSubmenu, openSubmenu, onClick, shouldCloseOnClick, closeMenu]);
|
|
4072
|
+
}, [disabled, hasSubmenu, submenuTrigger, openSubmenu, onClick, shouldCloseOnClick, closeMenu]);
|
|
4058
4073
|
return {
|
|
4059
4074
|
liRef,
|
|
4060
4075
|
mergedRef,
|
|
@@ -4064,6 +4079,7 @@ const useMenuItem = ({ ref, role, hasSubmenu, disabled, onClick, closeOnClick, }
|
|
|
4064
4079
|
scheduleClose,
|
|
4065
4080
|
clearTimers,
|
|
4066
4081
|
closeSubmenu,
|
|
4082
|
+
submenuTrigger,
|
|
4067
4083
|
};
|
|
4068
4084
|
};
|
|
4069
4085
|
|
|
@@ -4138,13 +4154,14 @@ const MENU_ITEM_STYLES = theme.createStyles((theme) => {
|
|
|
4138
4154
|
};
|
|
4139
4155
|
}, { id: 'menu-item' });
|
|
4140
4156
|
|
|
4141
|
-
const MenuItem = ({ ref, label, icon, iconColor, role = 'menuitem', checked, selected, focused, disabled, size = 'default', closeOnClick, submenu, submenuPlacement = 'right', onClick, ...rest }) => {
|
|
4157
|
+
const MenuItem = ({ ref, label, icon, iconColor, role = 'menuitem', checked, selected, focused, disabled, size = 'default', closeOnClick, submenu, submenuTrigger = 'click', submenuPlacement = 'right', onClick, ...rest }) => {
|
|
4142
4158
|
const hasSubmenu = submenu !== undefined;
|
|
4143
4159
|
const isCheckable = role === 'menuitemcheckbox' || role === 'menuitemradio';
|
|
4144
4160
|
const isOption = role === 'option';
|
|
4145
4161
|
const isHighlighted = isCheckable ? Boolean(checked) : Boolean(selected);
|
|
4146
|
-
const { liRef, mergedRef, submenuOpen, handleClick, scheduleOpen, scheduleClose, clearTimers, closeSubmenu, } = useMenuItem({ ref, role, hasSubmenu, disabled, onClick, closeOnClick });
|
|
4147
|
-
|
|
4162
|
+
const { liRef, mergedRef, submenuOpen, handleClick, scheduleOpen, scheduleClose, clearTimers, closeSubmenu, } = useMenuItem({ ref, role, hasSubmenu, disabled, onClick, closeOnClick, submenuTrigger });
|
|
4163
|
+
const isHoverTrigger = submenuTrigger === 'hover';
|
|
4164
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("li", { ref: mergedRef, role: role, "aria-checked": isCheckable ? Boolean(checked) : undefined, "aria-selected": isOption ? Boolean(selected) : undefined, "aria-disabled": disabled, "aria-haspopup": hasSubmenu ? 'menu' : undefined, "aria-expanded": hasSubmenu ? submenuOpen : undefined, "data-selected": isHighlighted || undefined, "data-focused": focused || undefined, "data-disabled": disabled || undefined, className: MENU_ITEM_STYLES.root({ size }), onClick: handleClick, onMouseEnter: hasSubmenu && !disabled && isHoverTrigger ? scheduleOpen : undefined, onMouseLeave: hasSubmenu && isHoverTrigger ? scheduleClose : undefined, ...rest, children: [isCheckable && (jsxRuntime.jsxs("span", { className: MENU_ITEM_STYLES.indicator, "aria-hidden": true, children: [checked && role === 'menuitemcheckbox' && (jsxRuntime.jsx(Icon, { icon: CheckIcon, size: size === 'default' ? 'sm' : 'md', strokeColor: 'primaryMain' })), checked && role === 'menuitemradio' && (jsxRuntime.jsx("span", { className: MENU_ITEM_STYLES.radioDot }))] })), icon !== undefined && (jsxRuntime.jsx(Icon, { icon: icon, size: 'sm', strokeColor: iconColor ?? (isHighlighted ? 'primaryMain' : 'textSecondary') })), jsxRuntime.jsx(Text, { variant: 'span', fontSize: 'sm', className: MENU_ITEM_STYLES.label, children: label }), hasSubmenu && (jsxRuntime.jsx("span", { className: MENU_ITEM_STYLES.submenuChevron, "aria-hidden": true, children: jsxRuntime.jsx(Icon, { icon: ChevronRightIcon, size: 'sm', strokeColor: 'textTertiary' }) }))] }), hasSubmenu && (jsxRuntime.jsx(MenuPanel, { open: submenuOpen, onClose: () => closeSubmenu(true), onArrowLeft: () => closeSubmenu(true), anchorEl: liRef.current, placement: submenuPlacement, isSubmenu: true, "aria-label": label, onMouseEnter: isHoverTrigger ? clearTimers : undefined, onMouseLeave: isHoverTrigger ? scheduleClose : undefined, children: submenu }))] }));
|
|
4148
4165
|
};
|
|
4149
4166
|
MenuItem.displayName = 'MenuItem';
|
|
4150
4167
|
|