@lobehub/ui 5.58.0 → 5.60.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.
Files changed (135) hide show
  1. package/es/ActionIcon/style.mjs +8 -2
  2. package/es/ActionIcon/style.mjs.map +1 -1
  3. package/es/Grid/style.mjs +8 -8
  4. package/es/Grid/style.mjs.map +1 -1
  5. package/es/awesome/Grainient/Grainient.d.mts +11 -0
  6. package/es/awesome/Grainient/Grainient.mjs +311 -0
  7. package/es/awesome/Grainient/Grainient.mjs.map +1 -0
  8. package/es/awesome/Grainient/index.d.mts +3 -0
  9. package/es/awesome/Grainient/style.mjs +25 -0
  10. package/es/awesome/Grainient/style.mjs.map +1 -0
  11. package/es/awesome/Grainient/type.d.mts +122 -0
  12. package/es/awesome/index.d.mts +4 -1
  13. package/es/awesome/index.mjs +2 -1
  14. package/es/base-ui/ActionIcon/style.mjs +8 -2
  15. package/es/base-ui/ActionIcon/style.mjs.map +1 -1
  16. package/es/base-ui/Input/style.mjs +8 -2
  17. package/es/base-ui/Input/style.mjs.map +1 -1
  18. package/es/dashboard/AuthLayout/Aside.d.mts +10 -0
  19. package/es/dashboard/AuthLayout/Aside.mjs +30 -0
  20. package/es/dashboard/AuthLayout/Aside.mjs.map +1 -0
  21. package/es/dashboard/AuthLayout/AuthLayout.d.mts +3 -1
  22. package/es/dashboard/AuthLayout/AuthLayout.mjs +93 -37
  23. package/es/dashboard/AuthLayout/AuthLayout.mjs.map +1 -1
  24. package/es/dashboard/AuthLayout/index.d.mts +3 -2
  25. package/es/dashboard/AuthLayout/style.mjs +120 -1
  26. package/es/dashboard/AuthLayout/style.mjs.map +1 -1
  27. package/es/dashboard/AuthLayout/type.d.mts +39 -3
  28. package/es/dashboard/AuthTools/AuthLocaleSwitch.d.mts +10 -0
  29. package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs +32 -0
  30. package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs.map +1 -0
  31. package/es/dashboard/AuthTools/AuthThemeSwitch.d.mts +10 -0
  32. package/es/dashboard/AuthTools/AuthThemeSwitch.mjs +59 -0
  33. package/es/dashboard/AuthTools/AuthThemeSwitch.mjs.map +1 -0
  34. package/es/dashboard/AuthTools/index.d.mts +4 -0
  35. package/es/dashboard/AuthTools/style.mjs +63 -0
  36. package/es/dashboard/AuthTools/style.mjs.map +1 -0
  37. package/es/dashboard/AuthTools/type.d.mts +30 -0
  38. package/es/dashboard/ChartGrid/ChartGrid.d.mts +10 -0
  39. package/es/dashboard/ChartGrid/ChartGrid.mjs +18 -0
  40. package/es/dashboard/ChartGrid/ChartGrid.mjs.map +1 -0
  41. package/es/dashboard/ChartGrid/index.d.mts +3 -0
  42. package/es/dashboard/ChartGrid/style.mjs +32 -0
  43. package/es/dashboard/ChartGrid/style.mjs.map +1 -0
  44. package/es/dashboard/ChartGrid/type.d.mts +9 -0
  45. package/es/dashboard/ConsoleNav/Skeleton.d.mts +15 -0
  46. package/es/dashboard/ConsoleNav/Skeleton.mjs +81 -0
  47. package/es/dashboard/ConsoleNav/Skeleton.mjs.map +1 -0
  48. package/es/dashboard/ConsoleNav/index.d.mts +3 -2
  49. package/es/dashboard/ConsoleNav/style.mjs +15 -0
  50. package/es/dashboard/ConsoleNav/style.mjs.map +1 -1
  51. package/es/dashboard/ConsoleNav/type.d.mts +14 -1
  52. package/es/dashboard/ConsoleShell/ConsoleShell.d.mts +1 -1
  53. package/es/dashboard/ConsoleShell/ConsoleShell.mjs +22 -6
  54. package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -1
  55. package/es/dashboard/ConsoleShell/style.mjs +21 -0
  56. package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
  57. package/es/dashboard/ConsoleShell/type.d.mts +11 -0
  58. package/es/dashboard/FilterSidebar/FilterSidebar.mjs +18 -17
  59. package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -1
  60. package/es/dashboard/FilterStrip/FilterStrip.d.mts +11 -0
  61. package/es/dashboard/FilterStrip/FilterStrip.mjs +55 -0
  62. package/es/dashboard/FilterStrip/FilterStrip.mjs.map +1 -0
  63. package/es/dashboard/FilterStrip/index.d.mts +3 -0
  64. package/es/dashboard/FilterStrip/style.mjs +94 -0
  65. package/es/dashboard/FilterStrip/style.mjs.map +1 -0
  66. package/es/dashboard/FilterStrip/type.d.mts +26 -0
  67. package/es/dashboard/LabelWithKey/LabelWithKey.d.mts +10 -0
  68. package/es/dashboard/LabelWithKey/LabelWithKey.mjs +18 -0
  69. package/es/dashboard/LabelWithKey/LabelWithKey.mjs.map +1 -0
  70. package/es/dashboard/LabelWithKey/index.d.mts +3 -0
  71. package/es/dashboard/LabelWithKey/type.d.mts +12 -0
  72. package/es/dashboard/MetricStrip/MetricCell.mjs +81 -0
  73. package/es/dashboard/MetricStrip/MetricCell.mjs.map +1 -0
  74. package/es/dashboard/MetricStrip/MetricStrip.d.mts +13 -0
  75. package/es/dashboard/MetricStrip/MetricStrip.mjs +47 -0
  76. package/es/dashboard/MetricStrip/MetricStrip.mjs.map +1 -0
  77. package/es/dashboard/MetricStrip/index.d.mts +3 -0
  78. package/es/dashboard/MetricStrip/style.mjs +161 -0
  79. package/es/dashboard/MetricStrip/style.mjs.map +1 -0
  80. package/es/dashboard/MetricStrip/type.d.mts +37 -0
  81. package/es/dashboard/PageSkeleton/PageSkeleton.mjs +20 -18
  82. package/es/dashboard/PageSkeleton/PageSkeleton.mjs.map +1 -1
  83. package/es/dashboard/PageSkeleton/style.mjs +1 -1
  84. package/es/dashboard/PageSkeleton/style.mjs.map +1 -1
  85. package/es/dashboard/PageToolbar/PageToolbar.d.mts +10 -0
  86. package/es/dashboard/PageToolbar/PageToolbar.mjs +21 -0
  87. package/es/dashboard/PageToolbar/PageToolbar.mjs.map +1 -0
  88. package/es/dashboard/PageToolbar/index.d.mts +3 -0
  89. package/es/dashboard/PageToolbar/style.mjs +34 -0
  90. package/es/dashboard/PageToolbar/style.mjs.map +1 -0
  91. package/es/dashboard/PageToolbar/type.d.mts +12 -0
  92. package/es/dashboard/PanelSurface/PanelSurface.d.mts +10 -0
  93. package/es/dashboard/PanelSurface/PanelSurface.mjs +39 -0
  94. package/es/dashboard/PanelSurface/PanelSurface.mjs.map +1 -0
  95. package/es/dashboard/PanelSurface/index.d.mts +3 -0
  96. package/es/dashboard/PanelSurface/style.mjs +24 -0
  97. package/es/dashboard/PanelSurface/style.mjs.map +1 -0
  98. package/es/dashboard/PanelSurface/type.d.mts +18 -0
  99. package/es/dashboard/Section/Section.d.mts +10 -0
  100. package/es/dashboard/Section/Section.mjs +81 -0
  101. package/es/dashboard/Section/Section.mjs.map +1 -0
  102. package/es/dashboard/Section/index.d.mts +3 -0
  103. package/es/dashboard/Section/style.mjs +35 -0
  104. package/es/dashboard/Section/style.mjs.map +1 -0
  105. package/es/dashboard/Section/type.d.mts +24 -0
  106. package/es/dashboard/StatCard/StatCard.d.mts +2 -1
  107. package/es/dashboard/StatCard/StatCard.mjs +24 -72
  108. package/es/dashboard/StatCard/StatCard.mjs.map +1 -1
  109. package/es/dashboard/StatCard/type.d.mts +16 -5
  110. package/es/dashboard/Surface/Surface.d.mts +4 -3
  111. package/es/dashboard/Surface/Surface.mjs +83 -7
  112. package/es/dashboard/Surface/Surface.mjs.map +1 -1
  113. package/es/dashboard/Surface/index.d.mts +3 -2
  114. package/es/dashboard/Surface/link.d.mts +19 -0
  115. package/es/dashboard/Surface/link.mjs +33 -0
  116. package/es/dashboard/Surface/link.mjs.map +1 -0
  117. package/es/dashboard/Surface/style.d.mts +45 -3
  118. package/es/dashboard/Surface/style.mjs +358 -8
  119. package/es/dashboard/Surface/style.mjs.map +1 -1
  120. package/es/dashboard/Surface/type.d.mts +30 -2
  121. package/es/dashboard/TableIconActions/TableIconActions.d.mts +17 -0
  122. package/es/dashboard/TableIconActions/TableIconActions.mjs +39 -0
  123. package/es/dashboard/TableIconActions/TableIconActions.mjs.map +1 -0
  124. package/es/dashboard/TableIconActions/index.d.mts +3 -0
  125. package/es/dashboard/TableIconActions/type.d.mts +18 -0
  126. package/es/dashboard/TitleWithTips/TitleWithTips.d.mts +10 -0
  127. package/es/dashboard/TitleWithTips/TitleWithTips.mjs +28 -0
  128. package/es/dashboard/TitleWithTips/TitleWithTips.mjs.map +1 -0
  129. package/es/dashboard/TitleWithTips/index.d.mts +3 -0
  130. package/es/dashboard/TitleWithTips/type.d.mts +11 -0
  131. package/es/dashboard/index.d.mts +38 -4
  132. package/es/dashboard/index.mjs +17 -3
  133. package/package.json +1 -1
  134. package/es/dashboard/StatCard/style.mjs +0 -135
  135. package/es/dashboard/StatCard/style.mjs.map +0 -1
