@xsolla/xui-b2b-sidebar 0.150.0 → 0.151.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.mjs CHANGED
@@ -1168,6 +1168,7 @@ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1168
1168
  var SidebarGroup = ({
1169
1169
  label,
1170
1170
  dataId,
1171
+ pinnedToBottom,
1171
1172
  children
1172
1173
  }) => {
1173
1174
  const { theme } = useResolvedTheme6();
@@ -1179,6 +1180,7 @@ var SidebarGroup = ({
1179
1180
  "data-id": dataId,
1180
1181
  role: label ? "group" : void 0,
1181
1182
  "aria-label": label,
1183
+ style: pinnedToBottom ? { marginTop: "auto" } : void 0,
1182
1184
  children: [
1183
1185
  label && /* @__PURE__ */ jsx9(
1184
1186
  Box,
@@ -1208,7 +1210,7 @@ import styled5 from "styled-components";
1208
1210
  import { useResolvedTheme as useResolvedTheme7 } from "@xsolla/xui-core";
1209
1211
  import { Typography as Typography3 } from "@xsolla/xui-typography";
1210
1212
  import { Tooltip } from "@xsolla/xui-tooltip";
1211
- import { OpenIn } from "@xsolla/xui-icons-base";
1213
+ import { Drag, OpenIn, Pin, Remove } from "@xsolla/xui-icons-base";
1212
1214
 
1213
1215
  // src/constants.ts
1214
1216
  var ITEM_BASE_CLASS = "xui-sb-item";
@@ -1271,8 +1273,76 @@ var IconBox = styled5.div`
1271
1273
  color: inherit;
1272
1274
 
1273
1275
  svg {
1274
- width: ${(p) => p.$pin ? "12px" : `${p.$size}px`};
1275
- height: ${(p) => p.$pin ? "12px" : `${p.$size}px`};
1276
+ width: ${(p) => p.$size}px;
1277
+ height: ${(p) => p.$size}px;
1278
+ }
1279
+ `;
1280
+ var PinDragSlot = styled5.div`
1281
+ position: relative;
1282
+ width: ${(p) => p.$size}px;
1283
+ height: ${(p) => p.$size}px;
1284
+ flex-shrink: 0;
1285
+ cursor: grab;
1286
+
1287
+ .${ITEM_BASE_CLASS}:active & {
1288
+ cursor: grabbing;
1289
+ }
1290
+ `;
1291
+ var PinDragLayer = styled5.div`
1292
+ position: absolute;
1293
+ inset: 0;
1294
+ display: flex;
1295
+ align-items: center;
1296
+ justify-content: center;
1297
+ color: inherit;
1298
+ opacity: ${(p) => p.$hideOnHover ? 1 : 0};
1299
+ transition: opacity 0.15s ease-in-out;
1300
+
1301
+ .${ITEM_BASE_CLASS}:hover & {
1302
+ opacity: ${(p) => p.$hideOnHover ? 0 : 1};
1303
+ }
1304
+
1305
+ svg {
1306
+ width: 12px;
1307
+ height: 12px;
1308
+ }
1309
+ `;
1310
+ var PinButton = styled5.button`
1311
+ display: flex;
1312
+ width: ${(p) => p.$size}px;
1313
+ height: ${(p) => p.$size}px;
1314
+ flex-shrink: 0;
1315
+ margin-left: auto;
1316
+ align-items: center;
1317
+ justify-content: center;
1318
+ padding: 0;
1319
+ border: none;
1320
+ background: transparent;
1321
+ color: ${(p) => p.$isPinned ? p.$activeColor : p.$color};
1322
+ cursor: pointer;
1323
+ border-radius: 4px;
1324
+ opacity: 0;
1325
+ transition:
1326
+ opacity 0.15s ease-in-out,
1327
+ color 0.15s ease-in-out;
1328
+
1329
+ .${ITEM_BASE_CLASS}:hover & {
1330
+ opacity: 1;
1331
+ }
1332
+
1333
+ &:hover {
1334
+ color: ${(p) => p.$hoverColor};
1335
+ }
1336
+
1337
+ &:focus-visible {
1338
+ opacity: 1;
1339
+ outline: 1px solid currentColor;
1340
+ outline-offset: 1px;
1341
+ }
1342
+
1343
+ svg {
1344
+ width: 12px;
1345
+ height: 12px;
1276
1346
  }
1277
1347
  `;
1278
1348
  var LabelBox = styled5.span`
@@ -1324,6 +1394,8 @@ var SidebarMenuItem = ({
1324
1394
  dataId,
1325
1395
  isActive,
1326
1396
  isPinned,
1397
+ onPinToggle,
1398
+ dragHandle,
1327
1399
  showBadge,
1328
1400
  hasTooltip,
1329
1401
  beta,
@@ -1364,7 +1436,10 @@ var SidebarMenuItem = ({
1364
1436
  activeClassName: ITEM_ACTIVE_CLASS,
1365
1437
  dataId,
1366
1438
  children: [
1367
- icon && !isNested && /* @__PURE__ */ jsx11(IconBox, { $size: sizing.iconSize, $pin: isPinned, children: icon }),
1439
+ !isNested && (isPinned && dragHandle ? /* @__PURE__ */ jsxs5(PinDragSlot, { $size: sizing.iconSize, "data-drag-handle": "true", children: [
1440
+ /* @__PURE__ */ jsx11(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: true, children: /* @__PURE__ */ jsx11(Pin, { size: 12, variant: "solid" }) }),
1441
+ /* @__PURE__ */ jsx11(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: false, children: /* @__PURE__ */ jsx11(Drag, { size: 12, variant: "line" }) })
1442
+ ] }) : 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),
1368
1443
  extra,
1369
1444
  /* @__PURE__ */ jsxs5(LabelBox, { children: [
1370
1445
  /* @__PURE__ */ jsx11(
@@ -1384,6 +1459,33 @@ var SidebarMenuItem = ({
1384
1459
  }
1385
1460
  )
1386
1461
  ] }),
1462
+ onPinToggle && /* @__PURE__ */ jsx11(
1463
+ Tooltip,
1464
+ {
1465
+ content: isPinned ? "Unpin" : "Pin",
1466
+ placement: "top",
1467
+ size: "sm",
1468
+ children: /* @__PURE__ */ jsx11(
1469
+ PinButton,
1470
+ {
1471
+ type: "button",
1472
+ "aria-label": isPinned ? "Unpin item" : "Pin item",
1473
+ "aria-pressed": Boolean(isPinned),
1474
+ $size: sizing.iconSize,
1475
+ $color: theme.colors.content.tertiary,
1476
+ $hoverColor: theme.colors.content.primary,
1477
+ $activeColor: theme.colors.content.primary,
1478
+ $isPinned: Boolean(isPinned),
1479
+ onClick: (e) => {
1480
+ e.preventDefault();
1481
+ e.stopPropagation();
1482
+ onPinToggle(e);
1483
+ },
1484
+ children: isPinned ? /* @__PURE__ */ jsx11(Remove, { size: 12, variant: "line" }) : /* @__PURE__ */ jsx11(Pin, { size: 12, variant: "solid" })
1485
+ }
1486
+ )
1487
+ }
1488
+ ),
1387
1489
  beta && /* @__PURE__ */ jsx11(
1388
1490
  BetaTag,
1389
1491
  {
@@ -1457,7 +1559,7 @@ var ExpandRegion = styled6.div`
1457
1559
  overflow: hidden;
1458
1560
  }
1459
1561
 
1460
- & .${ITEM_BASE_CLASS} {
1562
+ && .${ITEM_BASE_CLASS} {
1461
1563
  position: relative;
1462
1564
  padding: 0 ${(p) => p.$padding}px 0 ${(p) => p.$nestedPaddingLeft}px;
1463
1565
  font-weight: 400;
@@ -1474,7 +1576,7 @@ var ExpandRegion = styled6.div`
1474
1576
  }
1475
1577
  }
1476
1578
 
1477
- & .${ITEM_ACTIVE_CLASS} {
1579
+ && .${ITEM_ACTIVE_CLASS} {
1478
1580
  font-weight: 500;
1479
1581
  color: ${(p) => p.$colorActive};
1480
1582
  background-color: ${(p) => p.$activeBg};
@@ -1697,6 +1799,92 @@ var SidebarChatButton = ({
1697
1799
  }
1698
1800
  );
1699
1801
  };
1802
+
1803
+ // src/SidebarPinnedList.tsx
1804
+ import { useState as useState3 } from "react";
1805
+ import { Pin as Pin2 } from "@xsolla/xui-icons-base";
1806
+ import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1807
+ var SidebarPinnedList = ({
1808
+ items,
1809
+ onUnpin,
1810
+ onReorder,
1811
+ spacers = true
1812
+ }) => {
1813
+ const [dragKey, setDragKey] = useState3(null);
1814
+ const canReorder = Boolean(onReorder) && items.length > 1;
1815
+ if (items.length === 0) return null;
1816
+ return /* @__PURE__ */ jsxs8(Fragment4, { children: [
1817
+ spacers && /* @__PURE__ */ jsx15("div", { style: { height: 8 } }),
1818
+ items.map((item) => /* @__PURE__ */ jsx15(
1819
+ "div",
1820
+ {
1821
+ "data-pinned-key": item.key,
1822
+ onPointerDown: (e) => {
1823
+ if (!canReorder) return;
1824
+ const t = e.target;
1825
+ if (!t.closest('[data-drag-handle="true"]')) return;
1826
+ e.preventDefault();
1827
+ setDragKey(item.key);
1828
+ e.currentTarget.setPointerCapture(e.pointerId);
1829
+ },
1830
+ onPointerMove: (e) => {
1831
+ if (dragKey !== item.key) return;
1832
+ const elt = document.elementFromPoint(
1833
+ e.clientX,
1834
+ e.clientY
1835
+ );
1836
+ const row = elt?.closest("[data-pinned-key]");
1837
+ const overKey = row?.getAttribute("data-pinned-key");
1838
+ if (overKey && overKey !== dragKey) {
1839
+ onReorder?.(dragKey, overKey);
1840
+ }
1841
+ },
1842
+ onPointerUp: (e) => {
1843
+ if (dragKey === item.key) {
1844
+ e.currentTarget.releasePointerCapture(
1845
+ e.pointerId
1846
+ );
1847
+ setDragKey(null);
1848
+ }
1849
+ },
1850
+ onPointerCancel: () => {
1851
+ if (dragKey === item.key) setDragKey(null);
1852
+ },
1853
+ style: {
1854
+ opacity: dragKey === item.key ? 0.4 : 1,
1855
+ transition: "opacity 0.15s ease-in-out",
1856
+ touchAction: canReorder ? "none" : void 0
1857
+ },
1858
+ children: /* @__PURE__ */ jsx15(
1859
+ SidebarMenuItem,
1860
+ {
1861
+ to: item.to,
1862
+ label: item.label,
1863
+ exact: item.exact,
1864
+ isPinned: true,
1865
+ dragHandle: canReorder,
1866
+ onPinToggle: () => onUnpin(item.key)
1867
+ }
1868
+ )
1869
+ },
1870
+ item.key
1871
+ )),
1872
+ spacers && /* @__PURE__ */ jsx15("div", { style: { height: 8 } })
1873
+ ] });
1874
+ };
1875
+ var getPinnedCollapsedItem = (items, options = {}) => {
1876
+ if (items.length === 0) return null;
1877
+ return {
1878
+ label: options.label ?? "Pinned",
1879
+ icon: /* @__PURE__ */ jsx15(Pin2, { size: 18, variant: "solid" }),
1880
+ dataId: options.dataId ?? "sidebar-collapsed-pinned",
1881
+ children: items.map((i) => ({
1882
+ to: i.to,
1883
+ label: i.label,
1884
+ exact: i.exact
1885
+ }))
1886
+ };
1887
+ };
1700
1888
  export {
1701
1889
  Sidebar,
1702
1890
  SidebarChatButton,
@@ -1708,8 +1896,10 @@ export {
1708
1896
  SidebarMenuCollapsible,
1709
1897
  SidebarMenuItem,
1710
1898
  SidebarMenuSub,
1899
+ SidebarPinnedList,
1711
1900
  SidebarProvider,
1712
1901
  SidebarTrigger,
1902
+ getPinnedCollapsedItem,
1713
1903
  useSidebar
1714
1904
  };
1715
1905
  //# sourceMappingURL=index.mjs.map