@versini/ui-menu 7.1.0 → 7.1.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/index.d.ts +3 -2
- package/dist/index.js +41 -23
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { JSX } from 'react
|
|
1
|
+
import { JSX } from 'react';
|
|
2
|
+
import * as React_2 from 'react';
|
|
2
3
|
|
|
3
4
|
export declare const Menu: {
|
|
4
|
-
({ trigger, children, label, defaultPlacement, onOpenChange, mode, sideOffset, noBackdrop, }: MenuProps): JSX.Element;
|
|
5
|
+
({ trigger, children, label, defaultPlacement, onOpenChange, mode, sideOffset, noBackdrop, }: MenuProps): React_2.JSX.Element;
|
|
5
6
|
displayName: string;
|
|
6
7
|
};
|
|
7
8
|
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
@versini/ui-menu v7.1.
|
|
2
|
+
@versini/ui-menu v7.1.2
|
|
3
3
|
© 2026 gizmette.com
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useUniqueId } from "@versini/ui-hooks/use-unique-id";
|
|
8
|
-
import {
|
|
9
|
-
import clsx_0
|
|
8
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
9
|
+
import clsx_0, { clsx } from "clsx";
|
|
10
10
|
import { IconNext } from "@versini/ui-icons";
|
|
11
11
|
|
|
12
|
+
import * as __rspack_external_react from "react";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
|
|
@@ -30,6 +34,7 @@ const MenuContentContext = createContext({
|
|
|
30
34
|
}); /* v8 ignore stop */
|
|
31
35
|
|
|
32
36
|
|
|
37
|
+
|
|
33
38
|
function getNextEnabledIndex(items, currentIndex, direction) {
|
|
34
39
|
const count = items.length;
|
|
35
40
|
/* v8 ignore start - empty items edge case */ if (count === 0) {
|
|
@@ -65,8 +70,8 @@ function getTypeaheadMatchIndex(items, searchString, startIndex) {
|
|
|
65
70
|
if (items[index].disabled) {
|
|
66
71
|
continue;
|
|
67
72
|
}
|
|
68
|
-
|
|
69
|
-
if (text.startsWith(matchStr)) {
|
|
73
|
+
/* v8 ignore start -- textContent is always a string in DOM */ const text = (items[index].element.textContent ?? "").trim().toLowerCase();
|
|
74
|
+
/* v8 ignore stop */ if (text.startsWith(matchStr)) {
|
|
70
75
|
return index;
|
|
71
76
|
}
|
|
72
77
|
}
|
|
@@ -258,6 +263,7 @@ function getLastEnabledIndex(items) {
|
|
|
258
263
|
|
|
259
264
|
|
|
260
265
|
|
|
266
|
+
|
|
261
267
|
const getDisplayName = (element)=>{
|
|
262
268
|
if (typeof element === "string") {
|
|
263
269
|
return element;
|
|
@@ -419,14 +425,14 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
419
425
|
isSub: false,
|
|
420
426
|
noBackdrop
|
|
421
427
|
});
|
|
422
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
423
|
-
const [activeIndex, setActiveIndex] = useState(-1);
|
|
424
|
-
const [openSubMenuId, setOpenSubMenuId] = useState(null);
|
|
428
|
+
const [isOpen, setIsOpen] = (0,__rspack_external_react.useState)(false);
|
|
429
|
+
const [activeIndex, setActiveIndex] = (0,__rspack_external_react.useState)(-1);
|
|
430
|
+
const [openSubMenuId, setOpenSubMenuId] = (0,__rspack_external_react.useState)(null);
|
|
425
431
|
const menuId = useUniqueId("av-menu-");
|
|
426
|
-
const triggerRef = useRef(null);
|
|
427
|
-
const menuRef = useRef(null);
|
|
428
|
-
const itemsRef = useRef([]);
|
|
429
|
-
const isTogglingRef = useRef(false);
|
|
432
|
+
const triggerRef = (0,__rspack_external_react.useRef)(null);
|
|
433
|
+
const menuRef = (0,__rspack_external_react.useRef)(null);
|
|
434
|
+
const itemsRef = (0,__rspack_external_react.useRef)([]);
|
|
435
|
+
const isTogglingRef = (0,__rspack_external_react.useRef)(false);
|
|
430
436
|
useMenuPosition({
|
|
431
437
|
triggerRef,
|
|
432
438
|
menuRef,
|
|
@@ -435,7 +441,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
435
441
|
isOpen
|
|
436
442
|
});
|
|
437
443
|
// Show/hide popover after the menu element is mounted/unmounted
|
|
438
|
-
/* v8 ignore start - popover API may not be available in test env */ useEffect(()=>{
|
|
444
|
+
/* v8 ignore start - popover API may not be available in test env */ (0,__rspack_external_react.useEffect)(()=>{
|
|
439
445
|
if (isOpen && menuRef.current && typeof menuRef.current.showPopover === "function") {
|
|
440
446
|
try {
|
|
441
447
|
menuRef.current.showPopover();
|
|
@@ -446,7 +452,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
446
452
|
}, [
|
|
447
453
|
isOpen
|
|
448
454
|
]);
|
|
449
|
-
/* v8 ignore stop */ const handleClose = useCallback(()=>{
|
|
455
|
+
/* v8 ignore stop */ const handleClose = (0,__rspack_external_react.useCallback)(()=>{
|
|
450
456
|
/* v8 ignore start - guard against double-close */ if (!isOpen) {
|
|
451
457
|
return;
|
|
452
458
|
}
|
|
@@ -467,7 +473,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
467
473
|
onOpenChange
|
|
468
474
|
]);
|
|
469
475
|
// Click-outside detection: only active when menu is open
|
|
470
|
-
/* v8 ignore start - click-outside detection requires full browser env */ useEffect(()=>{
|
|
476
|
+
/* v8 ignore start - click-outside detection requires full browser env */ (0,__rspack_external_react.useEffect)(()=>{
|
|
471
477
|
if (!isOpen) {
|
|
472
478
|
return;
|
|
473
479
|
}
|
|
@@ -493,8 +499,8 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
493
499
|
isOpen,
|
|
494
500
|
onOpenChange
|
|
495
501
|
]);
|
|
496
|
-
/* v8 ignore stop */ const getItems = useCallback(()=>itemsRef.current, []);
|
|
497
|
-
const registerItem = useCallback((element, disabled)=>{
|
|
502
|
+
/* v8 ignore stop */ const getItems = (0,__rspack_external_react.useCallback)(()=>itemsRef.current, []);
|
|
503
|
+
const registerItem = (0,__rspack_external_react.useCallback)((element, disabled)=>{
|
|
498
504
|
// Maintain DOM order by using compareDocumentPosition
|
|
499
505
|
const existing = itemsRef.current.findIndex((item)=>item.element === element);
|
|
500
506
|
/* v8 ignore start - re-registration on re-render */ if (existing >= 0) {
|
|
@@ -513,10 +519,10 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
513
519
|
itemsRef.current.splice(insertIndex, 0, newItem);
|
|
514
520
|
}
|
|
515
521
|
/* v8 ignore stop */ }, []);
|
|
516
|
-
const unregisterItem = useCallback((element)=>{
|
|
522
|
+
const unregisterItem = (0,__rspack_external_react.useCallback)((element)=>{
|
|
517
523
|
itemsRef.current = itemsRef.current.filter((item)=>item.element !== element);
|
|
518
524
|
}, []);
|
|
519
|
-
/* v8 ignore start - sub-menu keyboard nav requires full browser env */ const handleOpenSubMenu = useCallback((element)=>{
|
|
525
|
+
/* v8 ignore start - sub-menu keyboard nav requires full browser env */ const handleOpenSubMenu = (0,__rspack_external_react.useCallback)((element)=>{
|
|
520
526
|
element.click();
|
|
521
527
|
}, []);
|
|
522
528
|
/* v8 ignore stop */ const { focusItem } = useMenuKeyboard({
|
|
@@ -528,7 +534,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
528
534
|
onClose: handleClose,
|
|
529
535
|
onOpenSubMenu: handleOpenSubMenu
|
|
530
536
|
});
|
|
531
|
-
const handleOpen = useCallback(()=>{
|
|
537
|
+
const handleOpen = (0,__rspack_external_react.useCallback)(()=>{
|
|
532
538
|
setIsOpen(true);
|
|
533
539
|
onOpenChange?.(true);
|
|
534
540
|
// Focus first enabled item after menu renders
|
|
@@ -547,7 +553,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
547
553
|
getItems,
|
|
548
554
|
focusItem
|
|
549
555
|
]);
|
|
550
|
-
const handleToggle = useCallback(()=>{
|
|
556
|
+
const handleToggle = (0,__rspack_external_react.useCallback)(()=>{
|
|
551
557
|
/* v8 ignore start - re-entrant guard for synthetic click dispatch */ if (isTogglingRef.current) {
|
|
552
558
|
return;
|
|
553
559
|
}
|
|
@@ -575,7 +581,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
575
581
|
handleClose,
|
|
576
582
|
handleOpen
|
|
577
583
|
]);
|
|
578
|
-
/* v8 ignore start - trigger keyboard handler tested via integration */ const handleTriggerKeyDown = useCallback((event)=>{
|
|
584
|
+
/* v8 ignore start - trigger keyboard handler tested via integration */ const handleTriggerKeyDown = (0,__rspack_external_react.useCallback)((event)=>{
|
|
579
585
|
if (event.key === "Enter" || event.key === " " || event.key === "ArrowDown") {
|
|
580
586
|
event.preventDefault();
|
|
581
587
|
if (!isOpen) {
|
|
@@ -592,7 +598,7 @@ const Menu = ({ trigger, children, label = "Open menu", defaultPlacement = "bott
|
|
|
592
598
|
noInternalClick,
|
|
593
599
|
mode
|
|
594
600
|
} : {};
|
|
595
|
-
/* v8 ignore start - trigger is required in practice */ const triggerElement = /*#__PURE__*/ isValidElement(trigger) ? /*#__PURE__*/ cloneElement(trigger, {
|
|
601
|
+
/* v8 ignore start - trigger is required in practice */ const triggerElement = /*#__PURE__*/ __rspack_external_react.isValidElement(trigger) ? /*#__PURE__*/ __rspack_external_react.cloneElement(trigger, {
|
|
596
602
|
...uiButtonsExtraProps,
|
|
597
603
|
"aria-label": label,
|
|
598
604
|
"aria-haspopup": "menu",
|
|
@@ -639,6 +645,8 @@ Menu.displayName = "Menu";
|
|
|
639
645
|
|
|
640
646
|
|
|
641
647
|
|
|
648
|
+
|
|
649
|
+
|
|
642
650
|
const MenuGroup = ({ children, label, className, icon })=>{
|
|
643
651
|
const groupClass = clsx_0("rounded-md", "p-2", "first:mt-0 mt-1", "bg-surface-dark", "text-copy-light", className);
|
|
644
652
|
const labelContainerClass = clsx_0("pt-2 pb-2", "px-3 sm:px-2", "-mx-1 -mt-1", "flex items-center justify-between", "text-xs text-copy-medium uppercase font-bold", "rounded-t-md");
|
|
@@ -672,6 +680,9 @@ MenuGroup.displayName = "MenuGroup";
|
|
|
672
680
|
|
|
673
681
|
|
|
674
682
|
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
|
|
675
686
|
const ITEM_CLASS = getMenuItemClasses({
|
|
676
687
|
isSub: false
|
|
677
688
|
});
|
|
@@ -804,6 +815,8 @@ MenuItem.displayName = "MenuItem";
|
|
|
804
815
|
|
|
805
816
|
|
|
806
817
|
|
|
818
|
+
|
|
819
|
+
|
|
807
820
|
const MenuLabel = ({ className, icon, children, ...props })=>{
|
|
808
821
|
const groupLabelClass = clsx_0(className, "pt-1 pb-2", "text-xs text-copy-medium uppercase font-bold", "border-b border-border-medium", {
|
|
809
822
|
"flex items-center": icon
|
|
@@ -825,6 +838,8 @@ MenuLabel.displayName = "MenuLabel";
|
|
|
825
838
|
|
|
826
839
|
|
|
827
840
|
|
|
841
|
+
|
|
842
|
+
|
|
828
843
|
const MenuSeparator = ({ className, ...props })=>{
|
|
829
844
|
const separatorClass = clsx_0(className, "my-1 border-t border-border-medium");
|
|
830
845
|
return /*#__PURE__*/ jsx("div", {
|
|
@@ -844,6 +859,9 @@ MenuSeparator.displayName = "MenuSeparator";
|
|
|
844
859
|
|
|
845
860
|
|
|
846
861
|
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
|
|
847
865
|
const SUB_CONTENT_CLASS = getMenuClasses({
|
|
848
866
|
isSub: true
|
|
849
867
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/ui-menu",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@versini/ui-hooks": "6.1.1",
|
|
45
|
-
"@versini/ui-icons": "4.
|
|
45
|
+
"@versini/ui-icons": "4.29.0",
|
|
46
46
|
"clsx": "2.1.1",
|
|
47
|
-
"tailwindcss": "4.3.
|
|
47
|
+
"tailwindcss": "4.3.1"
|
|
48
48
|
},
|
|
49
49
|
"sideEffects": [
|
|
50
50
|
"**/*.css"
|
|
51
51
|
],
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "f25e4b557175f745705c249d10e2e77dc02ed462"
|
|
53
53
|
}
|