@lobehub/ui 5.50.2 → 5.51.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/es/base-ui/Input/style.d.mts +2 -2
- package/es/base-ui/Segmented/style.mjs +4 -0
- package/es/base-ui/Segmented/style.mjs.map +1 -1
- package/es/dashboard/ConsoleNav/ConsoleNav.mjs +130 -132
- package/es/dashboard/ConsoleNav/ConsoleNav.mjs.map +1 -1
- package/es/dashboard/ConsoleNav/style.mjs +360 -237
- package/es/dashboard/ConsoleNav/style.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/ConsoleBrand.mjs +1 -3
- package/es/dashboard/ConsoleShell/ConsoleBrand.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/style.mjs +16 -12
- package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
- package/es/eslint/index.d.mts +12 -4
- package/es/eslint/index.mjs +108 -51
- package/es/eslint/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -23,8 +23,8 @@ declare const styles: {
|
|
|
23
23
|
};
|
|
24
24
|
declare const rootVariants: (props?: ({
|
|
25
25
|
shadow?: boolean | null | undefined;
|
|
26
|
-
size?: "
|
|
27
|
-
variant?: "
|
|
26
|
+
size?: "small" | "middle" | "large" | null | undefined;
|
|
27
|
+
variant?: "outlined" | "borderless" | "filled" | null | undefined;
|
|
28
28
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
29
29
|
//#endregion
|
|
30
30
|
export { rootVariants, styles };
|
|
@@ -24,6 +24,10 @@ const styles = createStaticStyles(({ css, cssVar }) => {
|
|
|
24
24
|
transition-duration: 240ms;
|
|
25
25
|
transition-property: inset-inline-start, inset-block-start, width, height;
|
|
26
26
|
|
|
27
|
+
[data-variant='outlined'] > & {
|
|
28
|
+
background: ${cssVar.colorFillSecondary};
|
|
29
|
+
}
|
|
30
|
+
|
|
27
31
|
[data-orientation='horizontal'] &:dir(rtl) {
|
|
28
32
|
inset-inline-start: var(--active-item-right);
|
|
29
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.mjs","names":["lobeStaticStylish"],"sources":["../../../src/base-ui/Segmented/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nimport { focusRing } from '@/base-ui/focusRing';\nimport { lobeStaticStylish } from '@/styles';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => {\n const indicator = css`\n pointer-events: none;\n\n position: absolute;\n z-index: 0;\n inset-block-start: var(--active-item-top);\n inset-inline-start: var(--active-item-left);\n\n width: var(--active-item-width);\n height: var(--active-item-height);\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n box-shadow: none;\n\n transition-timing-function: ${cssVar.motionEaseOut};\n transition-duration: 240ms;\n transition-property: inset-inline-start, inset-block-start, width, height;\n\n [data-orientation='horizontal'] &:dir(rtl) {\n inset-inline-start: var(--active-item-right);\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `;\n\n return {\n indicator,\n item: css`\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n flex-shrink: 0;\n gap: 6px;\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n border: 0;\n border-radius: ${cssVar.borderRadius};\n\n font-weight: 500;\n color: ${cssVar.colorTextSecondary};\n white-space: nowrap;\n\n background: transparent;\n outline: none;\n\n transition:\n color 120ms ${cssVar.motionEaseOut},\n transform 120ms ${cssVar.motionEaseOut};\n\n &:hover:not([data-disabled], [data-pressed]) {\n color: ${cssVar.colorText};\n }\n\n &:active:not([data-disabled]) {\n transform: scale(0.98);\n }\n\n ${focusRing};\n\n &[data-pressed] {\n color: ${cssVar.colorText};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n itemBlock: css`\n flex: 1 1 0;\n `,\n itemIcon: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n `,\n itemLabel: css`\n display: inline-flex;\n align-items: center;\n `,\n itemLarge: css`\n height: 36px;\n padding-inline: 16px;\n border-radius: ${cssVar.borderRadius};\n font-size: 14px;\n `,\n itemMiddle: css`\n height: 32px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n font-size: 13px;\n `,\n itemSmall: css`\n height: 26px;\n padding-inline: 10px;\n border-radius: ${cssVar.borderRadius};\n font-size: 12px;\n `,\n list: css`\n position: relative;\n\n display: inline-flex;\n flex-wrap: nowrap;\n gap: 4px;\n align-items: center;\n align-self: flex-start;\n\n box-sizing: border-box;\n padding: 3px;\n border-radius: ${cssVar.borderRadiusLG};\n\n &[data-orientation='vertical'] {\n flex-direction: column;\n align-items: stretch;\n align-self: stretch;\n }\n `,\n listBlock: css`\n display: flex;\n align-self: stretch;\n width: 100%;\n `,\n listFilled: css`\n border: 1px solid ${cssVar.colorFillQuaternary};\n background: ${cssVar.colorBgLayout};\n `,\n listGlass: lobeStaticStylish.blur,\n listOutlined: css`\n border: 1px solid ${cssVar.colorBorderSecondary};\n background: transparent;\n `,\n listShadow: lobeStaticStylish.shadow,\n root: css`\n display: inline-flex;\n\n &[data-block='true'] {\n display: flex;\n width: 100%;\n }\n `,\n };\n});\n\nexport const listVariants = cva(styles.list, {\n defaultVariants: {\n block: false,\n glass: false,\n shadow: false,\n variant: 'filled',\n },\n variants: {\n block: {\n false: null,\n true: styles.listBlock,\n },\n glass: {\n false: null,\n true: styles.listGlass,\n },\n shadow: {\n false: null,\n true: styles.listShadow,\n },\n variant: {\n filled: styles.listFilled,\n outlined: styles.listOutlined,\n },\n },\n});\n\nexport const itemVariants = cva(styles.item, {\n defaultVariants: {\n block: false,\n size: 'middle',\n },\n variants: {\n block: {\n false: null,\n true: styles.itemBlock,\n },\n size: {\n large: styles.itemLarge,\n middle: styles.itemMiddle,\n small: styles.itemSmall,\n },\n },\n});\n"],"mappings":";;;;;AAMA,MAAa,SAAS,oBAAoB,EAAE,KAAK,aAAa;
|
|
1
|
+
{"version":3,"file":"style.mjs","names":["lobeStaticStylish"],"sources":["../../../src/base-ui/Segmented/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\nimport { cva } from 'class-variance-authority';\n\nimport { focusRing } from '@/base-ui/focusRing';\nimport { lobeStaticStylish } from '@/styles';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => {\n const indicator = css`\n pointer-events: none;\n\n position: absolute;\n z-index: 0;\n inset-block-start: var(--active-item-top);\n inset-inline-start: var(--active-item-left);\n\n width: var(--active-item-width);\n height: var(--active-item-height);\n border-radius: ${cssVar.borderRadius};\n\n background: ${cssVar.colorBgElevated};\n box-shadow: none;\n\n transition-timing-function: ${cssVar.motionEaseOut};\n transition-duration: 240ms;\n transition-property: inset-inline-start, inset-block-start, width, height;\n\n [data-variant='outlined'] > & {\n background: ${cssVar.colorFillSecondary};\n }\n\n [data-orientation='horizontal'] &:dir(rtl) {\n inset-inline-start: var(--active-item-right);\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `;\n\n return {\n indicator,\n item: css`\n cursor: pointer;\n user-select: none;\n\n position: relative;\n z-index: 1;\n\n display: inline-flex;\n flex-shrink: 0;\n gap: 6px;\n align-items: center;\n justify-content: center;\n\n box-sizing: border-box;\n border: 0;\n border-radius: ${cssVar.borderRadius};\n\n font-weight: 500;\n color: ${cssVar.colorTextSecondary};\n white-space: nowrap;\n\n background: transparent;\n outline: none;\n\n transition:\n color 120ms ${cssVar.motionEaseOut},\n transform 120ms ${cssVar.motionEaseOut};\n\n &:hover:not([data-disabled], [data-pressed]) {\n color: ${cssVar.colorText};\n }\n\n &:active:not([data-disabled]) {\n transform: scale(0.98);\n }\n\n ${focusRing};\n\n &[data-pressed] {\n color: ${cssVar.colorText};\n }\n\n &[data-disabled] {\n cursor: not-allowed;\n color: ${cssVar.colorTextDisabled};\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition-duration: 0s;\n }\n `,\n itemBlock: css`\n flex: 1 1 0;\n `,\n itemIcon: css`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n `,\n itemLabel: css`\n display: inline-flex;\n align-items: center;\n `,\n itemLarge: css`\n height: 36px;\n padding-inline: 16px;\n border-radius: ${cssVar.borderRadius};\n font-size: 14px;\n `,\n itemMiddle: css`\n height: 32px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n font-size: 13px;\n `,\n itemSmall: css`\n height: 26px;\n padding-inline: 10px;\n border-radius: ${cssVar.borderRadius};\n font-size: 12px;\n `,\n list: css`\n position: relative;\n\n display: inline-flex;\n flex-wrap: nowrap;\n gap: 4px;\n align-items: center;\n align-self: flex-start;\n\n box-sizing: border-box;\n padding: 3px;\n border-radius: ${cssVar.borderRadiusLG};\n\n &[data-orientation='vertical'] {\n flex-direction: column;\n align-items: stretch;\n align-self: stretch;\n }\n `,\n listBlock: css`\n display: flex;\n align-self: stretch;\n width: 100%;\n `,\n listFilled: css`\n border: 1px solid ${cssVar.colorFillQuaternary};\n background: ${cssVar.colorBgLayout};\n `,\n listGlass: lobeStaticStylish.blur,\n listOutlined: css`\n border: 1px solid ${cssVar.colorBorderSecondary};\n background: transparent;\n `,\n listShadow: lobeStaticStylish.shadow,\n root: css`\n display: inline-flex;\n\n &[data-block='true'] {\n display: flex;\n width: 100%;\n }\n `,\n };\n});\n\nexport const listVariants = cva(styles.list, {\n defaultVariants: {\n block: false,\n glass: false,\n shadow: false,\n variant: 'filled',\n },\n variants: {\n block: {\n false: null,\n true: styles.listBlock,\n },\n glass: {\n false: null,\n true: styles.listGlass,\n },\n shadow: {\n false: null,\n true: styles.listShadow,\n },\n variant: {\n filled: styles.listFilled,\n outlined: styles.listOutlined,\n },\n },\n});\n\nexport const itemVariants = cva(styles.item, {\n defaultVariants: {\n block: false,\n size: 'middle',\n },\n variants: {\n block: {\n false: null,\n true: styles.itemBlock,\n },\n size: {\n large: styles.itemLarge,\n middle: styles.itemMiddle,\n small: styles.itemSmall,\n },\n },\n});\n"],"mappings":";;;;;AAMA,MAAa,SAAS,oBAAoB,EAAE,KAAK,aAAa;CAiC5D,OAAO;EACL,WAjCgB,GAAG;;;;;;;;;;qBAUF,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kCAGP,OAAO,cAAc;;;;;oBAKnC,OAAO,mBAAmB;;;;;;;;;;;EAc1C,MAAM,GAAG;;;;;;;;;;;;;;;uBAeU,OAAO,aAAa;;;eAG5B,OAAO,mBAAmB;;;;;;;sBAOnB,OAAO,cAAc;0BACjB,OAAO,cAAc;;;iBAG9B,OAAO,UAAU;;;;;;;QAO1B,UAAU;;;iBAGD,OAAO,UAAU;;;;;iBAKjB,OAAO,kBAAkB;;;;;;;EAOtC,WAAW,GAAG;;;EAGd,UAAU,GAAG;;;;;EAKb,WAAW,GAAG;;;;EAId,WAAW,GAAG;;;uBAGK,OAAO,aAAa;;;EAGvC,YAAY,GAAG;;;uBAGI,OAAO,aAAa;;;EAGvC,WAAW,GAAG;;;uBAGK,OAAO,aAAa;;;EAGvC,MAAM,GAAG;;;;;;;;;;;uBAWU,OAAO,eAAe;;;;;;;;EAQzC,WAAW,GAAG;;;;;EAKd,YAAY,GAAG;0BACO,OAAO,oBAAoB;oBACjC,OAAO,cAAc;;EAErC,WAAWA,cAAkB;EAC7B,cAAc,GAAG;0BACK,OAAO,qBAAqB;;;EAGlD,YAAYA,cAAkB;EAC9B,MAAM,GAAG;;;;;;;;CAQX;AACF,CAAC;AAED,MAAa,eAAe,IAAI,OAAO,MAAM;CAC3C,iBAAiB;EACf,OAAO;EACP,OAAO;EACP,QAAQ;EACR,SAAS;CACX;CACA,UAAU;EACR,OAAO;GACL,OAAO;GACP,MAAM,OAAO;EACf;EACA,OAAO;GACL,OAAO;GACP,MAAM,OAAO;EACf;EACA,QAAQ;GACN,OAAO;GACP,MAAM,OAAO;EACf;EACA,SAAS;GACP,QAAQ,OAAO;GACf,UAAU,OAAO;EACnB;CACF;AACF,CAAC;AAED,MAAa,eAAe,IAAI,OAAO,MAAM;CAC3C,iBAAiB;EACf,OAAO;EACP,MAAM;CACR;CACA,UAAU;EACR,OAAO;GACL,OAAO;GACP,MAAM,OAAO;EACf;EACA,MAAM;GACJ,OAAO,OAAO;GACd,QAAQ,OAAO;GACf,OAAO,OAAO;EAChB;CACF;AACF,CAAC"}
|
|
@@ -11,48 +11,72 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
import { ChevronDown, Play } from "lucide-react";
|
|
12
12
|
//#region src/dashboard/ConsoleNav/ConsoleNav.tsx
|
|
13
13
|
const PANEL_TRANSITION_MS = 160;
|
|
14
|
+
const RAIL_TRANSITION_MS = 200;
|
|
14
15
|
/** Older builds stored the closed group keys as an array. */
|
|
15
16
|
function readOverrides(value) {
|
|
16
17
|
if (Array.isArray(value)) return Object.fromEntries(value.map((key) => [String(key), false]));
|
|
17
18
|
return value && typeof value === "object" ? value : {};
|
|
18
19
|
}
|
|
19
|
-
function scrollActiveIntoView(container) {
|
|
20
|
+
function scrollActiveIntoView(container, behavior = "auto") {
|
|
20
21
|
const link = container.querySelector("[aria-current=\"page\"]") ?? [...container.querySelectorAll("button[data-active=\"true\"]")].at(-1);
|
|
21
22
|
if (!link) return;
|
|
22
23
|
const containerRect = container.getBoundingClientRect();
|
|
23
24
|
const linkRect = link.getBoundingClientRect();
|
|
24
25
|
if (linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom) return;
|
|
25
|
-
container.
|
|
26
|
+
container.scrollBy({
|
|
27
|
+
behavior,
|
|
28
|
+
top: linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function renderAnchor(context, linkProps, onFollow) {
|
|
32
|
+
if (context.renderLink) return context.renderLink(linkProps);
|
|
33
|
+
return /* @__PURE__ */ jsx("a", {
|
|
34
|
+
"aria-current": linkProps["aria-current"],
|
|
35
|
+
"aria-label": linkProps["aria-label"],
|
|
36
|
+
className: linkProps.className,
|
|
37
|
+
"data-active": linkProps["data-active"],
|
|
38
|
+
"data-collapsed": linkProps["data-collapsed"],
|
|
39
|
+
"data-indent": linkProps["data-indent"],
|
|
40
|
+
href: linkProps.href,
|
|
41
|
+
rel: linkProps.external ? "noreferrer" : void 0,
|
|
42
|
+
target: linkProps.external ? "_blank" : void 0,
|
|
43
|
+
title: linkProps.title,
|
|
44
|
+
onClick: (event) => {
|
|
45
|
+
if (context.onNavigate && !linkProps.external) event.preventDefault();
|
|
46
|
+
onFollow();
|
|
47
|
+
},
|
|
48
|
+
children: linkProps.children
|
|
49
|
+
});
|
|
26
50
|
}
|
|
27
|
-
function NavLink({ active, collapsed, context, href, icon, indent = 0, item, name }) {
|
|
51
|
+
function NavLink({ active, collapsed, context, href, icon, indent = 0, item, name, overlay = false }) {
|
|
28
52
|
const shell = useConsoleShellState();
|
|
29
53
|
const label = item?.label ?? name;
|
|
30
54
|
const follow = () => {
|
|
31
55
|
context.onNavigate?.(href);
|
|
32
56
|
shell?.closeNavigation();
|
|
33
57
|
};
|
|
34
|
-
const
|
|
58
|
+
const link = renderAnchor(context, {
|
|
35
59
|
"aria-current": active ? "page" : void 0,
|
|
36
60
|
"aria-label": collapsed ? name : void 0,
|
|
37
|
-
"children": /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
61
|
+
"children": overlay ? null : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
38
62
|
icon ? /* @__PURE__ */ jsx(Icon, {
|
|
39
63
|
icon,
|
|
40
64
|
size: 18
|
|
41
65
|
}) : null,
|
|
42
|
-
|
|
66
|
+
/* @__PURE__ */ jsx("span", {
|
|
43
67
|
className: styles.itemLabel,
|
|
44
68
|
children: label
|
|
45
69
|
}),
|
|
46
|
-
|
|
70
|
+
item?.badge ? /* @__PURE__ */ jsx("span", {
|
|
47
71
|
className: styles.badge,
|
|
48
72
|
children: item.badge
|
|
49
73
|
}) : null,
|
|
50
|
-
|
|
74
|
+
item?.badge ? /* @__PURE__ */ jsx("span", {
|
|
51
75
|
"aria-hidden": true,
|
|
52
76
|
className: styles.dot
|
|
53
77
|
}) : null
|
|
54
78
|
] }),
|
|
55
|
-
"className": styles.item,
|
|
79
|
+
"className": overlay ? styles.railLink : styles.item,
|
|
56
80
|
"data-active": active,
|
|
57
81
|
"data-collapsed": collapsed,
|
|
58
82
|
"data-indent": indent,
|
|
@@ -60,31 +84,24 @@ function NavLink({ active, collapsed, context, href, icon, indent = 0, item, nam
|
|
|
60
84
|
href,
|
|
61
85
|
"onClick": follow,
|
|
62
86
|
"title": collapsed ? void 0 : label
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
"aria-current": linkProps["aria-current"],
|
|
66
|
-
"aria-label": linkProps["aria-label"],
|
|
67
|
-
className: linkProps.className,
|
|
68
|
-
"data-active": active,
|
|
69
|
-
"data-collapsed": collapsed,
|
|
70
|
-
"data-indent": indent,
|
|
71
|
-
href,
|
|
72
|
-
rel: item?.external ? "noreferrer" : void 0,
|
|
73
|
-
target: item?.external ? "_blank" : void 0,
|
|
74
|
-
title: linkProps.title,
|
|
75
|
-
onClick: (event) => {
|
|
76
|
-
if (context.onNavigate && !item?.external) event.preventDefault();
|
|
77
|
-
follow();
|
|
78
|
-
},
|
|
79
|
-
children: linkProps.children
|
|
80
|
-
});
|
|
81
|
-
if (!collapsed) return link;
|
|
87
|
+
}, follow);
|
|
88
|
+
if (!icon && !overlay) return link;
|
|
82
89
|
return /* @__PURE__ */ jsx(Tooltip, {
|
|
90
|
+
disabled: !collapsed,
|
|
83
91
|
placement: "right",
|
|
84
92
|
title: name,
|
|
85
93
|
children: link
|
|
86
94
|
});
|
|
87
95
|
}
|
|
96
|
+
function Fold({ children, folded }) {
|
|
97
|
+
return /* @__PURE__ */ jsx("div", {
|
|
98
|
+
"aria-hidden": folded || void 0,
|
|
99
|
+
className: styles.fold,
|
|
100
|
+
"data-folded": folded,
|
|
101
|
+
inert: folded || void 0,
|
|
102
|
+
children: /* @__PURE__ */ jsx("div", { children })
|
|
103
|
+
});
|
|
104
|
+
}
|
|
88
105
|
function ConsoleNav({ collapsed: collapsedProp, defaultExpanded = "all", groups = [], items = [], label = "Primary", onNavigate, pathname, renderLink, storageKey }) {
|
|
89
106
|
const id = useId();
|
|
90
107
|
const navRef = useRef(null);
|
|
@@ -124,132 +141,111 @@ function ConsoleNav({ collapsed: collapsedProp, defaultExpanded = "all", groups
|
|
|
124
141
|
return () => window.clearTimeout(timer);
|
|
125
142
|
}, [
|
|
126
143
|
activeHref,
|
|
127
|
-
collapsed,
|
|
128
144
|
pathname,
|
|
129
145
|
reducedMotion
|
|
130
146
|
]);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
name: groupLabel ? `${groupLabel} / ${item.label}` : item.label
|
|
140
|
-
}, item.href));
|
|
141
|
-
if (collapsed) {
|
|
142
|
-
const railItems = (list, groupLabel) => list.filter((item) => item.icon).map((item) => /* @__PURE__ */ jsx(NavLink, {
|
|
143
|
-
collapsed: true,
|
|
147
|
+
useEffect(() => {
|
|
148
|
+
const container = navRef.current;
|
|
149
|
+
if (!container) return;
|
|
150
|
+
const timer = window.setTimeout(() => scrollActiveIntoView(container, reducedMotion ? "auto" : "smooth"), reducedMotion ? 0 : RAIL_TRANSITION_MS);
|
|
151
|
+
return () => window.clearTimeout(timer);
|
|
152
|
+
}, [collapsed, reducedMotion]);
|
|
153
|
+
const renderItems = (list, indent, groupLabel, foldable) => list.map((item) => {
|
|
154
|
+
const link = /* @__PURE__ */ jsx(NavLink, {
|
|
144
155
|
active: item.href === activeHref,
|
|
156
|
+
collapsed,
|
|
145
157
|
context,
|
|
146
158
|
href: item.href,
|
|
147
159
|
icon: item.icon,
|
|
160
|
+
indent: item.icon ? Math.max(0, indent - 1) : indent,
|
|
148
161
|
item,
|
|
149
162
|
name: groupLabel ? `${groupLabel} / ${item.label}` : item.label
|
|
150
|
-
}, item.href)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
}, item.href);
|
|
164
|
+
if (item.icon || !foldable) return link;
|
|
165
|
+
return /* @__PURE__ */ jsx(Fold, {
|
|
166
|
+
folded: collapsed,
|
|
167
|
+
children: link
|
|
168
|
+
}, item.href);
|
|
169
|
+
});
|
|
170
|
+
const renderGroup = (group, level, indent, underRailIcon) => {
|
|
171
|
+
const expanded = isExpanded(group);
|
|
172
|
+
const panelId = `${id}-${group.key}`;
|
|
173
|
+
const childIndent = indent + (group.icon ? 1 : 0);
|
|
174
|
+
const active = activeBranch.includes(group.key);
|
|
175
|
+
const railIcon = level === 0 && Boolean(group.icon);
|
|
176
|
+
const onRail = collapsed && !underRailIcon;
|
|
177
|
+
const open = onRail ? !railIcon : expanded;
|
|
178
|
+
const railHref = railIcon ? group.href ?? collectNavItems([group])[0]?.href : void 0;
|
|
179
|
+
const railEmpty = !railIcon && !collectNavItems([group]).some((item) => item.icon);
|
|
180
|
+
const header = /* @__PURE__ */ jsxs("button", {
|
|
181
|
+
"aria-controls": panelId,
|
|
182
|
+
"aria-expanded": open,
|
|
183
|
+
"aria-hidden": onRail && railIcon || void 0,
|
|
184
|
+
className: styles.groupHeader,
|
|
185
|
+
"data-active": active,
|
|
186
|
+
"data-icon": Boolean(group.icon),
|
|
187
|
+
"data-indent": indent,
|
|
188
|
+
"data-level": level,
|
|
189
|
+
tabIndex: onRail && railIcon ? -1 : void 0,
|
|
190
|
+
type: "button",
|
|
191
|
+
onClick: () => toggleGroup(group.key, expanded),
|
|
161
192
|
children: [
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
193
|
+
group.icon ? /* @__PURE__ */ jsx(Icon, {
|
|
194
|
+
icon: group.icon,
|
|
195
|
+
size: 16
|
|
165
196
|
}) : null,
|
|
166
|
-
|
|
167
|
-
className: styles.
|
|
168
|
-
"data-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
197
|
+
/* @__PURE__ */ jsx("span", {
|
|
198
|
+
className: styles.itemLabel,
|
|
199
|
+
"data-label": "",
|
|
200
|
+
children: group.label
|
|
201
|
+
}),
|
|
202
|
+
level === 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
203
|
+
className: styles.chevron,
|
|
204
|
+
"data-expanded": expanded,
|
|
205
|
+
icon: ChevronDown,
|
|
206
|
+
size: 14
|
|
207
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
208
|
+
className: styles.indicator,
|
|
209
|
+
"data-expanded": expanded,
|
|
210
|
+
children: /* @__PURE__ */ jsx(Play, {
|
|
211
|
+
fill: "currentColor",
|
|
212
|
+
size: 7,
|
|
213
|
+
strokeWidth: 1
|
|
181
214
|
})
|
|
182
|
-
}) : null,
|
|
183
|
-
groups.filter((group) => !group.icon).map((group, index) => {
|
|
184
|
-
const rail = railItems(collectNavItems([group]), group.label);
|
|
185
|
-
if (rail.length === 0) return null;
|
|
186
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
187
|
-
className: styles.railGroup,
|
|
188
|
-
"data-first": topRail.length === 0 && iconGroups.length === 0 && index === 0,
|
|
189
|
-
role: "group",
|
|
190
|
-
children: [/* @__PURE__ */ jsx("h2", {
|
|
191
|
-
className: styles.srOnly,
|
|
192
|
-
children: group.label
|
|
193
|
-
}), rail]
|
|
194
|
-
}, group.key);
|
|
195
215
|
})
|
|
196
216
|
]
|
|
197
217
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
218
|
+
let head = header;
|
|
219
|
+
if (railIcon) head = /* @__PURE__ */ jsxs("div", {
|
|
220
|
+
className: styles.groupHead,
|
|
221
|
+
children: [header, onRail && railHref ? /* @__PURE__ */ jsx(NavLink, {
|
|
222
|
+
collapsed: true,
|
|
223
|
+
overlay: true,
|
|
224
|
+
active: activeBranch[0] === group.key,
|
|
225
|
+
context,
|
|
226
|
+
href: railHref,
|
|
227
|
+
name: group.label
|
|
228
|
+
}) : null]
|
|
229
|
+
});
|
|
230
|
+
else if (!underRailIcon) head = /* @__PURE__ */ jsx(Fold, {
|
|
231
|
+
folded: onRail,
|
|
232
|
+
children: header
|
|
233
|
+
});
|
|
204
234
|
return /* @__PURE__ */ jsxs("div", {
|
|
205
235
|
className: styles.group,
|
|
206
236
|
"data-icon": Boolean(group.icon),
|
|
207
237
|
"data-level": level,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
"aria-
|
|
211
|
-
className: styles.groupHeader,
|
|
212
|
-
"data-active": active,
|
|
213
|
-
"data-icon": Boolean(group.icon),
|
|
214
|
-
"data-indent": indent,
|
|
215
|
-
"data-level": level,
|
|
216
|
-
type: "button",
|
|
217
|
-
onClick: () => toggleGroup(group.key, expanded),
|
|
218
|
-
children: [
|
|
219
|
-
group.icon ? /* @__PURE__ */ jsx(Icon, {
|
|
220
|
-
icon: group.icon,
|
|
221
|
-
size: 16
|
|
222
|
-
}) : null,
|
|
223
|
-
/* @__PURE__ */ jsx("span", {
|
|
224
|
-
className: styles.itemLabel,
|
|
225
|
-
"data-label": "",
|
|
226
|
-
children: group.label
|
|
227
|
-
}),
|
|
228
|
-
level === 0 ? /* @__PURE__ */ jsx(Icon, {
|
|
229
|
-
className: styles.chevron,
|
|
230
|
-
"data-expanded": expanded,
|
|
231
|
-
icon: ChevronDown,
|
|
232
|
-
size: 14
|
|
233
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
234
|
-
className: styles.indicator,
|
|
235
|
-
"data-expanded": expanded,
|
|
236
|
-
children: /* @__PURE__ */ jsx(Play, {
|
|
237
|
-
fill: "currentColor",
|
|
238
|
-
size: 7,
|
|
239
|
-
strokeWidth: 1
|
|
240
|
-
})
|
|
241
|
-
})
|
|
242
|
-
]
|
|
243
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
244
|
-
"aria-hidden": !expanded,
|
|
238
|
+
"data-rail-empty": railEmpty,
|
|
239
|
+
children: [head, /* @__PURE__ */ jsx("div", {
|
|
240
|
+
"aria-hidden": !open,
|
|
245
241
|
className: styles.groupPanel,
|
|
246
|
-
"data-expanded":
|
|
242
|
+
"data-expanded": open,
|
|
247
243
|
"data-instant": reducedMotion,
|
|
248
244
|
id: panelId,
|
|
249
|
-
inert:
|
|
245
|
+
inert: open ? void 0 : true,
|
|
250
246
|
children: /* @__PURE__ */ jsxs("div", {
|
|
251
247
|
className: styles.groupItems,
|
|
252
|
-
children: [renderItems(group.items ?? [], childIndent, group.label), (group.groups ?? []).map((child) => renderGroup(child, level + 1, childIndent))]
|
|
248
|
+
children: [renderItems(group.items ?? [], childIndent, group.label, !(underRailIcon || railIcon)), (group.groups ?? []).map((child) => renderGroup(child, level + 1, childIndent, underRailIcon || railIcon))]
|
|
253
249
|
})
|
|
254
250
|
})]
|
|
255
251
|
}, group.key);
|
|
@@ -258,14 +254,16 @@ function ConsoleNav({ collapsed: collapsedProp, defaultExpanded = "all", groups
|
|
|
258
254
|
"aria-label": label,
|
|
259
255
|
as: "nav",
|
|
260
256
|
className: styles.nav,
|
|
257
|
+
"data-collapsed": collapsed,
|
|
261
258
|
orientation: "vertical",
|
|
262
259
|
ref: navRef,
|
|
263
260
|
size: 4,
|
|
264
261
|
children: [items.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
265
262
|
className: styles.topItems,
|
|
266
263
|
"data-divided": groups.length > 0,
|
|
267
|
-
|
|
268
|
-
|
|
264
|
+
"data-rail-empty": !items.some((item) => item.icon),
|
|
265
|
+
children: renderItems(items, 0, void 0, true)
|
|
266
|
+
}) : null, groups.map((group) => renderGroup(group, 0, 0, false))]
|
|
269
267
|
});
|
|
270
268
|
}
|
|
271
269
|
ConsoleNav.displayName = "ConsoleNav";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConsoleNav.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/ConsoleNav.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown, Play } from 'lucide-react';\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\n\nimport Tooltip from '@/base-ui/Tooltip';\nimport Icon from '@/Icon';\nimport ScrollShadow from '@/ScrollShadow';\n\nimport { useConsoleShellState } from '../ConsoleShell/context';\nimport { useLocalStorage, usePrefersReducedMotion } from '../hooks';\nimport { collectNavItems, findActiveBranch, resolveActiveHref } from './active';\nimport { styles } from './style';\nimport type { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps } from './type';\n\nconst PANEL_TRANSITION_MS = 160;\n\ntype ExpandedOverrides = Record<string, boolean>;\n\n/** Older builds stored the closed group keys as an array. */\nfunction readOverrides(value: unknown): ExpandedOverrides {\n if (Array.isArray(value)) {\n return Object.fromEntries(value.map((key) => [String(key), false]));\n }\n return value && typeof value === 'object' ? (value as ExpandedOverrides) : {};\n}\n\nfunction scrollActiveIntoView(container: HTMLElement) {\n const link =\n container.querySelector<HTMLElement>('[aria-current=\"page\"]') ??\n [...container.querySelectorAll<HTMLElement>('button[data-active=\"true\"]')].at(-1);\n if (!link) return;\n const containerRect = container.getBoundingClientRect();\n const linkRect = link.getBoundingClientRect();\n if (linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom) return;\n container.scrollTop +=\n linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2;\n}\n\ninterface LinkContext {\n onNavigate?: (href: string) => void;\n renderLink?: ConsoleNavProps['renderLink'];\n}\n\nfunction NavLink({\n active,\n collapsed,\n context,\n href,\n icon,\n indent = 0,\n item,\n name,\n}: {\n active: boolean;\n collapsed: boolean;\n context: LinkContext;\n href: string;\n icon?: ConsoleNavItem['icon'];\n indent?: number;\n item?: ConsoleNavItem;\n name: string;\n}) {\n const shell = useConsoleShellState();\n const label = item?.label ?? name;\n const follow = () => {\n context.onNavigate?.(href);\n shell?.closeNavigation();\n };\n const linkProps: ConsoleNavLinkProps = {\n 'aria-current': active ? 'page' : undefined,\n 'aria-label': collapsed ? name : undefined,\n 'children': (\n <>\n {icon ? <Icon icon={icon} size={18} /> : null}\n {collapsed ? null : <span className={styles.itemLabel}>{label}</span>}\n {!collapsed && item?.badge ? <span className={styles.badge}>{item.badge}</span> : null}\n {collapsed && item?.badge ? <span aria-hidden className={styles.dot} /> : null}\n </>\n ),\n 'className': styles.item,\n 'data-active': active,\n 'data-collapsed': collapsed,\n 'data-indent': indent,\n 'external': item?.external,\n href,\n 'onClick': follow,\n 'title': collapsed ? undefined : label,\n };\n\n const link = context.renderLink ? (\n context.renderLink(linkProps)\n ) : (\n <a\n aria-current={linkProps['aria-current']}\n aria-label={linkProps['aria-label']}\n className={linkProps.className}\n data-active={active}\n data-collapsed={collapsed}\n data-indent={indent}\n href={href}\n rel={item?.external ? 'noreferrer' : undefined}\n target={item?.external ? '_blank' : undefined}\n title={linkProps.title}\n onClick={(event) => {\n if (context.onNavigate && !item?.external) event.preventDefault();\n follow();\n }}\n >\n {linkProps.children}\n </a>\n );\n\n if (!collapsed) return link;\n return (\n <Tooltip placement=\"right\" title={name}>\n {link}\n </Tooltip>\n );\n}\n\nfunction ConsoleNav({\n collapsed: collapsedProp,\n defaultExpanded = 'all',\n groups = [],\n items = [],\n label = 'Primary',\n onNavigate,\n pathname,\n renderLink,\n storageKey,\n}: ConsoleNavProps) {\n const id = useId();\n const navRef = useRef<HTMLDivElement>(null);\n const shell = useConsoleShellState();\n const collapsed = collapsedProp ?? shell?.collapsed ?? false;\n const reducedMotion = usePrefersReducedMotion();\n const [storedOverrides, setStoredOverrides] = useLocalStorage<unknown>(storageKey, {});\n const overrides = readOverrides(storedOverrides);\n const context: LinkContext = { onNavigate, renderLink };\n\n const activeHref = resolveActiveHref(pathname, [...items, ...collectNavItems(groups)]);\n const activeBranch = findActiveBranch(pathname, groups, activeHref);\n\n // Arriving on a page reopens its branch even if it was closed by hand earlier.\n const [trackedPathname, setTrackedPathname] = useState(pathname);\n if (trackedPathname !== pathname) {\n setTrackedPathname(pathname);\n if (activeBranch.some((key) => overrides[key] === false)) {\n const next = { ...overrides };\n for (const key of activeBranch) delete next[key];\n setStoredOverrides(next);\n }\n }\n\n const isExpanded = (group: ConsoleNavGroup) =>\n overrides[group.key] ??\n (activeBranch.includes(group.key) || (group.defaultExpanded ?? defaultExpanded === 'all'));\n\n const toggleGroup = useCallback(\n (key: string, expanded: boolean) => {\n setStoredOverrides((current: unknown) => ({ ...readOverrides(current), [key]: !expanded }));\n },\n [setStoredOverrides],\n );\n\n useEffect(() => {\n const container = navRef.current;\n if (!container) return;\n scrollActiveIntoView(container);\n if (reducedMotion) return;\n const timer = window.setTimeout(() => scrollActiveIntoView(container), PANEL_TRANSITION_MS);\n return () => window.clearTimeout(timer);\n }, [activeHref, collapsed, pathname, reducedMotion]);\n\n const renderItems = (list: ConsoleNavItem[], indent: number, groupLabel?: string) =>\n list.map((item) => (\n <NavLink\n active={item.href === activeHref}\n collapsed={false}\n context={context}\n href={item.href}\n icon={item.icon}\n indent={item.icon ? Math.max(0, indent - 1) : indent}\n item={item}\n key={item.href}\n name={groupLabel ? `${groupLabel} / ${item.label}` : item.label}\n />\n ));\n\n if (collapsed) {\n const railItems = (list: ConsoleNavItem[], groupLabel?: string) =>\n list\n .filter((item) => item.icon)\n .map((item) => (\n <NavLink\n collapsed\n active={item.href === activeHref}\n context={context}\n href={item.href}\n icon={item.icon}\n item={item}\n key={item.href}\n name={groupLabel ? `${groupLabel} / ${item.label}` : item.label}\n />\n ));\n const topRail = railItems(items);\n const iconGroups = groups.filter((group) => group.icon);\n\n return (\n <ScrollShadow\n aria-label={label}\n as={'nav'}\n className={styles.nav}\n data-collapsed=\"\"\n orientation={'vertical'}\n ref={navRef}\n size={8}\n >\n {topRail.length > 0 ? <div className={styles.railTop}>{topRail}</div> : null}\n {iconGroups.length > 0 ? (\n <div className={styles.railGroup} data-first={topRail.length === 0} role=\"group\">\n {iconGroups.map((group) => {\n const href = group.href ?? collectNavItems([group])[0]?.href;\n if (!href) return null;\n return (\n <NavLink\n collapsed\n active={activeBranch[0] === group.key}\n context={context}\n href={href}\n icon={group.icon}\n key={group.key}\n name={group.label}\n />\n );\n })}\n </div>\n ) : null}\n {groups\n .filter((group) => !group.icon)\n .map((group, index) => {\n const rail = railItems(collectNavItems([group]), group.label);\n if (rail.length === 0) return null;\n return (\n <div\n className={styles.railGroup}\n data-first={topRail.length === 0 && iconGroups.length === 0 && index === 0}\n key={group.key}\n role=\"group\"\n >\n <h2 className={styles.srOnly}>{group.label}</h2>\n {rail}\n </div>\n );\n })}\n </ScrollShadow>\n );\n }\n\n const renderGroup = (group: ConsoleNavGroup, level: number, indent: number) => {\n const expanded = isExpanded(group);\n const panelId = `${id}-${group.key}`;\n // Nested groups are headings over their items, so the items keep the same indent.\n const childIndent = indent + (group.icon ? 1 : 0);\n const active = activeBranch.includes(group.key);\n\n return (\n <div\n className={styles.group}\n data-icon={Boolean(group.icon)}\n data-level={level}\n key={group.key}\n >\n <button\n aria-controls={panelId}\n aria-expanded={expanded}\n className={styles.groupHeader}\n data-active={active}\n data-icon={Boolean(group.icon)}\n data-indent={indent}\n data-level={level}\n type=\"button\"\n onClick={() => toggleGroup(group.key, expanded)}\n >\n {group.icon ? <Icon icon={group.icon} size={16} /> : null}\n <span className={styles.itemLabel} data-label=\"\">\n {group.label}\n </span>\n {level === 0 ? (\n <Icon\n className={styles.chevron}\n data-expanded={expanded}\n icon={ChevronDown}\n size={14}\n />\n ) : (\n <span className={styles.indicator} data-expanded={expanded}>\n <Play fill={'currentColor'} size={7} strokeWidth={1} />\n </span>\n )}\n </button>\n <div\n aria-hidden={!expanded}\n className={styles.groupPanel}\n data-expanded={expanded}\n data-instant={reducedMotion}\n id={panelId}\n inert={expanded ? undefined : true}\n >\n <div className={styles.groupItems}>\n {renderItems(group.items ?? [], childIndent, group.label)}\n {(group.groups ?? []).map((child) => renderGroup(child, level + 1, childIndent))}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <ScrollShadow\n aria-label={label}\n as={'nav'}\n className={styles.nav}\n orientation={'vertical'}\n ref={navRef}\n size={4}\n >\n {items.length > 0 ? (\n <div className={styles.topItems} data-divided={groups.length > 0}>\n {renderItems(items, 0)}\n </div>\n ) : null}\n {groups.map((group) => renderGroup(group, 0, 0))}\n </ScrollShadow>\n );\n}\n\nConsoleNav.displayName = 'ConsoleNav';\n\nexport default ConsoleNav;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ConsoleNav.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/ConsoleNav.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown, Play } from 'lucide-react';\nimport { type ReactNode, useCallback, useEffect, useId, useRef, useState } from 'react';\n\nimport Tooltip from '@/base-ui/Tooltip';\nimport Icon from '@/Icon';\nimport ScrollShadow from '@/ScrollShadow';\n\nimport { useConsoleShellState } from '../ConsoleShell/context';\nimport { useLocalStorage, usePrefersReducedMotion } from '../hooks';\nimport { collectNavItems, findActiveBranch, resolveActiveHref } from './active';\nimport { styles } from './style';\nimport type { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps } from './type';\n\nconst PANEL_TRANSITION_MS = 160;\nconst RAIL_TRANSITION_MS = 200;\n\ntype ExpandedOverrides = Record<string, boolean>;\n\n/** Older builds stored the closed group keys as an array. */\nfunction readOverrides(value: unknown): ExpandedOverrides {\n if (Array.isArray(value)) {\n return Object.fromEntries(value.map((key) => [String(key), false]));\n }\n return value && typeof value === 'object' ? (value as ExpandedOverrides) : {};\n}\n\nfunction scrollActiveIntoView(container: HTMLElement, behavior: ScrollBehavior = 'auto') {\n const link =\n container.querySelector<HTMLElement>('[aria-current=\"page\"]') ??\n [...container.querySelectorAll<HTMLElement>('button[data-active=\"true\"]')].at(-1);\n if (!link) return;\n const containerRect = container.getBoundingClientRect();\n const linkRect = link.getBoundingClientRect();\n if (linkRect.top >= containerRect.top && linkRect.bottom <= containerRect.bottom) return;\n container.scrollBy({\n behavior,\n top: linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2,\n });\n}\n\ninterface LinkContext {\n onNavigate?: (href: string) => void;\n renderLink?: ConsoleNavProps['renderLink'];\n}\n\nfunction renderAnchor(context: LinkContext, linkProps: ConsoleNavLinkProps, onFollow: () => void) {\n if (context.renderLink) return context.renderLink(linkProps);\n return (\n <a\n aria-current={linkProps['aria-current']}\n aria-label={linkProps['aria-label']}\n className={linkProps.className}\n data-active={linkProps['data-active']}\n data-collapsed={linkProps['data-collapsed']}\n data-indent={linkProps['data-indent']}\n href={linkProps.href}\n rel={linkProps.external ? 'noreferrer' : undefined}\n target={linkProps.external ? '_blank' : undefined}\n title={linkProps.title}\n onClick={(event) => {\n if (context.onNavigate && !linkProps.external) event.preventDefault();\n onFollow();\n }}\n >\n {linkProps.children}\n </a>\n );\n}\n\nfunction NavLink({\n active,\n collapsed,\n context,\n href,\n icon,\n indent = 0,\n item,\n name,\n overlay = false,\n}: {\n active: boolean;\n collapsed: boolean;\n context: LinkContext;\n href: string;\n icon?: ConsoleNavItem['icon'];\n indent?: number;\n item?: ConsoleNavItem;\n name: string;\n overlay?: boolean;\n}) {\n const shell = useConsoleShellState();\n const label = item?.label ?? name;\n const follow = () => {\n context.onNavigate?.(href);\n shell?.closeNavigation();\n };\n const linkProps: ConsoleNavLinkProps = {\n 'aria-current': active ? 'page' : undefined,\n 'aria-label': collapsed ? name : undefined,\n 'children': overlay ? null : (\n <>\n {icon ? <Icon icon={icon} size={18} /> : null}\n <span className={styles.itemLabel}>{label}</span>\n {item?.badge ? <span className={styles.badge}>{item.badge}</span> : null}\n {item?.badge ? <span aria-hidden className={styles.dot} /> : null}\n </>\n ),\n 'className': overlay ? styles.railLink : styles.item,\n 'data-active': active,\n 'data-collapsed': collapsed,\n 'data-indent': indent,\n 'external': item?.external,\n href,\n 'onClick': follow,\n 'title': collapsed ? undefined : label,\n };\n\n const link = renderAnchor(context, linkProps, follow);\n\n if (!icon && !overlay) return link;\n // Always mounted so toggling the rail keeps the same link element and its label can fade.\n return (\n <Tooltip disabled={!collapsed} placement=\"right\" title={name}>\n {link}\n </Tooltip>\n );\n}\n\nfunction Fold({ children, folded }: { children: ReactNode; folded: boolean }) {\n return (\n <div\n aria-hidden={folded || undefined}\n className={styles.fold}\n data-folded={folded}\n inert={folded || undefined}\n >\n <div>{children}</div>\n </div>\n );\n}\n\nfunction ConsoleNav({\n collapsed: collapsedProp,\n defaultExpanded = 'all',\n groups = [],\n items = [],\n label = 'Primary',\n onNavigate,\n pathname,\n renderLink,\n storageKey,\n}: ConsoleNavProps) {\n const id = useId();\n const navRef = useRef<HTMLDivElement>(null);\n const shell = useConsoleShellState();\n const collapsed = collapsedProp ?? shell?.collapsed ?? false;\n const reducedMotion = usePrefersReducedMotion();\n const [storedOverrides, setStoredOverrides] = useLocalStorage<unknown>(storageKey, {});\n const overrides = readOverrides(storedOverrides);\n const context: LinkContext = { onNavigate, renderLink };\n\n const activeHref = resolveActiveHref(pathname, [...items, ...collectNavItems(groups)]);\n const activeBranch = findActiveBranch(pathname, groups, activeHref);\n\n // Arriving on a page reopens its branch even if it was closed by hand earlier.\n const [trackedPathname, setTrackedPathname] = useState(pathname);\n if (trackedPathname !== pathname) {\n setTrackedPathname(pathname);\n if (activeBranch.some((key) => overrides[key] === false)) {\n const next = { ...overrides };\n for (const key of activeBranch) delete next[key];\n setStoredOverrides(next);\n }\n }\n\n const isExpanded = (group: ConsoleNavGroup) =>\n overrides[group.key] ??\n (activeBranch.includes(group.key) || (group.defaultExpanded ?? defaultExpanded === 'all'));\n\n const toggleGroup = useCallback(\n (key: string, expanded: boolean) => {\n setStoredOverrides((current: unknown) => ({ ...readOverrides(current), [key]: !expanded }));\n },\n [setStoredOverrides],\n );\n\n useEffect(() => {\n const container = navRef.current;\n if (!container) return;\n scrollActiveIntoView(container);\n if (reducedMotion) return;\n const timer = window.setTimeout(() => scrollActiveIntoView(container), PANEL_TRANSITION_MS);\n return () => window.clearTimeout(timer);\n }, [activeHref, pathname, reducedMotion]);\n\n useEffect(() => {\n const container = navRef.current;\n if (!container) return;\n const timer = window.setTimeout(\n () => scrollActiveIntoView(container, reducedMotion ? 'auto' : 'smooth'),\n reducedMotion ? 0 : RAIL_TRANSITION_MS,\n );\n return () => window.clearTimeout(timer);\n }, [collapsed, reducedMotion]);\n\n // The rail folds rows out of this same tree instead of rendering its own, so icons stay put\n // while the sidebar width animates.\n const renderItems = (\n list: ConsoleNavItem[],\n indent: number,\n groupLabel: string | undefined,\n foldable: boolean,\n ) =>\n list.map((item) => {\n const link = (\n <NavLink\n active={item.href === activeHref}\n collapsed={collapsed}\n context={context}\n href={item.href}\n icon={item.icon}\n indent={item.icon ? Math.max(0, indent - 1) : indent}\n item={item}\n key={item.href}\n name={groupLabel ? `${groupLabel} / ${item.label}` : item.label}\n />\n );\n if (item.icon || !foldable) return link;\n return (\n <Fold folded={collapsed} key={item.href}>\n {link}\n </Fold>\n );\n });\n\n const renderGroup = (\n group: ConsoleNavGroup,\n level: number,\n indent: number,\n underRailIcon: boolean,\n ) => {\n const expanded = isExpanded(group);\n const panelId = `${id}-${group.key}`;\n // Nested groups are headings over their items, so the items keep the same indent.\n const childIndent = indent + (group.icon ? 1 : 0);\n const active = activeBranch.includes(group.key);\n const railIcon = level === 0 && Boolean(group.icon);\n const onRail = collapsed && !underRailIcon;\n const open = onRail ? !railIcon : expanded;\n const railHref = railIcon ? (group.href ?? collectNavItems([group])[0]?.href) : undefined;\n const railEmpty = !railIcon && !collectNavItems([group]).some((item) => item.icon);\n\n const header = (\n <button\n aria-controls={panelId}\n aria-expanded={open}\n aria-hidden={(onRail && railIcon) || undefined}\n className={styles.groupHeader}\n data-active={active}\n data-icon={Boolean(group.icon)}\n data-indent={indent}\n data-level={level}\n tabIndex={onRail && railIcon ? -1 : undefined}\n type=\"button\"\n onClick={() => toggleGroup(group.key, expanded)}\n >\n {group.icon ? <Icon icon={group.icon} size={16} /> : null}\n <span className={styles.itemLabel} data-label=\"\">\n {group.label}\n </span>\n {level === 0 ? (\n <Icon className={styles.chevron} data-expanded={expanded} icon={ChevronDown} size={14} />\n ) : (\n <span className={styles.indicator} data-expanded={expanded}>\n <Play fill={'currentColor'} size={7} strokeWidth={1} />\n </span>\n )}\n </button>\n );\n\n let head: ReactNode = header;\n if (railIcon) {\n head = (\n <div className={styles.groupHead}>\n {header}\n {onRail && railHref ? (\n <NavLink\n collapsed\n overlay\n active={activeBranch[0] === group.key}\n context={context}\n href={railHref}\n name={group.label}\n />\n ) : null}\n </div>\n );\n } else if (!underRailIcon) {\n head = <Fold folded={onRail}>{header}</Fold>;\n }\n\n return (\n <div\n className={styles.group}\n data-icon={Boolean(group.icon)}\n data-level={level}\n data-rail-empty={railEmpty}\n key={group.key}\n >\n {head}\n <div\n aria-hidden={!open}\n className={styles.groupPanel}\n data-expanded={open}\n data-instant={reducedMotion}\n id={panelId}\n inert={open ? undefined : true}\n >\n <div className={styles.groupItems}>\n {renderItems(group.items ?? [], childIndent, group.label, !(underRailIcon || railIcon))}\n {(group.groups ?? []).map((child) =>\n renderGroup(child, level + 1, childIndent, underRailIcon || railIcon),\n )}\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <ScrollShadow\n aria-label={label}\n as={'nav'}\n className={styles.nav}\n data-collapsed={collapsed}\n orientation={'vertical'}\n ref={navRef}\n size={4}\n >\n {items.length > 0 ? (\n <div\n className={styles.topItems}\n data-divided={groups.length > 0}\n data-rail-empty={!items.some((item) => item.icon)}\n >\n {renderItems(items, 0, undefined, true)}\n </div>\n ) : null}\n {groups.map((group) => renderGroup(group, 0, 0, false))}\n </ScrollShadow>\n );\n}\n\nConsoleNav.displayName = 'ConsoleNav';\n\nexport default ConsoleNav;\n"],"mappings":";;;;;;;;;;;;AAeA,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;;AAK3B,SAAS,cAAc,OAAmC;CACxD,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,OAAO,YAAY,MAAM,KAAK,QAAQ,CAAC,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC;CAEpE,OAAO,SAAS,OAAO,UAAU,WAAY,QAA8B,CAAC;AAC9E;AAEA,SAAS,qBAAqB,WAAwB,WAA2B,QAAQ;CACvF,MAAM,OACJ,UAAU,cAA2B,yBAAuB,KAC5D,CAAC,GAAG,UAAU,iBAA8B,8BAA4B,CAAC,CAAC,CAAC,GAAG,EAAE;CAClF,IAAI,CAAC,MAAM;CACX,MAAM,gBAAgB,UAAU,sBAAsB;CACtD,MAAM,WAAW,KAAK,sBAAsB;CAC5C,IAAI,SAAS,OAAO,cAAc,OAAO,SAAS,UAAU,cAAc,QAAQ;CAClF,UAAU,SAAS;EACjB;EACA,KAAK,SAAS,MAAM,cAAc,OAAO,cAAc,SAAS,SAAS,UAAU;CACrF,CAAC;AACH;AAOA,SAAS,aAAa,SAAsB,WAAgC,UAAsB;CAChG,IAAI,QAAQ,YAAY,OAAO,QAAQ,WAAW,SAAS;CAC3D,OACE,oBAAC,KAAD;EACE,gBAAc,UAAU;EACxB,cAAY,UAAU;EACtB,WAAW,UAAU;EACrB,eAAa,UAAU;EACvB,kBAAgB,UAAU;EAC1B,eAAa,UAAU;EACvB,MAAM,UAAU;EAChB,KAAK,UAAU,WAAW,eAAe,KAAA;EACzC,QAAQ,UAAU,WAAW,WAAW,KAAA;EACxC,OAAO,UAAU;EACjB,UAAU,UAAU;GAClB,IAAI,QAAQ,cAAc,CAAC,UAAU,UAAU,MAAM,eAAe;GACpE,SAAS;EACX;EAEC,UAAA,UAAU;CACV,CAAA;AAEP;AAEA,SAAS,QAAQ,EACf,QACA,WACA,SACA,MACA,MACA,SAAS,GACT,MACA,MACA,UAAU,SAWT;CACD,MAAM,QAAQ,qBAAqB;CACnC,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,eAAe;EACnB,QAAQ,aAAa,IAAI;EACzB,OAAO,gBAAgB;CACzB;CAsBA,MAAM,OAAO,aAAa,SAAS;EApBjC,gBAAgB,SAAS,SAAS,KAAA;EAClC,cAAc,YAAY,OAAO,KAAA;EACjC,YAAY,UAAU,OACpB,qBAAA,YAAA,EAAA,UAAA;GACG,OAAO,oBAAC,MAAD;IAAY;IAAM,MAAM;GAAK,CAAA,IAAI;GACzC,oBAAC,QAAD;IAAM,WAAW,OAAO;IAAY,UAAA;GAAY,CAAA;GAC/C,MAAM,QAAQ,oBAAC,QAAD;IAAM,WAAW,OAAO;IAAQ,UAAA,KAAK;GAAY,CAAA,IAAI;GACnE,MAAM,QAAQ,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAW,OAAO;GAAM,CAAA,IAAI;EAC7D,EAAA,CAAA;EAEJ,aAAa,UAAU,OAAO,WAAW,OAAO;EAChD,eAAe;EACf,kBAAkB;EAClB,eAAe;EACf,YAAY,MAAM;EAClB;EACA,WAAW;EACX,SAAS,YAAY,KAAA,IAAY;CAGQ,GAAG,MAAM;CAEpD,IAAI,CAAC,QAAQ,CAAC,SAAS,OAAO;CAE9B,OACE,oBAAC,SAAD;EAAS,UAAU,CAAC;EAAW,WAAU;EAAQ,OAAO;EACrD,UAAA;CACM,CAAA;AAEb;AAEA,SAAS,KAAK,EAAE,UAAU,UAAoD;CAC5E,OACE,oBAAC,OAAD;EACE,eAAa,UAAU,KAAA;EACvB,WAAW,OAAO;EAClB,eAAa;EACb,OAAO,UAAU,KAAA;EAEjB,UAAA,oBAAC,OAAD,EAAM,SAAc,CAAA;CACjB,CAAA;AAET;AAEA,SAAS,WAAW,EAClB,WAAW,eACX,kBAAkB,OAClB,SAAS,CAAC,GACV,QAAQ,CAAC,GACT,QAAQ,WACR,YACA,UACA,YACA,cACkB;CAClB,MAAM,KAAK,MAAM;CACjB,MAAM,SAAS,OAAuB,IAAI;CAC1C,MAAM,QAAQ,qBAAqB;CACnC,MAAM,YAAY,iBAAiB,OAAO,aAAa;CACvD,MAAM,gBAAgB,wBAAwB;CAC9C,MAAM,CAAC,iBAAiB,sBAAsB,gBAAyB,YAAY,CAAC,CAAC;CACrF,MAAM,YAAY,cAAc,eAAe;CAC/C,MAAM,UAAuB;EAAE;EAAY;CAAW;CAEtD,MAAM,aAAa,kBAAkB,UAAU,CAAC,GAAG,OAAO,GAAG,gBAAgB,MAAM,CAAC,CAAC;CACrF,MAAM,eAAe,iBAAiB,UAAU,QAAQ,UAAU;CAGlE,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,QAAQ;CAC/D,IAAI,oBAAoB,UAAU;EAChC,mBAAmB,QAAQ;EAC3B,IAAI,aAAa,MAAM,QAAQ,UAAU,SAAS,KAAK,GAAG;GACxD,MAAM,OAAO,EAAE,GAAG,UAAU;GAC5B,KAAK,MAAM,OAAO,cAAc,OAAO,KAAK;GAC5C,mBAAmB,IAAI;EACzB;CACF;CAEA,MAAM,cAAc,UAClB,UAAU,MAAM,SACf,aAAa,SAAS,MAAM,GAAG,MAAM,MAAM,mBAAmB,oBAAoB;CAErF,MAAM,cAAc,aACjB,KAAa,aAAsB;EAClC,oBAAoB,aAAsB;GAAE,GAAG,cAAc,OAAO;IAAI,MAAM,CAAC;EAAS,EAAE;CAC5F,GACA,CAAC,kBAAkB,CACrB;CAEA,gBAAgB;EACd,MAAM,YAAY,OAAO;EACzB,IAAI,CAAC,WAAW;EAChB,qBAAqB,SAAS;EAC9B,IAAI,eAAe;EACnB,MAAM,QAAQ,OAAO,iBAAiB,qBAAqB,SAAS,GAAG,mBAAmB;EAC1F,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG;EAAC;EAAY;EAAU;CAAa,CAAC;CAExC,gBAAgB;EACd,MAAM,YAAY,OAAO;EACzB,IAAI,CAAC,WAAW;EAChB,MAAM,QAAQ,OAAO,iBACb,qBAAqB,WAAW,gBAAgB,SAAS,QAAQ,GACvE,gBAAgB,IAAI,kBACtB;EACA,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG,CAAC,WAAW,aAAa,CAAC;CAI7B,MAAM,eACJ,MACA,QACA,YACA,aAEA,KAAK,KAAK,SAAS;EACjB,MAAM,OACJ,oBAAC,SAAD;GACE,QAAQ,KAAK,SAAS;GACX;GACF;GACT,MAAM,KAAK;GACX,MAAM,KAAK;GACX,QAAQ,KAAK,OAAO,KAAK,IAAI,GAAG,SAAS,CAAC,IAAI;GACxC;GAEN,MAAM,aAAa,GAAG,WAAW,KAAK,KAAK,UAAU,KAAK;EAC3D,GAFM,KAAK,IAEX;EAEH,IAAI,KAAK,QAAQ,CAAC,UAAU,OAAO;EACnC,OACE,oBAAC,MAAD;GAAM,QAAQ;GACX,UAAA;EACG,GAFwB,KAAK,IAE7B;CAEV,CAAC;CAEH,MAAM,eACJ,OACA,OACA,QACA,kBACG;EACH,MAAM,WAAW,WAAW,KAAK;EACjC,MAAM,UAAU,GAAG,GAAG,GAAG,MAAM;EAE/B,MAAM,cAAc,UAAU,MAAM,OAAO,IAAI;EAC/C,MAAM,SAAS,aAAa,SAAS,MAAM,GAAG;EAC9C,MAAM,WAAW,UAAU,KAAK,QAAQ,MAAM,IAAI;EAClD,MAAM,SAAS,aAAa,CAAC;EAC7B,MAAM,OAAO,SAAS,CAAC,WAAW;EAClC,MAAM,WAAW,WAAY,MAAM,QAAQ,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,OAAQ,KAAA;EAChF,MAAM,YAAY,CAAC,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,SAAS,KAAK,IAAI;EAEjF,MAAM,SACJ,qBAAC,UAAD;GACE,iBAAe;GACf,iBAAe;GACf,eAAc,UAAU,YAAa,KAAA;GACrC,WAAW,OAAO;GAClB,eAAa;GACb,aAAW,QAAQ,MAAM,IAAI;GAC7B,eAAa;GACb,cAAY;GACZ,UAAU,UAAU,WAAW,KAAK,KAAA;GACpC,MAAK;GACL,eAAe,YAAY,MAAM,KAAK,QAAQ;GAXhD,UAAA;IAaG,MAAM,OAAO,oBAAC,MAAD;KAAM,MAAM,MAAM;KAAM,MAAM;IAAK,CAAA,IAAI;IACrD,oBAAC,QAAD;KAAM,WAAW,OAAO;KAAW,cAAW;KAC3C,UAAA,MAAM;IACH,CAAA;IACL,UAAU,IACT,oBAAC,MAAD;KAAM,WAAW,OAAO;KAAS,iBAAe;KAAU,MAAM;KAAa,MAAM;IAAK,CAAA,IAExF,oBAAC,QAAD;KAAM,WAAW,OAAO;KAAW,iBAAe;KAChD,UAAA,oBAAC,MAAD;MAAM,MAAM;MAAgB,MAAM;MAAG,aAAa;KAAI,CAAA;IAClD,CAAA;GAEF;;EAGV,IAAI,OAAkB;EACtB,IAAI,UACF,OACE,qBAAC,OAAD;GAAK,WAAW,OAAO;GAAvB,UAAA,CACG,QACA,UAAU,WACT,oBAAC,SAAD;IACE,WAAA;IACA,SAAA;IACA,QAAQ,aAAa,OAAO,MAAM;IACzB;IACT,MAAM;IACN,MAAM,MAAM;GACb,CAAA,IACC,IACD;;OAEF,IAAI,CAAC,eACV,OAAO,oBAAC,MAAD;GAAM,QAAQ;GAAS,UAAA;EAAa,CAAA;EAG7C,OACE,qBAAC,OAAD;GACE,WAAW,OAAO;GAClB,aAAW,QAAQ,MAAM,IAAI;GAC7B,cAAY;GACZ,mBAAiB;GAJnB,UAAA,CAOG,MACD,oBAAC,OAAD;IACE,eAAa,CAAC;IACd,WAAW,OAAO;IAClB,iBAAe;IACf,gBAAc;IACd,IAAI;IACJ,OAAO,OAAO,KAAA,IAAY;IAE1B,UAAA,qBAAC,OAAD;KAAK,WAAW,OAAO;KAAvB,UAAA,CACG,YAAY,MAAM,SAAS,CAAC,GAAG,aAAa,MAAM,OAAO,EAAE,iBAAiB,SAAS,IACpF,MAAM,UAAU,CAAC,EAAA,CAAG,KAAK,UACzB,YAAY,OAAO,QAAQ,GAAG,aAAa,iBAAiB,QAAQ,CACtE,CACG;;GACF,CAAA,CACF;EAlBE,GAAA,MAAM,GAkBR;CAET;CAEA,OACE,qBAAC,cAAD;EACE,cAAY;EACZ,IAAI;EACJ,WAAW,OAAO;EAClB,kBAAgB;EAChB,aAAa;EACb,KAAK;EACL,MAAM;EAPR,UAAA,CASG,MAAM,SAAS,IACd,oBAAC,OAAD;GACE,WAAW,OAAO;GAClB,gBAAc,OAAO,SAAS;GAC9B,mBAAiB,CAAC,MAAM,MAAM,SAAS,KAAK,IAAI;GAE/C,UAAA,YAAY,OAAO,GAAG,KAAA,GAAW,IAAI;EACnC,CAAA,IACH,MACH,OAAO,KAAK,UAAU,YAAY,OAAO,GAAG,GAAG,KAAK,CAAC,CAC1C;;AAElB;AAEA,WAAW,cAAc"}
|