@@ -0,0 +1,10 @@
1
+ import { AuthThemeSwitchProps } from "./type.mjs";
2
+ //#region src/dashboard/AuthTools/AuthThemeSwitch.d.ts
3
+ /** Compact icon-only theme picker for auth corner tools. Controlled; wire it to your store. */
4
+ declare function AuthThemeSwitch({ className, labels, onChange, style, value }: AuthThemeSwitchProps): import("react").JSX.Element;
5
+ declare namespace AuthThemeSwitch {
6
+ var displayName: string;
7
+ }
8
+ //#endregion
9
+ export { AuthThemeSwitch as default };
10
+ //# sourceMappingURL=AuthThemeSwitch.d.mts.map
@@ -0,0 +1,59 @@
1
+ "use client";
2
+ import Icon from "../../Icon/Icon.mjs";
3
+ import Segmented from "../../base-ui/Segmented/Segmented.mjs";
4
+ import { styles } from "./style.mjs";
5
+ import { jsx } from "react/jsx-runtime";
6
+ import { cx } from "antd-style";
7
+ import { Monitor, Moon, Sun } from "lucide-react";
8
+ //#region src/dashboard/AuthTools/AuthThemeSwitch.tsx
9
+ const OPTIONS = [
10
+ {
11
+ icon: Moon,
12
+ value: "dark"
13
+ },
14
+ {
15
+ icon: Monitor,
16
+ value: "auto"
17
+ },
18
+ {
19
+ icon: Sun,
20
+ value: "light"
21
+ }
22
+ ];
23
+ const DEFAULT_LABELS = {
24
+ auto: "System",
25
+ dark: "Dark",
26
+ light: "Light"
27
+ };
28
+ /** Compact icon-only theme picker for auth corner tools. Controlled; wire it to your store. */
29
+ function AuthThemeSwitch({ className, labels, onChange, style, value = "auto" }) {
30
+ const names = {
31
+ ...DEFAULT_LABELS,
32
+ ...labels
33
+ };
34
+ return /* @__PURE__ */ jsx(Segmented, {
35
+ className: cx(styles.theme, className),
36
+ size: "small",
37
+ style,
38
+ value,
39
+ variant: "outlined",
40
+ classNames: {
41
+ indicator: styles.themeIndicator,
42
+ item: styles.themeItem,
43
+ itemIcon: styles.themeIcon,
44
+ itemLabel: styles.themeLabel
45
+ },
46
+ options: OPTIONS.map((option) => ({
47
+ icon: /* @__PURE__ */ jsx(Icon, { icon: option.icon }),
48
+ label: names[option.value],
49
+ title: names[option.value],
50
+ value: option.value
51
+ })),
52
+ onChange: (next) => onChange?.(next)
53
+ });
54
+ }
55
+ AuthThemeSwitch.displayName = "AuthThemeSwitch";
56
+ //#endregion
57
+ export { AuthThemeSwitch as default };
58
+
59
+ //# sourceMappingURL=AuthThemeSwitch.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthThemeSwitch.mjs","names":[],"sources":["../../../src/dashboard/AuthTools/AuthThemeSwitch.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { Monitor, Moon, Sun } from 'lucide-react';\n\nimport Segmented from '@/base-ui/Segmented';\nimport Icon from '@/Icon';\n\nimport { styles } from './style';\nimport type { AuthThemeMode, AuthThemeSwitchProps } from './type';\n\nconst OPTIONS = [\n { icon: Moon, value: 'dark' },\n { icon: Monitor, value: 'auto' },\n { icon: Sun, value: 'light' },\n] as const;\n\nconst DEFAULT_LABELS: Record<AuthThemeMode, string> = {\n auto: 'System',\n dark: 'Dark',\n light: 'Light',\n};\n\n/** Compact icon-only theme picker for auth corner tools. Controlled; wire it to your store. */\nfunction AuthThemeSwitch({\n className,\n labels,\n onChange,\n style,\n value = 'auto',\n}: AuthThemeSwitchProps) {\n const names = { ...DEFAULT_LABELS, ...labels };\n return (\n <Segmented<AuthThemeMode>\n className={cx(styles.theme, className)}\n size=\"small\"\n style={style}\n value={value}\n variant=\"outlined\"\n classNames={{\n indicator: styles.themeIndicator,\n item: styles.themeItem,\n itemIcon: styles.themeIcon,\n itemLabel: styles.themeLabel,\n }}\n options={OPTIONS.map((option) => ({\n icon: <Icon icon={option.icon} />,\n label: names[option.value],\n title: names[option.value],\n value: option.value,\n }))}\n onChange={(next) => onChange?.(next)}\n />\n );\n}\n\nAuthThemeSwitch.displayName = 'AuthThemeSwitch';\n\nexport default AuthThemeSwitch;\n"],"mappings":";;;;;;;;AAWA,MAAM,UAAU;CACd;EAAE,MAAM;EAAM,OAAO;CAAO;CAC5B;EAAE,MAAM;EAAS,OAAO;CAAO;CAC/B;EAAE,MAAM;EAAK,OAAO;CAAQ;AAC9B;AAEA,MAAM,iBAAgD;CACpD,MAAM;CACN,MAAM;CACN,OAAO;AACT;;AAGA,SAAS,gBAAgB,EACvB,WACA,QACA,UACA,OACA,QAAQ,UACe;CACvB,MAAM,QAAQ;EAAE,GAAG;EAAgB,GAAG;CAAO;CAC7C,OACE,oBAAC,WAAD;EACE,WAAW,GAAG,OAAO,OAAO,SAAS;EACrC,MAAK;EACE;EACA;EACP,SAAQ;EACR,YAAY;GACV,WAAW,OAAO;GAClB,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,WAAW,OAAO;EACpB;EACA,SAAS,QAAQ,KAAK,YAAY;GAChC,MAAM,oBAAC,MAAD,EAAM,MAAM,OAAO,KAAO,CAAA;GAChC,OAAO,MAAM,OAAO;GACpB,OAAO,MAAM,OAAO;GACpB,OAAO,OAAO;EAChB,EAAE;EACF,WAAW,SAAS,WAAW,IAAI;CACpC,CAAA;AAEL;AAEA,gBAAgB,cAAc"}
@@ -0,0 +1,4 @@
1
+ import { AuthLocaleOption, AuthLocaleSwitchProps, AuthThemeMode, AuthThemeSwitchProps } from "./type.mjs";
2
+ import AuthLocaleSwitch from "./AuthLocaleSwitch.mjs";
3
+ import AuthThemeSwitch from "./AuthThemeSwitch.mjs";
4
+ export { type AuthLocaleOption, AuthLocaleSwitch, type AuthLocaleSwitchProps, type AuthThemeMode, AuthThemeSwitch, type AuthThemeSwitchProps };
@@ -0,0 +1,63 @@
1
+ import { createStaticStyles } from "antd-style";
2
+ //#region src/dashboard/AuthTools/style.ts
3
+ const styles = createStaticStyles(({ css, cssVar }) => ({
4
+ locale: css`
5
+ && {
6
+ inline-size: fit-content;
7
+ min-inline-size: 120px;
8
+ block-size: 28px;
9
+ border-radius: 28px;
10
+
11
+ background: ${cssVar.colorBgLayout};
12
+ }
13
+ `,
14
+ localeIcon: css`
15
+ margin-inline-end: 2px;
16
+ `,
17
+ theme: css`
18
+ && {
19
+ block-size: 28px;
20
+ padding: 2px;
21
+ border-radius: 28px;
22
+ }
23
+ `,
24
+ themeIcon: css`
25
+ inline-size: 16px;
26
+ block-size: 16px;
27
+ `,
28
+ themeIndicator: css`
29
+ && {
30
+ border-radius: 22px;
31
+ }
32
+ `,
33
+ themeItem: css`
34
+ && {
35
+ block-size: 22px;
36
+ padding-inline: 8px;
37
+ border-radius: 22px;
38
+ }
39
+ `,
40
+ themeLabel: css`
41
+ position: absolute;
42
+
43
+ overflow: hidden;
44
+
45
+ inline-size: 1px;
46
+ block-size: 1px;
47
+ padding: 0;
48
+ border: 0;
49
+
50
+ white-space: nowrap;
51
+
52
+ clip-path: inset(50%);
53
+ `,
54
+ toolRow: css`
55
+ display: flex;
56
+ gap: 8px;
57
+ align-items: center;
58
+ `
59
+ }));
60
+ //#endregion
61
+ export { styles };
62
+
63
+ //# sourceMappingURL=style.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/AuthTools/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css, cssVar }) => ({\n locale: css`\n && {\n inline-size: fit-content;\n min-inline-size: 120px;\n block-size: 28px;\n border-radius: 28px;\n\n background: ${cssVar.colorBgLayout};\n }\n `,\n localeIcon: css`\n margin-inline-end: 2px;\n `,\n theme: css`\n && {\n block-size: 28px;\n padding: 2px;\n border-radius: 28px;\n }\n `,\n themeIcon: css`\n inline-size: 16px;\n block-size: 16px;\n `,\n themeIndicator: css`\n && {\n border-radius: 22px;\n }\n `,\n themeItem: css`\n && {\n block-size: 22px;\n padding-inline: 8px;\n border-radius: 22px;\n }\n `,\n themeLabel: css`\n position: absolute;\n\n overflow: hidden;\n\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n border: 0;\n\n white-space: nowrap;\n\n clip-path: inset(50%);\n `,\n toolRow: css`\n display: flex;\n gap: 8px;\n align-items: center;\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,KAAK,cAAc;CAC7D,QAAQ,GAAG;;;;;;;oBAOO,OAAO,cAAc;;;CAGvC,YAAY,GAAG;;;CAGf,OAAO,GAAG;;;;;;;CAOV,WAAW,GAAG;;;;CAId,gBAAgB,GAAG;;;;;CAKnB,WAAW,GAAG;;;;;;;CAOd,YAAY,GAAG;;;;;;;;;;;;;;CAcf,SAAS,GAAG;;;;;AAKd,EAAE"}
@@ -0,0 +1,30 @@
1
+ import { CSSProperties } from "react";
2
+ //#region src/dashboard/AuthTools/type.d.ts
3
+ type AuthThemeMode = 'auto' | 'dark' | 'light';
4
+ interface AuthThemeSwitchProps {
5
+ className?: string;
6
+ /**
7
+ * Accessible names, also shown as tooltips. Labels are visually hidden.
8
+ * @default { auto: 'System', dark: 'Dark', light: 'Light' }
9
+ */
10
+ labels?: Partial<Record<AuthThemeMode, string>>;
11
+ onChange?: (mode: AuthThemeMode) => void;
12
+ style?: CSSProperties;
13
+ value?: AuthThemeMode;
14
+ }
15
+ interface AuthLocaleOption {
16
+ label: string;
17
+ value: string;
18
+ }
19
+ interface AuthLocaleSwitchProps {
20
+ /** Accessible name of the select. @default 'Language' */
21
+ 'aria-label'?: string;
22
+ 'className'?: string;
23
+ 'onChange'?: (locale: string) => void;
24
+ 'options': AuthLocaleOption[];
25
+ 'style'?: CSSProperties;
26
+ 'value'?: string;
27
+ }
28
+ //#endregion
29
+ export { AuthLocaleOption, AuthLocaleSwitchProps, AuthThemeMode, AuthThemeSwitchProps };
30
+ //# sourceMappingURL=type.d.mts.map
@@ -0,0 +1,10 @@
1
+ import { ChartGridProps } from "./type.mjs";
2
+ //#region src/dashboard/ChartGrid/ChartGrid.d.ts
3
+ /** Peer charts and ranked lists, two-up, one column below 640px. Not for label/value rows. */
4
+ declare const ChartGrid: {
5
+ ({ children, className }: ChartGridProps): import("react").JSX.Element;
6
+ displayName: string;
7
+ };
8
+ //#endregion
9
+ export { ChartGrid as default };
10
+ //# sourceMappingURL=ChartGrid.d.mts.map
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { styles } from "./style.mjs";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { cx } from "antd-style";
5
+ //#region src/dashboard/ChartGrid/ChartGrid.tsx
6
+ /** Peer charts and ranked lists, two-up, one column below 640px. Not for label/value rows. */
7
+ const ChartGrid = ({ children, className }) => /* @__PURE__ */ jsx("div", {
8
+ className: styles.frame,
9
+ children: /* @__PURE__ */ jsx("div", {
10
+ className: cx(styles.root, className),
11
+ children
12
+ })
13
+ });
14
+ ChartGrid.displayName = "ChartGrid";
15
+ //#endregion
16
+ export { ChartGrid as default };
17
+
18
+ //# sourceMappingURL=ChartGrid.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartGrid.mjs","names":[],"sources":["../../../src/dashboard/ChartGrid/ChartGrid.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport { styles } from './style';\nimport type { ChartGridProps } from './type';\n\n/** Peer charts and ranked lists, two-up, one column below 640px. Not for label/value rows. */\nconst ChartGrid = ({ children, className }: ChartGridProps) => (\n <div className={styles.frame}>\n <div className={cx(styles.root, className)}>{children}</div>\n </div>\n);\n\nChartGrid.displayName = 'ChartGrid';\n\nexport default ChartGrid;\n"],"mappings":";;;;;;AAQA,MAAM,aAAa,EAAE,UAAU,gBAC7B,oBAAC,OAAD;CAAK,WAAW,OAAO;CACrB,UAAA,oBAAC,OAAD;EAAK,WAAW,GAAG,OAAO,MAAM,SAAS;EAAI;CAAc,CAAA;AACxD,CAAA;AAGP,UAAU,cAAc"}
@@ -0,0 +1,3 @@
1
+ import { ChartGridProps } from "./type.mjs";
2
+ import ChartGrid from "./ChartGrid.mjs";
3
+ export { type ChartGridProps, ChartGrid as default };
@@ -0,0 +1,32 @@
1
+ import { createStaticStyles } from "antd-style";
2
+ //#region src/dashboard/ChartGrid/style.ts
3
+ const styles = createStaticStyles(({ css }) => ({
4
+ /**
5
+ * The frame is the container. A query on the grid itself would not see its own width.
6
+ * Charts stay two-up so a trend and its switch stay readable; one child does not
7
+ * stretch across the page.
8
+ */
9
+ frame: css`
10
+ container-type: inline-size;
11
+
12
+ @container (max-width: 640px) {
13
+ & > * {
14
+ grid-template-columns: minmax(0, 1fr);
15
+ }
16
+ }
17
+ `,
18
+ root: css`
19
+ display: grid;
20
+ grid-template-columns: repeat(2, minmax(0, 1fr));
21
+ gap: 16px;
22
+ align-items: stretch;
23
+
24
+ &:has(> :only-child) {
25
+ grid-template-columns: minmax(0, min(100%, 560px));
26
+ }
27
+ `
28
+ }));
29
+ //#endregion
30
+ export { styles };
31
+
32
+ //# sourceMappingURL=style.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"style.mjs","names":[],"sources":["../../../src/dashboard/ChartGrid/style.ts"],"sourcesContent":["import { createStaticStyles } from 'antd-style';\n\nexport const styles = createStaticStyles(({ css }) => ({\n /**\n * The frame is the container. A query on the grid itself would not see its own width.\n * Charts stay two-up so a trend and its switch stay readable; one child does not\n * stretch across the page.\n */\n frame: css`\n container-type: inline-size;\n\n @container (max-width: 640px) {\n & > * {\n grid-template-columns: minmax(0, 1fr);\n }\n }\n `,\n root: css`\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 16px;\n align-items: stretch;\n\n &:has(> :only-child) {\n grid-template-columns: minmax(0, min(100%, 560px));\n }\n `,\n}));\n"],"mappings":";;AAEA,MAAa,SAAS,oBAAoB,EAAE,WAAW;;;;;;CAMrD,OAAO,GAAG;;;;;;;;;CASV,MAAM,GAAG;;;;;;;;;;AAUX,EAAE"}
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/dashboard/ChartGrid/type.d.ts
3
+ interface ChartGridProps {
4
+ children?: ReactNode;
5
+ className?: string;
6
+ }
7
+ //#endregion
8
+ export { ChartGridProps };
9
+ //# sourceMappingURL=type.d.mts.map
@@ -0,0 +1,15 @@
1
+ import { ConsoleNavSkeletonProps } from "./type.mjs";
2
+ //#region src/dashboard/ConsoleNav/Skeleton.d.ts
3
+ /**
4
+ * Placeholder for `ConsoleNav` while the session or menu loads. Rows use the nav's own item,
5
+ * group header and indent metrics, so swapping in the real nav does not shift anything.
6
+ */
7
+ declare function ConsoleNavSkeleton({ className, groups, items }: ConsoleNavSkeletonProps): import("react").JSX.Element;
8
+ declare namespace ConsoleNavSkeleton {
9
+ var displayName: string;
10
+ }
11
+ /** Footer placeholder matching an account row: avatar plus name. */
12
+ declare function ConsoleFooterSkeleton(): import("react").JSX.Element;
13
+ //#endregion
14
+ export { ConsoleFooterSkeleton, ConsoleNavSkeleton as default };
15
+ //# sourceMappingURL=Skeleton.d.mts.map
@@ -0,0 +1,81 @@
1
+ "use client";
2
+ import Skeleton from "../../base-ui/Skeleton/index.mjs";
3
+ import { styles } from "./style.mjs";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { cx } from "antd-style";
6
+ //#region src/dashboard/ConsoleNav/Skeleton.tsx
7
+ const DEFAULT_GROUPS = [
8
+ 3,
9
+ 6,
10
+ 4,
11
+ 3
12
+ ];
13
+ const Row = ({ group, index }) => /* @__PURE__ */ jsxs("div", {
14
+ className: cx(styles.item, styles.skeletonRow),
15
+ "data-indent": 0,
16
+ children: [/* @__PURE__ */ jsx(Skeleton, {
17
+ height: 16,
18
+ radius: 4,
19
+ width: 16
20
+ }), /* @__PURE__ */ jsx(Skeleton, {
21
+ height: 14,
22
+ radius: 4,
23
+ width: 56 + (index + group) % 3 * 20
24
+ })]
25
+ });
26
+ /**
27
+ * Placeholder for `ConsoleNav` while the session or menu loads. Rows use the nav's own item,
28
+ * group header and indent metrics, so swapping in the real nav does not shift anything.
29
+ */
30
+ function ConsoleNavSkeleton({ className, groups = DEFAULT_GROUPS, items = 1 }) {
31
+ const counts = groups.map((group) => typeof group === "number" ? group : group.items?.length ?? 0);
32
+ return /* @__PURE__ */ jsxs("div", {
33
+ "aria-hidden": true,
34
+ className: cx(styles.nav, className),
35
+ "data-console-nav-skeleton": "",
36
+ children: [Array.from({ length: items }, (_, index) => /* @__PURE__ */ jsx(Row, {
37
+ group: 0,
38
+ index
39
+ }, index)), counts.map((count, group) => /* @__PURE__ */ jsxs("div", {
40
+ className: styles.skeletonGroup,
41
+ children: [/* @__PURE__ */ jsx("div", {
42
+ className: cx(styles.groupHeader, styles.skeletonRow),
43
+ "data-level": 0,
44
+ children: /* @__PURE__ */ jsx(Skeleton, {
45
+ height: 12,
46
+ radius: 4,
47
+ width: 64 + group % 2 * 16
48
+ })
49
+ }), Array.from({ length: count }, (_, index) => /* @__PURE__ */ jsx("div", {
50
+ className: cx(styles.item, styles.skeletonRow),
51
+ "data-indent": 1,
52
+ children: /* @__PURE__ */ jsx(Skeleton, {
53
+ height: 14,
54
+ radius: 4,
55
+ width: 56 + (index + group) % 3 * 20
56
+ })
57
+ }, index))]
58
+ }, group))]
59
+ });
60
+ }
61
+ ConsoleNavSkeleton.displayName = "ConsoleNavSkeleton";
62
+ /** Footer placeholder matching an account row: avatar plus name. */
63
+ function ConsoleFooterSkeleton() {
64
+ return /* @__PURE__ */ jsxs("div", {
65
+ "aria-hidden": true,
66
+ className: styles.skeletonFooter,
67
+ children: [/* @__PURE__ */ jsx(Skeleton, {
68
+ height: 32,
69
+ radius: 16,
70
+ width: 32
71
+ }), /* @__PURE__ */ jsx(Skeleton, {
72
+ height: 14,
73
+ radius: 4,
74
+ width: 96
75
+ })]
76
+ });
77
+ }
78
+ //#endregion
79
+ export { ConsoleFooterSkeleton, ConsoleNavSkeleton as default };
80
+
81
+ //# sourceMappingURL=Skeleton.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.mjs","names":[],"sources":["../../../src/dashboard/ConsoleNav/Skeleton.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\n\nimport Skeleton from '@/base-ui/Skeleton';\n\nimport { styles } from './style';\nimport type { ConsoleNavGroup, ConsoleNavSkeletonProps } from './type';\n\nconst DEFAULT_GROUPS = [3, 6, 4, 3];\n\nconst Row = ({ group, index }: { group: number; index: number }) => (\n <div className={cx(styles.item, styles.skeletonRow)} data-indent={0}>\n <Skeleton height={16} radius={4} width={16} />\n <Skeleton height={14} radius={4} width={56 + ((index + group) % 3) * 20} />\n </div>\n);\n\n/**\n * Placeholder for `ConsoleNav` while the session or menu loads. Rows use the nav's own item,\n * group header and indent metrics, so swapping in the real nav does not shift anything.\n */\nfunction ConsoleNavSkeleton({\n className,\n groups = DEFAULT_GROUPS,\n items = 1,\n}: ConsoleNavSkeletonProps) {\n const counts = groups.map((group: number | ConsoleNavGroup) =>\n typeof group === 'number' ? group : (group.items?.length ?? 0),\n );\n return (\n <div aria-hidden className={cx(styles.nav, className)} data-console-nav-skeleton=\"\">\n {Array.from({ length: items }, (_, index) => (\n <Row group={0} index={index} key={index} />\n ))}\n {counts.map((count, group) => (\n <div className={styles.skeletonGroup} key={group}>\n <div className={cx(styles.groupHeader, styles.skeletonRow)} data-level={0}>\n <Skeleton height={12} radius={4} width={64 + (group % 2) * 16} />\n </div>\n {Array.from({ length: count }, (_, index) => (\n <div className={cx(styles.item, styles.skeletonRow)} data-indent={1} key={index}>\n <Skeleton height={14} radius={4} width={56 + ((index + group) % 3) * 20} />\n </div>\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nConsoleNavSkeleton.displayName = 'ConsoleNavSkeleton';\n\n/** Footer placeholder matching an account row: avatar plus name. */\nexport function ConsoleFooterSkeleton() {\n return (\n <div aria-hidden className={styles.skeletonFooter}>\n <Skeleton height={32} radius={16} width={32} />\n <Skeleton height={14} radius={4} width={96} />\n </div>\n );\n}\n\nexport default ConsoleNavSkeleton;\n"],"mappings":";;;;;;AASA,MAAM,iBAAiB;CAAC;CAAG;CAAG;CAAG;AAAC;AAElC,MAAM,OAAO,EAAE,OAAO,YACpB,qBAAC,OAAD;CAAK,WAAW,GAAG,OAAO,MAAM,OAAO,WAAW;CAAG,eAAa;CAAlE,UAAA,CACE,oBAAC,UAAD;EAAU,QAAQ;EAAI,QAAQ;EAAG,OAAO;CAAK,CAAA,GAC7C,oBAAC,UAAD;EAAU,QAAQ;EAAI,QAAQ;EAAG,OAAO,MAAO,QAAQ,SAAS,IAAK;CAAK,CAAA,CACvE;;;;;;AAOP,SAAS,mBAAmB,EAC1B,WACA,SAAS,gBACT,QAAQ,KACkB;CAC1B,MAAM,SAAS,OAAO,KAAK,UACzB,OAAO,UAAU,WAAW,QAAS,MAAM,OAAO,UAAU,CAC9D;CACA,OACE,qBAAC,OAAD;EAAK,eAAA;EAAY,WAAW,GAAG,OAAO,KAAK,SAAS;EAAG,6BAA0B;EAAjF,UAAA,CACG,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,UACjC,oBAAC,KAAD;GAAK,OAAO;GAAU;EAAoB,GAAR,KAAQ,CAC3C,GACA,OAAO,KAAK,OAAO,UAClB,qBAAC,OAAD;GAAK,WAAW,OAAO;GAAvB,UAAA,CACE,oBAAC,OAAD;IAAK,WAAW,GAAG,OAAO,aAAa,OAAO,WAAW;IAAG,cAAY;IACtE,UAAA,oBAAC,UAAD;KAAU,QAAQ;KAAI,QAAQ;KAAG,OAAO,KAAM,QAAQ,IAAK;IAAK,CAAA;GAC7D,CAAA,GACJ,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,UACjC,oBAAC,OAAD;IAAK,WAAW,GAAG,OAAO,MAAM,OAAO,WAAW;IAAG,eAAa;IAChE,UAAA,oBAAC,UAAD;KAAU,QAAQ;KAAI,QAAQ;KAAG,OAAO,MAAO,QAAQ,SAAS,IAAK;IAAK,CAAA;GACvE,GAFqE,KAErE,CACN,CACE;EATsC,GAAA,KAStC,CACN,CACE;;AAET;AAEA,mBAAmB,cAAc;;AAGjC,SAAgB,wBAAwB;CACtC,OACE,qBAAC,OAAD;EAAK,eAAA;EAAY,WAAW,OAAO;EAAnC,UAAA,CACE,oBAAC,UAAD;GAAU,QAAQ;GAAI,QAAQ;GAAI,OAAO;EAAK,CAAA,GAC9C,oBAAC,UAAD;GAAU,QAAQ;GAAI,QAAQ;GAAG,OAAO;EAAK,CAAA,CAC1C;;AAET"}
@@ -1,4 +1,5 @@
1
- import { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps } from "./type.mjs";
1
+ import { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps, ConsoleNavSkeletonProps } from "./type.mjs";
2
2
  import { resolveActiveHref } from "./active.mjs";
