@xsolla/xui-context-menu 0.184.0 → 0.185.1
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.d.mts +14 -1
- package/native/index.d.ts +14 -1
- package/native/index.js +48 -11
- package/native/index.js.map +1 -1
- package/native/index.mjs +57 -20
- package/native/index.mjs.map +1 -1
- package/package.json +10 -10
- package/web/index.d.mts +14 -1
- package/web/index.d.ts +14 -1
- package/web/index.js +48 -11
- package/web/index.js.map +1 -1
- package/web/index.mjs +57 -20
- package/web/index.mjs.map +1 -1
package/web/index.js
CHANGED
|
@@ -456,6 +456,7 @@ var OptionCell = ({
|
|
|
456
456
|
const closeTimerRef = import_react4.default.useRef(
|
|
457
457
|
null
|
|
458
458
|
);
|
|
459
|
+
const ownsSubmenu = Boolean(hasSubmenu && submenu != null);
|
|
459
460
|
const cancelClose = () => {
|
|
460
461
|
if (closeTimerRef.current) {
|
|
461
462
|
clearTimeout(closeTimerRef.current);
|
|
@@ -464,9 +465,22 @@ var OptionCell = ({
|
|
|
464
465
|
};
|
|
465
466
|
const scheduleClose = () => {
|
|
466
467
|
cancelClose();
|
|
467
|
-
closeTimerRef.current = setTimeout(() =>
|
|
468
|
+
closeTimerRef.current = setTimeout(() => {
|
|
469
|
+
setSubmenuOpen(false);
|
|
470
|
+
if (ownsSubmenu && ctx?.activeSubmenuId === id) {
|
|
471
|
+
ctx.setActiveSubmenuId?.(null);
|
|
472
|
+
}
|
|
473
|
+
}, 120);
|
|
468
474
|
};
|
|
469
475
|
(0, import_react4.useEffect)(() => () => cancelClose(), []);
|
|
476
|
+
(0, import_react4.useEffect)(() => {
|
|
477
|
+
if (!ownsSubmenu || !submenuOpen) return;
|
|
478
|
+
const activeId = ctx?.activeSubmenuId;
|
|
479
|
+
if (activeId != null && activeId !== id) {
|
|
480
|
+
cancelClose();
|
|
481
|
+
setSubmenuOpen(false);
|
|
482
|
+
}
|
|
483
|
+
}, [ctx?.activeSubmenuId, ownsSubmenu, submenuOpen, id]);
|
|
470
484
|
(0, import_react4.useEffect)(() => {
|
|
471
485
|
if (!hasSubmenu || !submenuOpen) return;
|
|
472
486
|
const onMouseDown = (e) => {
|
|
@@ -557,6 +571,7 @@ var OptionCell = ({
|
|
|
557
571
|
if (ctx && index2 >= 0) ctx.setActiveIndex(index2);
|
|
558
572
|
if (!ctx) setIsHovered(true);
|
|
559
573
|
if (hasSubmenu) setSubmenuOpen(true);
|
|
574
|
+
if (ownsSubmenu) ctx?.setActiveSubmenuId?.(id);
|
|
560
575
|
};
|
|
561
576
|
const handleLeave = () => {
|
|
562
577
|
if (!ctx) setIsHovered(false);
|
|
@@ -1156,12 +1171,13 @@ var joinPlacement = (vertical, horizontal) => `${vertical}-${horizontal}`;
|
|
|
1156
1171
|
var useContextMenuPosition = ({
|
|
1157
1172
|
triggerRef,
|
|
1158
1173
|
panelRef,
|
|
1174
|
+
containerRef,
|
|
1159
1175
|
isOpen,
|
|
1160
1176
|
placement = "bottom-start",
|
|
1161
1177
|
offset = 4
|
|
1162
1178
|
}) => {
|
|
1163
1179
|
const [resolved, setResolved] = (0, import_react6.useState)();
|
|
1164
|
-
(0, import_react6.
|
|
1180
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
1165
1181
|
if (!isOpen) {
|
|
1166
1182
|
setResolved(void 0);
|
|
1167
1183
|
return;
|
|
@@ -1169,6 +1185,7 @@ var useContextMenuPosition = ({
|
|
|
1169
1185
|
const compute = () => {
|
|
1170
1186
|
const trigger = triggerRef.current;
|
|
1171
1187
|
const panel = panelRef.current;
|
|
1188
|
+
const container = containerRef.current;
|
|
1172
1189
|
if (!trigger || !panel) return;
|
|
1173
1190
|
const triggerRect = trigger.getBoundingClientRect();
|
|
1174
1191
|
const panelRect = panel.getBoundingClientRect();
|
|
@@ -1208,6 +1225,15 @@ var useContextMenuPosition = ({
|
|
|
1208
1225
|
}
|
|
1209
1226
|
}
|
|
1210
1227
|
}
|
|
1228
|
+
if (container) {
|
|
1229
|
+
const containerRect = container.getBoundingClientRect();
|
|
1230
|
+
const cOffsetW = container.offsetWidth;
|
|
1231
|
+
const cOffsetH = container.offsetHeight;
|
|
1232
|
+
const scaleX = cOffsetW > 0 ? containerRect.width / cOffsetW : 1;
|
|
1233
|
+
const scaleY = cOffsetH > 0 ? containerRect.height / cOffsetH : 1;
|
|
1234
|
+
left = (left - containerRect.left) / (scaleX || 1);
|
|
1235
|
+
top = (top - containerRect.top) / (scaleY || 1);
|
|
1236
|
+
}
|
|
1211
1237
|
const next = {
|
|
1212
1238
|
top,
|
|
1213
1239
|
left,
|
|
@@ -1217,14 +1243,13 @@ var useContextMenuPosition = ({
|
|
|
1217
1243
|
(prev) => prev && prev.top === next.top && prev.left === next.left && prev.placement === next.placement ? prev : next
|
|
1218
1244
|
);
|
|
1219
1245
|
};
|
|
1220
|
-
|
|
1246
|
+
compute();
|
|
1221
1247
|
const onResize = () => compute();
|
|
1222
1248
|
window.addEventListener("resize", onResize);
|
|
1223
1249
|
return () => {
|
|
1224
|
-
window.cancelAnimationFrame(rafId);
|
|
1225
1250
|
window.removeEventListener("resize", onResize);
|
|
1226
1251
|
};
|
|
1227
|
-
}, [isOpen, placement, offset, triggerRef, panelRef]);
|
|
1252
|
+
}, [isOpen, placement, offset, triggerRef, panelRef, containerRef]);
|
|
1228
1253
|
return resolved;
|
|
1229
1254
|
};
|
|
1230
1255
|
|
|
@@ -1356,6 +1381,7 @@ var SEARCH_DEBOUNCE_MS = 200;
|
|
|
1356
1381
|
var ARROW_SIZE = 10;
|
|
1357
1382
|
var ARROW_HALF = ARROW_SIZE / 2;
|
|
1358
1383
|
var ARROW_EDGE_OFFSET = 12;
|
|
1384
|
+
var ARROW_TIP_PROTRUSION = ARROW_HALF * Math.SQRT2;
|
|
1359
1385
|
var PANEL_SHADOW = "0 4px 12px rgba(0,0,0,0.15)";
|
|
1360
1386
|
var textFromNode = (node) => {
|
|
1361
1387
|
if (node === null || node === void 0 || typeof node === "boolean")
|
|
@@ -1405,7 +1431,9 @@ var ContextMenuRoot = (0, import_react8.forwardRef)(
|
|
|
1405
1431
|
isOpen: propIsOpen,
|
|
1406
1432
|
onOpenChange,
|
|
1407
1433
|
trigger,
|
|
1434
|
+
triggerFullWidth = false,
|
|
1408
1435
|
placement = "bottom-start",
|
|
1436
|
+
offset = 4,
|
|
1409
1437
|
position,
|
|
1410
1438
|
width,
|
|
1411
1439
|
maxHeight = 300,
|
|
@@ -1439,11 +1467,14 @@ var ContextMenuRoot = (0, import_react8.forwardRef)(
|
|
|
1439
1467
|
const sizeStyles = xuiTheme.sizing.contextMenu(size);
|
|
1440
1468
|
const borderRadius = xuiTheme.shape?.contextMenu?.[size]?.borderRadius ?? 8;
|
|
1441
1469
|
const shouldCloseOnSelect = closeOnSelect ?? (type === "checkbox" ? false : true);
|
|
1470
|
+
const positionOffset = withArrow ? offset + ARROW_TIP_PROTRUSION : offset;
|
|
1442
1471
|
const positioned = useContextMenuPosition({
|
|
1443
1472
|
triggerRef,
|
|
1444
1473
|
panelRef,
|
|
1474
|
+
containerRef,
|
|
1445
1475
|
isOpen: isOpen && !!trigger && !position,
|
|
1446
|
-
placement
|
|
1476
|
+
placement,
|
|
1477
|
+
offset: positionOffset
|
|
1447
1478
|
});
|
|
1448
1479
|
const resolvedPlacement = positioned?.placement ?? placement;
|
|
1449
1480
|
const getArrowStyle = (arrowPlacement) => {
|
|
@@ -1699,7 +1730,10 @@ var ContextMenuRoot = (0, import_react8.forwardRef)(
|
|
|
1699
1730
|
onClick: (event) => {
|
|
1700
1731
|
if (!event.defaultPrevented) toggleMenu();
|
|
1701
1732
|
},
|
|
1702
|
-
style: {
|
|
1733
|
+
style: {
|
|
1734
|
+
display: "inline-flex",
|
|
1735
|
+
width: triggerFullWidth ? "100%" : "auto"
|
|
1736
|
+
},
|
|
1703
1737
|
children: (0, import_react8.cloneElement)(trigger, {
|
|
1704
1738
|
"aria-haspopup": "menu",
|
|
1705
1739
|
"aria-expanded": isOpen ? "true" : "false"
|
|
@@ -1721,10 +1755,13 @@ var ContextMenuRoot = (0, import_react8.forwardRef)(
|
|
|
1721
1755
|
position: "fixed",
|
|
1722
1756
|
left: position.x,
|
|
1723
1757
|
top: position.y
|
|
1724
|
-
} : trigger ? {
|
|
1725
|
-
position: "
|
|
1726
|
-
left: positioned
|
|
1727
|
-
top: positioned
|
|
1758
|
+
} : trigger ? positioned ? {
|
|
1759
|
+
position: "absolute",
|
|
1760
|
+
left: positioned.left,
|
|
1761
|
+
top: positioned.top
|
|
1762
|
+
} : {
|
|
1763
|
+
position: "absolute",
|
|
1764
|
+
visibility: "hidden"
|
|
1728
1765
|
} : void 0;
|
|
1729
1766
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ContextMenuContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1730
1767
|
"div",
|