@lobehub/ui 5.59.0 → 5.61.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 (164) hide show
  1. package/es/ActionIcon/style.mjs +8 -2
  2. package/es/ActionIcon/style.mjs.map +1 -1
  3. package/es/EmojiPicker/AvatarUploader.mjs +1 -1
  4. package/es/Form/components/FormSubmitFooter.mjs +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.d.mts +1 -1
  17. package/es/base-ui/Pagination/Pagination.mjs +158 -41
  18. package/es/base-ui/Pagination/Pagination.mjs.map +1 -1
  19. package/es/base-ui/Pagination/helpers.mjs +3 -3
  20. package/es/base-ui/Pagination/helpers.mjs.map +1 -1
  21. package/es/base-ui/Pagination/index.d.mts +2 -2
  22. package/es/base-ui/Pagination/style.mjs +39 -0
  23. package/es/base-ui/Pagination/style.mjs.map +1 -1
  24. package/es/base-ui/Pagination/type.d.mts +42 -4
  25. package/es/base-ui/QRCode/QRCode.mjs +1 -1
  26. package/es/base-ui/Table/Column.d.mts +9 -0
  27. package/es/base-ui/Table/Column.mjs +7 -0
  28. package/es/base-ui/Table/Column.mjs.map +1 -0
  29. package/es/base-ui/Table/ColumnGroup.d.mts +12 -0
  30. package/es/base-ui/Table/ColumnGroup.mjs +7 -0
  31. package/es/base-ui/Table/ColumnGroup.mjs.map +1 -0
  32. package/es/base-ui/Table/ExpandIcon.mjs +33 -0
  33. package/es/base-ui/Table/ExpandIcon.mjs.map +1 -0
  34. package/es/base-ui/Table/FilterDropdown.mjs +284 -0
  35. package/es/base-ui/Table/FilterDropdown.mjs.map +1 -0
  36. package/es/base-ui/Table/LoadingSkeleton.mjs +83 -0
  37. package/es/base-ui/Table/LoadingSkeleton.mjs.map +1 -0
  38. package/es/base-ui/Table/Table.d.mts +21 -3
  39. package/es/base-ui/Table/Table.mjs +444 -97
  40. package/es/base-ui/Table/Table.mjs.map +1 -1
  41. package/es/base-ui/Table/columnUtils.mjs +56 -0
  42. package/es/base-ui/Table/columnUtils.mjs.map +1 -0
  43. package/es/base-ui/Table/index.d.mts +4 -2
  44. package/es/base-ui/Table/selectionUtils.d.mts +9 -0
  45. package/es/base-ui/Table/selectionUtils.mjs +128 -0
  46. package/es/base-ui/Table/selectionUtils.mjs.map +1 -0
  47. package/es/base-ui/Table/semantic.mjs +55 -0
  48. package/es/base-ui/Table/semantic.mjs.map +1 -0
  49. package/es/base-ui/Table/style.mjs +801 -161
  50. package/es/base-ui/Table/style.mjs.map +1 -1
  51. package/es/base-ui/Table/type.d.mts +471 -37
  52. package/es/base-ui/Table/useBreakpoint.mjs +41 -0
  53. package/es/base-ui/Table/useBreakpoint.mjs.map +1 -0
  54. package/es/base-ui/Table/useFilter.mjs +64 -0
  55. package/es/base-ui/Table/useFilter.mjs.map +1 -0
  56. package/es/base-ui/Table/useSelection.mjs +421 -0
  57. package/es/base-ui/Table/useSelection.mjs.map +1 -0
  58. package/es/base-ui/Table/useSorter.mjs +152 -0
  59. package/es/base-ui/Table/useSorter.mjs.map +1 -0
  60. package/es/base-ui/Table/useTableState.mjs +82 -55
  61. package/es/base-ui/Table/useTableState.mjs.map +1 -1
  62. package/es/base-ui/index.d.mts +6 -4
  63. package/es/base-ui/index.mjs +9 -9
  64. package/es/chat/EditableMessageList/EditableMessageList.mjs +1 -1
  65. package/es/chat/MessageInput/MessageInput.mjs +1 -1
  66. package/es/chat/MessageModal/MessageModal.mjs +1 -1
  67. package/es/chat/TokenTag/TokenTag.mjs +1 -1
  68. package/es/dashboard/AuthLayout/Aside.d.mts +10 -0
  69. package/es/dashboard/AuthLayout/Aside.mjs +30 -0
  70. package/es/dashboard/AuthLayout/Aside.mjs.map +1 -0
  71. package/es/dashboard/AuthLayout/AuthLayout.d.mts +3 -1
  72. package/es/dashboard/AuthLayout/AuthLayout.mjs +93 -37
  73. package/es/dashboard/AuthLayout/AuthLayout.mjs.map +1 -1
  74. package/es/dashboard/AuthLayout/index.d.mts +3 -2
  75. package/es/dashboard/AuthLayout/style.mjs +120 -1
  76. package/es/dashboard/AuthLayout/style.mjs.map +1 -1
  77. package/es/dashboard/AuthLayout/type.d.mts +39 -3
  78. package/es/dashboard/AuthTools/AuthLocaleSwitch.d.mts +10 -0
  79. package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs +32 -0
  80. package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs.map +1 -0
  81. package/es/dashboard/AuthTools/AuthThemeSwitch.d.mts +10 -0
  82. package/es/dashboard/AuthTools/AuthThemeSwitch.mjs +59 -0
  83. package/es/dashboard/AuthTools/AuthThemeSwitch.mjs.map +1 -0
  84. package/es/dashboard/AuthTools/index.d.mts +4 -0
  85. package/es/dashboard/AuthTools/style.mjs +63 -0
  86. package/es/dashboard/AuthTools/style.mjs.map +1 -0
  87. package/es/dashboard/AuthTools/type.d.mts +30 -0
  88. package/es/dashboard/ConsoleNav/Skeleton.d.mts +15 -0
  89. package/es/dashboard/ConsoleNav/Skeleton.mjs +81 -0
  90. package/es/dashboard/ConsoleNav/Skeleton.mjs.map +1 -0
  91. package/es/dashboard/ConsoleNav/index.d.mts +3 -2
  92. package/es/dashboard/ConsoleNav/style.mjs +15 -0
  93. package/es/dashboard/ConsoleNav/style.mjs.map +1 -1
  94. package/es/dashboard/ConsoleNav/type.d.mts +14 -1
  95. package/es/dashboard/ConsoleShell/ConsoleShell.d.mts +1 -1
  96. package/es/dashboard/ConsoleShell/ConsoleShell.mjs +11 -3
  97. package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -1
  98. package/es/dashboard/ConsoleShell/style.mjs +6 -0
  99. package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
  100. package/es/dashboard/ConsoleShell/type.d.mts +9 -0
  101. package/es/dashboard/FilterSidebar/FilterSidebar.mjs +18 -17
  102. package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -1
  103. package/es/dashboard/FilterStrip/FilterStrip.mjs +36 -32
  104. package/es/dashboard/FilterStrip/FilterStrip.mjs.map +1 -1
  105. package/es/dashboard/FilterStrip/style.mjs +2 -1
  106. package/es/dashboard/FilterStrip/style.mjs.map +1 -1
  107. package/es/dashboard/MetricStrip/MetricCell.mjs +81 -0
  108. package/es/dashboard/MetricStrip/MetricCell.mjs.map +1 -0
  109. package/es/dashboard/MetricStrip/MetricStrip.d.mts +5 -2
  110. package/es/dashboard/MetricStrip/MetricStrip.mjs +33 -62
  111. package/es/dashboard/MetricStrip/MetricStrip.mjs.map +1 -1
  112. package/es/dashboard/MetricStrip/style.mjs +49 -4
  113. package/es/dashboard/MetricStrip/style.mjs.map +1 -1
  114. package/es/dashboard/MetricStrip/type.d.mts +12 -0
  115. package/es/dashboard/PageSkeleton/PageSkeleton.mjs +20 -18
  116. package/es/dashboard/PageSkeleton/PageSkeleton.mjs.map +1 -1
  117. package/es/dashboard/PageSkeleton/style.mjs +1 -1
  118. package/es/dashboard/PageSkeleton/style.mjs.map +1 -1
  119. package/es/dashboard/PanelSurface/PanelSurface.mjs +4 -1
  120. package/es/dashboard/PanelSurface/PanelSurface.mjs.map +1 -1
  121. package/es/dashboard/StatCard/StatCard.d.mts +2 -1
  122. package/es/dashboard/StatCard/StatCard.mjs +24 -72
  123. package/es/dashboard/StatCard/StatCard.mjs.map +1 -1
  124. package/es/dashboard/StatCard/type.d.mts +16 -5
  125. package/es/dashboard/Surface/Surface.mjs +26 -10
  126. package/es/dashboard/Surface/Surface.mjs.map +1 -1
  127. package/es/dashboard/Surface/index.d.mts +2 -2
  128. package/es/dashboard/Surface/link.d.mts +6 -1
  129. package/es/dashboard/Surface/link.mjs +12 -1
  130. package/es/dashboard/Surface/link.mjs.map +1 -1
  131. package/es/dashboard/Surface/style.d.mts +22 -3
  132. package/es/dashboard/Surface/style.mjs +95 -26
  133. package/es/dashboard/Surface/style.mjs.map +1 -1
  134. package/es/dashboard/index.d.mts +10 -4
  135. package/es/dashboard/index.mjs +7 -3
  136. package/es/i18n/resources/en/index.d.mts +3 -2
  137. package/es/i18n/resources/en/index.mjs +4 -2
  138. package/es/i18n/resources/en/index.mjs.map +1 -1
  139. package/es/i18n/resources/en/table.d.mts +23 -0
  140. package/es/i18n/resources/en/table.mjs +24 -0
  141. package/es/i18n/resources/en/table.mjs.map +1 -0
  142. package/es/i18n/resources/zhCn/index.d.mts +3 -2
  143. package/es/i18n/resources/zhCn/index.mjs +4 -2
  144. package/es/i18n/resources/zhCn/index.mjs.map +1 -1
  145. package/es/i18n/resources/zhCn/table.d.mts +23 -0
  146. package/es/i18n/resources/zhCn/table.mjs +24 -0
  147. package/es/i18n/resources/zhCn/table.mjs.map +1 -0
  148. package/es/i18n/types.d.mts +2 -1
  149. package/es/index.mjs +2 -2
  150. package/package.json +2 -2
  151. package/es/base-ui/Table/FilterMenu.mjs +0 -45
  152. package/es/base-ui/Table/FilterMenu.mjs.map +0 -1
  153. package/es/base-ui/Table/TableBody.mjs +0 -59
  154. package/es/base-ui/Table/TableBody.mjs.map +0 -1
  155. package/es/base-ui/Table/TableHead.mjs +0 -50
  156. package/es/base-ui/Table/TableHead.mjs.map +0 -1
  157. package/es/base-ui/Table/features.mjs +0 -12
  158. package/es/base-ui/Table/features.mjs.map +0 -1
  159. package/es/base-ui/Table/fixedOffsets.mjs +0 -29
  160. package/es/base-ui/Table/fixedOffsets.mjs.map +0 -1
  161. package/es/base-ui/Table/toColumnDefs.mjs +0 -26
  162. package/es/base-ui/Table/toColumnDefs.mjs.map +0 -1
  163. package/es/dashboard/StatCard/style.mjs +0 -135
  164. package/es/dashboard/StatCard/style.mjs.map +0 -1
