@aurora-ds/components 1.8.1 → 1.8.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/dist/cjs/index.js +18 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +18 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -3466,6 +3466,13 @@ width = '100%', minWidth = 0, maxWidth, flex, flexGrow, flexShrink, flexBasis, .
|
|
|
3466
3466
|
};
|
|
3467
3467
|
TextField.displayName = 'TextField';
|
|
3468
3468
|
|
|
3469
|
+
/**
|
|
3470
|
+
* Vertical padding (in px) applied to the top and bottom of the menu panel.
|
|
3471
|
+
* Matches `theme.spacing.xs` (0.25rem = 4px at 16px base font).
|
|
3472
|
+
* Exported so submenus can offset their position upward by this amount to align
|
|
3473
|
+
* their first item with the trigger item.
|
|
3474
|
+
*/
|
|
3475
|
+
const MENU_PANEL_PADDING_Y_PX = 6;
|
|
3469
3476
|
const MENU_PANEL_STYLES = createStyles((theme) => ({
|
|
3470
3477
|
backdrop: {
|
|
3471
3478
|
position: 'fixed',
|
|
@@ -3539,7 +3546,7 @@ const MENU_MIN_WIDTH_PX = 224;
|
|
|
3539
3546
|
* Uses a two-pass strategy: first render with `menuHeight = 0`, then a rAF
|
|
3540
3547
|
* recompute with the actual rendered size to apply any overflow offset.
|
|
3541
3548
|
*/
|
|
3542
|
-
const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement = 'bottom', }) => {
|
|
3549
|
+
const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, verticalOffset = 0, placement = 'bottom', }) => {
|
|
3543
3550
|
const [style, setStyle] = useState({});
|
|
3544
3551
|
// Stays false until the rAF second pass has run with the real panel dimensions.
|
|
3545
3552
|
// Keeps the panel invisible during the initial style={} state and the first
|
|
@@ -3556,8 +3563,10 @@ const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement
|
|
|
3556
3563
|
const viewportRight = window.innerWidth - VIEWPORT_MARGIN_PX;
|
|
3557
3564
|
const viewportBottom = window.innerHeight - VIEWPORT_MARGIN_PX;
|
|
3558
3565
|
if (placement === 'right' || placement === 'left') {
|
|
3559
|
-
// --- Vertical: align with the anchor top,
|
|
3560
|
-
|
|
3566
|
+
// --- Vertical: align with the anchor top, offset upward by verticalOffset
|
|
3567
|
+
// (e.g. the panel's paddingTop) so the first item lines up with the trigger,
|
|
3568
|
+
// then clamp inside the viewport. ---
|
|
3569
|
+
let top = anchor.top - verticalOffset;
|
|
3561
3570
|
if (menuHeight > 0 && top + menuHeight > viewportBottom) {
|
|
3562
3571
|
top = Math.max(VIEWPORT_MARGIN_PX, viewportBottom - menuHeight);
|
|
3563
3572
|
}
|
|
@@ -3617,7 +3626,7 @@ const useMenuPosition = ({ anchorEl, open, menuRef, minWidth, gap = 4, placement
|
|
|
3617
3626
|
const maxLeft = window.innerWidth - effectiveWidth - VIEWPORT_MARGIN_PX;
|
|
3618
3627
|
const left = Math.max(VIEWPORT_MARGIN_PX, Math.min(anchor.left, maxLeft));
|
|
3619
3628
|
setStyle({ top, left, minWidth: minWidth ?? fallbackMinWidth });
|
|
3620
|
-
}, [anchorEl, menuRef, minWidth, gap, placement]);
|
|
3629
|
+
}, [anchorEl, menuRef, minWidth, gap, verticalOffset, placement]);
|
|
3621
3630
|
// First pass: compute as soon as the menu opens (menuHeight = 0)
|
|
3622
3631
|
useLayoutEffect(() => {
|
|
3623
3632
|
if (open) {
|
|
@@ -3690,12 +3699,12 @@ const ITEM_SELECTOR = '[role^="menuitem"]:not([data-disabled]), [role="option"]:
|
|
|
3690
3699
|
* `aria-activedescendant`. Item order is read from the DOM (read-only) so the
|
|
3691
3700
|
* logic stays correct across groups and dynamic content.
|
|
3692
3701
|
*/
|
|
3693
|
-
const useMenuPanel = ({ open, onClose, anchorEl, minWidth, placement = 'bottom', onArrowLeft, }) => {
|
|
3702
|
+
const useMenuPanel = ({ open, onClose, anchorEl, minWidth, placement = 'bottom', verticalOffset = 0, onArrowLeft, }) => {
|
|
3694
3703
|
const panelRef = useRef(null);
|
|
3695
3704
|
const [focusedId, setFocusedId] = useState(undefined);
|
|
3696
3705
|
// True while a descendant submenu is open → pause this panel's keyboard nav.
|
|
3697
3706
|
const [childOpen, setChildOpen] = useState(false);
|
|
3698
|
-
const { style } = useMenuPosition({ anchorEl, open, menuRef: panelRef, minWidth, placement });
|
|
3707
|
+
const { style } = useMenuPosition({ anchorEl, open, menuRef: panelRef, minWidth, placement, verticalOffset });
|
|
3699
3708
|
/** Read this panel's focusable items in DOM order (excluding nested submenus). */
|
|
3700
3709
|
const getItems = useCallback(() => {
|
|
3701
3710
|
const panel = panelRef.current;
|
|
@@ -3909,6 +3918,9 @@ const MenuPanel = ({ open, onClose, anchorEl, minWidth, maxHeight = '20rem', pla
|
|
|
3909
3918
|
anchorEl,
|
|
3910
3919
|
minWidth,
|
|
3911
3920
|
placement,
|
|
3921
|
+
// Shift submenus upward by the panel's paddingTop so the first item aligns
|
|
3922
|
+
// visually with the trigger item in the parent menu.
|
|
3923
|
+
verticalOffset: isSubmenu ? MENU_PANEL_PADDING_Y_PX : 0,
|
|
3912
3924
|
onArrowLeft,
|
|
3913
3925
|
});
|
|
3914
3926
|
const contextValue = useMemo(() => ({ setChildOpen, closeMenu }), [setChildOpen, closeMenu]);
|