@xsolla/xui-context-menu 0.185.0 → 0.185.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/native/index.js +31 -6
- package/native/index.js.map +1 -1
- package/native/index.mjs +31 -6
- package/native/index.mjs.map +1 -1
- package/package.json +10 -10
- package/web/index.js +31 -6
- package/web/index.js.map +1 -1
- package/web/index.mjs +31 -6
- package/web/index.mjs.map +1 -1
package/web/index.mjs
CHANGED
|
@@ -426,6 +426,7 @@ var OptionCell = ({
|
|
|
426
426
|
const closeTimerRef = React3.useRef(
|
|
427
427
|
null
|
|
428
428
|
);
|
|
429
|
+
const ownsSubmenu = Boolean(hasSubmenu && submenu != null);
|
|
429
430
|
const cancelClose = () => {
|
|
430
431
|
if (closeTimerRef.current) {
|
|
431
432
|
clearTimeout(closeTimerRef.current);
|
|
@@ -434,9 +435,22 @@ var OptionCell = ({
|
|
|
434
435
|
};
|
|
435
436
|
const scheduleClose = () => {
|
|
436
437
|
cancelClose();
|
|
437
|
-
closeTimerRef.current = setTimeout(() =>
|
|
438
|
+
closeTimerRef.current = setTimeout(() => {
|
|
439
|
+
setSubmenuOpen(false);
|
|
440
|
+
if (ownsSubmenu && ctx?.activeSubmenuId === id) {
|
|
441
|
+
ctx.setActiveSubmenuId?.(null);
|
|
442
|
+
}
|
|
443
|
+
}, 120);
|
|
438
444
|
};
|
|
439
445
|
useEffect(() => () => cancelClose(), []);
|
|
446
|
+
useEffect(() => {
|
|
447
|
+
if (!ownsSubmenu || !submenuOpen) return;
|
|
448
|
+
const activeId = ctx?.activeSubmenuId;
|
|
449
|
+
if (activeId != null && activeId !== id) {
|
|
450
|
+
cancelClose();
|
|
451
|
+
setSubmenuOpen(false);
|
|
452
|
+
}
|
|
453
|
+
}, [ctx?.activeSubmenuId, ownsSubmenu, submenuOpen, id]);
|
|
440
454
|
useEffect(() => {
|
|
441
455
|
if (!hasSubmenu || !submenuOpen) return;
|
|
442
456
|
const onMouseDown = (e) => {
|
|
@@ -445,13 +459,16 @@ var OptionCell = ({
|
|
|
445
459
|
const inOption = optionRef.current?.contains(target);
|
|
446
460
|
const inSubmenu = submenuWrapperRef.current?.contains(target);
|
|
447
461
|
if (!inOption && !inSubmenu) {
|
|
462
|
+
if (target.closest("[data-xui-context-menu-portal]")) return;
|
|
448
463
|
setSubmenuOpen(false);
|
|
449
464
|
return;
|
|
450
465
|
}
|
|
451
|
-
if (inSubmenu
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
466
|
+
if (inSubmenu) {
|
|
467
|
+
const activated = target.closest(
|
|
468
|
+
'[role="menuitem"],[role="menuitemcheckbox"],[role="menuitemradio"]'
|
|
469
|
+
);
|
|
470
|
+
const isLeafAction = activated?.getAttribute("role") === "menuitem" && activated.getAttribute("aria-haspopup") !== "menu";
|
|
471
|
+
if (isLeafAction) setSubmenuOpen(false);
|
|
455
472
|
}
|
|
456
473
|
};
|
|
457
474
|
document.addEventListener("mousedown", onMouseDown);
|
|
@@ -527,6 +544,7 @@ var OptionCell = ({
|
|
|
527
544
|
if (ctx && index2 >= 0) ctx.setActiveIndex(index2);
|
|
528
545
|
if (!ctx) setIsHovered(true);
|
|
529
546
|
if (hasSubmenu) setSubmenuOpen(true);
|
|
547
|
+
if (ownsSubmenu) ctx?.setActiveSubmenuId?.(id);
|
|
530
548
|
};
|
|
531
549
|
const handleLeave = () => {
|
|
532
550
|
if (!ctx) setIsHovered(false);
|
|
@@ -1344,6 +1362,7 @@ var ARROW_HALF = ARROW_SIZE / 2;
|
|
|
1344
1362
|
var ARROW_EDGE_OFFSET = 12;
|
|
1345
1363
|
var ARROW_TIP_PROTRUSION = ARROW_HALF * Math.SQRT2;
|
|
1346
1364
|
var PANEL_SHADOW = "0 4px 12px rgba(0,0,0,0.15)";
|
|
1365
|
+
var PORTALED_LAYER_SELECTOR = '[data-modal-id],[role="listbox"],[data-xui-context-menu-portal]';
|
|
1347
1366
|
var textFromNode = (node) => {
|
|
1348
1367
|
if (node === null || node === void 0 || typeof node === "boolean")
|
|
1349
1368
|
return "";
|
|
@@ -1530,7 +1549,13 @@ var ContextMenuRoot = forwardRef(
|
|
|
1530
1549
|
if (!isOpen || !trigger) return;
|
|
1531
1550
|
const onMouseDown = (event) => {
|
|
1532
1551
|
const target = event.target;
|
|
1533
|
-
if (!target
|
|
1552
|
+
if (!target) return;
|
|
1553
|
+
if (containerRef.current?.contains(target)) return;
|
|
1554
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
1555
|
+
const isInsidePortaledLayer = path.length ? path.some(
|
|
1556
|
+
(node) => node instanceof Element && node.matches(PORTALED_LAYER_SELECTOR)
|
|
1557
|
+
) : target instanceof Element && !!target.closest(PORTALED_LAYER_SELECTOR);
|
|
1558
|
+
if (isInsidePortaledLayer) return;
|
|
1534
1559
|
closeMenu();
|
|
1535
1560
|
};
|
|
1536
1561
|
const onScroll = () => closeMenu();
|