@lobehub/ui 5.50.2 → 5.50.3

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.
@@ -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;CA6B5D,OAAO;EACL,WA7BgB,GAAG;;;;;;;;;;qBAUF,OAAO,aAAa;;kBAEvB,OAAO,gBAAgB;;;kCAGP,OAAO,cAAc;;;;;;;;;;;;EAenD,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"}
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.scrollTop += linkRect.top - containerRect.top - (containerRect.height - linkRect.height) / 2;
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 linkProps = {
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
- collapsed ? null : /* @__PURE__ */ jsx("span", {
66
+ /* @__PURE__ */ jsx("span", {
43
67
  className: styles.itemLabel,
44
68
  children: label
45
69
  }),
46
- !collapsed && item?.badge ? /* @__PURE__ */ jsx("span", {
70
+ item?.badge ? /* @__PURE__ */ jsx("span", {
47
71
  className: styles.badge,
48
72
  children: item.badge
49
73
  }) : null,
50
- collapsed && item?.badge ? /* @__PURE__ */ jsx("span", {
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
- const link = context.renderLink ? context.renderLink(linkProps) : /* @__PURE__ */ jsx("a", {
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
- const renderItems = (list, indent, groupLabel) => list.map((item) => /* @__PURE__ */ jsx(NavLink, {
132
- active: item.href === activeHref,
133
- collapsed: false,
134
- context,
135
- href: item.href,
136
- icon: item.icon,
137
- indent: item.icon ? Math.max(0, indent - 1) : indent,
138
- item,
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
- const topRail = railItems(items);
152
- const iconGroups = groups.filter((group) => group.icon);
153
- return /* @__PURE__ */ jsxs(ScrollShadow, {
154
- "aria-label": label,
155
- as: "nav",
156
- className: styles.nav,
157
- "data-collapsed": "",
158
- orientation: "vertical",
159
- ref: navRef,
160
- size: 8,
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
- topRail.length > 0 ? /* @__PURE__ */ jsx("div", {
163
- className: styles.railTop,
164
- children: topRail
193
+ group.icon ? /* @__PURE__ */ jsx(Icon, {
194
+ icon: group.icon,
195
+ size: 16
165
196
  }) : null,
166
- iconGroups.length > 0 ? /* @__PURE__ */ jsx("div", {
167
- className: styles.railGroup,
168
- "data-first": topRail.length === 0,
169
- role: "group",
170
- children: iconGroups.map((group) => {
171
- const href = group.href ?? collectNavItems([group])[0]?.href;
172
- if (!href) return null;
173
- return /* @__PURE__ */ jsx(NavLink, {
174
- collapsed: true,
175
- active: activeBranch[0] === group.key,
176
- context,
177
- href,
178
- icon: group.icon,
179
- name: group.label
180
- }, group.key);
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
- const renderGroup = (group, level, indent) => {
200
- const expanded = isExpanded(group);
201
- const panelId = `${id}-${group.key}`;
202
- const childIndent = indent + (group.icon ? 1 : 0);
203
- const active = activeBranch.includes(group.key);
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
- children: [/* @__PURE__ */ jsxs("button", {
209
- "aria-controls": panelId,
210
- "aria-expanded": expanded,
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": expanded,
242
+ "data-expanded": open,
247
243
  "data-instant": reducedMotion,
248
244
  id: panelId,
249
- inert: expanded ? void 0 : true,
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
- children: renderItems(items, 0)
268
- }) : null, groups.map((group) => renderGroup(group, 0, 0))]
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":"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"}
@@ -1,282 +1,405 @@
1
1
  import { createStaticStyles } from "antd-style";
2
2
  //#region src/dashboard/ConsoleNav/style.ts
3
- const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
4
- badge: css`
5
- flex: none;
6
-
7
- min-inline-size: 20px;
8
- padding-inline: 6px;
9
- border-radius: 999px;
10
-
11
- font-size: ${cssVar.fontSizeSM};
12
- font-variant-numeric: tabular-nums;
13
- color: ${cssVar.colorError};
14
- text-align: center;
15
-
16
- background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);
17
- `,
18
- chevron: css`
19
- flex: none;
20
- transition: transform 160ms ease;
21
-
22
- &[data-expanded='false'] {
23
- transform: rotate(-90deg);
3
+ const styles = createStaticStyles(({ css, cssVar, responsive }) => {
4
+ const railFade = `
5
+ transition: opacity 120ms ease 80ms;
6
+
7
+ [data-collapsed='true'] & {
8
+ opacity: 0;
9
+ transition-delay: 0s;
24
10
  }
25
- `,
26
- indicator: css`
27
- display: flex;
28
- flex: none;
29
- align-items: center;
30
- justify-content: center;
31
11
 
32
- width: 18px;
33
- height: 18px;
34
- margin-inline-start: -6px;
12
+ @media (prefers-reduced-motion: reduce) {
13
+ transition: none;
14
+ }
15
+ `;
16
+ return {
17
+ badge: css`
18
+ flex: none;
35
19
 
36
- color: ${cssVar.colorTextDescription};
20
+ min-inline-size: 20px;
21
+ padding-inline: 6px;
22
+ border-radius: 999px;
37
23
 
38
- transition: transform 160ms ease;
24
+ font-size: ${cssVar.fontSizeSM};
25
+ font-variant-numeric: tabular-nums;
26
+ color: ${cssVar.colorError};
27
+ text-align: center;
39
28
 
40
- &[data-expanded='true'] {
41
- transform: rotate(90deg);
42
- }
43
- `,
44
- dot: css`
45
- position: absolute;
46
- inset-block-start: 7px;
47
- inset-inline-end: 9px;
48
-
49
- inline-size: 7px;
50
- block-size: 7px;
51
- border-radius: 999px;
52
-
53
- background: ${cssVar.colorError};
54
- `,
55
- group: css`
56
- display: flex;
57
- flex-direction: column;
58
- margin-block-start: 12px;
59
-
60
- &[data-level='0'][data-icon='true'] {
61
- margin-block-start: 2px;
62
- }
29
+ background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);
63
30
 
64
- &:not([data-level='0']) {
65
- margin-block-start: 6px;
66
- }
67
- `,
68
- groupHeader: css`
69
- cursor: pointer;
70
-
71
- display: flex;
72
- gap: 8px;
73
- align-items: center;
74
- justify-content: space-between;
75
-
76
- min-block-size: 32px;
77
- padding-inline: 10px;
78
- border: none;
79
- border-radius: ${cssVar.borderRadius};
80
-
81
- font-size: ${cssVar.fontSizeSM};
82
- font-weight: 500;
83
- color: ${cssVar.colorTextSecondary};
84
- text-align: start;
85
-
86
- background: none;
87
-
88
- &:hover,
89
- &[data-active='true'] {
90
- color: ${cssVar.colorText};
91
- }
31
+ ${railFade}
32
+ `,
33
+ chevron: css`
34
+ flex: none;
35
+ transition:
36
+ transform 160ms ease,
37
+ opacity 120ms ease 80ms;
92
38
 
93
- &[data-icon='true'] {
94
- gap: 12px;
95
- justify-content: flex-start;
96
- min-block-size: 36px;
97
- font-size: ${cssVar.fontSize};
98
- }
39
+ &[data-expanded='false'] {
40
+ transform: rotate(-90deg);
41
+ }
99
42
 
100
- &[data-level='0'][data-icon='true']:hover {
101
- background: ${cssVar.colorFillTertiary};
102
- }
43
+ [data-collapsed='true'] & {
44
+ opacity: 0;
45
+ transition-delay: 0s;
46
+ }
103
47
 
104
- /* Nested groups read as quiet subheadings with the indicator right after the label. */
105
- &:not([data-level='0']) {
106
- gap: 8px;
107
- justify-content: flex-start;
48
+ @media (prefers-reduced-motion: reduce) {
49
+ transition: none;
50
+ }
51
+ `,
52
+ indicator: css`
53
+ display: flex;
54
+ flex: none;
55
+ align-items: center;
56
+ justify-content: center;
108
57
 
109
- min-block-size: 26px;
58
+ width: 18px;
59
+ height: 18px;
60
+ margin-inline-start: -6px;
110
61
 
111
- font-size: ${cssVar.fontSizeSM};
112
- font-weight: 400;
113
62
  color: ${cssVar.colorTextDescription};
114
63
 
115
- > [data-label] {
116
- flex: 0 1 auto;
64
+ transition: transform 160ms ease;
65
+
66
+ &[data-expanded='true'] {
67
+ transform: rotate(90deg);
117
68
  }
69
+ `,
70
+ dot: css`
71
+ position: absolute;
72
+ inset-block-start: 7px;
73
+ inset-inline-end: 9px;
118
74
 
119
- &:hover,
120
- &[data-active='true'] {
121
- color: ${cssVar.colorTextSecondary};
75
+ inline-size: 7px;
76
+ block-size: 7px;
77
+ border-radius: 999px;
78
+
79
+ opacity: 0;
80
+ background: ${cssVar.colorError};
81
+
82
+ transition: opacity 120ms ease;
83
+
84
+ [data-collapsed='true'] & {
85
+ opacity: 1;
122
86
  }
123
- }
124
87
 
125
- &[data-indent='1'] {
126
- padding-inline-start: 38px;
127
- }
88
+ @media (prefers-reduced-motion: reduce) {
89
+ transition: none;
90
+ }
91
+ `,
92
+ fold: css`
93
+ display: grid;
94
+ grid-template-rows: 1fr;
95
+ transition:
96
+ grid-template-rows 200ms ease,
97
+ margin 200ms ease,
98
+ opacity 120ms ease;
99
+
100
+ > div {
101
+ overflow: hidden;
102
+ min-block-size: 0;
103
+ }
128
104
 
129
- &[data-indent='2'] {
130
- padding-inline-start: 56px;
131
- }
105
+ &[data-folded='true'] {
106
+ grid-template-rows: 0fr;
107
+ opacity: 0;
108
+ }
109
+
110
+ &[data-folded='true']:not(:first-child) {
111
+ margin-block-start: -2px;
112
+ }
113
+
114
+ @media (prefers-reduced-motion: reduce) {
115
+ transition: none;
116
+ }
117
+ `,
118
+ group: css`
119
+ position: relative;
132
120
 
133
- > [role='img'] {
134
121
  display: flex;
135
- flex: none;
136
- }
137
- `,
138
- groupItems: css`
139
- display: flex;
140
- flex-direction: column;
141
- gap: 2px;
142
- min-block-size: 0;
143
- `,
144
- groupPanel: css`
145
- display: grid;
146
- grid-template-rows: 1fr;
147
- transition: grid-template-rows 160ms ease;
148
-
149
- > div {
150
- overflow: hidden;
151
- }
122
+ flex-direction: column;
152
123
 
153
- &[data-expanded='false'] {
154
- grid-template-rows: 0fr;
155
- }
124
+ margin-block-start: 12px;
156
125
 
157
- &[data-instant='true'] {
158
- transition: none;
159
- }
160
- `,
161
- item: css`
162
- position: relative;
126
+ transition: margin 200ms ease;
163
127
 
164
- display: flex;
165
- gap: 10px;
166
- align-items: center;
128
+ &::before {
129
+ content: '';
167
130
 
168
- min-block-size: 36px;
169
- padding-inline: 10px;
170
- border-radius: ${cssVar.borderRadius};
131
+ position: absolute;
132
+ inset-block-start: -6px;
133
+ inset-inline: 0;
171
134
 
172
- color: ${cssVar.colorTextSecondary};
173
- text-decoration: none;
135
+ block-size: 1px;
174
136
 
175
- transition:
176
- background 120ms ease,
177
- color 120ms ease;
137
+ opacity: 0;
138
+ background: ${cssVar.colorBorderSecondary};
178
139
 
179
- &:hover {
180
- color: ${cssVar.colorText};
181
- background: ${cssVar.colorFillTertiary};
182
- }
140
+ transition: opacity 200ms ease;
141
+ }
183
142
 
184
- &[data-active='true'] {
185
- font-weight: 500;
186
- color: ${cssVar.colorText};
187
- background: ${cssVar.colorFillSecondary};
188
- }
143
+ &[data-level='0'][data-icon='true'] {
144
+ margin-block-start: 2px;
145
+ }
146
+
147
+ &:not([data-level='0']) {
148
+ margin-block-start: 6px;
149
+ }
150
+
151
+ [data-collapsed='true'] & + &[data-level='0'][data-icon='false']::before {
152
+ opacity: 1;
153
+ }
154
+
155
+ [data-collapsed='true'] &[data-rail-empty='true'] {
156
+ margin-block-start: 0;
157
+
158
+ &::before {
159
+ opacity: 0;
160
+ }
161
+ }
162
+
163
+ @media (prefers-reduced-motion: reduce) {
164
+ transition: none;
165
+
166
+ &::before {
167
+ transition: none;
168
+ }
169
+ }
170
+ `,
171
+ groupHead: css`
172
+ position: relative;
173
+ display: flex;
174
+ flex-direction: column;
175
+ `,
176
+ groupHeader: css`
177
+ cursor: pointer;
178
+
179
+ display: flex;
180
+ gap: 8px;
181
+ align-items: center;
182
+ justify-content: space-between;
189
183
 
190
- &[data-indent='1'],
191
- &[data-indent='2'] {
192
184
  min-block-size: 32px;
193
- color: ${cssVar.colorText};
194
- }
185
+ padding-inline: 10px;
186
+ border: none;
187
+ border-radius: ${cssVar.borderRadius};
195
188
 
196
- &[data-indent='1'] {
197
- padding-inline-start: 38px;
198
- }
189
+ font-size: ${cssVar.fontSizeSM};
190
+ font-weight: 500;
191
+ color: ${cssVar.colorTextSecondary};
192
+ text-align: start;
193
+ white-space: nowrap;
199
194
 
200
- &[data-indent='2'] {
201
- padding-inline-start: 56px;
202
- }
195
+ background: none;
203
196
 
204
- > [role='img'] {
197
+ &:hover,
198
+ &[data-active='true'] {
199
+ color: ${cssVar.colorText};
200
+ }
201
+
202
+ &[data-icon='true'] {
203
+ gap: 10px;
204
+ justify-content: flex-start;
205
+ min-block-size: 36px;
206
+ font-size: ${cssVar.fontSize};
207
+
208
+ > [role='img'] {
209
+ justify-content: center;
210
+ inline-size: 18px;
211
+ }
212
+ }
213
+
214
+ &[data-level='0'][data-icon='true']:hover {
215
+ background: ${cssVar.colorFillTertiary};
216
+ }
217
+
218
+ /* Nested groups read as quiet subheadings with the indicator right after the label. */
219
+ &:not([data-level='0']) {
220
+ gap: 8px;
221
+ justify-content: flex-start;
222
+
223
+ min-block-size: 26px;
224
+
225
+ font-size: ${cssVar.fontSizeSM};
226
+ font-weight: 400;
227
+ color: ${cssVar.colorTextDescription};
228
+
229
+ > [data-label] {
230
+ flex: 0 1 auto;
231
+ }
232
+
233
+ &:hover,
234
+ &[data-active='true'] {
235
+ color: ${cssVar.colorTextSecondary};
236
+ }
237
+ }
238
+
239
+ &[data-indent='1'] {
240
+ padding-inline-start: 38px;
241
+ }
242
+
243
+ &[data-indent='2'] {
244
+ padding-inline-start: 56px;
245
+ }
246
+
247
+ > [role='img'] {
248
+ display: flex;
249
+ flex: none;
250
+ }
251
+ `,
252
+ groupItems: css`
205
253
  display: flex;
206
- flex: none;
207
- }
254
+ flex-direction: column;
255
+ gap: 2px;
256
+ min-block-size: 0;
257
+ `,
258
+ groupPanel: css`
259
+ display: grid;
260
+ grid-template-rows: 1fr;
261
+ transition: grid-template-rows 160ms ease;
262
+
263
+ > div {
264
+ overflow: hidden;
265
+ }
208
266
 
209
- &[data-collapsed='true'] {
210
- justify-content: center;
211
- min-block-size: 40px;
212
- padding-inline: 0;
213
- }
267
+ &[data-expanded='false'] {
268
+ grid-template-rows: 0fr;
269
+ }
214
270
 
215
- ${responsive.mobile} {
216
- min-block-size: 44px;
217
- }
218
- `,
219
- itemLabel: css`
220
- overflow: hidden;
221
- flex: 1;
222
- text-overflow: ellipsis;
223
- white-space: nowrap;
224
- `,
225
- nav: css`
226
- scrollbar-width: thin;
227
-
228
- display: flex;
229
- flex: 1;
230
- flex-direction: column;
231
- gap: 2px;
232
-
233
- min-block-size: 0;
234
- padding-block-end: 12px;
235
- padding-inline: 8px;
236
- `,
237
- railGroup: css`
238
- display: flex;
239
- flex-direction: column;
240
- gap: 2px;
241
-
242
- margin-block-start: 6px;
243
- padding-block-start: 6px;
244
- border-block-start: 1px solid ${cssVar.colorBorderSecondary};
245
-
246
- &[data-first='true'] {
247
- margin-block-start: 0;
248
- border-block-start: none;
249
- }
250
- `,
251
- railTop: css`
252
- display: flex;
253
- flex-direction: column;
254
- gap: 2px;
255
- `,
256
- topItems: css`
257
- display: flex;
258
- flex-direction: column;
259
- gap: 2px;
260
-
261
- &[data-divided='true'] {
262
- margin-block-end: 6px;
263
- padding-block-end: 8px;
264
- border-block-end: 1px solid ${cssVar.colorBorderSecondary};
265
- }
266
- `,
267
- srOnly: css`
268
- position: absolute;
271
+ &[data-instant='true'] {
272
+ transition: none;
273
+ }
274
+ `,
275
+ item: css`
276
+ position: relative;
269
277
 
270
- overflow: hidden;
278
+ display: flex;
279
+ gap: 10px;
280
+ align-items: center;
281
+
282
+ min-block-size: 36px;
283
+ padding-inline: 10px;
284
+ border-radius: ${cssVar.borderRadius};
271
285
 
272
- inline-size: 1px;
273
- block-size: 1px;
286
+ color: ${cssVar.colorTextSecondary};
287
+ text-decoration: none;
288
+ white-space: nowrap;
274
289
 
275
- white-space: nowrap;
290
+ transition:
291
+ background 120ms ease,
292
+ color 120ms ease;
276
293
 
277
- clip-path: inset(50%);
278
- `
279
- }));
294
+ &:hover {
295
+ color: ${cssVar.colorText};
296
+ background: ${cssVar.colorFillTertiary};
297
+ }
298
+
299
+ &[data-active='true'] {
300
+ font-weight: 500;
301
+ color: ${cssVar.colorText};
302
+ background: ${cssVar.colorFillSecondary};
303
+ }
304
+
305
+ &[data-indent='1'],
306
+ &[data-indent='2'] {
307
+ min-block-size: 32px;
308
+ color: ${cssVar.colorText};
309
+ }
310
+
311
+ &[data-indent='1'] {
312
+ padding-inline-start: 38px;
313
+ }
314
+
315
+ &[data-indent='2'] {
316
+ padding-inline-start: 56px;
317
+ }
318
+
319
+ [data-collapsed='true'] &:not([data-indent='0']) {
320
+ padding-inline-start: 10px;
321
+ }
322
+
323
+ > [role='img'] {
324
+ display: flex;
325
+ flex: none;
326
+ }
327
+
328
+ ${responsive.mobile} {
329
+ min-block-size: 44px;
330
+ }
331
+ `,
332
+ itemLabel: css`
333
+ overflow: hidden;
334
+ flex: 1;
335
+ text-overflow: ellipsis;
336
+ white-space: nowrap;
337
+
338
+ [data-collapsed='true'] & {
339
+ text-overflow: clip;
340
+ }
341
+
342
+ ${railFade}
343
+ `,
344
+ nav: css`
345
+ /* Scroll anchoring would jump the list in one frame while rail rows fold and unfold. */
346
+ overflow-anchor: none;
347
+ scrollbar-width: thin;
348
+
349
+ display: flex;
350
+ flex: 1;
351
+ flex-direction: column;
352
+ gap: 2px;
353
+
354
+ min-block-size: 0;
355
+ padding-block-end: 12px;
356
+ padding-inline: 8px;
357
+ `,
358
+ railLink: css`
359
+ position: absolute;
360
+ inset: 0;
361
+ border-radius: ${cssVar.borderRadius};
362
+ transition: background 120ms ease;
363
+
364
+ &:hover {
365
+ background: ${cssVar.colorFillTertiary};
366
+ }
367
+
368
+ &[data-active='true'] {
369
+ background: ${cssVar.colorFillSecondary};
370
+ }
371
+
372
+ @starting-style {
373
+ background: transparent;
374
+ }
375
+ `,
376
+ topItems: css`
377
+ display: flex;
378
+ flex-direction: column;
379
+ gap: 2px;
380
+ transition:
381
+ margin 200ms ease,
382
+ padding 200ms ease,
383
+ border-color 200ms ease;
384
+
385
+ &[data-divided='true'] {
386
+ margin-block-end: 6px;
387
+ padding-block-end: 8px;
388
+ border-block-end: 1px solid ${cssVar.colorBorderSecondary};
389
+ }
390
+
391
+ [data-collapsed='true'] &[data-rail-empty='true'] {
392
+ margin-block-end: 0;
393
+ padding-block-end: 0;
394
+ border-block-end-color: transparent;
395
+ }
396
+
397
+ @media (prefers-reduced-motion: reduce) {
398
+ transition: none;
399
+ }
400
+ `
401
+ };
402
+ });
280
403
  //#endregion
281
404
  export { styles };
282
405
 
@@ -1 +1 @@
1
- {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n badge: css`\n flex: none;\n\n min-inline-size: 20px;\n padding-inline: 6px;\n border-radius: 999px;\n\n font-size: ${cssVar.fontSizeSM};\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorError};\n text-align: center;\n\n background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);\n `,\n chevron: css`\n flex: none;\n transition: transform 160ms ease;\n\n &[data-expanded='false'] {\n transform: rotate(-90deg);\n }\n `,\n indicator: css`\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n\n width: 18px;\n height: 18px;\n margin-inline-start: -6px;\n\n color: ${cssVar.colorTextDescription};\n\n transition: transform 160ms ease;\n\n &[data-expanded='true'] {\n transform: rotate(90deg);\n }\n `,\n dot: css`\n position: absolute;\n inset-block-start: 7px;\n inset-inline-end: 9px;\n\n inline-size: 7px;\n block-size: 7px;\n border-radius: 999px;\n\n background: ${cssVar.colorError};\n `,\n group: css`\n display: flex;\n flex-direction: column;\n margin-block-start: 12px;\n\n &[data-level='0'][data-icon='true'] {\n margin-block-start: 2px;\n }\n\n &:not([data-level='0']) {\n margin-block-start: 6px;\n }\n `,\n groupHeader: css`\n cursor: pointer;\n\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n min-block-size: 32px;\n padding-inline: 10px;\n border: none;\n border-radius: ${cssVar.borderRadius};\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 500;\n color: ${cssVar.colorTextSecondary};\n text-align: start;\n\n background: none;\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorText};\n }\n\n &[data-icon='true'] {\n gap: 12px;\n justify-content: flex-start;\n min-block-size: 36px;\n font-size: ${cssVar.fontSize};\n }\n\n &[data-level='0'][data-icon='true']:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n /* Nested groups read as quiet subheadings with the indicator right after the label. */\n &:not([data-level='0']) {\n gap: 8px;\n justify-content: flex-start;\n\n min-block-size: 26px;\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 400;\n color: ${cssVar.colorTextDescription};\n\n > [data-label] {\n flex: 0 1 auto;\n }\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorTextSecondary};\n }\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n `,\n groupItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-block-size: 0;\n `,\n groupPanel: css`\n display: grid;\n grid-template-rows: 1fr;\n transition: grid-template-rows 160ms ease;\n\n > div {\n overflow: hidden;\n }\n\n &[data-expanded='false'] {\n grid-template-rows: 0fr;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n `,\n item: css`\n position: relative;\n\n display: flex;\n gap: 10px;\n align-items: center;\n\n min-block-size: 36px;\n padding-inline: 10px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorTextSecondary};\n text-decoration: none;\n\n transition:\n background 120ms ease,\n color 120ms ease;\n\n &:hover {\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-active='true'] {\n font-weight: 500;\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-indent='1'],\n &[data-indent='2'] {\n min-block-size: 32px;\n color: ${cssVar.colorText};\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n\n &[data-collapsed='true'] {\n justify-content: center;\n min-block-size: 40px;\n padding-inline: 0;\n }\n\n ${responsive.mobile} {\n min-block-size: 44px;\n }\n `,\n itemLabel: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n nav: css`\n scrollbar-width: thin;\n\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 2px;\n\n min-block-size: 0;\n padding-block-end: 12px;\n padding-inline: 8px;\n `,\n railGroup: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n\n margin-block-start: 6px;\n padding-block-start: 6px;\n border-block-start: 1px solid ${cssVar.colorBorderSecondary};\n\n &[data-first='true'] {\n margin-block-start: 0;\n border-block-start: none;\n }\n `,\n railTop: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n `,\n topItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n\n &[data-divided='true'] {\n margin-block-end: 6px;\n padding-block-end: 8px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n }\n `,\n srOnly: css`\n position: absolute;\n\n overflow: hidden;\n\n inline-size: 1px;\n block-size: 1px;\n\n white-space: nowrap;\n\n clip-path: inset(50%);\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;;iBAOK,OAAO,WAAW;;aAEtB,OAAO,WAAW;;;qCAGM,OAAO,WAAW;;CAErD,SAAS,GAAG;;;;;;;;CAQZ,WAAW,GAAG;;;;;;;;;;aAUH,OAAO,qBAAqB;;;;;;;;CAQvC,KAAK,GAAG;;;;;;;;;kBASQ,OAAO,WAAW;;CAElC,OAAO,GAAG;;;;;;;;;;;;;CAaV,aAAa,GAAG;;;;;;;;;;;qBAWG,OAAO,aAAa;;iBAExB,OAAO,WAAW;;aAEtB,OAAO,mBAAmB;;;;;;;eAOxB,OAAO,UAAU;;;;;;;mBAOb,OAAO,SAAS;;;;oBAIf,OAAO,kBAAkB;;;;;;;;;;mBAU1B,OAAO,WAAW;;eAEtB,OAAO,qBAAqB;;;;;;;;iBAQ1B,OAAO,mBAAmB;;;;;;;;;;;;;;;;;CAiBzC,YAAY,GAAG;;;;;;CAMf,YAAY,GAAG;;;;;;;;;;;;;;;;;CAiBf,MAAM,GAAG;;;;;;;;;qBASU,OAAO,aAAa;;aAE5B,OAAO,mBAAmB;;;;;;;;eAQxB,OAAO,UAAU;oBACZ,OAAO,kBAAkB;;;;;eAK9B,OAAO,UAAU;oBACZ,OAAO,mBAAmB;;;;;;eAM/B,OAAO,UAAU;;;;;;;;;;;;;;;;;;;;;;MAsB1B,WAAW,OAAO;;;;CAItB,WAAW,GAAG;;;;;;CAMd,KAAK,GAAG;;;;;;;;;;;;CAYR,WAAW,GAAG;;;;;;;oCAOoB,OAAO,qBAAqB;;;;;;;CAO9D,SAAS,GAAG;;;;;CAKZ,UAAU,GAAG;;;;;;;;oCAQqB,OAAO,qBAAqB;;;CAG9D,QAAQ,GAAG;;;;;;;;;;;;AAYb,EAAE"}
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => {\n // Fades out at once on collapse, but waits on expand until the width has room for the text.\n const railFade = `\n transition: opacity 120ms ease 80ms;\n\n [data-collapsed='true'] & {\n opacity: 0;\n transition-delay: 0s;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `;\n\n return {\n badge: css`\n flex: none;\n\n min-inline-size: 20px;\n padding-inline: 6px;\n border-radius: 999px;\n\n font-size: ${cssVar.fontSizeSM};\n font-variant-numeric: tabular-nums;\n color: ${cssVar.colorError};\n text-align: center;\n\n background: color-mix(in srgb, ${cssVar.colorError} 12%, transparent);\n\n ${railFade}\n `,\n chevron: css`\n flex: none;\n transition:\n transform 160ms ease,\n opacity 120ms ease 80ms;\n\n &[data-expanded='false'] {\n transform: rotate(-90deg);\n }\n\n [data-collapsed='true'] & {\n opacity: 0;\n transition-delay: 0s;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n indicator: css`\n display: flex;\n flex: none;\n align-items: center;\n justify-content: center;\n\n width: 18px;\n height: 18px;\n margin-inline-start: -6px;\n\n color: ${cssVar.colorTextDescription};\n\n transition: transform 160ms ease;\n\n &[data-expanded='true'] {\n transform: rotate(90deg);\n }\n `,\n dot: css`\n position: absolute;\n inset-block-start: 7px;\n inset-inline-end: 9px;\n\n inline-size: 7px;\n block-size: 7px;\n border-radius: 999px;\n\n opacity: 0;\n background: ${cssVar.colorError};\n\n transition: opacity 120ms ease;\n\n [data-collapsed='true'] & {\n opacity: 1;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n fold: css`\n display: grid;\n grid-template-rows: 1fr;\n transition:\n grid-template-rows 200ms ease,\n margin 200ms ease,\n opacity 120ms ease;\n\n > div {\n overflow: hidden;\n min-block-size: 0;\n }\n\n &[data-folded='true'] {\n grid-template-rows: 0fr;\n opacity: 0;\n }\n\n &[data-folded='true']:not(:first-child) {\n margin-block-start: -2px;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n group: css`\n position: relative;\n\n display: flex;\n flex-direction: column;\n\n margin-block-start: 12px;\n\n transition: margin 200ms ease;\n\n &::before {\n content: '';\n\n position: absolute;\n inset-block-start: -6px;\n inset-inline: 0;\n\n block-size: 1px;\n\n opacity: 0;\n background: ${cssVar.colorBorderSecondary};\n\n transition: opacity 200ms ease;\n }\n\n &[data-level='0'][data-icon='true'] {\n margin-block-start: 2px;\n }\n\n &:not([data-level='0']) {\n margin-block-start: 6px;\n }\n\n [data-collapsed='true'] & + &[data-level='0'][data-icon='false']::before {\n opacity: 1;\n }\n\n [data-collapsed='true'] &[data-rail-empty='true'] {\n margin-block-start: 0;\n\n &::before {\n opacity: 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n\n &::before {\n transition: none;\n }\n }\n `,\n groupHead: css`\n position: relative;\n display: flex;\n flex-direction: column;\n `,\n groupHeader: css`\n cursor: pointer;\n\n display: flex;\n gap: 8px;\n align-items: center;\n justify-content: space-between;\n\n min-block-size: 32px;\n padding-inline: 10px;\n border: none;\n border-radius: ${cssVar.borderRadius};\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 500;\n color: ${cssVar.colorTextSecondary};\n text-align: start;\n white-space: nowrap;\n\n background: none;\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorText};\n }\n\n &[data-icon='true'] {\n gap: 10px;\n justify-content: flex-start;\n min-block-size: 36px;\n font-size: ${cssVar.fontSize};\n\n > [role='img'] {\n justify-content: center;\n inline-size: 18px;\n }\n }\n\n &[data-level='0'][data-icon='true']:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n /* Nested groups read as quiet subheadings with the indicator right after the label. */\n &:not([data-level='0']) {\n gap: 8px;\n justify-content: flex-start;\n\n min-block-size: 26px;\n\n font-size: ${cssVar.fontSizeSM};\n font-weight: 400;\n color: ${cssVar.colorTextDescription};\n\n > [data-label] {\n flex: 0 1 auto;\n }\n\n &:hover,\n &[data-active='true'] {\n color: ${cssVar.colorTextSecondary};\n }\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n `,\n groupItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-block-size: 0;\n `,\n groupPanel: css`\n display: grid;\n grid-template-rows: 1fr;\n transition: grid-template-rows 160ms ease;\n\n > div {\n overflow: hidden;\n }\n\n &[data-expanded='false'] {\n grid-template-rows: 0fr;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n `,\n item: css`\n position: relative;\n\n display: flex;\n gap: 10px;\n align-items: center;\n\n min-block-size: 36px;\n padding-inline: 10px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorTextSecondary};\n text-decoration: none;\n white-space: nowrap;\n\n transition:\n background 120ms ease,\n color 120ms ease;\n\n &:hover {\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-active='true'] {\n font-weight: 500;\n color: ${cssVar.colorText};\n background: ${cssVar.colorFillSecondary};\n }\n\n &[data-indent='1'],\n &[data-indent='2'] {\n min-block-size: 32px;\n color: ${cssVar.colorText};\n }\n\n &[data-indent='1'] {\n padding-inline-start: 38px;\n }\n\n &[data-indent='2'] {\n padding-inline-start: 56px;\n }\n\n [data-collapsed='true'] &:not([data-indent='0']) {\n padding-inline-start: 10px;\n }\n\n > [role='img'] {\n display: flex;\n flex: none;\n }\n\n ${responsive.mobile} {\n min-block-size: 44px;\n }\n `,\n itemLabel: css`\n overflow: hidden;\n flex: 1;\n text-overflow: ellipsis;\n white-space: nowrap;\n\n [data-collapsed='true'] & {\n text-overflow: clip;\n }\n\n ${railFade}\n `,\n nav: css`\n /* Scroll anchoring would jump the list in one frame while rail rows fold and unfold. */\n overflow-anchor: none;\n scrollbar-width: thin;\n\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 2px;\n\n min-block-size: 0;\n padding-block-end: 12px;\n padding-inline: 8px;\n `,\n railLink: css`\n position: absolute;\n inset: 0;\n border-radius: ${cssVar.borderRadius};\n transition: background 120ms ease;\n\n &:hover {\n background: ${cssVar.colorFillTertiary};\n }\n\n &[data-active='true'] {\n background: ${cssVar.colorFillSecondary};\n }\n\n @starting-style {\n background: transparent;\n }\n `,\n topItems: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n transition:\n margin 200ms ease,\n padding 200ms ease,\n border-color 200ms ease;\n\n &[data-divided='true'] {\n margin-block-end: 6px;\n padding-block-end: 8px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n }\n\n [data-collapsed='true'] &[data-rail-empty='true'] {\n margin-block-end: 0;\n padding-block-end: 0;\n border-block-end-color: transparent;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n };\n});\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,iBAAiB;CAExE,MAAM,WAAW;;;;;;;;;;;;CAajB,OAAO;EACL,OAAO,GAAG;;;;;;;mBAOK,OAAO,WAAW;;eAEtB,OAAO,WAAW;;;uCAGM,OAAO,WAAW;;QAEjD,SAAS;;EAEb,SAAS,GAAG;;;;;;;;;;;;;;;;;;;EAmBZ,WAAW,GAAG;;;;;;;;;;eAUH,OAAO,qBAAqB;;;;;;;;EAQvC,KAAK,GAAG;;;;;;;;;;oBAUQ,OAAO,WAAW;;;;;;;;;;;;EAYlC,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BT,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;sBAoBQ,OAAO,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC9C,WAAW,GAAG;;;;;EAKd,aAAa,GAAG;;;;;;;;;;;uBAWG,OAAO,aAAa;;mBAExB,OAAO,WAAW;;eAEtB,OAAO,mBAAmB;;;;;;;;iBAQxB,OAAO,UAAU;;;;;;;qBAOb,OAAO,SAAS;;;;;;;;;sBASf,OAAO,kBAAkB;;;;;;;;;;qBAU1B,OAAO,WAAW;;iBAEtB,OAAO,qBAAqB;;;;;;;;mBAQ1B,OAAO,mBAAmB;;;;;;;;;;;;;;;;;EAiBzC,YAAY,GAAG;;;;;;EAMf,YAAY,GAAG;;;;;;;;;;;;;;;;;EAiBf,MAAM,GAAG;;;;;;;;;uBASU,OAAO,aAAa;;eAE5B,OAAO,mBAAmB;;;;;;;;;iBASxB,OAAO,UAAU;sBACZ,OAAO,kBAAkB;;;;;iBAK9B,OAAO,UAAU;sBACZ,OAAO,mBAAmB;;;;;;iBAM/B,OAAO,UAAU;;;;;;;;;;;;;;;;;;;;QAoB1B,WAAW,OAAO;;;;EAItB,WAAW,GAAG;;;;;;;;;;QAUV,SAAS;;EAEb,KAAK,GAAG;;;;;;;;;;;;;;EAcR,UAAU,GAAG;;;uBAGM,OAAO,aAAa;;;;sBAIrB,OAAO,kBAAkB;;;;sBAIzB,OAAO,mBAAmB;;;;;;;EAO5C,UAAU,GAAG;;;;;;;;;;;;sCAYqB,OAAO,qBAAqB;;;;;;;;;;;;;CAahE;AACF,CAAC"}
@@ -5,15 +5,13 @@ import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region src/dashboard/ConsoleShell/ConsoleBrand.tsx
6
6
  function ConsoleBrand({ href = "/", label, logo, renderLink, title }) {
7
7
  const shell = useConsoleShellState();
8
- const collapsed = shell?.collapsed ?? false;
9
- const lockup = title == null || title === false || title === "" ? logo : /* @__PURE__ */ jsxs("span", {
8
+ const content = title == null || title === false || title === "" ? logo : /* @__PURE__ */ jsxs("span", {
10
9
  className: styles.brandLockup,
11
10
  children: [logo, /* @__PURE__ */ jsx("span", {
12
11
  className: styles.brandName,
13
12
  children: title
14
13
  })]
15
14
  });
16
- const content = collapsed ? logo : lockup;
17
15
  const linkProps = {
18
16
  "aria-label": label ?? (typeof title === "string" ? title : "Home"),
19
17
  "children": content,
@@ -1 +1 @@
1
- {"version":3,"file":"ConsoleBrand.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/ConsoleBrand.tsx"],"sourcesContent":["'use client';\n\nimport { useConsoleShellState } from './context';\nimport { styles } from './style';\nimport type { ConsoleBrandProps } from './type';\n\nfunction ConsoleBrand({ href = '/', label, logo, renderLink, title }: ConsoleBrandProps) {\n const shell = useConsoleShellState();\n const collapsed = shell?.collapsed ?? false;\n const lockup =\n title == null || title === false || title === '' ? (\n logo\n ) : (\n <span className={styles.brandLockup}>\n {logo}\n <span className={styles.brandName}>{title}</span>\n </span>\n );\n const content = collapsed ? logo : lockup;\n const linkProps = {\n 'aria-label': label ?? (typeof title === 'string' ? title : 'Home'),\n 'children': content,\n 'className': styles.brandAnchor,\n href,\n 'onClick': () => shell?.closeNavigation(),\n };\n if (renderLink) return renderLink(linkProps);\n return (\n <a\n aria-label={linkProps['aria-label']}\n className={linkProps.className}\n href={href}\n onClick={linkProps.onClick}\n >\n {content}\n </a>\n );\n}\n\nConsoleBrand.displayName = 'ConsoleBrand';\n\nexport default ConsoleBrand;\n"],"mappings":";;;;;AAMA,SAAS,aAAa,EAAE,OAAO,KAAK,OAAO,MAAM,YAAY,SAA4B;CACvF,MAAM,QAAQ,qBAAqB;CACnC,MAAM,YAAY,OAAO,aAAa;CACtC,MAAM,SACJ,SAAS,QAAQ,UAAU,SAAS,UAAU,KAC5C,OAEA,qBAAC,QAAD;EAAM,WAAW,OAAO;EAAxB,UAAA,CACG,MACD,oBAAC,QAAD;GAAM,WAAW,OAAO;GAAY,UAAA;EAAY,CAAA,CAC5C;;CAEV,MAAM,UAAU,YAAY,OAAO;CACnC,MAAM,YAAY;EAChB,cAAc,UAAU,OAAO,UAAU,WAAW,QAAQ;EAC5D,YAAY;EACZ,aAAa,OAAO;EACpB;EACA,iBAAiB,OAAO,gBAAgB;CAC1C;CACA,IAAI,YAAY,OAAO,WAAW,SAAS;CAC3C,OACE,oBAAC,KAAD;EACE,cAAY,UAAU;EACtB,WAAW,UAAU;EACf;EACN,SAAS,UAAU;EAElB,UAAA;CACA,CAAA;AAEP;AAEA,aAAa,cAAc"}
1
+ {"version":3,"file":"ConsoleBrand.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/ConsoleBrand.tsx"],"sourcesContent":["'use client';\n\nimport { useConsoleShellState } from './context';\nimport { styles } from './style';\nimport type { ConsoleBrandProps } from './type';\n\nfunction ConsoleBrand({ href = '/', label, logo, renderLink, title }: ConsoleBrandProps) {\n const shell = useConsoleShellState();\n const content =\n title == null || title === false || title === '' ? (\n logo\n ) : (\n <span className={styles.brandLockup}>\n {logo}\n <span className={styles.brandName}>{title}</span>\n </span>\n );\n const linkProps = {\n 'aria-label': label ?? (typeof title === 'string' ? title : 'Home'),\n 'children': content,\n 'className': styles.brandAnchor,\n href,\n 'onClick': () => shell?.closeNavigation(),\n };\n if (renderLink) return renderLink(linkProps);\n return (\n <a\n aria-label={linkProps['aria-label']}\n className={linkProps.className}\n href={href}\n onClick={linkProps.onClick}\n >\n {content}\n </a>\n );\n}\n\nConsoleBrand.displayName = 'ConsoleBrand';\n\nexport default ConsoleBrand;\n"],"mappings":";;;;;AAMA,SAAS,aAAa,EAAE,OAAO,KAAK,OAAO,MAAM,YAAY,SAA4B;CACvF,MAAM,QAAQ,qBAAqB;CACnC,MAAM,UACJ,SAAS,QAAQ,UAAU,SAAS,UAAU,KAC5C,OAEA,qBAAC,QAAD;EAAM,WAAW,OAAO;EAAxB,UAAA,CACG,MACD,oBAAC,QAAD;GAAM,WAAW,OAAO;GAAY,UAAA;EAAY,CAAA,CAC5C;;CAEV,MAAM,YAAY;EAChB,cAAc,UAAU,OAAO,UAAU,WAAW,QAAQ;EAC5D,YAAY;EACZ,aAAa,OAAO;EACpB;EACA,iBAAiB,OAAO,gBAAgB;CAC1C;CACA,IAAI,YAAY,OAAO,WAAW,SAAS;CAC3C,OACE,oBAAC,KAAD;EACE,cAAY,UAAU;EACtB,WAAW,UAAU;EACf;EACN,SAAS,UAAU;EAElB,UAAA;CACA,CAAA;AAEP;AAEA,aAAa,cAAc"}
@@ -1,7 +1,7 @@
1
1
  import { createStaticStyles } from "antd-style";
2
2
  //#region src/dashboard/ConsoleShell/style.ts
3
3
  const SIDEBAR_INLINE_SIZE = 248;
4
- const SIDEBAR_RAIL_INLINE_SIZE = 64;
4
+ const SIDEBAR_RAIL_INLINE_SIZE = 54;
5
5
  const WORKSPACE_INSET = 8;
6
6
  /**
7
7
  * `responsive.laptop`, not `responsive.tablet`. The aliases are named for
@@ -15,19 +15,10 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
15
15
 
16
16
  block-size: 56px;
17
17
  margin-block-start: ${WORKSPACE_INSET}px;
18
- padding-inline: 16px;
18
+ padding-inline: 15px;
19
19
 
20
20
  color: ${cssVar.colorText};
21
-
22
- &[data-collapsed='true'] {
23
- justify-content: center;
24
- padding-inline: 0;
25
-
26
- > * {
27
- justify-content: center;
28
- inline-size: auto;
29
- }
30
- }
21
+ white-space: nowrap;
31
22
 
32
23
  ${responsive.laptop} {
33
24
  margin-block-start: 0;
@@ -58,6 +49,18 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
58
49
  color: ${cssVar.colorText};
59
50
  text-overflow: ellipsis;
60
51
  white-space: nowrap;
52
+
53
+ transition: opacity 120ms ease 80ms;
54
+
55
+ [data-collapsed='true'] & {
56
+ text-overflow: clip;
57
+ opacity: 0;
58
+ transition-delay: 0s;
59
+ }
60
+
61
+ @media (prefers-reduced-motion: reduce) {
62
+ transition: none;
63
+ }
61
64
  `,
62
65
  main: css`
63
66
  overflow: auto;
@@ -102,6 +105,7 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
102
105
  background: ${cssVar.colorBgLayout};
103
106
  `,
104
107
  sidebar: css`
108
+ overflow: hidden;
105
109
  display: flex;
106
110
  flex: none;
107
111
  flex-direction: column;
@@ -1 +1 @@
1
- {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nconst SIDEBAR_INLINE_SIZE = 248;\nconst SIDEBAR_RAIL_INLINE_SIZE = 64;\nconst WORKSPACE_INSET = 8;\n\n/**\n * `responsive.laptop`, not `responsive.tablet`. The aliases are named for\n * devices, and only `laptop` (max-width 991px) lines up with `useIsCompact`.\n */\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n brand: css`\n display: flex;\n flex: none;\n align-items: center;\n\n block-size: 56px;\n margin-block-start: ${WORKSPACE_INSET}px;\n padding-inline: 16px;\n\n color: ${cssVar.colorText};\n\n &[data-collapsed='true'] {\n justify-content: center;\n padding-inline: 0;\n\n > * {\n justify-content: center;\n inline-size: auto;\n }\n }\n\n ${responsive.laptop} {\n margin-block-start: 0;\n }\n `,\n brandAnchor: css`\n display: flex;\n align-items: center;\n\n inline-size: 100%;\n min-inline-size: 0;\n\n color: inherit;\n text-decoration: none;\n `,\n brandLockup: css`\n display: flex;\n gap: 10px;\n align-items: center;\n min-inline-size: 0;\n `,\n brandName: css`\n overflow: hidden;\n\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: ${cssVar.colorText};\n text-overflow: ellipsis;\n white-space: nowrap;\n `,\n main: css`\n overflow: auto;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 20px;\n\n min-inline-size: 0;\n min-block-size: 0;\n padding: 24px;\n\n /*\n * A page that owns a full-height split sets data-page-layout=\"flush\" and\n * takes over padding and scrolling, so its sidebar can sit on the card edge.\n */\n &:has([data-page-layout='flush']) {\n overflow: hidden;\n gap: 0;\n padding: 0;\n }\n\n ${responsive.mobile} {\n gap: 16px;\n padding: 16px;\n }\n `,\n navSlot: css`\n display: flex;\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n `,\n shell: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n\n block-size: 100%;\n min-block-size: 0;\n\n background: ${cssVar.colorBgLayout};\n `,\n sidebar: css`\n display: flex;\n flex: none;\n flex-direction: column;\n\n inline-size: ${SIDEBAR_INLINE_SIZE}px;\n block-size: 100%;\n min-block-size: 0;\n\n transition: inline-size 200ms ease;\n\n &[data-collapsed='true'] {\n inline-size: ${SIDEBAR_RAIL_INLINE_SIZE}px;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n\n ${responsive.laptop} {\n display: none;\n }\n `,\n sidebarBottom: css`\n flex: none;\n padding: 8px;\n `,\n skipLink: css`\n position: fixed;\n z-index: 2000;\n inset-block-start: -100px;\n inset-inline-start: 12px;\n\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n\n &:focus {\n inset-block-start: 12px;\n }\n `,\n topbar: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n\n block-size: 56px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n `,\n topbarDivider: css`\n flex: none;\n\n inline-size: 1px;\n block-size: 18px;\n margin-inline: 2px;\n\n background: ${cssVar.colorBorderSecondary};\n `,\n topbarMain: css`\n display: flex;\n flex: 1;\n align-items: center;\n min-inline-size: 0;\n `,\n tools: css`\n display: flex;\n flex: none;\n gap: 6px;\n align-items: center;\n\n margin-inline-start: auto;\n `,\n workspace: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-inline-size: 0;\n min-block-size: 0;\n margin-block: ${WORKSPACE_INSET}px;\n margin-inline: 0 ${WORKSPACE_INSET}px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n\n background: ${cssVar.colorBgContainer};\n box-shadow: ${cssVar.boxShadowTertiary};\n\n ${responsive.laptop} {\n margin: 0;\n border: none;\n border-radius: 0;\n box-shadow: none;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAC5B,MAAM,2BAA2B;AACjC,MAAM,kBAAkB;;;;;AAMxB,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;0BAMc,gBAAgB;;;aAG7B,OAAO,UAAU;;;;;;;;;;;;MAYxB,WAAW,OAAO;;;;CAItB,aAAa,GAAG;;;;;;;;;;CAUhB,aAAa,GAAG;;;;;;CAMhB,WAAW,GAAG;;;;;;aAMH,OAAO,UAAU;;;;CAI5B,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;MAqBL,WAAW,OAAO;;;;;CAKtB,SAAS,GAAG;;;;;;CAMZ,OAAO,GAAG;;;;;;;;kBAQM,OAAO,cAAc;;CAErC,SAAS,GAAG;;;;;mBAKK,oBAAoB;;;;;;;qBAOlB,yBAAyB;;;;;;;MAOxC,WAAW,OAAO;;;;CAItB,eAAe,GAAG;;;;CAIlB,UAAU,GAAG;;;;;;;;qBAQM,OAAO,aAAa;;aAE5B,OAAO,UAAU;;kBAEZ,OAAO,gBAAgB;;;;;;CAMvC,QAAQ,GAAG;;;;;;;;kCAQqB,OAAO,qBAAqB;;CAE5D,eAAe,GAAG;;;;;;;kBAOF,OAAO,qBAAqB;;CAE5C,YAAY,GAAG;;;;;;CAMf,OAAO,GAAG;;;;;;;;CAQV,WAAW,GAAG;;;;;;;;oBAQI,gBAAgB;uBACb,gBAAgB;wBACf,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;kBAEzB,OAAO,iBAAiB;kBACxB,OAAO,kBAAkB;;MAErC,WAAW,OAAO;;;;;;;AAOxB,EAAE"}
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ConsoleShell/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nconst SIDEBAR_INLINE_SIZE = 248;\n// Twice the nav icon inset (8px nav padding + 10px item padding) plus the 18px icon, so the icons\n// land centered on the rail without moving sideways.\nconst SIDEBAR_RAIL_INLINE_SIZE = 54;\nconst WORKSPACE_INSET = 8;\n\n/**\n * `responsive.laptop`, not `responsive.tablet`. The aliases are named for\n * devices, and only `laptop` (max-width 991px) lines up with `useIsCompact`.\n */\nexport const styles = createStaticStyles(({ css, cssVar, responsive }) => ({\n brand: css`\n display: flex;\n flex: none;\n align-items: center;\n\n block-size: 56px;\n margin-block-start: ${WORKSPACE_INSET}px;\n padding-inline: 15px;\n\n color: ${cssVar.colorText};\n white-space: nowrap;\n\n ${responsive.laptop} {\n margin-block-start: 0;\n }\n `,\n brandAnchor: css`\n display: flex;\n align-items: center;\n\n inline-size: 100%;\n min-inline-size: 0;\n\n color: inherit;\n text-decoration: none;\n `,\n brandLockup: css`\n display: flex;\n gap: 10px;\n align-items: center;\n min-inline-size: 0;\n `,\n brandName: css`\n overflow: hidden;\n\n font-size: 14px;\n font-weight: 600;\n line-height: 1.3;\n color: ${cssVar.colorText};\n text-overflow: ellipsis;\n white-space: nowrap;\n\n transition: opacity 120ms ease 80ms;\n\n [data-collapsed='true'] & {\n text-overflow: clip;\n opacity: 0;\n transition-delay: 0s;\n }\n\n @media (prefers-reduced-motion: reduce) {\n transition: none;\n }\n `,\n main: css`\n overflow: auto;\n display: flex;\n flex: 1;\n flex-direction: column;\n gap: 20px;\n\n min-inline-size: 0;\n min-block-size: 0;\n padding: 24px;\n\n /*\n * A page that owns a full-height split sets data-page-layout=\"flush\" and\n * takes over padding and scrolling, so its sidebar can sit on the card edge.\n */\n &:has([data-page-layout='flush']) {\n overflow: hidden;\n gap: 0;\n padding: 0;\n }\n\n ${responsive.mobile} {\n gap: 16px;\n padding: 16px;\n }\n `,\n navSlot: css`\n display: flex;\n flex: 1;\n flex-direction: column;\n min-block-size: 0;\n `,\n shell: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n\n block-size: 100%;\n min-block-size: 0;\n\n background: ${cssVar.colorBgLayout};\n `,\n sidebar: css`\n overflow: hidden;\n display: flex;\n flex: none;\n flex-direction: column;\n\n inline-size: ${SIDEBAR_INLINE_SIZE}px;\n block-size: 100%;\n min-block-size: 0;\n\n transition: inline-size 200ms ease;\n\n &[data-collapsed='true'] {\n inline-size: ${SIDEBAR_RAIL_INLINE_SIZE}px;\n }\n\n &[data-instant='true'] {\n transition: none;\n }\n\n ${responsive.laptop} {\n display: none;\n }\n `,\n sidebarBottom: css`\n flex: none;\n padding: 8px;\n `,\n skipLink: css`\n position: fixed;\n z-index: 2000;\n inset-block-start: -100px;\n inset-inline-start: 12px;\n\n padding-block: 8px;\n padding-inline: 12px;\n border-radius: ${cssVar.borderRadius};\n\n color: ${cssVar.colorText};\n\n background: ${cssVar.colorBgElevated};\n\n &:focus {\n inset-block-start: 12px;\n }\n `,\n topbar: css`\n display: flex;\n flex: none;\n gap: 8px;\n align-items: center;\n\n block-size: 56px;\n padding-inline: 12px;\n border-block-end: 1px solid ${cssVar.colorBorderSecondary};\n `,\n topbarDivider: css`\n flex: none;\n\n inline-size: 1px;\n block-size: 18px;\n margin-inline: 2px;\n\n background: ${cssVar.colorBorderSecondary};\n `,\n topbarMain: css`\n display: flex;\n flex: 1;\n align-items: center;\n min-inline-size: 0;\n `,\n tools: css`\n display: flex;\n flex: none;\n gap: 6px;\n align-items: center;\n\n margin-inline-start: auto;\n `,\n workspace: css`\n overflow: hidden;\n display: flex;\n flex: 1;\n flex-direction: column;\n\n min-inline-size: 0;\n min-block-size: 0;\n margin-block: ${WORKSPACE_INSET}px;\n margin-inline: 0 ${WORKSPACE_INSET}px;\n border: 1px solid ${cssVar.colorBorderSecondary};\n border-radius: ${cssVar.borderRadiusLG};\n\n background: ${cssVar.colorBgContainer};\n box-shadow: ${cssVar.boxShadowTertiary};\n\n ${responsive.laptop} {\n margin: 0;\n border: none;\n border-radius: 0;\n box-shadow: none;\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAM,sBAAsB;AAG5B,MAAM,2BAA2B;AACjC,MAAM,kBAAkB;;;;;AAMxB,MAAa,SAAS,oBAAoB,EAAE,KAAK,QAAQ,kBAAkB;CACzE,OAAO,GAAG;;;;;;0BAMc,gBAAgB;;;aAG7B,OAAO,UAAU;;;MAGxB,WAAW,OAAO;;;;CAItB,aAAa,GAAG;;;;;;;;;;CAUhB,aAAa,GAAG;;;;;;CAMhB,WAAW,GAAG;;;;;;aAMH,OAAO,UAAU;;;;;;;;;;;;;;;;CAgB5B,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;MAqBL,WAAW,OAAO;;;;;CAKtB,SAAS,GAAG;;;;;;CAMZ,OAAO,GAAG;;;;;;;;kBAQM,OAAO,cAAc;;CAErC,SAAS,GAAG;;;;;;mBAMK,oBAAoB;;;;;;;qBAOlB,yBAAyB;;;;;;;MAOxC,WAAW,OAAO;;;;CAItB,eAAe,GAAG;;;;CAIlB,UAAU,GAAG;;;;;;;;qBAQM,OAAO,aAAa;;aAE5B,OAAO,UAAU;;kBAEZ,OAAO,gBAAgB;;;;;;CAMvC,QAAQ,GAAG;;;;;;;;kCAQqB,OAAO,qBAAqB;;CAE5D,eAAe,GAAG;;;;;;;kBAOF,OAAO,qBAAqB;;CAE5C,YAAY,GAAG;;;;;;CAMf,OAAO,GAAG;;;;;;;;CAQV,WAAW,GAAG;;;;;;;;oBAQI,gBAAgB;uBACb,gBAAgB;wBACf,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;kBAEzB,OAAO,iBAAiB;kBACxB,OAAO,kBAAkB;;MAErC,WAAW,OAAO;;;;;;;AAOxB,EAAE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/ui",
3
- "version": "5.50.2",
3
+ "version": "5.50.3",
4
4
  "description": "Lobe UI is an open-source UI component library for building AIGC web apps",
5
5
  "keywords": [
6
6
  "lobehub",