3
3
  import ConsoleNav from "./ConsoleNav.mjs";
4
- export { type ConsoleNavGroup, type ConsoleNavItem, type ConsoleNavProps, ConsoleNav as default, resolveActiveHref };
4
+ import ConsoleNavSkeleton, { ConsoleFooterSkeleton } from "./Skeleton.mjs";
5
+ export { ConsoleFooterSkeleton, type ConsoleNavGroup, type ConsoleNavItem, type ConsoleNavProps, ConsoleNavSkeleton, type ConsoleNavSkeletonProps, ConsoleNav as default, resolveActiveHref };
@@ -372,6 +372,21 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => {
372
372
  @starting-style {
373
373
  background: transparent;
374
374
  }
375
+ `,
376
+ skeletonFooter: css`
377
+ display: flex;
378
+ gap: 10px;
379
+ align-items: center;
380
+ padding-inline: 4px;
381
+ `,
382
+ skeletonGroup: css`
383
+ display: flex;
384
+ flex-direction: column;
385
+ gap: 2px;
386
+ margin-block-start: 12px;
387
+ `,
388
+ skeletonRow: css`
389
+ pointer-events: none;
375
390
  `,
376
391
  topItems: css`
377
392
  display: flex;
@@ -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 // 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"}
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 skeletonFooter: css`\n display: flex;\n gap: 10px;\n align-items: center;\n padding-inline: 4px;\n `,\n skeletonGroup: css`\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-block-start: 12px;\n `,\n skeletonRow: css`\n pointer-events: none;\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,gBAAgB,GAAG;;;;;;EAMnB,eAAe,GAAG;;;;;;EAMlB,aAAa,GAAG;;;EAGhB,UAAU,GAAG;;;;;;;;;;;;sCAYqB,OAAO,qBAAqB;;;;;;;;;;;;;CAahE;AACF,CAAC"}
@@ -66,6 +66,19 @@ interface ConsoleNavProps {
66
66
  /** Persists which groups were opened or closed by hand. */
67
67
  storageKey?: string;
68
68
  }
69
+ interface ConsoleNavSkeletonProps {
70
+ className?: string;
71
+ /**
72
+ * Rows per group. Pass counts, or the real `ConsoleNavGroup[]` to mirror its item counts.
73
+ * @default [3, 6, 4, 3]
74
+ */
75
+ groups?: Array<number | ConsoleNavGroup>;
76
+ /**
77
+ * Ungrouped rows before the groups.
78
+ * @default 1
79
+ */
80
+ items?: number;
81
+ }
69
82
  //#endregion
70
- export { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps };
83
+ export { ConsoleNavGroup, ConsoleNavItem, ConsoleNavLinkProps, ConsoleNavProps, ConsoleNavSkeletonProps };
71
84
  //# sourceMappingURL=type.d.mts.map
@@ -1,6 +1,6 @@
1
1
  import { ConsoleShellProps } from "./type.mjs";
2
2
  //#region src/dashboard/ConsoleShell/ConsoleShell.d.ts
3
- declare function ConsoleShell({ brand, breadcrumb, children, className, collapsed, collapseLabel, defaultCollapsed, expandLabel, footer, hotkey, navigation, onCollapsedChange, openNavigationLabel, skipToContentLabel, storageKey, tools, ...rest }: ConsoleShellProps): import("react").JSX.Element;
3
+ declare function ConsoleShell({ brand, breadcrumb, children, className, collapsed, closeNavigationLabel, collapseLabel, defaultCollapsed, expandLabel, footer: footerProp, loading, loadingContent, loadingNavigation, hotkey, navigation: navigationProp, onCollapsedChange, openNavigationLabel, skipToContentLabel, storageKey, tools, ...rest }: ConsoleShellProps): import("react").JSX.Element;
4
4
  declare namespace ConsoleShell {
5
5
  var displayName: string;
6
6
  }
@@ -4,20 +4,27 @@ import Button from "../../base-ui/Button/Button.mjs";
4
4
  import Drawer from "../../base-ui/Drawer/Drawer.mjs";
5
5
  import { ConsoleShellContext } from "./context.mjs";
6
6
  import { useIsCompact, useLocalStorage, usePrefersReducedMotion } from "../hooks.mjs";
7
+ import ConsoleNavSkeleton, { ConsoleFooterSkeleton } from "../ConsoleNav/Skeleton.mjs";
7
8
  import { styles } from "./style.mjs";
9
+ import PageLoading from "../PageSkeleton/PageSkeleton.mjs";
8
10
  import { useEffect, useId, useRef, useState } from "react";
9
11
  import { jsx, jsxs } from "react/jsx-runtime";
10
- import { PanelLeft } from "lucide-react";
12
+ import { useThemeMode } from "antd-style";
13
+ import { PanelLeft, X } from "lucide-react";
11
14
  //#region src/dashboard/ConsoleShell/ConsoleShell.tsx
12
15
  function isTypingTarget(target) {
13
16
  if (!(target instanceof HTMLElement)) return false;
14
17
  const tag = target.tagName;
15
18
  return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || target.isContentEditable;
16
19
  }
17
- function ConsoleShell({ brand, breadcrumb, children, className, collapsed, collapseLabel = "Collapse sidebar", defaultCollapsed = false, expandLabel = "Expand sidebar", footer, hotkey = true, navigation, onCollapsedChange, openNavigationLabel = "Open navigation", skipToContentLabel = "Skip to content", storageKey, tools, ...rest }) {
20
+ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, closeNavigationLabel = "Close navigation", collapseLabel = "Collapse sidebar", defaultCollapsed = false, expandLabel = "Expand sidebar", footer: footerProp, loading, loadingContent, loadingNavigation, hotkey = true, navigation: navigationProp, onCollapsedChange, openNavigationLabel = "Open navigation", skipToContentLabel = "Skip to content", storageKey, tools, ...rest }) {
21
+ const navigation = loading ? loadingNavigation ?? /* @__PURE__ */ jsx(ConsoleNavSkeleton, {}) : navigationProp;
22
+ const footer = loading ? /* @__PURE__ */ jsx(ConsoleFooterSkeleton, {}) : footerProp;
23
+ const body = loading ? loadingContent ?? /* @__PURE__ */ jsx(PageLoading, {}) : children;
18
24
  const mainId = `console-main-${useId().replaceAll(":", "")}`;
19
25
  const shellRef = useRef(null);
20
26
  const isCompact = useIsCompact();
27
+ const { isDarkMode } = useThemeMode();
21
28
  const reducedMotion = usePrefersReducedMotion();
22
29
  const [storedCollapsed, setStoredCollapsed] = useLocalStorage(storageKey, defaultCollapsed);
23
30
  const [drawerOpen, setDrawerOpen] = useState(false);
@@ -60,10 +67,16 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, colla
60
67
  const sidebar = (rail) => /* @__PURE__ */ jsxs(ConsoleShellContext, {
61
68
  value: stateFor(rail),
62
69
  children: [
63
- brand ? /* @__PURE__ */ jsx("div", {
70
+ brand || isCompact ? /* @__PURE__ */ jsxs("div", {
64
71
  className: styles.brand,
65
72
  "data-collapsed": rail,
66
- children: brand
73
+ children: [brand, isCompact ? /* @__PURE__ */ jsx(Button, {
74
+ "aria-label": closeNavigationLabel,
75
+ className: styles.brandClose,
76
+ icon: X,
77
+ type: "text",
78
+ onClick: closeNavigation
79
+ }) : null]
67
80
  }) : null,
68
81
  navigation ? /* @__PURE__ */ jsx("div", {
69
82
  className: styles.navSlot,
@@ -99,6 +112,8 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, colla
99
112
  }),
100
113
  isCompact ? /* @__PURE__ */ jsx(Drawer, {
101
114
  noHeader: true,
115
+ classNames: { bodyContent: styles.drawerBody },
116
+ closable: false,
102
117
  open: drawerOpen,
103
118
  placement: "left",
104
119
  width: 272,
@@ -109,7 +124,7 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, colla
109
124
  })
110
125
  }) : null,
111
126
  /* @__PURE__ */ jsxs("div", {
112
- className: styles.workspace,
127
+ className: isDarkMode ? styles.workspace : `${styles.workspace} ${styles.workspaceLight}`,
113
128
  children: [/* @__PURE__ */ jsxs("header", {
114
129
  className: styles.topbar,
115
130
  children: [
@@ -133,10 +148,11 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, colla
133
148
  }) : null
134
149
  ]
135
150
  }), /* @__PURE__ */ jsx("main", {
151
+ "aria-busy": loading || void 0,
136
152
  className: styles.main,
137
153
  id: mainId,
138
154
  tabIndex: -1,
139
- children
155
+ children: body
140
156
  })]
141
157
  })
142
158
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"ConsoleShell.mjs","names":["Flexbox"],"sources":["../../../src/dashboard/ConsoleShell/ConsoleShell.tsx"],"sourcesContent":["'use client';\n\nimport { PanelLeft } from 'lucide-react';\nimport { useEffect, useId, useRef, useState } from 'react';\n\nimport Button from '@/base-ui/Button';\nimport { Drawer } from '@/base-ui/Drawer';\nimport { Flexbox } from '@/Flex';\n\nimport { useIsCompact, useLocalStorage, usePrefersReducedMotion } from '../hooks';\nimport { ConsoleShellContext } from './context';\nimport { styles } from './style';\nimport type { ConsoleShellProps, ConsoleShellState } from './type';\n\nfunction isTypingTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;\n}\n\nfunction ConsoleShell({\n brand,\n breadcrumb,\n children,\n className,\n collapsed,\n collapseLabel = 'Collapse sidebar',\n defaultCollapsed = false,\n expandLabel = 'Expand sidebar',\n footer,\n hotkey = true,\n navigation,\n onCollapsedChange,\n openNavigationLabel = 'Open navigation',\n skipToContentLabel = 'Skip to content',\n storageKey,\n tools,\n ...rest\n}: ConsoleShellProps) {\n const mainId = `console-main-${useId().replaceAll(':', '')}`;\n const shellRef = useRef<HTMLDivElement>(null);\n const isCompact = useIsCompact();\n const reducedMotion = usePrefersReducedMotion();\n const [storedCollapsed, setStoredCollapsed] = useLocalStorage(storageKey, defaultCollapsed);\n const [drawerOpen, setDrawerOpen] = useState(false);\n const isControlled = collapsed !== undefined;\n const railCollapsed = isControlled ? collapsed : storedCollapsed;\n const railed = railCollapsed && !isCompact;\n\n const setCollapsed = (next: boolean) => {\n if (!isControlled) setStoredCollapsed(next);\n onCollapsedChange?.(next);\n };\n\n const closeNavigation = () => setDrawerOpen(false);\n const toggleNavigation = () => {\n if (isCompact) {\n setDrawerOpen((open) => !open);\n return;\n }\n setCollapsed(!railCollapsed);\n };\n const toggleRef = useRef(toggleNavigation);\n toggleRef.current = toggleNavigation;\n\n useEffect(() => {\n if (!hotkey) return;\n const node = shellRef.current;\n if (!node) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key.toLowerCase() !== 'b' || !(event.metaKey || event.ctrlKey) || event.altKey) {\n return;\n }\n if (event.repeat || isTypingTarget(event.target)) return;\n if (!node.contains(event.target as Node)) return;\n event.preventDefault();\n toggleRef.current();\n };\n\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [hotkey]);\n\n const stateFor = (rail: boolean): ConsoleShellState => ({\n closeNavigation,\n collapsed: rail,\n compact: isCompact,\n });\n\n const sidebar = (rail: boolean) => (\n <ConsoleShellContext value={stateFor(rail)}>\n {brand ? (\n <div className={styles.brand} data-collapsed={rail}>\n {brand}\n </div>\n ) : null}\n {navigation ? <div className={styles.navSlot}>{navigation}</div> : null}\n {footer ? <div className={styles.sidebarBottom}>{footer}</div> : null}\n </ConsoleShellContext>\n );\n\n const toggleLabel = isCompact ? openNavigationLabel : railed ? expandLabel : collapseLabel;\n\n return (\n <div\n className={className ? `${styles.shell} ${className}` : styles.shell}\n data-console-shell=\"\"\n ref={shellRef}\n {...rest}\n >\n <a\n className={styles.skipLink}\n href={`#${mainId}`}\n onClick={(event) => {\n event.preventDefault();\n document.getElementById(mainId)?.focus();\n }}\n >\n {skipToContentLabel}\n </a>\n <aside className={styles.sidebar} data-collapsed={railed} data-instant={reducedMotion}>\n {!isCompact && sidebar(railed)}\n </aside>\n {isCompact ? (\n <Drawer noHeader open={drawerOpen} placement=\"left\" width={272} onClose={closeNavigation}>\n <Flexbox height=\"100%\">{sidebar(false)}</Flexbox>\n </Drawer>\n ) : null}\n <div className={styles.workspace}>\n <header className={styles.topbar}>\n <Button\n aria-label={toggleLabel}\n icon={PanelLeft}\n type=\"text\"\n onClick={toggleNavigation}\n />\n <span aria-hidden className={styles.topbarDivider} />\n <div className={styles.topbarMain}>{breadcrumb}</div>\n {tools ? <div className={styles.tools}>{tools}</div> : null}\n </header>\n <main className={styles.main} id={mainId} tabIndex={-1}>\n {children}\n </main>\n </div>\n </div>\n );\n}\n\nConsoleShell.displayName = 'ConsoleShell';\n\nexport default ConsoleShell;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConsoleShell.mjs","names":["Flexbox"],"sources":["../../../src/dashboard/ConsoleShell/ConsoleShell.tsx"],"sourcesContent":["'use client';\n\nimport { useThemeMode } from 'antd-style';\nimport { PanelLeft, X } from 'lucide-react';\nimport { useEffect, useId, useRef, useState } from 'react';\n\nimport Button from '@/base-ui/Button';\nimport { Drawer } from '@/base-ui/Drawer';\nimport { Flexbox } from '@/Flex';\n\nimport ConsoleNavSkeleton, { ConsoleFooterSkeleton } from '../ConsoleNav/Skeleton';\nimport { useIsCompact, useLocalStorage, usePrefersReducedMotion } from '../hooks';\nimport PageLoading from '../PageSkeleton';\nimport { ConsoleShellContext } from './context';\nimport { styles } from './style';\nimport type { ConsoleShellProps, ConsoleShellState } from './type';\n\nfunction isTypingTarget(target: EventTarget | null) {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;\n}\n\nfunction ConsoleShell({\n brand,\n breadcrumb,\n children,\n className,\n collapsed,\n closeNavigationLabel = 'Close navigation',\n collapseLabel = 'Collapse sidebar',\n defaultCollapsed = false,\n expandLabel = 'Expand sidebar',\n footer: footerProp,\n loading,\n loadingContent,\n loadingNavigation,\n hotkey = true,\n navigation: navigationProp,\n onCollapsedChange,\n openNavigationLabel = 'Open navigation',\n skipToContentLabel = 'Skip to content',\n storageKey,\n tools,\n ...rest\n}: ConsoleShellProps) {\n const navigation = loading ? (loadingNavigation ?? <ConsoleNavSkeleton />) : navigationProp;\n const footer = loading ? <ConsoleFooterSkeleton /> : footerProp;\n const body = loading ? (loadingContent ?? <PageLoading />) : children;\n const mainId = `console-main-${useId().replaceAll(':', '')}`;\n const shellRef = useRef<HTMLDivElement>(null);\n const isCompact = useIsCompact();\n const { isDarkMode } = useThemeMode();\n const reducedMotion = usePrefersReducedMotion();\n const [storedCollapsed, setStoredCollapsed] = useLocalStorage(storageKey, defaultCollapsed);\n const [drawerOpen, setDrawerOpen] = useState(false);\n const isControlled = collapsed !== undefined;\n const railCollapsed = isControlled ? collapsed : storedCollapsed;\n const railed = railCollapsed && !isCompact;\n\n const setCollapsed = (next: boolean) => {\n if (!isControlled) setStoredCollapsed(next);\n onCollapsedChange?.(next);\n };\n\n const closeNavigation = () => setDrawerOpen(false);\n const toggleNavigation = () => {\n if (isCompact) {\n setDrawerOpen((open) => !open);\n return;\n }\n setCollapsed(!railCollapsed);\n };\n const toggleRef = useRef(toggleNavigation);\n toggleRef.current = toggleNavigation;\n\n useEffect(() => {\n if (!hotkey) return;\n const node = shellRef.current;\n if (!node) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key.toLowerCase() !== 'b' || !(event.metaKey || event.ctrlKey) || event.altKey) {\n return;\n }\n if (event.repeat || isTypingTarget(event.target)) return;\n if (!node.contains(event.target as Node)) return;\n event.preventDefault();\n toggleRef.current();\n };\n\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [hotkey]);\n\n const stateFor = (rail: boolean): ConsoleShellState => ({\n closeNavigation,\n collapsed: rail,\n compact: isCompact,\n });\n\n const sidebar = (rail: boolean) => (\n <ConsoleShellContext value={stateFor(rail)}>\n {brand || isCompact ? (\n <div className={styles.brand} data-collapsed={rail}>\n {brand}\n {isCompact ? (\n // In the drawer the close button sits in the brand row's flow, so it never\n // overlaps a brand switcher the way the drawer's floating close button did.\n <Button\n aria-label={closeNavigationLabel}\n className={styles.brandClose}\n icon={X}\n type=\"text\"\n onClick={closeNavigation}\n />\n ) : null}\n </div>\n ) : null}\n {navigation ? <div className={styles.navSlot}>{navigation}</div> : null}\n {footer ? <div className={styles.sidebarBottom}>{footer}</div> : null}\n </ConsoleShellContext>\n );\n\n const toggleLabel = isCompact ? openNavigationLabel : railed ? expandLabel : collapseLabel;\n\n return (\n <div\n className={className ? `${styles.shell} ${className}` : styles.shell}\n data-console-shell=\"\"\n ref={shellRef}\n {...rest}\n >\n <a\n className={styles.skipLink}\n href={`#${mainId}`}\n onClick={(event) => {\n event.preventDefault();\n document.getElementById(mainId)?.focus();\n }}\n >\n {skipToContentLabel}\n </a>\n <aside className={styles.sidebar} data-collapsed={railed} data-instant={reducedMotion}>\n {!isCompact && sidebar(railed)}\n </aside>\n {isCompact ? (\n <Drawer\n noHeader\n classNames={{ bodyContent: styles.drawerBody }}\n closable={false}\n open={drawerOpen}\n placement=\"left\"\n width={272}\n onClose={closeNavigation}\n >\n <Flexbox height=\"100%\">{sidebar(false)}</Flexbox>\n </Drawer>\n ) : null}\n <div\n className={isDarkMode ? styles.workspace : `${styles.workspace} ${styles.workspaceLight}`}\n >\n <header className={styles.topbar}>\n <Button\n aria-label={toggleLabel}\n icon={PanelLeft}\n type=\"text\"\n onClick={toggleNavigation}\n />\n <span aria-hidden className={styles.topbarDivider} />\n <div className={styles.topbarMain}>{breadcrumb}</div>\n {tools ? <div className={styles.tools}>{tools}</div> : null}\n </header>\n <main aria-busy={loading || undefined} className={styles.main} id={mainId} tabIndex={-1}>\n {body}\n </main>\n </div>\n </div>\n );\n}\n\nConsoleShell.displayName = 'ConsoleShell';\n\nexport default ConsoleShell;\n"],"mappings":"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"}