@xsolla/xui-context-menu 0.181.0 → 0.182.0
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 +92 -22
- package/native/index.js.map +1 -1
- package/native/index.mjs +93 -23
- 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 +92 -22
- package/web/index.js.map +1 -1
- package/web/index.mjs +93 -23
- package/web/index.mjs.map +1 -1
package/web/index.mjs
CHANGED
|
@@ -1152,7 +1152,11 @@ var useContextMenuPosition = ({
|
|
|
1152
1152
|
const viewportHeight = window.innerHeight;
|
|
1153
1153
|
let { vertical, horizontal } = splitPlacement(placement);
|
|
1154
1154
|
const computeTop = (v) => v === "bottom" ? triggerRect.bottom + offset : triggerRect.top - panelRect.height - offset;
|
|
1155
|
-
const computeLeft = (h) =>
|
|
1155
|
+
const computeLeft = (h) => {
|
|
1156
|
+
if (h === "center")
|
|
1157
|
+
return triggerRect.left + triggerRect.width / 2 - panelRect.width / 2;
|
|
1158
|
+
return h === "start" ? triggerRect.left : triggerRect.right - panelRect.width;
|
|
1159
|
+
};
|
|
1156
1160
|
let top = computeTop(vertical);
|
|
1157
1161
|
const wantedBottom = top + panelRect.height;
|
|
1158
1162
|
if (top < 0 || wantedBottom > viewportHeight) {
|
|
@@ -1165,14 +1169,19 @@ var useContextMenuPosition = ({
|
|
|
1165
1169
|
}
|
|
1166
1170
|
}
|
|
1167
1171
|
let left = computeLeft(horizontal);
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
const
|
|
1173
|
-
if (
|
|
1174
|
-
|
|
1175
|
-
|
|
1172
|
+
if (horizontal === "center") {
|
|
1173
|
+
const maxLeft = viewportWidth - panelRect.width;
|
|
1174
|
+
left = maxLeft >= 0 ? Math.min(Math.max(left, 0), maxLeft) : 0;
|
|
1175
|
+
} else {
|
|
1176
|
+
const wantedRight = left + panelRect.width;
|
|
1177
|
+
if (left < 0 || wantedRight > viewportWidth) {
|
|
1178
|
+
const flipped = horizontal === "start" ? "end" : "start";
|
|
1179
|
+
const flippedLeft = computeLeft(flipped);
|
|
1180
|
+
const flippedRight = flippedLeft + panelRect.width;
|
|
1181
|
+
if (flippedLeft >= 0 && flippedRight <= viewportWidth) {
|
|
1182
|
+
horizontal = flipped;
|
|
1183
|
+
left = flippedLeft;
|
|
1184
|
+
}
|
|
1176
1185
|
}
|
|
1177
1186
|
}
|
|
1178
1187
|
const next = {
|
|
@@ -1317,9 +1326,13 @@ var useKeyboardNavigation = ({
|
|
|
1317
1326
|
};
|
|
1318
1327
|
|
|
1319
1328
|
// src/ContextMenu.tsx
|
|
1320
|
-
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1329
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1321
1330
|
var DEFAULT_EMPTY_MESSAGE = "No results";
|
|
1322
1331
|
var SEARCH_DEBOUNCE_MS = 200;
|
|
1332
|
+
var ARROW_SIZE = 10;
|
|
1333
|
+
var ARROW_HALF = ARROW_SIZE / 2;
|
|
1334
|
+
var ARROW_EDGE_OFFSET = 12;
|
|
1335
|
+
var PANEL_SHADOW = "0 4px 12px rgba(0,0,0,0.15)";
|
|
1323
1336
|
var textFromNode = (node) => {
|
|
1324
1337
|
if (node === null || node === void 0 || typeof node === "boolean")
|
|
1325
1338
|
return "";
|
|
@@ -1372,6 +1385,7 @@ var ContextMenuRoot = forwardRef(
|
|
|
1372
1385
|
position,
|
|
1373
1386
|
width,
|
|
1374
1387
|
maxHeight = 300,
|
|
1388
|
+
withArrow = false,
|
|
1375
1389
|
onSelect,
|
|
1376
1390
|
closeOnSelect,
|
|
1377
1391
|
"aria-label": ariaLabel,
|
|
@@ -1407,6 +1421,33 @@ var ContextMenuRoot = forwardRef(
|
|
|
1407
1421
|
isOpen: isOpen && !!trigger && !position,
|
|
1408
1422
|
placement
|
|
1409
1423
|
});
|
|
1424
|
+
const resolvedPlacement = positioned?.placement ?? placement;
|
|
1425
|
+
const getArrowStyle = (arrowPlacement) => {
|
|
1426
|
+
const isTop = arrowPlacement.startsWith("top");
|
|
1427
|
+
const arrowStyle = {
|
|
1428
|
+
position: "absolute",
|
|
1429
|
+
width: ARROW_SIZE,
|
|
1430
|
+
height: ARROW_SIZE,
|
|
1431
|
+
backgroundColor: xuiTheme.colors.background.secondary,
|
|
1432
|
+
borderStyle: "solid",
|
|
1433
|
+
borderColor: xuiTheme.colors.border.secondary,
|
|
1434
|
+
// 1px outline only on the two outward-facing edges of the rotated square
|
|
1435
|
+
borderWidth: isTop ? "0 1px 1px 0" : "1px 0 0 1px",
|
|
1436
|
+
transform: "rotate(45deg)",
|
|
1437
|
+
pointerEvents: "none"
|
|
1438
|
+
};
|
|
1439
|
+
if (isTop) arrowStyle.bottom = -ARROW_HALF;
|
|
1440
|
+
else arrowStyle.top = -ARROW_HALF;
|
|
1441
|
+
if (arrowPlacement.endsWith("center")) {
|
|
1442
|
+
arrowStyle.left = "50%";
|
|
1443
|
+
arrowStyle.marginLeft = -ARROW_HALF;
|
|
1444
|
+
} else if (arrowPlacement.endsWith("end")) {
|
|
1445
|
+
arrowStyle.right = ARROW_EDGE_OFFSET;
|
|
1446
|
+
} else {
|
|
1447
|
+
arrowStyle.left = ARROW_EDGE_OFFSET;
|
|
1448
|
+
}
|
|
1449
|
+
return arrowStyle;
|
|
1450
|
+
};
|
|
1410
1451
|
const setOpen = useCallback3(
|
|
1411
1452
|
(nextOpen) => {
|
|
1412
1453
|
if (propIsOpen === void 0) setInternalIsOpen(nextOpen);
|
|
@@ -1617,15 +1658,30 @@ var ContextMenuRoot = forwardRef(
|
|
|
1617
1658
|
const assignTriggerRef = (node) => {
|
|
1618
1659
|
triggerRef.current = node;
|
|
1619
1660
|
};
|
|
1620
|
-
const
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
onClick: (event) => {
|
|
1625
|
-
trigger.props.onClick?.(event);
|
|
1626
|
-
if (!event.defaultPrevented) toggleMenu();
|
|
1661
|
+
const assignTriggerWrapperRef = (node) => {
|
|
1662
|
+
if (!node) {
|
|
1663
|
+
assignTriggerRef(null);
|
|
1664
|
+
return;
|
|
1627
1665
|
}
|
|
1628
|
-
|
|
1666
|
+
const firstChild = node.firstElementChild;
|
|
1667
|
+
assignTriggerRef(
|
|
1668
|
+
firstChild instanceof HTMLElement ? firstChild : node
|
|
1669
|
+
);
|
|
1670
|
+
};
|
|
1671
|
+
const triggerNode = trigger && isValidElement(trigger) ? /* @__PURE__ */ jsx4(
|
|
1672
|
+
"span",
|
|
1673
|
+
{
|
|
1674
|
+
ref: assignTriggerWrapperRef,
|
|
1675
|
+
onClick: (event) => {
|
|
1676
|
+
if (!event.defaultPrevented) toggleMenu();
|
|
1677
|
+
},
|
|
1678
|
+
style: { display: "inline-flex" },
|
|
1679
|
+
children: cloneElement(trigger, {
|
|
1680
|
+
"aria-haspopup": "menu",
|
|
1681
|
+
"aria-expanded": isOpen ? "true" : "false"
|
|
1682
|
+
})
|
|
1683
|
+
}
|
|
1684
|
+
) : trigger ? /* @__PURE__ */ jsx4(
|
|
1629
1685
|
"span",
|
|
1630
1686
|
{
|
|
1631
1687
|
ref: assignTriggerRef,
|
|
@@ -1663,7 +1719,7 @@ var ContextMenuRoot = forwardRef(
|
|
|
1663
1719
|
role: "menu",
|
|
1664
1720
|
"aria-label": ariaLabel,
|
|
1665
1721
|
"data-testid": dataTestId ?? testID ?? "context-menu",
|
|
1666
|
-
"data-placement":
|
|
1722
|
+
"data-placement": resolvedPlacement,
|
|
1667
1723
|
backgroundColor: xuiTheme.colors.background.secondary,
|
|
1668
1724
|
borderColor: xuiTheme.colors.border.secondary,
|
|
1669
1725
|
borderWidth: 1,
|
|
@@ -1678,12 +1734,26 @@ var ContextMenuRoot = forwardRef(
|
|
|
1678
1734
|
...positionStyle,
|
|
1679
1735
|
...style,
|
|
1680
1736
|
zIndex: 1e3,
|
|
1681
|
-
boxShadow:
|
|
1682
|
-
|
|
1683
|
-
|
|
1737
|
+
boxShadow: PANEL_SHADOW,
|
|
1738
|
+
...withArrow ? {
|
|
1739
|
+
overflow: "visible"
|
|
1740
|
+
} : {
|
|
1741
|
+
maxHeight,
|
|
1742
|
+
overflowY: "auto"
|
|
1743
|
+
},
|
|
1684
1744
|
outline: "none"
|
|
1685
1745
|
},
|
|
1686
|
-
children:
|
|
1746
|
+
children: withArrow ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
1747
|
+
/* @__PURE__ */ jsx4(
|
|
1748
|
+
"span",
|
|
1749
|
+
{
|
|
1750
|
+
"aria-hidden": "true",
|
|
1751
|
+
"data-testid": "context-menu-arrow",
|
|
1752
|
+
style: getArrowStyle(resolvedPlacement)
|
|
1753
|
+
}
|
|
1754
|
+
),
|
|
1755
|
+
/* @__PURE__ */ jsx4("div", { style: { maxHeight, overflowY: "auto", borderRadius }, children: renderContent() })
|
|
1756
|
+
] }) : renderContent()
|
|
1687
1757
|
}
|
|
1688
1758
|
)
|
|
1689
1759
|
]
|