@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/README.md +265 -140
- package/native/index.d.mts +46 -1
- package/native/index.d.ts +46 -1
- package/native/index.js +197 -5
- package/native/index.js.map +1 -1
- package/native/index.mjs +196 -6
- package/native/index.mjs.map +1 -1
- package/package.json +6 -6
- package/web/index.d.mts +46 -1
- package/web/index.d.ts +46 -1
- package/web/index.js +197 -5
- package/web/index.js.map +1 -1
- package/web/index.mjs +196 -6
- package/web/index.mjs.map +1 -1
package/web/index.d.ts
CHANGED
|
@@ -61,6 +61,7 @@ type SidebarItemType = {
|
|
|
61
61
|
visibility?: string;
|
|
62
62
|
disallowedIntegrationTypes?: Array<string>;
|
|
63
63
|
isPinned?: boolean;
|
|
64
|
+
onPinToggle?: (e: MouseEvent<HTMLButtonElement>) => void;
|
|
64
65
|
showBadge?: boolean;
|
|
65
66
|
};
|
|
66
67
|
|
|
@@ -119,6 +120,8 @@ declare const SidebarTrigger: React.FC;
|
|
|
119
120
|
interface SidebarGroupProps {
|
|
120
121
|
label?: string;
|
|
121
122
|
dataId?: string;
|
|
123
|
+
/** Docks this group to the bottom of the expanded sidebar (e.g. Settings, Billing). */
|
|
124
|
+
pinnedToBottom?: boolean;
|
|
122
125
|
children: ReactNode;
|
|
123
126
|
}
|
|
124
127
|
declare const SidebarGroup: React.FC<SidebarGroupProps>;
|
|
@@ -139,6 +142,10 @@ interface SidebarMenuItemProps {
|
|
|
139
142
|
dataId?: string;
|
|
140
143
|
isActive?: SidebarLinkActiveCheck;
|
|
141
144
|
isPinned?: boolean;
|
|
145
|
+
/** When provided, renders a pin/unpin toggle on hover (or always, when pinned). */
|
|
146
|
+
onPinToggle?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
147
|
+
/** When true on a pinned item, the leading pin glyph swaps to a drag handle on row hover (reorder affordance). */
|
|
148
|
+
dragHandle?: boolean;
|
|
142
149
|
showBadge?: boolean;
|
|
143
150
|
hasTooltip?: boolean;
|
|
144
151
|
beta?: boolean;
|
|
@@ -185,4 +192,42 @@ interface SidebarCollapsedProps {
|
|
|
185
192
|
}
|
|
186
193
|
declare const SidebarCollapsed: React.FC<SidebarCollapsedProps>;
|
|
187
194
|
|
|
188
|
-
|
|
195
|
+
interface SidebarPinnedItem {
|
|
196
|
+
key: string;
|
|
197
|
+
to: string;
|
|
198
|
+
label: ReactNode;
|
|
199
|
+
exact?: boolean;
|
|
200
|
+
}
|
|
201
|
+
interface SidebarPinnedListProps {
|
|
202
|
+
/** Ordered list of currently-pinned items. */
|
|
203
|
+
items: SidebarPinnedItem[];
|
|
204
|
+
/** Called when the user clicks the × on a pinned shortcut. */
|
|
205
|
+
onUnpin: (key: string) => void;
|
|
206
|
+
/**
|
|
207
|
+
* Called as the user drags to reorder. Omit to disable drag-and-drop —
|
|
208
|
+
* the leading icon stays as the static pin glyph.
|
|
209
|
+
*/
|
|
210
|
+
onReorder?: (fromKey: string, toKey: string) => void;
|
|
211
|
+
/** Render 8px top/bottom spacers when items are present. Default true. */
|
|
212
|
+
spacers?: boolean;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Renders the pinned shortcuts list with pointer-event-based drag-and-drop
|
|
216
|
+
* reorder. Drag only initiates from the leading drag-handle area on each row.
|
|
217
|
+
*
|
|
218
|
+
* Pinning is fully opt-in: consumers who don't render this component get no
|
|
219
|
+
* pin UI. Consumers without a reorder backend can omit `onReorder`; the list
|
|
220
|
+
* stays static but unpinning still works.
|
|
221
|
+
*/
|
|
222
|
+
declare const SidebarPinnedList: React.FC<SidebarPinnedListProps>;
|
|
223
|
+
/**
|
|
224
|
+
* Helper for the collapsed sidebar: returns a single `SidebarItemType` whose
|
|
225
|
+
* popover lists every pinned shortcut. Spread it into `collapsedItems` at the
|
|
226
|
+
* position you want the Pin button to appear. Returns `null` when no items.
|
|
227
|
+
*/
|
|
228
|
+
declare const getPinnedCollapsedItem: (items: SidebarPinnedItem[], options?: {
|
|
229
|
+
label?: string;
|
|
230
|
+
dataId?: string;
|
|
231
|
+
}) => SidebarItemType | null;
|
|
232
|
+
|
|
233
|
+
export { Sidebar, SidebarChatButton, SidebarCollapsed, type SidebarCollapsedProps, SidebarContent, SidebarFooter, SidebarGroup, type SidebarItemType, type SidebarLinkActiveCheck, type SidebarLinkClickHandler, type SidebarLinkProps, SidebarMenu, SidebarMenuCollapsible, type SidebarMenuCollapsibleProps, SidebarMenuItem, type SidebarMenuItemProps, SidebarMenuSub, type SidebarPinnedItem, SidebarPinnedList, type SidebarPinnedListProps, type SidebarProps, SidebarProvider, type SidebarProviderProps, SidebarTrigger, getPinnedCollapsedItem, useSidebar };
|
package/web/index.js
CHANGED
|
@@ -40,8 +40,10 @@ __export(index_exports, {
|
|
|
40
40
|
SidebarMenuCollapsible: () => SidebarMenuCollapsible,
|
|
41
41
|
SidebarMenuItem: () => SidebarMenuItem,
|
|
42
42
|
SidebarMenuSub: () => SidebarMenuSub,
|
|
43
|
+
SidebarPinnedList: () => SidebarPinnedList,
|
|
43
44
|
SidebarProvider: () => SidebarProvider,
|
|
44
45
|
SidebarTrigger: () => SidebarTrigger,
|
|
46
|
+
getPinnedCollapsedItem: () => getPinnedCollapsedItem,
|
|
45
47
|
useSidebar: () => useSidebar
|
|
46
48
|
});
|
|
47
49
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -1276,6 +1278,7 @@ var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
|
1276
1278
|
var SidebarGroup = ({
|
|
1277
1279
|
label,
|
|
1278
1280
|
dataId,
|
|
1281
|
+
pinnedToBottom,
|
|
1279
1282
|
children
|
|
1280
1283
|
}) => {
|
|
1281
1284
|
const { theme } = (0, import_xui_core6.useResolvedTheme)();
|
|
@@ -1287,6 +1290,7 @@ var SidebarGroup = ({
|
|
|
1287
1290
|
"data-id": dataId,
|
|
1288
1291
|
role: label ? "group" : void 0,
|
|
1289
1292
|
"aria-label": label,
|
|
1293
|
+
style: pinnedToBottom ? { marginTop: "auto" } : void 0,
|
|
1290
1294
|
children: [
|
|
1291
1295
|
label && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1292
1296
|
Box,
|
|
@@ -1379,8 +1383,76 @@ var IconBox = import_styled_components6.default.div`
|
|
|
1379
1383
|
color: inherit;
|
|
1380
1384
|
|
|
1381
1385
|
svg {
|
|
1382
|
-
width: ${(p) => p.$
|
|
1383
|
-
height: ${(p) => p.$
|
|
1386
|
+
width: ${(p) => p.$size}px;
|
|
1387
|
+
height: ${(p) => p.$size}px;
|
|
1388
|
+
}
|
|
1389
|
+
`;
|
|
1390
|
+
var PinDragSlot = import_styled_components6.default.div`
|
|
1391
|
+
position: relative;
|
|
1392
|
+
width: ${(p) => p.$size}px;
|
|
1393
|
+
height: ${(p) => p.$size}px;
|
|
1394
|
+
flex-shrink: 0;
|
|
1395
|
+
cursor: grab;
|
|
1396
|
+
|
|
1397
|
+
.${ITEM_BASE_CLASS}:active & {
|
|
1398
|
+
cursor: grabbing;
|
|
1399
|
+
}
|
|
1400
|
+
`;
|
|
1401
|
+
var PinDragLayer = import_styled_components6.default.div`
|
|
1402
|
+
position: absolute;
|
|
1403
|
+
inset: 0;
|
|
1404
|
+
display: flex;
|
|
1405
|
+
align-items: center;
|
|
1406
|
+
justify-content: center;
|
|
1407
|
+
color: inherit;
|
|
1408
|
+
opacity: ${(p) => p.$hideOnHover ? 1 : 0};
|
|
1409
|
+
transition: opacity 0.15s ease-in-out;
|
|
1410
|
+
|
|
1411
|
+
.${ITEM_BASE_CLASS}:hover & {
|
|
1412
|
+
opacity: ${(p) => p.$hideOnHover ? 0 : 1};
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
svg {
|
|
1416
|
+
width: 12px;
|
|
1417
|
+
height: 12px;
|
|
1418
|
+
}
|
|
1419
|
+
`;
|
|
1420
|
+
var PinButton = import_styled_components6.default.button`
|
|
1421
|
+
display: flex;
|
|
1422
|
+
width: ${(p) => p.$size}px;
|
|
1423
|
+
height: ${(p) => p.$size}px;
|
|
1424
|
+
flex-shrink: 0;
|
|
1425
|
+
margin-left: auto;
|
|
1426
|
+
align-items: center;
|
|
1427
|
+
justify-content: center;
|
|
1428
|
+
padding: 0;
|
|
1429
|
+
border: none;
|
|
1430
|
+
background: transparent;
|
|
1431
|
+
color: ${(p) => p.$isPinned ? p.$activeColor : p.$color};
|
|
1432
|
+
cursor: pointer;
|
|
1433
|
+
border-radius: 4px;
|
|
1434
|
+
opacity: 0;
|
|
1435
|
+
transition:
|
|
1436
|
+
opacity 0.15s ease-in-out,
|
|
1437
|
+
color 0.15s ease-in-out;
|
|
1438
|
+
|
|
1439
|
+
.${ITEM_BASE_CLASS}:hover & {
|
|
1440
|
+
opacity: 1;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
&:hover {
|
|
1444
|
+
color: ${(p) => p.$hoverColor};
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
&:focus-visible {
|
|
1448
|
+
opacity: 1;
|
|
1449
|
+
outline: 1px solid currentColor;
|
|
1450
|
+
outline-offset: 1px;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
svg {
|
|
1454
|
+
width: 12px;
|
|
1455
|
+
height: 12px;
|
|
1384
1456
|
}
|
|
1385
1457
|
`;
|
|
1386
1458
|
var LabelBox = import_styled_components6.default.span`
|
|
@@ -1432,6 +1504,8 @@ var SidebarMenuItem = ({
|
|
|
1432
1504
|
dataId,
|
|
1433
1505
|
isActive,
|
|
1434
1506
|
isPinned,
|
|
1507
|
+
onPinToggle,
|
|
1508
|
+
dragHandle,
|
|
1435
1509
|
showBadge,
|
|
1436
1510
|
hasTooltip,
|
|
1437
1511
|
beta,
|
|
@@ -1472,7 +1546,10 @@ var SidebarMenuItem = ({
|
|
|
1472
1546
|
activeClassName: ITEM_ACTIVE_CLASS,
|
|
1473
1547
|
dataId,
|
|
1474
1548
|
children: [
|
|
1475
|
-
|
|
1549
|
+
!isNested && (isPinned && dragHandle ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(PinDragSlot, { $size: sizing.iconSize, "data-drag-handle": "true", children: [
|
|
1550
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_xui_icons_base2.Pin, { size: 12, variant: "solid" }) }),
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PinDragLayer, { $size: sizing.iconSize, $hideOnHover: false, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_xui_icons_base2.Drag, { size: 12, variant: "line" }) })
|
|
1552
|
+
] }) : isPinned ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconBox, { $size: sizing.iconSize, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_xui_icons_base2.Pin, { size: 12, variant: "solid" }) }) : icon ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconBox, { $size: sizing.iconSize, children: icon }) : null),
|
|
1476
1553
|
extra,
|
|
1477
1554
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(LabelBox, { children: [
|
|
1478
1555
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
@@ -1492,6 +1569,33 @@ var SidebarMenuItem = ({
|
|
|
1492
1569
|
}
|
|
1493
1570
|
)
|
|
1494
1571
|
] }),
|
|
1572
|
+
onPinToggle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1573
|
+
import_xui_tooltip.Tooltip,
|
|
1574
|
+
{
|
|
1575
|
+
content: isPinned ? "Unpin" : "Pin",
|
|
1576
|
+
placement: "top",
|
|
1577
|
+
size: "sm",
|
|
1578
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1579
|
+
PinButton,
|
|
1580
|
+
{
|
|
1581
|
+
type: "button",
|
|
1582
|
+
"aria-label": isPinned ? "Unpin item" : "Pin item",
|
|
1583
|
+
"aria-pressed": Boolean(isPinned),
|
|
1584
|
+
$size: sizing.iconSize,
|
|
1585
|
+
$color: theme.colors.content.tertiary,
|
|
1586
|
+
$hoverColor: theme.colors.content.primary,
|
|
1587
|
+
$activeColor: theme.colors.content.primary,
|
|
1588
|
+
$isPinned: Boolean(isPinned),
|
|
1589
|
+
onClick: (e) => {
|
|
1590
|
+
e.preventDefault();
|
|
1591
|
+
e.stopPropagation();
|
|
1592
|
+
onPinToggle(e);
|
|
1593
|
+
},
|
|
1594
|
+
children: isPinned ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_xui_icons_base2.Remove, { size: 12, variant: "line" }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_xui_icons_base2.Pin, { size: 12, variant: "solid" })
|
|
1595
|
+
}
|
|
1596
|
+
)
|
|
1597
|
+
}
|
|
1598
|
+
),
|
|
1495
1599
|
beta && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1496
1600
|
BetaTag,
|
|
1497
1601
|
{
|
|
@@ -1565,7 +1669,7 @@ var ExpandRegion = import_styled_components7.default.div`
|
|
|
1565
1669
|
overflow: hidden;
|
|
1566
1670
|
}
|
|
1567
1671
|
|
|
1568
|
-
|
|
1672
|
+
&& .${ITEM_BASE_CLASS} {
|
|
1569
1673
|
position: relative;
|
|
1570
1674
|
padding: 0 ${(p) => p.$padding}px 0 ${(p) => p.$nestedPaddingLeft}px;
|
|
1571
1675
|
font-weight: 400;
|
|
@@ -1582,7 +1686,7 @@ var ExpandRegion = import_styled_components7.default.div`
|
|
|
1582
1686
|
}
|
|
1583
1687
|
}
|
|
1584
1688
|
|
|
1585
|
-
|
|
1689
|
+
&& .${ITEM_ACTIVE_CLASS} {
|
|
1586
1690
|
font-weight: 500;
|
|
1587
1691
|
color: ${(p) => p.$colorActive};
|
|
1588
1692
|
background-color: ${(p) => p.$activeBg};
|
|
@@ -1805,6 +1909,92 @@ var SidebarChatButton = ({
|
|
|
1805
1909
|
}
|
|
1806
1910
|
);
|
|
1807
1911
|
};
|
|
1912
|
+
|
|
1913
|
+
// src/SidebarPinnedList.tsx
|
|
1914
|
+
var import_react6 = require("react");
|
|
1915
|
+
var import_xui_icons_base5 = require("@xsolla/xui-icons-base");
|
|
1916
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1917
|
+
var SidebarPinnedList = ({
|
|
1918
|
+
items,
|
|
1919
|
+
onUnpin,
|
|
1920
|
+
onReorder,
|
|
1921
|
+
spacers = true
|
|
1922
|
+
}) => {
|
|
1923
|
+
const [dragKey, setDragKey] = (0, import_react6.useState)(null);
|
|
1924
|
+
const canReorder = Boolean(onReorder) && items.length > 1;
|
|
1925
|
+
if (items.length === 0) return null;
|
|
1926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
1927
|
+
spacers && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { height: 8 } }),
|
|
1928
|
+
items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1929
|
+
"div",
|
|
1930
|
+
{
|
|
1931
|
+
"data-pinned-key": item.key,
|
|
1932
|
+
onPointerDown: (e) => {
|
|
1933
|
+
if (!canReorder) return;
|
|
1934
|
+
const t = e.target;
|
|
1935
|
+
if (!t.closest('[data-drag-handle="true"]')) return;
|
|
1936
|
+
e.preventDefault();
|
|
1937
|
+
setDragKey(item.key);
|
|
1938
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
1939
|
+
},
|
|
1940
|
+
onPointerMove: (e) => {
|
|
1941
|
+
if (dragKey !== item.key) return;
|
|
1942
|
+
const elt = document.elementFromPoint(
|
|
1943
|
+
e.clientX,
|
|
1944
|
+
e.clientY
|
|
1945
|
+
);
|
|
1946
|
+
const row = elt?.closest("[data-pinned-key]");
|
|
1947
|
+
const overKey = row?.getAttribute("data-pinned-key");
|
|
1948
|
+
if (overKey && overKey !== dragKey) {
|
|
1949
|
+
onReorder?.(dragKey, overKey);
|
|
1950
|
+
}
|
|
1951
|
+
},
|
|
1952
|
+
onPointerUp: (e) => {
|
|
1953
|
+
if (dragKey === item.key) {
|
|
1954
|
+
e.currentTarget.releasePointerCapture(
|
|
1955
|
+
e.pointerId
|
|
1956
|
+
);
|
|
1957
|
+
setDragKey(null);
|
|
1958
|
+
}
|
|
1959
|
+
},
|
|
1960
|
+
onPointerCancel: () => {
|
|
1961
|
+
if (dragKey === item.key) setDragKey(null);
|
|
1962
|
+
},
|
|
1963
|
+
style: {
|
|
1964
|
+
opacity: dragKey === item.key ? 0.4 : 1,
|
|
1965
|
+
transition: "opacity 0.15s ease-in-out",
|
|
1966
|
+
touchAction: canReorder ? "none" : void 0
|
|
1967
|
+
},
|
|
1968
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1969
|
+
SidebarMenuItem,
|
|
1970
|
+
{
|
|
1971
|
+
to: item.to,
|
|
1972
|
+
label: item.label,
|
|
1973
|
+
exact: item.exact,
|
|
1974
|
+
isPinned: true,
|
|
1975
|
+
dragHandle: canReorder,
|
|
1976
|
+
onPinToggle: () => onUnpin(item.key)
|
|
1977
|
+
}
|
|
1978
|
+
)
|
|
1979
|
+
},
|
|
1980
|
+
item.key
|
|
1981
|
+
)),
|
|
1982
|
+
spacers && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { height: 8 } })
|
|
1983
|
+
] });
|
|
1984
|
+
};
|
|
1985
|
+
var getPinnedCollapsedItem = (items, options = {}) => {
|
|
1986
|
+
if (items.length === 0) return null;
|
|
1987
|
+
return {
|
|
1988
|
+
label: options.label ?? "Pinned",
|
|
1989
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_xui_icons_base5.Pin, { size: 18, variant: "solid" }),
|
|
1990
|
+
dataId: options.dataId ?? "sidebar-collapsed-pinned",
|
|
1991
|
+
children: items.map((i) => ({
|
|
1992
|
+
to: i.to,
|
|
1993
|
+
label: i.label,
|
|
1994
|
+
exact: i.exact
|
|
1995
|
+
}))
|
|
1996
|
+
};
|
|
1997
|
+
};
|
|
1808
1998
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1809
1999
|
0 && (module.exports = {
|
|
1810
2000
|
Sidebar,
|
|
@@ -1817,8 +2007,10 @@ var SidebarChatButton = ({
|
|
|
1817
2007
|
SidebarMenuCollapsible,
|
|
1818
2008
|
SidebarMenuItem,
|
|
1819
2009
|
SidebarMenuSub,
|
|
2010
|
+
SidebarPinnedList,
|
|
1820
2011
|
SidebarProvider,
|
|
1821
2012
|
SidebarTrigger,
|
|
2013
|
+
getPinnedCollapsedItem,
|
|
1822
2014
|
useSidebar
|
|
1823
2015
|
});
|
|
1824
2016
|
//# sourceMappingURL=index.js.map
|