@@ -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,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, closeNavigationLabel, 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,9 +4,12 @@ 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";
12
+ import { useThemeMode } from "antd-style";
10
13
  import { PanelLeft, X } from "lucide-react";
11
14
  //#region src/dashboard/ConsoleShell/ConsoleShell.tsx
12
15
  function isTypingTarget(target) {
@@ -14,10 +17,14 @@ function isTypingTarget(target) {
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, closeNavigationLabel = "Close navigation", 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);
@@ -117,7 +124,7 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, close
117
124
  })
118
125
  }) : null,
119
126
  /* @__PURE__ */ jsxs("div", {
120
- className: styles.workspace,
127
+ className: isDarkMode ? styles.workspace : `${styles.workspace} ${styles.workspaceLight}`,
121
128
  children: [/* @__PURE__ */ jsxs("header", {
122
129
  className: styles.topbar,
123
130
  children: [
@@ -141,10 +148,11 @@ function ConsoleShell({ brand, breadcrumb, children, className, collapsed, close
141
148
  }) : null
142
149
  ]
143
150
  }), /* @__PURE__ */ jsx("main", {
151
+ "aria-busy": loading || void 0,
144
152
  className: styles.main,
145
153
  id: mainId,
146
154
  tabIndex: -1,
147
- children
155
+ children: body
148
156
  })]
149
157
  })
