@xsolla/xui-b2b-sidebar 0.150.0 → 0.152.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/web/index.mjs CHANGED
@@ -1240,6 +1240,7 @@ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1240
1240
  var SidebarGroup = ({
1241
1241
  label,
1242
1242
  dataId,
1243
+ pinnedToBottom,
1243
1244
  children
1244
1245
  }) => {
1245
1246
  const { theme } = useResolvedTheme6();
@@ -1251,6 +1252,7 @@ var SidebarGroup = ({
1251
1252
  "data-id": dataId,
1252
1253
  role: label ? "group" : void 0,
1253
1254
  "aria-label": label,
1255
+ style: pinnedToBottom ? { marginTop: "auto" } : void 0,
1254
1256
  children: [
1255
1257
  label && /* @__PURE__ */ jsx9(
1256
1258
  Box,
@@ -1280,7 +1282,7 @@ import styled6 from "styled-components";
1280
1282
  import { useResolvedTheme as useResolvedTheme7 } from "@xsolla/xui-core";
1281
1283
  import { Typography as Typography3 } from "@xsolla/xui-typography";
1282
1284
  import { Tooltip } from "@xsolla/xui-tooltip";
1283
- import { OpenIn } from "@xsolla/xui-icons-base";
1285
+ import { Drag, OpenIn, Pin, Remove } from "@xsolla/xui-icons-base";
1284
1286
 
1285
1287
  // src/constants.ts
1286
1288
  var ITEM_BASE_CLASS = "xui-sb-item";
@@ -1343,8 +1345,76 @@ var IconBox = styled6.div`
1343
1345
  color: inherit;
1344
1346
 
1345
1347
  svg {
1346
- width: ${(p) => p.$pin ? "12px" : `${p.$size}px`};
1347
- height: ${(p) => p.$pin ? "12px" : `${p.$size}px`};
1348
+ width: ${(p) => p.$size}px;
1349
+ height: ${(p) => p.$size}px;
1350
+ }
1351
+ `;
1352
+ var PinDragSlot = styled6.div`
1353
+ position: relative;
1354
+ width: ${(p) => p.$size}px;
1355
+ height: ${(p) => p.$size}px;
1356
+ flex-shrink: 0;
1357
+ cursor: grab;
1358
+
1359
+ .${ITEM_BASE_CLASS}:active & {
1360
+ cursor: grabbing;
1361
+ }
1362
+ `;
1363
+ var PinDragLayer = styled6.div`
1364
+ position: absolute;
1365
+ inset: 0;
1366
+ display: flex;
1367
+ align-items: center;
1368
+ justify-content: center;
1369
+ color: inherit;
1370
+ opacity: ${(p) => p.$hideOnHover ? 1 : 0};
1371
+ transition: opacity 0.15s ease-in-out;
1372
+
1373
+ .${ITEM_BASE_CLASS}:hover & {
1374
+ opacity: ${(p) => p.$hideOnHover ? 0 : 1};
1375
+ }
1376
+
1377
+ svg {
1378
+ width: 12px;
1379
+ height: 12px;
1380
+ }
1381
+ `;
1382
+ var PinButton = styled6.button`
1383
+ display: flex;
1384
+ width: ${(p) => p.$size}px;
1385
+ height: ${(p) => p.$size}px;
1386
+ flex-shrink: 0;
1387
+ margin-left: auto;
1388
+ align-items: center;
1389
+ justify-content: center;
1390
+ padding: 0;
1391
+ border: none;
1392
+ background: transparent;
1393
+ color: ${(p) => p.$isPinned ? p.$activeColor : p.$color};
1394
+ cursor: pointer;
1395
+ border-radius: 4px;
1396
+ opacity: 0;
1397
+ transition:
1398
+ opacity 0.15s ease-in-out,
1399
+ color 0.15s ease-in-out;
1400
+
1401
+ .${ITEM_BASE_CLASS}:hover & {
1402
+ opacity: 1;
1403
+ }
1404
+
1405
+ &:hover {
1406
+ color: ${(p) => p.$hoverColor};
1407
+ }
1408
+
1409
+ &:focus-visible {
1410
+ opacity: 1;
1411
+ outline: 1px solid currentColor;
1412
+ outline-offset: 1px;
1413
+ }
1414
+
1415
+ svg {
1416
+ width: 12px;
1417
+ height: 12px;
1348
1418
  }
1349
1419
  `;
1350
1420
  var LabelBox = styled6.span`
@@ -1396,6 +1466,8 @@ var SidebarMenuItem = ({
1396
1466
  dataId,
1397
1467
  isActive,
1398
1468
  isPinned,
1469
+ onPinToggle,
1470
+ dragHandle,
1399
1471
  showBadge,
1400
1472
  hasTooltip,
1401
1473
  beta,
@@ -1436,7 +1508,10 @@ var SidebarMenuItem = ({
1436
1508
  activeClassName: ITEM_ACTIVE_CLASS,
1437
1509
  dataId,
1438
1510
  children: [
1439
- icon && !isNested && /* @__PURE__ */ jsx11(IconBox, { $size: sizing.iconSize, $pin: isPinned, children: icon }),
1511
+ !isNested && (isPinned && dragHandle ? /* @__PURE__ */ jsxs5(PinDragSlot, { $size: sizing.iconSize, "data-drag-handle": "true", children: [
1512
+ /* @__PURE__ */ jsx11(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: true, children: /* @__PURE__ */ jsx11(Pin, { size: 12, variant: "solid" }) }),
1513
+ /* @__PURE__ */ jsx11(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: false, children: /* @__PURE__ */ jsx11(Drag, { size: 12, variant: "line" }) })
1514
+ ] }) : isPinned ? /* @__PURE__ */ jsx11(IconBox, { $size: sizing.iconSize, children: /* @__PURE__ */ jsx11(Pin, { size: 12, variant: "solid" }) }) : icon ? /* @__PURE__ */ jsx11(IconBox, { $size: sizing.iconSize, children: icon }) : null),
1440
1515
  extra,
1441
1516
  /* @__PURE__ */ jsxs5(LabelBox, { children: [
1442
1517
  /* @__PURE__ */ jsx11(
@@ -1456,6 +1531,33 @@ var SidebarMenuItem = ({
1456
1531
  }
1457
1532
  )
1458
1533
  ] }),
1534
+ onPinToggle && /* @__PURE__ */ jsx11(
1535
+ Tooltip,
1536
+ {
1537
+ content: isPinned ? "Unpin" : "Pin",
1538
+ placement: "top",
1539
+ size: "sm",
1540
+ children: /* @__PURE__ */ jsx11(
1541
+ PinButton,
1542
+ {
1543
+ type: "button",
1544
+ "aria-label": isPinned ? "Unpin item" : "Pin item",
1545
+ "aria-pressed": Boolean(isPinned),
1546
+ $size: sizing.iconSize,
1547
+ $color: theme.colors.content.tertiary,
1548
+ $hoverColor: theme.colors.content.primary,
1549
+ $activeColor: theme.colors.content.primary,
1550
+ $isPinned: Boolean(isPinned),
1551
+ onClick: (e) => {
1552
+ e.preventDefault();
1553
+ e.stopPropagation();
1554
+ onPinToggle(e);
1555
+ },
1556
+ children: isPinned ? /* @__PURE__ */ jsx11(Remove, { size: 12, variant: "line" }) : /* @__PURE__ */ jsx11(Pin, { size: 12, variant: "solid" })
1557
+ }
1558
+ )
1559
+ }
1560
+ ),
1459
1561
  beta && /* @__PURE__ */ jsx11(
1460
1562
  BetaTag,
1461
1563
  {
@@ -1529,7 +1631,7 @@ var ExpandRegion = styled7.div`
1529
1631
  overflow: hidden;
1530
1632
  }
1531
1633
 
1532
- & .${ITEM_BASE_CLASS} {
1634
+ && .${ITEM_BASE_CLASS} {
1533
1635
  position: relative;
1534
1636
  padding: 0 ${(p) => p.$padding}px 0 ${(p) => p.$nestedPaddingLeft}px;
1535
1637
  font-weight: 400;
@@ -1546,7 +1648,7 @@ var ExpandRegion = styled7.div`
1546
1648
  }
1547
1649
  }
1548
1650
 
1549
- & .${ITEM_ACTIVE_CLASS} {
1651
+ && .${ITEM_ACTIVE_CLASS} {
1550
1652
  font-weight: 500;
1551
1653
  color: ${(p) => p.$colorActive};
1552
1654
  background-color: ${(p) => p.$activeBg};
@@ -1769,6 +1871,92 @@ var SidebarChatButton = ({
1769
1871
  }
1770
1872
  );
1771
1873
  };
1874
+
1875
+ // src/SidebarPinnedList.tsx
1876
+ import { useState as useState3 } from "react";
1877
+ import { Pin as Pin2 } from "@xsolla/xui-icons-base";
1878
+ import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1879
+ var SidebarPinnedList = ({
1880
+ items,
1881
+ onUnpin,
1882
+ onReorder,
1883
+ spacers = true
1884
+ }) => {
1885
+ const [dragKey, setDragKey] = useState3(null);
1886
+ const canReorder = Boolean(onReorder) && items.length > 1;
1887
+ if (items.length === 0) return null;
1888
+ return /* @__PURE__ */ jsxs8(Fragment4, { children: [
1889
+ spacers && /* @__PURE__ */ jsx15("div", { style: { height: 8 } }),
1890
+ items.map((item) => /* @__PURE__ */ jsx15(
1891
+ "div",
1892
+ {
1893
+ "data-pinned-key": item.key,
1894
+ onPointerDown: (e) => {
1895
+ if (!canReorder) return;
1896
+ const t = e.target;
1897
+ if (!t.closest('[data-drag-handle="true"]')) return;
1898
+ e.preventDefault();
1899
+ setDragKey(item.key);
1900
+ e.currentTarget.setPointerCapture(e.pointerId);
1901
+ },
1902
+ onPointerMove: (e) => {
1903
+ if (dragKey !== item.key) return;
1904
+ const elt = document.elementFromPoint(
1905
+ e.clientX,
1906
+ e.clientY
1907
+ );
1908
+ const row = elt?.closest("[data-pinned-key]");
1909
+ const overKey = row?.getAttribute("data-pinned-key");
1910
+ if (overKey && overKey !== dragKey) {
1911
+ onReorder?.(dragKey, overKey);
1912
+ }
1913
+ },
1914
+ onPointerUp: (e) => {
1915
+ if (dragKey === item.key) {
1916
+ e.currentTarget.releasePointerCapture(
1917
+ e.pointerId
1918
+ );
1919
+ setDragKey(null);
1920
+ }
1921
+ },
1922
+ onPointerCancel: () => {
1923
+ if (dragKey === item.key) setDragKey(null);
1924
+ },
1925
+ style: {
1926
+ opacity: dragKey === item.key ? 0.4 : 1,
1927
+ transition: "opacity 0.15s ease-in-out",
1928
+ touchAction: canReorder ? "none" : void 0
1929
+ },
1930
+ children: /* @__PURE__ */ jsx15(
1931
+ SidebarMenuItem,
1932
+ {
1933
+ to: item.to,
1934
+ label: item.label,
1935
+ exact: item.exact,
1936
+ isPinned: true,
1937
+ dragHandle: canReorder,
1938
+ onPinToggle: () => onUnpin(item.key)
1939
+ }
1940
+ )
1941
+ },
1942
+ item.key
1943
+ )),
1944
+ spacers && /* @__PURE__ */ jsx15("div", { style: { height: 8 } })
1945
+ ] });
1946
+ };
1947
+ var getPinnedCollapsedItem = (items, options = {}) => {
1948
+ if (items.length === 0) return null;
1949
+ return {
1950
+ label: options.label ?? "Pinned",
1951
+ icon: /* @__PURE__ */ jsx15(Pin2, { size: 18, variant: "solid" }),
1952
+ dataId: options.dataId ?? "sidebar-collapsed-pinned",
1953
+ children: items.map((i) => ({
1954
+ to: i.to,
1955
+ label: i.label,
1956
+ exact: i.exact
1957
+ }))
1958
+ };
1959
+ };
1772
1960
  export {
1773
1961
  Sidebar,
1774
1962
  SidebarChatButton,
@@ -1780,8 +1968,10 @@ export {
1780
1968
  SidebarMenuCollapsible,
1781
1969
  SidebarMenuItem,
1782
1970
  SidebarMenuSub,
1971
+ SidebarPinnedList,
1783
1972
  SidebarProvider,
1784
1973
  SidebarTrigger,
1974
+ getPinnedCollapsedItem,
1785
1975
  useSidebar
1786
1976
  };
1787
1977
  //# sourceMappingURL=index.mjs.map