@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.
- package/es/ActionIcon/style.mjs +8 -2
- package/es/ActionIcon/style.mjs.map +1 -1
- package/es/Grid/style.mjs +8 -8
- package/es/Grid/style.mjs.map +1 -1
- package/es/awesome/Grainient/Grainient.d.mts +11 -0
- package/es/awesome/Grainient/Grainient.mjs +311 -0
- package/es/awesome/Grainient/Grainient.mjs.map +1 -0
- package/es/awesome/Grainient/index.d.mts +3 -0
- package/es/awesome/Grainient/style.mjs +25 -0
- package/es/awesome/Grainient/style.mjs.map +1 -0
- package/es/awesome/Grainient/type.d.mts +122 -0
- package/es/awesome/index.d.mts +4 -1
- package/es/awesome/index.mjs +2 -1
- package/es/base-ui/ActionIcon/style.mjs +8 -2
- package/es/base-ui/ActionIcon/style.mjs.map +1 -1
- package/es/base-ui/Input/style.mjs +8 -2
- package/es/base-ui/Input/style.mjs.map +1 -1
- package/es/dashboard/AuthLayout/Aside.d.mts +10 -0
- package/es/dashboard/AuthLayout/Aside.mjs +30 -0
- package/es/dashboard/AuthLayout/Aside.mjs.map +1 -0
- package/es/dashboard/AuthLayout/AuthLayout.d.mts +3 -1
- package/es/dashboard/AuthLayout/AuthLayout.mjs +93 -37
- package/es/dashboard/AuthLayout/AuthLayout.mjs.map +1 -1
- package/es/dashboard/AuthLayout/index.d.mts +3 -2
- package/es/dashboard/AuthLayout/style.mjs +120 -1
- package/es/dashboard/AuthLayout/style.mjs.map +1 -1
- package/es/dashboard/AuthLayout/type.d.mts +39 -3
- package/es/dashboard/AuthTools/AuthLocaleSwitch.d.mts +10 -0
- package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs +32 -0
- package/es/dashboard/AuthTools/AuthLocaleSwitch.mjs.map +1 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.d.mts +10 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.mjs +59 -0
- package/es/dashboard/AuthTools/AuthThemeSwitch.mjs.map +1 -0
- package/es/dashboard/AuthTools/index.d.mts +4 -0
- package/es/dashboard/AuthTools/style.mjs +63 -0
- package/es/dashboard/AuthTools/style.mjs.map +1 -0
- package/es/dashboard/AuthTools/type.d.mts +30 -0
- package/es/dashboard/ChartGrid/ChartGrid.d.mts +10 -0
- package/es/dashboard/ChartGrid/ChartGrid.mjs +18 -0
- package/es/dashboard/ChartGrid/ChartGrid.mjs.map +1 -0
- package/es/dashboard/ChartGrid/index.d.mts +3 -0
- package/es/dashboard/ChartGrid/style.mjs +32 -0
- package/es/dashboard/ChartGrid/style.mjs.map +1 -0
- package/es/dashboard/ChartGrid/type.d.mts +9 -0
- package/es/dashboard/ConsoleNav/Skeleton.d.mts +15 -0
- package/es/dashboard/ConsoleNav/Skeleton.mjs +81 -0
- package/es/dashboard/ConsoleNav/Skeleton.mjs.map +1 -0
- package/es/dashboard/ConsoleNav/index.d.mts +3 -2
- package/es/dashboard/ConsoleNav/style.mjs +15 -0
- package/es/dashboard/ConsoleNav/style.mjs.map +1 -1
- package/es/dashboard/ConsoleNav/type.d.mts +14 -1
- package/es/dashboard/ConsoleShell/ConsoleShell.d.mts +1 -1
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs +22 -6
- package/es/dashboard/ConsoleShell/ConsoleShell.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/style.mjs +21 -0
- package/es/dashboard/ConsoleShell/style.mjs.map +1 -1
- package/es/dashboard/ConsoleShell/type.d.mts +11 -0
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs +18 -17
- package/es/dashboard/FilterSidebar/FilterSidebar.mjs.map +1 -1
- package/es/dashboard/FilterStrip/FilterStrip.d.mts +11 -0
- package/es/dashboard/FilterStrip/FilterStrip.mjs +55 -0
- package/es/dashboard/FilterStrip/FilterStrip.mjs.map +1 -0
- package/es/dashboard/FilterStrip/index.d.mts +3 -0
- package/es/dashboard/FilterStrip/style.mjs +94 -0
- package/es/dashboard/FilterStrip/style.mjs.map +1 -0
- package/es/dashboard/FilterStrip/type.d.mts +26 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.d.mts +10 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.mjs +18 -0
- package/es/dashboard/LabelWithKey/LabelWithKey.mjs.map +1 -0
- package/es/dashboard/LabelWithKey/index.d.mts +3 -0
- package/es/dashboard/LabelWithKey/type.d.mts +12 -0
- package/es/dashboard/MetricStrip/MetricCell.mjs +81 -0
- package/es/dashboard/MetricStrip/MetricCell.mjs.map +1 -0
- package/es/dashboard/MetricStrip/MetricStrip.d.mts +13 -0
- package/es/dashboard/MetricStrip/MetricStrip.mjs +47 -0
- package/es/dashboard/MetricStrip/MetricStrip.mjs.map +1 -0
- package/es/dashboard/MetricStrip/index.d.mts +3 -0
- package/es/dashboard/MetricStrip/style.mjs +161 -0
- package/es/dashboard/MetricStrip/style.mjs.map +1 -0
- package/es/dashboard/MetricStrip/type.d.mts +37 -0
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs +20 -18
- package/es/dashboard/PageSkeleton/PageSkeleton.mjs.map +1 -1
- package/es/dashboard/PageSkeleton/style.mjs +1 -1
- package/es/dashboard/PageSkeleton/style.mjs.map +1 -1
- package/es/dashboard/PageToolbar/PageToolbar.d.mts +10 -0
- package/es/dashboard/PageToolbar/PageToolbar.mjs +21 -0
- package/es/dashboard/PageToolbar/PageToolbar.mjs.map +1 -0
- package/es/dashboard/PageToolbar/index.d.mts +3 -0
- package/es/dashboard/PageToolbar/style.mjs +34 -0
- package/es/dashboard/PageToolbar/style.mjs.map +1 -0
- package/es/dashboard/PageToolbar/type.d.mts +12 -0
- package/es/dashboard/PanelSurface/PanelSurface.d.mts +10 -0
- package/es/dashboard/PanelSurface/PanelSurface.mjs +39 -0
- package/es/dashboard/PanelSurface/PanelSurface.mjs.map +1 -0
- package/es/dashboard/PanelSurface/index.d.mts +3 -0
- package/es/dashboard/PanelSurface/style.mjs +24 -0
- package/es/dashboard/PanelSurface/style.mjs.map +1 -0
- package/es/dashboard/PanelSurface/type.d.mts +18 -0
- package/es/dashboard/Section/Section.d.mts +10 -0
- package/es/dashboard/Section/Section.mjs +81 -0
- package/es/dashboard/Section/Section.mjs.map +1 -0
- package/es/dashboard/Section/index.d.mts +3 -0
- package/es/dashboard/Section/style.mjs +35 -0
- package/es/dashboard/Section/style.mjs.map +1 -0
- package/es/dashboard/Section/type.d.mts +24 -0
- package/es/dashboard/StatCard/StatCard.d.mts +2 -1
- package/es/dashboard/StatCard/StatCard.mjs +24 -72
- package/es/dashboard/StatCard/StatCard.mjs.map +1 -1
- package/es/dashboard/StatCard/type.d.mts +16 -5
- package/es/dashboard/Surface/Surface.d.mts +4 -3
- package/es/dashboard/Surface/Surface.mjs +83 -7
- package/es/dashboard/Surface/Surface.mjs.map +1 -1
- package/es/dashboard/Surface/index.d.mts +3 -2
- package/es/dashboard/Surface/link.d.mts +19 -0
- package/es/dashboard/Surface/link.mjs +33 -0
- package/es/dashboard/Surface/link.mjs.map +1 -0
- package/es/dashboard/Surface/style.d.mts +45 -3
- package/es/dashboard/Surface/style.mjs +358 -8
- package/es/dashboard/Surface/style.mjs.map +1 -1
- package/es/dashboard/Surface/type.d.mts +30 -2
- package/es/dashboard/TableIconActions/TableIconActions.d.mts +17 -0
- package/es/dashboard/TableIconActions/TableIconActions.mjs +39 -0
- package/es/dashboard/TableIconActions/TableIconActions.mjs.map +1 -0
- package/es/dashboard/TableIconActions/index.d.mts +3 -0
- package/es/dashboard/TableIconActions/type.d.mts +18 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.d.mts +10 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.mjs +28 -0
- package/es/dashboard/TitleWithTips/TitleWithTips.mjs.map +1 -0
- package/es/dashboard/TitleWithTips/index.d.mts +3 -0
- package/es/dashboard/TitleWithTips/type.d.mts +11 -0
- package/es/dashboard/index.d.mts +38 -4
- package/es/dashboard/index.mjs +17 -3
- package/package.json +1 -1
- package/es/dashboard/StatCard/style.mjs +0 -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,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,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
|
-
|
|
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 {
|
|
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__ */
|
|
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
|
|
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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"}
|