150
158
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"ConsoleShell.mjs","names":["Flexbox"],"sources":["../../../src/dashboard/ConsoleShell/ConsoleShell.tsx"],"sourcesContent":["'use client';\n\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 { 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 closeNavigationLabel = 'Close navigation',\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 || 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 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":";;;;;;;;;;;;;;AAiBA,SAAS,eAAe,QAA4B;CAClD,IAAI,EAAE,kBAAkB,cAAc,OAAO;CAC7C,MAAM,MAAM,OAAO;CACnB,OAAO,QAAQ,WAAW,QAAQ,cAAc,QAAQ,YAAY,OAAO;AAC7E;AAEA,SAAS,aAAa,EACpB,OACA,YACA,UACA,WACA,WACA,uBAAuB,oBACvB,gBAAgB,oBAChB,mBAAmB,OACnB,cAAc,kBACd,QAAQ,YACR,SACA,gBACA,mBACA,SAAS,MACT,YAAY,gBACZ,mBACA,sBAAsB,mBACtB,qBAAqB,mBACrB,YACA,OACA,GAAG,QACiB;CACpB,MAAM,aAAa,UAAW,qBAAqB,oBAAC,oBAAD,CAAqB,CAAA,IAAK;CAC7E,MAAM,SAAS,UAAU,oBAAC,uBAAD,CAAwB,CAAA,IAAI;CACrD,MAAM,OAAO,UAAW,kBAAkB,oBAAC,aAAD,CAAc,CAAA,IAAK;CAC7D,MAAM,SAAS,gBAAgB,MAAM,CAAC,CAAC,WAAW,KAAK,EAAE;CACzD,MAAM,WAAW,OAAuB,IAAI;CAC5C,MAAM,YAAY,aAAa;CAC/B,MAAM,EAAE,eAAe,aAAa;CACpC,MAAM,gBAAgB,wBAAwB;CAC9C,MAAM,CAAC,iBAAiB,sBAAsB,gBAAgB,YAAY,gBAAgB;CAC1F,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,eAAe,cAAc,KAAA;CACnC,MAAM,gBAAgB,eAAe,YAAY;CACjD,MAAM,SAAS,iBAAiB,CAAC;CAEjC,MAAM,gBAAgB,SAAkB;EACtC,IAAI,CAAC,cAAc,mBAAmB,IAAI;EAC1C,oBAAoB,IAAI;CAC1B;CAEA,MAAM,wBAAwB,cAAc,KAAK;CACjD,MAAM,yBAAyB;EAC7B,IAAI,WAAW;GACb,eAAe,SAAS,CAAC,IAAI;GAC7B;EACF;EACA,aAAa,CAAC,aAAa;CAC7B;CACA,MAAM,YAAY,OAAO,gBAAgB;CACzC,UAAU,UAAU;CAEpB,gBAAgB;EACd,IAAI,CAAC,QAAQ;EACb,MAAM,OAAO,SAAS;EACtB,IAAI,CAAC,MAAM;EAEX,MAAM,aAAa,UAAyB;GAC1C,IAAI,MAAM,IAAI,YAAY,MAAM,OAAO,EAAE,MAAM,WAAW,MAAM,YAAY,MAAM,QAChF;GAEF,IAAI,MAAM,UAAU,eAAe,MAAM,MAAM,GAAG;GAClD,IAAI,CAAC,KAAK,SAAS,MAAM,MAAc,GAAG;GAC1C,MAAM,eAAe;GACrB,UAAU,QAAQ;EACpB;EAEA,SAAS,iBAAiB,WAAW,SAAS;EAC9C,aAAa,SAAS,oBAAoB,WAAW,SAAS;CAChE,GAAG,CAAC,MAAM,CAAC;CAEX,MAAM,YAAY,UAAsC;EACtD;EACA,WAAW;EACX,SAAS;CACX;CAEA,MAAM,WAAW,SACf,qBAAC,qBAAD;EAAqB,OAAO,SAAS,IAAI;EAAzC,UAAA;GACG,SAAS,YACR,qBAAC,OAAD;IAAK,WAAW,OAAO;IAAO,kBAAgB;IAA9C,UAAA,CACG,OACA,YAGC,oBAAC,QAAD;KACE,cAAY;KACZ,WAAW,OAAO;KAClB,MAAM;KACN,MAAK;KACL,SAAS;IACV,CAAA,IACC,IACD;GACH,CAAA,IAAA;GACH,aAAa,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAU,UAAA;GAAgB,CAAA,IAAI;GAClE,SAAS,oBAAC,OAAD;IAAK,WAAW,OAAO;IAAgB,UAAA;GAAY,CAAA,IAAI;EAC9C;;CAGvB,MAAM,cAAc,YAAY,sBAAsB,SAAS,cAAc;CAE7E,OACE,qBAAC,OAAD;EACE,WAAW,YAAY,GAAG,OAAO,MAAM,GAAG,cAAc,OAAO;EAC/D,sBAAmB;EACnB,KAAK;EACL,GAAI;EAJN,UAAA;GAME,oBAAC,KAAD;IACE,WAAW,OAAO;IAClB,MAAM,IAAI;IACV,UAAU,UAAU;KAClB,MAAM,eAAe;KACrB,SAAS,eAAe,MAAM,CAAC,EAAE,MAAM;IACzC;IAEC,UAAA;GACA,CAAA;GACH,oBAAC,SAAD;IAAO,WAAW,OAAO;IAAS,kBAAgB;IAAQ,gBAAc;IACrE,UAAA,CAAC,aAAa,QAAQ,MAAM;GACxB,CAAA;GACN,YACC,oBAAC,QAAD;IACE,UAAA;IACA,YAAY,EAAE,aAAa,OAAO,WAAW;IAC7C,UAAU;IACV,MAAM;IACN,WAAU;IACV,OAAO;IACP,SAAS;IAET,UAAA,oBAACA,mBAAD;KAAS,QAAO;KAAQ,UAAA,QAAQ,KAAK;IAAW,CAAA;GAC1C,CAAA,IACN;GACJ,qBAAC,OAAD;IACE,WAAW,aAAa,OAAO,YAAY,GAAG,OAAO,UAAU,GAAG,OAAO;IAD3E,UAAA,CAGE,qBAAC,UAAD;KAAQ,WAAW,OAAO;KAA1B,UAAA;MACE,oBAAC,QAAD;OACE,cAAY;OACZ,MAAM;OACN,MAAK;OACL,SAAS;MACV,CAAA;MACD,oBAAC,QAAD;OAAM,eAAA;OAAY,WAAW,OAAO;MAAgB,CAAA;MACpD,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAa,UAAA;MAAgB,CAAA;MACnD,QAAQ,oBAAC,OAAD;OAAK,WAAW,OAAO;OAAQ,UAAA;MAAW,CAAA,IAAI;KACjD;IACR,CAAA,GAAA,oBAAC,QAAD;KAAM,aAAW,WAAW,KAAA;KAAW,WAAW,OAAO;KAAM,IAAI;KAAQ,UAAU;KAClF,UAAA;IACG,CAAA,CACH;;EACF;;AAET;AAEA,aAAa,cAAc"}
@@ -197,6 +197,12 @@ const styles = createStaticStyles(({ css, cssVar, responsive }) => ({
197
197
  align-items: center;
198
198
 
199
199
  margin-inline-start: auto;
200
+ `,
201
+ /** Light only: the content area sits midway between the layout canvas and container white. */
202
+ workspaceLight: css`
203
+ && {
204
+ background: color-mix(in srgb, ${cssVar.colorBgLayout} 50%, ${cssVar.colorBgContainer});
205
+ }
200
206
  `,
201
207
  workspace: css`
202
208
  overflow: hidden;
@@ -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;\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 /** Close button in the drawer's brand row: right edge, vertically centred with the brand. */\n brandClose: css`\n flex: none;\n margin-inline: auto -7px;\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 /**\n * The drawer body is the scroll container. Without its default padding the scrollbar sits on\n * the panel edge; the brand row, nav and footer keep their own insets.\n */\n drawerBody: css`\n && {\n min-block-size: 100%;\n padding: 0;\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;;;;;CAKtB,YAAY,GAAG;;;;CAIf,aAAa,GAAG;;;;;;;;;;CAUhB,aAAa,GAAG;;;;;;CAMhB,WAAW,GAAG;;;;;;aAMH,OAAO,UAAU;;;;;;;;;;;;;;;;CAgB5B,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;MAqBL,WAAW,OAAO;;;;;;;;;CAStB,YAAY,GAAG;;;;;;CAMf,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"}
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 /** Close button in the drawer's brand row: right edge, vertically centred with the brand. */\n brandClose: css`\n flex: none;\n margin-inline: auto -7px;\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 /**\n * The drawer body is the scroll container. Without its default padding the scrollbar sits on\n * the panel edge; the brand row, nav and footer keep their own insets.\n */\n drawerBody: css`\n && {\n min-block-size: 100%;\n padding: 0;\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 /** Light only: the content area sits midway between the layout canvas and container white. */\n workspaceLight: css`\n && {\n background: color-mix(in srgb, ${cssVar.colorBgLayout} 50%, ${cssVar.colorBgContainer});\n }\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;;;;;CAKtB,YAAY,GAAG;;;;CAIf,aAAa,GAAG;;;;;;;;;;CAUhB,aAAa,GAAG;;;;;;CAMhB,WAAW,GAAG;;;;;;aAMH,OAAO,UAAU;;;;;;;;;;;;;;;;CAgB5B,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;MAqBL,WAAW,OAAO;;;;;;;;;CAStB,YAAY,GAAG;;;;;;CAMf,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;;;;;;;;;CASV,gBAAgB,GAAG;;uCAEkB,OAAO,cAAc,QAAQ,OAAO,iBAAiB;;;CAG1F,WAAW,GAAG;;;;;;;;oBAQI,gBAAgB;uBACb,gBAAgB;wBACf,OAAO,qBAAqB;qBAC/B,OAAO,eAAe;;kBAEzB,OAAO,iBAAiB;kBACxB,OAAO,kBAAkB;;MAErC,WAAW,OAAO;;;;;;;AAOxB,EAAE"}
@@ -52,6 +52,15 @@ interface ConsoleShellProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'
52
52
  * @default true
53
53
  */
54
54
  hotkey?: boolean;
55
+ /**
56
+ * Swap navigation and footer for skeletons, and render `loadingContent` (default `PageLoading`)
57
+ * in place of children. Brand, tools and `storageKey` still come from the caller.
58
+ */
59
+ loading?: boolean;
60
+ /** Body while `loading`. Defaults to `<PageLoading />`. */
61
+ loadingContent?: ReactNode;
62
+ /** Skeleton nav shape while `loading`. Pass the real groups to mirror their row counts. */
63
+ loadingNavigation?: ReactNode;
55
64
  /** Grouped navigation. Collapsed state comes from the shell. */
56
65
  navigation?: ReactNode;
57
66
  onCollapsedChange?: (collapsed: boolean) => void;
@@ -2,10 +2,10 @@
2
2
  import Button from "../../base-ui/Button/Button.mjs";
3
3
  import Drawer from "../../base-ui/Drawer/Drawer.mjs";
4
4
  import DraggablePanel from "../../base-ui/DraggablePanel/DraggablePanel.mjs";
5
- import { styles } from "../Surface/style.mjs";
5
+ import { useSurfaceCardClassName } from "../Surface/link.mjs";
6
6
  import { useIsCompact, useLocalStorage } from "../hooks.mjs";
7
7
  import { FilterSplitProvider } from "./context.mjs";
8
- import { styles as styles$1 } from "./style.mjs";
8
+ import { styles } from "./style.mjs";
9
9
  import { clampSidebarWidth, sidebarWidth } from "./width.mjs";
10
10
  import { useState } from "react";
11
11
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -34,6 +34,7 @@ function usePageSidebar(wide, storageKey) {
34
34
  };
35
35
  }
36
36
  function FilterSidebar({ body, children, flush, head, header, label, storageKey, summary, wide }) {
37
+ const cardClassName = useSurfaceCardClassName();
37
38
  const isCompact = useIsCompact();
38
39
  const [drawerOpen, setDrawerOpen] = useState(false);
39
40
  const sidebar = usePageSidebar(wide, storageKey);
@@ -41,7 +42,7 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
41
42
  if (isCompact) return /* @__PURE__ */ jsx(FilterSplitProvider, {
42
43
  active: !flush,
43
44
  children: /* @__PURE__ */ jsxs("div", {
44
- className: styles$1.layout,
45
+ className: styles.layout,
45
46
  children: [
46
47
  header,
47
48
  /* @__PURE__ */ jsx(Button, {
@@ -57,12 +58,12 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
57
58
  width: 300,
58
59
  onClose: close,
59
60
  children: /* @__PURE__ */ jsxs("div", {
60
- className: styles$1.drawerPanel,
61
+ className: styles.drawerPanel,
61
62
  children: [head?.(close), body(close)]
62
63
  })
63
64
  }),
64
65
  /* @__PURE__ */ jsx("div", {
65
- className: styles$1.content,
66
+ className: styles.content,
66
67
  children
67
68
  })
68
69
  ]
@@ -71,7 +72,7 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
71
72
  return /* @__PURE__ */ jsx(FilterSplitProvider, {
72
73
  active: !flush,
73
74
  children: /* @__PURE__ */ jsxs("div", {
74
- className: flush ? styles$1.layout : `${styles$1.layout} ${styles.card}`,
75
+ className: flush ? styles.layout : `${styles.layout} ${cardClassName}`,
75
76
  "data-flush": flush ? true : void 0,
76
77
  "data-page-layout": flush ? "flush" : void 0,
77
78
  "data-split-card": flush ? void 0 : true,
@@ -79,8 +80,8 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
79
80
  expandable: true,
80
81
  showHandleWhenCollapsed: true,
81
82
  "aria-label": label,
82
- className: styles$1.sidebar,
83
- classNames: { content: styles$1.panel },
83
+ className: styles.sidebar,
84
+ classNames: { content: styles.panel },
84
85
  collapseThreshold: sidebarWidth.collapse,
85
86
  "data-flush": flush ? true : void 0,
86
87
  defaultSize: { width: wide ? sidebarWidth.wide : sidebarWidth.narrow },
@@ -94,15 +95,15 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
94
95
  onExpandChange: sidebar.onExpandChange,
95
96
  onSizeChange: (_delta, size) => sidebar.onSizeChange(size),
96
97
  children: [head ? /* @__PURE__ */ jsx("div", {
97
- className: styles$1.head,
98
+ className: styles.head,
98
99
  children: head(close)
99
100
  }) : null, /* @__PURE__ */ jsx("div", {
100
- className: styles$1.body,
101
+ className: styles.body,
101
102
  "data-flush": flush ? true : void 0,
102
103
  children: body(close)
103
104
  })]
104
105
  }), /* @__PURE__ */ jsxs("div", {
105
- className: styles$1.content,
106
+ className: styles.content,
106
107
  "data-flush": flush ? true : void 0,
107
108
  children: [header, children]
108
109
  })]
@@ -112,12 +113,12 @@ function FilterSidebar({ body, children, flush, head, header, label, storageKey,
112
113
  FilterSidebar.displayName = "FilterSidebar";
113
114
  function FilterRow({ count, name }) {
114
115
  return /* @__PURE__ */ jsxs("span", {
115
- className: styles$1.row,
116
+ className: styles.row,
116
117
  children: [/* @__PURE__ */ jsx("span", {
117
- className: styles$1.name,
118
+ className: styles.name,
118
119
  children: name
119
120
  }), count !== void 0 ? /* @__PURE__ */ jsx("span", {
120
- className: styles$1.count,
121
+ className: styles.count,
121
122
  children: count
122
123
  }) : null]
123
124
  });
@@ -127,18 +128,18 @@ function FilterOption({ count, icon, label, name, onClick, selected, title }) {
127
128
  return /* @__PURE__ */ jsxs("button", {
128
129
  "aria-label": label,
129
130
  "aria-pressed": selected,
130
- className: styles$1.option,
131
+ className: styles.option,
131
132
  title,
132
133
  type: "button",
133
134
  onClick,
134
135
  children: [
135
136
  icon,
136
137
  /* @__PURE__ */ jsx("span", {
137
- className: styles$1.name,
138
+ className: styles.name,
138
139
  children: name
139
140
  }),
140
141
  count !== void 0 ? /* @__PURE__ */ jsx("span", {
141
- className: styles$1.count,
142
+ className: styles.count,
142
143
  children: count
143
144
  }) : null
144
145
  ]