dishui 0.0.81 → 0.0.83
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/dist/components/Accordion/index.js +6 -6
- package/dist/components/Accordion/index.js.map +1 -1
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/ButtonMenu/index.d.ts +28 -0
- package/dist/components/ButtonMenu/index.js +197 -0
- package/dist/components/ButtonMenu/index.js.map +1 -0
- package/dist/components/Card/index.d.ts +7 -4
- package/dist/components/Card/index.js +98 -65
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Demo/index.d.ts +5 -0
- package/dist/components/Demo/index.js +131 -56
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/Demo/source.d.ts +9 -0
- package/dist/components/Demo/source.js +32 -0
- package/dist/components/Demo/source.js.map +1 -0
- package/dist/components/EmptyState/index.js +4 -4
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/Field/index.d.ts +8 -0
- package/dist/components/Field/index.js +43 -0
- package/dist/components/Field/index.js.map +1 -0
- package/dist/components/LayoutSuite/DashboardSuite.d.ts +35 -0
- package/dist/components/LayoutSuite/DashboardSuite.js +61 -0
- package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -0
- package/dist/components/LayoutSuite/index.d.ts +56 -0
- package/dist/components/LayoutSuite/index.js +101 -0
- package/dist/components/LayoutSuite/index.js.map +1 -0
- package/dist/components/List/index.js +5 -5
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Modal/focusScope.d.ts +1 -0
- package/dist/components/Modal/focusScope.js +81 -0
- package/dist/components/Modal/focusScope.js.map +1 -0
- package/dist/components/Modal/index.d.ts +4 -1
- package/dist/components/Modal/index.js +53 -48
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/Float.d.ts +14 -0
- package/dist/components/Page/Float2.js +154 -0
- package/dist/components/Page/Float2.js.map +1 -0
- package/dist/components/Page/index.d.ts +18 -5
- package/dist/components/Page/index.js +103 -34
- package/dist/components/Page/index.js.map +1 -1
- package/dist/components/Page/resize.d.ts +28 -0
- package/dist/components/Page/resize2.js +95 -0
- package/dist/components/Page/resize2.js.map +1 -0
- package/dist/components/PageHeader/index.d.ts +10 -3
- package/dist/components/PageHeader/index.js +46 -25
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/PagePanel/index.d.ts +29 -0
- package/dist/components/PagePanel/index.js +99 -0
- package/dist/components/PagePanel/index.js.map +1 -0
- package/dist/components/Resizable/ResizeGrip.d.ts +5 -0
- package/dist/components/Resizable/ResizeGrip.js +14 -0
- package/dist/components/Resizable/ResizeGrip.js.map +1 -0
- package/dist/components/Resizable/index.js +57 -59
- package/dist/components/Resizable/index.js.map +1 -1
- package/dist/components/Resizable/useResize.d.ts +6 -0
- package/dist/components/Resizable/useResize.js +29 -28
- package/dist/components/Resizable/useResize.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.d.ts +5 -3
- package/dist/components/SidebarToggleButton/index.js +24 -21
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/Table/index.d.ts +10 -12
- package/dist/components/Table/index.js +25 -20
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Text/index.d.ts +1 -1
- package/dist/components/Text/index.js +11 -10
- package/dist/components/Text/index.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +14 -0
- package/dist/components/Textarea/index.js +44 -0
- package/dist/components/Textarea/index.js.map +1 -0
- package/dist/components/Tree/Tree.d.ts +2 -0
- package/dist/components/Tree/Tree.js +49 -40
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +9 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +119 -113
- package/dist/layouts/Sidebar.d.ts +12 -1
- package/dist/layouts/Sidebar.js +121 -97
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/lite.d.ts +10 -2
- package/dist/lite.js +17 -12
- package/dist/styles/themeStyles.js +6 -6
- package/dist/styles/themeStyles.js.map +1 -1
- package/dist/utils/menu.js +14 -16
- package/dist/utils/menu.js.map +1 -1
- package/package.json +3 -1
|
@@ -1,35 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import e from "../Button/index.js";
|
|
2
|
+
import t from "../Text/index.js";
|
|
3
|
+
import { useCopyToClipboard as n } from "../../hooks/useCopyToClipboard.js";
|
|
4
|
+
import { formatDemoSource as r } from "./source.js";
|
|
5
|
+
import { useEffect as i, useId as a, useRef as o, useState as s } from "react";
|
|
6
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
|
+
import { Prism as u } from "react-syntax-highlighter";
|
|
8
|
+
import { coldarkDark as d } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
6
9
|
//#region src/components/Demo/index.tsx
|
|
7
|
-
var
|
|
8
|
-
let { copied:
|
|
9
|
-
return /* @__PURE__ */
|
|
10
|
+
var f = ({ children: r, language: i = "jsx" }) => {
|
|
11
|
+
let { copied: a, error: o, copy: s } = n();
|
|
12
|
+
return /* @__PURE__ */ l("div", {
|
|
10
13
|
className: "min-w-0 overflow-hidden rounded-lg border border-base-300",
|
|
11
|
-
children: [/* @__PURE__ */
|
|
14
|
+
children: [/* @__PURE__ */ l("div", {
|
|
12
15
|
className: "flex items-center justify-between gap-3 bg-base-200 px-4 py-2",
|
|
13
|
-
children: [/* @__PURE__ */
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
children: [/* @__PURE__ */ c(t, {
|
|
17
|
+
size: "xs",
|
|
18
|
+
mono: !0,
|
|
19
|
+
color: "secondary",
|
|
20
|
+
children: i
|
|
21
|
+
}), /* @__PURE__ */ l("div", {
|
|
17
22
|
className: "flex items-center gap-2",
|
|
18
|
-
children: [/* @__PURE__ */
|
|
23
|
+
children: [/* @__PURE__ */ c(t, {
|
|
19
24
|
role: "status",
|
|
20
|
-
|
|
21
|
-
children:
|
|
22
|
-
}), /* @__PURE__ */
|
|
25
|
+
size: "xs",
|
|
26
|
+
children: o ? "Copy failed / 复制失败,请手动复制" : a ? "Copied / 已复制" : ""
|
|
27
|
+
}), /* @__PURE__ */ c(e, {
|
|
23
28
|
type: "button",
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
variant: "ghost",
|
|
30
|
+
size: "xs",
|
|
31
|
+
onClick: () => void s(r),
|
|
26
32
|
"aria-label": "Copy source code / 复制源代码",
|
|
27
33
|
children: "Copy / 复制"
|
|
28
34
|
})]
|
|
29
35
|
})]
|
|
30
|
-
}), /* @__PURE__ */
|
|
31
|
-
language:
|
|
32
|
-
style:
|
|
36
|
+
}), /* @__PURE__ */ c(u, {
|
|
37
|
+
language: i,
|
|
38
|
+
style: d,
|
|
33
39
|
tabIndex: 0,
|
|
34
40
|
"aria-label": "Source code / 源代码",
|
|
35
41
|
customStyle: {
|
|
@@ -41,59 +47,128 @@ var s = ({ children: t, language: n = "jsx" }) => {
|
|
|
41
47
|
maxHeight: "32rem",
|
|
42
48
|
overflow: "auto"
|
|
43
49
|
},
|
|
44
|
-
children:
|
|
50
|
+
children: r
|
|
45
51
|
})]
|
|
46
52
|
});
|
|
47
|
-
},
|
|
48
|
-
let [
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
53
|
+
}, p = ({ title: n, description: u, children: d, code: p, language: m = "jsx", source: h, sourceContext: g }) => {
|
|
54
|
+
let [_, v] = s(!1), [y, b] = s(0), [x, S] = s(null), C = o(null);
|
|
55
|
+
i(() => {
|
|
56
|
+
if (!_ || typeof h != "function") return;
|
|
57
|
+
let e = !0;
|
|
58
|
+
return (C.current?.loader !== h || C.current.attempt !== y) && (C.current = {
|
|
59
|
+
loader: h,
|
|
60
|
+
attempt: y,
|
|
61
|
+
promise: Promise.resolve().then(() => h())
|
|
62
|
+
}), C.current.promise.then((t) => {
|
|
63
|
+
e && S({
|
|
64
|
+
loader: h,
|
|
65
|
+
attempt: y,
|
|
66
|
+
status: "success",
|
|
67
|
+
data: t
|
|
68
|
+
});
|
|
69
|
+
}, () => {
|
|
70
|
+
e && S({
|
|
71
|
+
loader: h,
|
|
72
|
+
attempt: y,
|
|
73
|
+
status: "error"
|
|
74
|
+
});
|
|
75
|
+
}), () => {
|
|
76
|
+
e = !1;
|
|
77
|
+
};
|
|
78
|
+
}, [
|
|
79
|
+
h,
|
|
80
|
+
_,
|
|
81
|
+
y
|
|
82
|
+
]);
|
|
83
|
+
let w = typeof h == "function" && x?.loader === h && x.attempt === y ? x : null, T = typeof h == "function" ? w?.status === "success" ? w.data : void 0 : h, E = typeof h == "function" && !w, D = a(), O = `${D}-title`, k = `${D}-code`;
|
|
84
|
+
return /* @__PURE__ */ l("section", {
|
|
85
|
+
"aria-labelledby": O,
|
|
86
|
+
className: "dishui-demo mb-4 min-w-0 rounded-lg border border-hairline bg-page",
|
|
52
87
|
children: [
|
|
53
|
-
/* @__PURE__ */
|
|
54
|
-
className: "border-b border-
|
|
55
|
-
children: [/* @__PURE__ */
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
88
|
+
/* @__PURE__ */ l("div", {
|
|
89
|
+
className: "border-b border-hairline bg-subtle px-4 py-3 rounded-t-lg",
|
|
90
|
+
children: [/* @__PURE__ */ c(t, {
|
|
91
|
+
as: "h3",
|
|
92
|
+
id: O,
|
|
93
|
+
size: "sm",
|
|
94
|
+
weight: "semibold",
|
|
95
|
+
children: n
|
|
96
|
+
}), u && /* @__PURE__ */ c(t, {
|
|
97
|
+
as: "p",
|
|
98
|
+
size: "sm",
|
|
99
|
+
color: "secondary",
|
|
100
|
+
className: "mt-1 leading-relaxed",
|
|
101
|
+
children: u
|
|
62
102
|
})]
|
|
63
103
|
}),
|
|
64
|
-
/* @__PURE__ */
|
|
65
|
-
className: "flex min-w-0 flex-wrap items-center gap-4
|
|
66
|
-
children:
|
|
104
|
+
/* @__PURE__ */ c("div", {
|
|
105
|
+
className: "flex min-w-0 flex-wrap items-center gap-4 p-4",
|
|
106
|
+
children: d
|
|
67
107
|
}),
|
|
68
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ l("div", {
|
|
69
109
|
className: "border-t border-base-300",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
110
|
+
children: [/* @__PURE__ */ l(e, {
|
|
71
111
|
type: "button",
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
"aria-
|
|
75
|
-
|
|
76
|
-
|
|
112
|
+
variant: "ghost",
|
|
113
|
+
className: "flex w-full items-center justify-between rounded-none rounded-b-lg px-4 text-xs font-medium",
|
|
114
|
+
"aria-expanded": _,
|
|
115
|
+
"aria-controls": k,
|
|
116
|
+
onClick: () => v((e) => !e),
|
|
117
|
+
children: [/* @__PURE__ */ c(t, {
|
|
118
|
+
size: "xs",
|
|
119
|
+
weight: "medium",
|
|
120
|
+
color: "inherit",
|
|
121
|
+
children: "Source Code / 源代码"
|
|
122
|
+
}), /* @__PURE__ */ c("svg", {
|
|
77
123
|
"aria-hidden": "true",
|
|
78
124
|
xmlns: "http://www.w3.org/2000/svg",
|
|
79
|
-
className: `h-4 w-4 transition-transform motion-reduce:transition-none ${
|
|
125
|
+
className: `h-4 w-4 transition-transform motion-reduce:transition-none ${_ ? "rotate-180" : ""}`,
|
|
80
126
|
fill: "none",
|
|
81
127
|
viewBox: "0 0 24 24",
|
|
82
128
|
stroke: "currentColor",
|
|
83
|
-
children: /* @__PURE__ */
|
|
129
|
+
children: /* @__PURE__ */ c("path", {
|
|
84
130
|
strokeLinecap: "round",
|
|
85
131
|
strokeLinejoin: "round",
|
|
86
132
|
strokeWidth: "2",
|
|
87
133
|
d: "M19 9l-7 7-7-7"
|
|
88
134
|
})
|
|
89
135
|
})]
|
|
90
|
-
}), /* @__PURE__ */
|
|
91
|
-
id:
|
|
92
|
-
hidden: !
|
|
136
|
+
}), /* @__PURE__ */ c("div", {
|
|
137
|
+
id: k,
|
|
138
|
+
hidden: !_,
|
|
93
139
|
className: "min-w-0 border-t border-base-300 p-4",
|
|
94
|
-
children:
|
|
95
|
-
|
|
96
|
-
children: c
|
|
140
|
+
children: _ && /* @__PURE__ */ c("div", {
|
|
141
|
+
className: "min-w-0 space-y-3",
|
|
142
|
+
children: /* @__PURE__ */ c("div", {
|
|
143
|
+
className: "min-w-0",
|
|
144
|
+
"aria-busy": E,
|
|
145
|
+
children: E ? /* @__PURE__ */ c(t, {
|
|
146
|
+
as: "p",
|
|
147
|
+
role: "status",
|
|
148
|
+
size: "sm",
|
|
149
|
+
children: "Loading source code… / 正在加载源码…"
|
|
150
|
+
}) : w?.status === "error" ? /* @__PURE__ */ l("div", {
|
|
151
|
+
className: "space-y-2",
|
|
152
|
+
children: [/* @__PURE__ */ c(t, {
|
|
153
|
+
as: "p",
|
|
154
|
+
role: "alert",
|
|
155
|
+
size: "sm",
|
|
156
|
+
children: "Could not load source code. Please retry. / 源码加载失败,请重试。"
|
|
157
|
+
}), /* @__PURE__ */ c(e, {
|
|
158
|
+
type: "button",
|
|
159
|
+
variant: "ghost",
|
|
160
|
+
size: "sm",
|
|
161
|
+
onClick: () => b((e) => e + 1),
|
|
162
|
+
children: "Retry loading source / 重新加载源码"
|
|
163
|
+
})]
|
|
164
|
+
}) : T ? /* @__PURE__ */ c(f, {
|
|
165
|
+
language: "tsx",
|
|
166
|
+
children: r(T, g)
|
|
167
|
+
}) : h ? null : /* @__PURE__ */ c(f, {
|
|
168
|
+
language: m,
|
|
169
|
+
children: p
|
|
170
|
+
})
|
|
171
|
+
})
|
|
97
172
|
})
|
|
98
173
|
})]
|
|
99
174
|
})
|
|
@@ -101,6 +176,6 @@ var s = ({ children: t, language: n = "jsx" }) => {
|
|
|
101
176
|
});
|
|
102
177
|
};
|
|
103
178
|
//#endregion
|
|
104
|
-
export {
|
|
179
|
+
export { p as default };
|
|
105
180
|
|
|
106
181
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Demo/index.tsx"],"sourcesContent":["import React, { useId, useState } from 'react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { coldarkDark } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport { useCopyToClipboard } from '../../hooks/useCopyToClipboard';\n\nexport interface CodeBlockProps {\n children: string;\n language?: string;\n}\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({ children, language = 'jsx' }) => {\n const { copied, error, copy } = useCopyToClipboard();\n\n return (\n <div className=\"min-w-0 overflow-hidden rounded-lg border border-base-300\">\n <div className=\"flex items-center justify-between gap-3 bg-base-200 px-4 py-2\">\n <
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Demo/index.tsx"],"sourcesContent":["import React, { useEffect, useId, useRef, useState } from 'react';\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { coldarkDark } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport { useCopyToClipboard } from '../../hooks/useCopyToClipboard';\nimport { formatDemoSource, type DemoSource } from './source';\nimport Button from '../Button';\nimport Text from '../Text';\n\nexport type { DemoSource } from './source';\n\nexport interface CodeBlockProps {\n children: string;\n language?: string;\n}\n\nconst CodeBlock: React.FC<CodeBlockProps> = ({ children, language = 'jsx' }) => {\n const { copied, error, copy } = useCopyToClipboard();\n\n return (\n <div className=\"min-w-0 overflow-hidden rounded-lg border border-base-300\">\n <div className=\"flex items-center justify-between gap-3 bg-base-200 px-4 py-2\">\n <Text size=\"xs\" mono color=\"secondary\">{language}</Text>\n <div className=\"flex items-center gap-2\">\n <Text role=\"status\" size=\"xs\">\n {error ? 'Copy failed / 复制失败,请手动复制' : copied ? 'Copied / 已复制' : ''}\n </Text>\n <Button\n type=\"button\"\n variant=\"ghost\" size=\"xs\"\n onClick={() => void copy(children)}\n aria-label=\"Copy source code / 复制源代码\"\n >\n Copy / 复制\n </Button>\n </div>\n </div>\n <SyntaxHighlighter\n language={language}\n style={coldarkDark}\n tabIndex={0}\n aria-label=\"Source code / 源代码\"\n customStyle={{\n margin: 0,\n borderRadius: 0,\n fontSize: '0.8125rem',\n lineHeight: 1.7,\n padding: '1rem',\n maxHeight: '32rem',\n overflow: 'auto',\n }}\n >\n {children}\n </SyntaxHighlighter>\n </div>\n );\n};\n\ntype DemoSourceLoader = () => Promise<DemoSource>;\n\ntype SourceLoadResult = {\n loader: DemoSourceLoader;\n attempt: number;\n} & ({ status: 'success'; data: DemoSource } | { status: 'error' });\n\nexport interface DemoProps {\n title: string;\n description?: string;\n children: React.ReactNode;\n code: string;\n language?: string;\n source?: DemoSource | DemoSourceLoader;\n sourceContext?: Record<string, unknown>;\n}\n\nconst Demo: React.FC<DemoProps> = ({\n title,\n description,\n children,\n code,\n language = 'jsx',\n source,\n sourceContext,\n}) => {\n const [showCode, setShowCode] = useState(false);\n const [attempt, setAttempt] = useState(0);\n const [loadResult, setLoadResult] = useState<SourceLoadResult | null>(null);\n const request = useRef<{\n loader: DemoSourceLoader;\n attempt: number;\n promise: Promise<DemoSource>;\n } | null>(null);\n\n useEffect(() => {\n if (!showCode || typeof source !== 'function') return;\n\n let active = true;\n // Reuse the request across collapse/reopen and StrictMode effect replays.\n if (request.current?.loader !== source || request.current.attempt !== attempt) {\n request.current = {\n loader: source,\n attempt,\n promise: Promise.resolve().then(() => source()),\n };\n }\n void request.current.promise.then(\n data => {\n if (active) setLoadResult({ loader: source, attempt, status: 'success', data });\n },\n () => {\n if (active) setLoadResult({ loader: source, attempt, status: 'error' });\n },\n );\n return () => { active = false; };\n }, [source, showCode, attempt]);\n\n // Match the loader before rendering so switching props cannot flash stale source.\n const currentResult = typeof source === 'function'\n && loadResult?.loader === source && loadResult.attempt === attempt\n ? loadResult : null;\n const resolvedSource = typeof source === 'function'\n ? currentResult?.status === 'success' ? currentResult.data : undefined\n : source;\n const loading = typeof source === 'function' && !currentResult;\n const id = useId();\n const titleId = `${id}-title`;\n const codeId = `${id}-code`;\n\n return (\n <section aria-labelledby={titleId} className=\"dishui-demo mb-4 min-w-0 rounded-lg border border-hairline bg-page\">\n <div className=\"border-b border-hairline bg-subtle px-4 py-3 rounded-t-lg\">\n <Text as=\"h3\" id={titleId} size=\"sm\" weight=\"semibold\">{title}</Text>\n {description && <Text as=\"p\" size=\"sm\" color=\"secondary\" className=\"mt-1 leading-relaxed\">{description}</Text>}\n </div>\n\n <div className=\"flex min-w-0 flex-wrap items-center gap-4 p-4\">\n {children}\n </div>\n\n <div className=\"border-t border-base-300\">\n <Button\n type=\"button\" variant=\"ghost\"\n className=\"flex w-full items-center justify-between rounded-none rounded-b-lg px-4 text-xs font-medium\"\n aria-expanded={showCode}\n aria-controls={codeId}\n onClick={() => setShowCode(value => !value)}\n >\n <Text size=\"xs\" weight=\"medium\" color=\"inherit\">Source Code / 源代码</Text>\n <svg\n aria-hidden=\"true\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={`h-4 w-4 transition-transform motion-reduce:transition-none ${showCode ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </Button>\n <div id={codeId} hidden={!showCode} className=\"min-w-0 border-t border-base-300 p-4\">\n {showCode && (\n <div className=\"min-w-0 space-y-3\">\n <div className=\"min-w-0\" aria-busy={loading}>\n {loading ? (\n <Text as=\"p\" role=\"status\" size=\"sm\">Loading source code… / 正在加载源码…</Text>\n ) : currentResult?.status === 'error' ? (\n <div className=\"space-y-2\">\n <Text as=\"p\" role=\"alert\" size=\"sm\">\n Could not load source code. Please retry. / 源码加载失败,请重试。\n </Text>\n <Button\n type=\"button\" variant=\"ghost\" size=\"sm\"\n onClick={() => setAttempt(value => value + 1)}\n >\n Retry loading source / 重新加载源码\n </Button>\n </div>\n ) : resolvedSource ? (\n <CodeBlock language=\"tsx\">\n {formatDemoSource(resolvedSource, sourceContext)}\n </CodeBlock>\n ) : !source ? (\n <CodeBlock language={language}>{code}</CodeBlock>\n ) : null}\n </div>\n </div>\n )}\n </div>\n </div>\n </section>\n );\n};\n\nexport default Demo;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/components/Demo/source.ts
|
|
2
|
+
function e(e, t = !1) {
|
|
3
|
+
let n = e.replace(/\r\n/g, "\n").split("\n");
|
|
4
|
+
for (; n.length && !n[0].trim();) n.shift();
|
|
5
|
+
for (; n.length && !n[n.length - 1].trim();) n.pop();
|
|
6
|
+
if (e.includes("`")) return n.join("\n");
|
|
7
|
+
let r = t && n[0]?.match(/^\S/) ? n.slice(1) : n, i = Math.min(...r.filter((e) => e.trim()).map((e) => e.match(/^[\t ]*/)?.[0].length ?? 0));
|
|
8
|
+
return n.map((e, n) => t && n === 0 && /^\S/.test(e) ? e : e.slice(i)).join("\n");
|
|
9
|
+
}
|
|
10
|
+
function t(t, n = {}) {
|
|
11
|
+
let r = [];
|
|
12
|
+
for (let e of new Set(t.context)) {
|
|
13
|
+
if (!Object.prototype.hasOwnProperty.call(n, e)) continue;
|
|
14
|
+
let t = n[e];
|
|
15
|
+
try {
|
|
16
|
+
let n = t === void 0 ? "undefined" : JSON.stringify(t, null, 2);
|
|
17
|
+
n !== void 0 && r.push(`const ${e} = ${n};`);
|
|
18
|
+
} catch {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return [
|
|
23
|
+
e(t.imports),
|
|
24
|
+
r.join("\n"),
|
|
25
|
+
e(t.setup),
|
|
26
|
+
e(t.preview, !0)
|
|
27
|
+
].filter(Boolean).join("\n\n");
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { t as formatDemoSource };
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","names":[],"sources":["../../../src/components/Demo/source.ts"],"sourcesContent":["export interface DemoSource {\n imports: string;\n setup: string;\n preview: string;\n context: string[];\n path?: string;\n line?: number;\n}\n\nfunction normalizeSection(code: string, trimmedFirstLine = false): string {\n const lines = code.replace(/\\r\\n/g, '\\n').split('\\n');\n while (lines.length && !lines[0].trim()) lines.shift();\n while (lines.length && !lines[lines.length - 1].trim()) lines.pop();\n // The extracted JSX starts at its first token; subsequent lines still carry the\n // page's indentation. Do not reindent template literals, whose spaces are data.\n if (code.includes('`')) return lines.join('\\n');\n const indentedLines = trimmedFirstLine && lines[0]?.match(/^\\S/) ? lines.slice(1) : lines;\n const indentation = Math.min(...indentedLines.filter(line => line.trim()).map(line => line.match(/^[\\t ]*/)?.[0].length ?? 0));\n return lines.map((line, index) => trimmedFirstLine && index === 0 && /^\\S/.test(line) ? line : line.slice(indentation)).join('\\n');\n}\n\nexport function formatDemoSource(\n source: DemoSource,\n sourceContext: Record<string, unknown> = {},\n): string {\n const declarations: string[] = [];\n for (const name of new Set(source.context)) {\n if (!Object.prototype.hasOwnProperty.call(sourceContext, name)) continue;\n const value = sourceContext[name];\n // Runtime functions and circular values cannot be represented as JSON source.\n try {\n const literal = value === undefined ? 'undefined' : JSON.stringify(value, null, 2);\n if (literal !== undefined) declarations.push(`const ${name} = ${literal};`);\n } catch {\n continue;\n }\n }\n\n return [\n normalizeSection(source.imports),\n declarations.join('\\n'),\n normalizeSection(source.setup),\n normalizeSection(source.preview, true),\n ].filter(Boolean).join('\\n\\n');\n}\n"],"mappings":";AASA,SAAS,EAAiB,GAAc,IAAmB,IAAe;CACxE,IAAM,IAAQ,EAAK,QAAQ,SAAS,IAAI,CAAC,CAAC,MAAM,IAAI;CACpD,OAAO,EAAM,UAAU,CAAC,EAAM,EAAE,CAAC,KAAK,IAAG,EAAM,MAAM;CACrD,OAAO,EAAM,UAAU,CAAC,EAAM,EAAM,SAAS,EAAE,CAAC,KAAK,IAAG,EAAM,IAAI;CAGlE,IAAI,EAAK,SAAS,GAAG,GAAG,OAAO,EAAM,KAAK,IAAI;CAC9C,IAAM,IAAgB,KAAoB,EAAM,EAAE,EAAE,MAAM,KAAK,IAAI,EAAM,MAAM,CAAC,IAAI,GAC9E,IAAc,KAAK,IAAI,GAAG,EAAc,QAAO,MAAQ,EAAK,KAAK,CAAC,CAAC,CAAC,KAAI,MAAQ,EAAK,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC;CAC7H,OAAO,EAAM,KAAK,GAAM,MAAU,KAAoB,MAAU,KAAK,MAAM,KAAK,CAAI,IAAI,IAAO,EAAK,MAAM,CAAW,CAAC,CAAC,CAAC,KAAK,IAAI;AACnI;AAEA,SAAgB,EACd,GACA,IAAyC,CAAC,GAClC;CACR,IAAM,IAAyB,CAAC;CAChC,KAAK,IAAM,KAAQ,IAAI,IAAI,EAAO,OAAO,GAAG;EAC1C,IAAI,CAAC,OAAO,UAAU,eAAe,KAAK,GAAe,CAAI,GAAG;EAChE,IAAM,IAAQ,EAAc;EAE5B,IAAI;GACF,IAAM,IAAU,MAAU,KAAA,IAAY,cAAc,KAAK,UAAU,GAAO,MAAM,CAAC;GACjF,AAAI,MAAY,KAAA,KAAW,EAAa,KAAK,SAAS,EAAK,KAAK,EAAQ,EAAE;EAC5E,QAAQ;GACN;EACF;CACF;CAEA,OAAO;EACL,EAAiB,EAAO,OAAO;EAC/B,EAAa,KAAK,IAAI;EACtB,EAAiB,EAAO,KAAK;EAC7B,EAAiB,EAAO,SAAS,EAAI;CACvC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,MAAM;AAC/B"}
|
|
@@ -2,18 +2,18 @@ import "react";
|
|
|
2
2
|
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
3
3
|
//#region src/components/EmptyState/index.tsx
|
|
4
4
|
var n = ({ icon: n, title: r, description: i, action: a, fill: o = !0, className: s = "" }) => /* @__PURE__ */ t("div", {
|
|
5
|
-
className: `flex flex-col items-center justify-center rounded-
|
|
5
|
+
className: `dishui-empty-state flex min-w-0 flex-col items-center justify-center rounded-lg border border-dashed border-base-300 bg-base-100 px-6 py-12 text-center text-body leading-5 ${o ? "h-full w-full" : ""} ${s}`.trim(),
|
|
6
6
|
children: [
|
|
7
7
|
n && /* @__PURE__ */ e("span", {
|
|
8
|
-
className: "mb-3 flex size-
|
|
8
|
+
className: "mb-3 flex size-10 items-center justify-center rounded-lg bg-base-200 text-base-content/70 [&>svg]:h-5 [&>svg]:w-5",
|
|
9
9
|
children: n
|
|
10
10
|
}),
|
|
11
11
|
/* @__PURE__ */ e("p", {
|
|
12
|
-
className: "text-
|
|
12
|
+
className: "max-w-full break-words text-body font-medium text-base-content",
|
|
13
13
|
children: r
|
|
14
14
|
}),
|
|
15
15
|
i && /* @__PURE__ */ e("p", {
|
|
16
|
-
className: "mt-1 max-w-sm text-
|
|
16
|
+
className: "mt-1 max-w-sm break-words text-body-sm leading-5 text-base-content/70",
|
|
17
17
|
children: i
|
|
18
18
|
}),
|
|
19
19
|
a && /* @__PURE__ */ e("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/EmptyState/index.tsx"],"sourcesContent":["import React from 'react';\n\nexport type EmptyStateProps = {\n /** 主图标(通常为 lucide 图标) */\n icon?: React.ReactNode;\n /** 主标题 */\n title: React.ReactNode;\n /** 补充说明 */\n description?: React.ReactNode;\n /** 底部操作(按钮等) */\n action?: React.ReactNode;\n /** 是否默认填满所在区域(宽高 100%,内容居中);默认 true */\n fill?: boolean;\n className?: string;\n};\n\n/**\n * 空状态:虚线边框卡片 + 图标 + 标题 + 说明,统一列表为空时的展示。\n * 默认填满所在区域(fill),在固定高度的容器内自动垂直居中。\n */\nconst EmptyState = ({\n icon,\n title,\n description,\n action,\n fill = true,\n className = '',\n}: EmptyStateProps) => {\n return (\n <div\n className={`flex flex-col items-center justify-center rounded-
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/EmptyState/index.tsx"],"sourcesContent":["import React from 'react';\n\nexport type EmptyStateProps = {\n /** 主图标(通常为 lucide 图标) */\n icon?: React.ReactNode;\n /** 主标题 */\n title: React.ReactNode;\n /** 补充说明 */\n description?: React.ReactNode;\n /** 底部操作(按钮等) */\n action?: React.ReactNode;\n /** 是否默认填满所在区域(宽高 100%,内容居中);默认 true */\n fill?: boolean;\n className?: string;\n};\n\n/**\n * 空状态:虚线边框卡片 + 图标 + 标题 + 说明,统一列表为空时的展示。\n * 默认填满所在区域(fill),在固定高度的容器内自动垂直居中。\n */\nconst EmptyState = ({\n icon,\n title,\n description,\n action,\n fill = true,\n className = '',\n}: EmptyStateProps) => {\n return (\n <div\n className={`dishui-empty-state flex min-w-0 flex-col items-center justify-center rounded-lg border border-dashed border-base-300 bg-base-100 px-6 py-12 text-center text-body leading-5 ${fill ? 'h-full w-full' : ''} ${className}`.trim()}\n >\n {icon && (\n <span className=\"mb-3 flex size-10 items-center justify-center rounded-lg bg-base-200 text-base-content/70 [&>svg]:h-5 [&>svg]:w-5\">\n {icon}\n </span>\n )}\n <p className=\"max-w-full break-words text-body font-medium text-base-content\">{title}</p>\n {description && (\n <p className=\"mt-1 max-w-sm break-words text-body-sm leading-5 text-base-content/70\">{description}</p>\n )}\n {action && <div className=\"mt-4\">{action}</div>}\n </div>\n );\n};\n\nexport default EmptyState;\n"],"mappings":";;;AAoBA,IAAM,KAAc,EAChB,SACA,UACA,gBACA,WACA,UAAO,IACP,eAAY,SAGR,kBAAC,OAAD;CACI,WAAW,+KAA+K,IAAO,kBAAkB,GAAG,GAAG,IAAY,KAAK;CAD9O,UAAA;EAGK,KACG,kBAAC,QAAD;GAAM,WAAU;GACX,UAAA;EACC,CAAA;EAEV,kBAAC,KAAD;GAAG,WAAU;GAAkE,UAAA;EAAS,CAAA;EACvF,KACG,kBAAC,KAAD;GAAG,WAAU;GAAyE,UAAA;EAAe,CAAA;EAExG,KAAU,kBAAC,OAAD;GAAK,WAAU;GAAQ,UAAA;EAAY,CAAA;CAC7C"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface FieldProps extends React.FieldsetHTMLAttributes<HTMLFieldSetElement> {
|
|
3
|
+
legend?: React.ReactNode;
|
|
4
|
+
description?: React.ReactNode;
|
|
5
|
+
error?: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
declare const Field: React.ForwardRefExoticComponent<FieldProps & React.RefAttributes<HTMLFieldSetElement>>;
|
|
8
|
+
export default Field;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import { forwardRef as t, useId as n } from "react";
|
|
4
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/Field/index.tsx
|
|
6
|
+
var a = (e) => e != null && typeof e != "boolean" && e !== "", o = t(function({ legend: t, description: o, error: s, children: c, className: l, "aria-describedby": u, "aria-invalid": d, ...f }, p) {
|
|
7
|
+
let m = n(), h = `${m}-description`, g = `${m}-error`, _ = a(o), v = a(s), y = [
|
|
8
|
+
u,
|
|
9
|
+
_ ? h : void 0,
|
|
10
|
+
v ? g : void 0
|
|
11
|
+
].filter(Boolean).join(" ") || void 0;
|
|
12
|
+
return /* @__PURE__ */ i("fieldset", {
|
|
13
|
+
...f,
|
|
14
|
+
ref: p,
|
|
15
|
+
className: e("dishui-field", l),
|
|
16
|
+
"aria-describedby": y,
|
|
17
|
+
"aria-invalid": d ?? (v ? !0 : void 0),
|
|
18
|
+
children: [a(t) && /* @__PURE__ */ r("legend", {
|
|
19
|
+
className: "dishui-field-legend",
|
|
20
|
+
children: t
|
|
21
|
+
}), /* @__PURE__ */ i("div", {
|
|
22
|
+
className: "dishui-field-content",
|
|
23
|
+
children: [
|
|
24
|
+
_ && /* @__PURE__ */ r("div", {
|
|
25
|
+
id: h,
|
|
26
|
+
className: "dishui-field-description",
|
|
27
|
+
children: o
|
|
28
|
+
}),
|
|
29
|
+
c,
|
|
30
|
+
v && /* @__PURE__ */ r("div", {
|
|
31
|
+
id: g,
|
|
32
|
+
className: "dishui-field-error",
|
|
33
|
+
role: "alert",
|
|
34
|
+
children: s
|
|
35
|
+
})
|
|
36
|
+
]
|
|
37
|
+
})]
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//#endregion
|
|
41
|
+
export { o as default };
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Field/index.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react';\nimport { cn } from '../../utils/cn';\nimport './style.css';\n\nexport interface FieldProps extends React.FieldsetHTMLAttributes<HTMLFieldSetElement> {\n legend?: React.ReactNode;\n description?: React.ReactNode;\n error?: React.ReactNode;\n}\n\nconst hasContent = (node: React.ReactNode) => node !== null && node !== undefined && typeof node !== 'boolean' && node !== '';\n\nconst Field = forwardRef<HTMLFieldSetElement, FieldProps>(function Field({\n legend,\n description,\n error,\n children,\n className,\n 'aria-describedby': describedBy,\n 'aria-invalid': invalid,\n ...props\n}, ref) {\n const id = useId();\n const descriptionId = `${id}-description`;\n const errorId = `${id}-error`;\n const showDescription = hasContent(description);\n const showError = hasContent(error);\n const ids = [describedBy, showDescription ? descriptionId : undefined, showError ? errorId : undefined]\n .filter(Boolean).join(' ') || undefined;\n\n return (\n <fieldset\n {...props}\n ref={ref}\n className={cn('dishui-field', className)}\n aria-describedby={ids}\n aria-invalid={invalid ?? (showError ? true : undefined)}\n >\n {hasContent(legend) && <legend className=\"dishui-field-legend\">{legend}</legend>}\n <div className=\"dishui-field-content\">\n {showDescription && <div id={descriptionId} className=\"dishui-field-description\">{description}</div>}\n {children}\n {showError && <div id={errorId} className=\"dishui-field-error\" role=\"alert\">{error}</div>}\n </div>\n </fieldset>\n );\n});\n\nexport default Field;\n"],"mappings":";;;;;AAUA,IAAM,KAAc,MAA0B,KAAS,QAA8B,OAAO,KAAS,aAAa,MAAS,IAErH,IAAQ,EAA4C,SAAe,EACvE,WACA,gBACA,UACA,aACA,cACA,oBAAoB,GACpB,gBAAgB,GAChB,GAAG,KACF,GAAK;CACN,IAAM,IAAK,EAAM,GACX,IAAgB,GAAG,EAAG,eACtB,IAAU,GAAG,EAAG,SAChB,IAAkB,EAAW,CAAW,GACxC,IAAY,EAAW,CAAK,GAC5B,IAAM;EAAC;EAAa,IAAkB,IAAgB,KAAA;EAAW,IAAY,IAAU,KAAA;CAAS,CAAC,CACpG,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA;CAEhC,OACE,kBAAC,YAAD;EACE,GAAI;EACC;EACL,WAAW,EAAG,gBAAgB,CAAS;EACvC,oBAAkB;EAClB,gBAAc,MAAY,IAAY,KAAO,KAAA;EAL/C,UAAA,CAOG,EAAW,CAAM,KAAK,kBAAC,UAAD;GAAQ,WAAU;GAAuB,UAAA;EAAe,CAAA,GAC/E,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACG,KAAmB,kBAAC,OAAD;KAAK,IAAI;KAAe,WAAU;KAA4B,UAAA;IAAiB,CAAA;IAClG;IACA,KAAa,kBAAC,OAAD;KAAK,IAAI;KAAS,WAAU;KAAqB,MAAK;KAAS,UAAA;IAAW,CAAA;GACrF;EACG,CAAA,CAAA;;AAEd,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type PageProps, type PageBodyProps, type PageMainProps, type PageAsideProps } from '../Page';
|
|
3
|
+
import { type CardMetricProps } from '../Card';
|
|
4
|
+
import { type NavigationListProps } from '../NavigationList';
|
|
5
|
+
import { type LayoutGridProps } from '../Layout';
|
|
6
|
+
export type DashboardSuiteProps = PageProps & {
|
|
7
|
+
header?: React.ReactNode;
|
|
8
|
+
overview?: React.ReactNode;
|
|
9
|
+
/** Persistent partial/stale/error feedback; data semantics remain with the caller. */
|
|
10
|
+
notice?: React.ReactNode;
|
|
11
|
+
metrics?: {
|
|
12
|
+
'aria-label': string;
|
|
13
|
+
items: readonly (CardMetricProps & {
|
|
14
|
+
key: React.Key;
|
|
15
|
+
})[];
|
|
16
|
+
loading?: boolean;
|
|
17
|
+
grid?: Omit<LayoutGridProps, 'children'>;
|
|
18
|
+
};
|
|
19
|
+
/** Cross-dashboard filters, above navigation and main content. */
|
|
20
|
+
filters?: React.ReactNode;
|
|
21
|
+
navigation?: NavigationListProps;
|
|
22
|
+
/** Explicit children (including null) override the built-in NavigationList. */
|
|
23
|
+
left?: PageAsideProps;
|
|
24
|
+
body?: Omit<PageBodyProps, 'children'>;
|
|
25
|
+
main?: PageMainProps;
|
|
26
|
+
toolbar?: React.ReactNode;
|
|
27
|
+
contentHeader?: React.ReactNode;
|
|
28
|
+
footer?: React.ReactNode;
|
|
29
|
+
};
|
|
30
|
+
/** Controlled dashboard composition; no fetching, filtering or table dependency. */
|
|
31
|
+
export declare const DashboardSuite: ({ header, overview, notice, metrics, filters, navigation, left, body, main, toolbar, contentHeader, footer, children, fullHeight, className, ...page }: DashboardSuiteProps) => React.JSX.Element;
|
|
32
|
+
export declare const LayoutSuite: {
|
|
33
|
+
DashboardSuite: typeof DashboardSuite;
|
|
34
|
+
};
|
|
35
|
+
export default DashboardSuite;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import t from "../NavigationList/index.js";
|
|
3
|
+
import n from "../Card/index.js";
|
|
4
|
+
import r from "../Page/index.js";
|
|
5
|
+
import { Grid as i, Group as a } from "../Layout/index.js";
|
|
6
|
+
import "react";
|
|
7
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/LayoutSuite/DashboardSuite.tsx
|
|
9
|
+
var c = ({ header: c, overview: l, notice: u, metrics: d, filters: f, navigation: p, left: m, body: h, main: g, toolbar: _, contentHeader: v, footer: y, children: b, fullHeight: x = !1, className: S, ...C }) => /* @__PURE__ */ s(r, {
|
|
10
|
+
...C,
|
|
11
|
+
fullHeight: x,
|
|
12
|
+
className: e("gap-4", S),
|
|
13
|
+
children: [
|
|
14
|
+
c,
|
|
15
|
+
l,
|
|
16
|
+
u,
|
|
17
|
+
d && d.items.length > 0 && /* @__PURE__ */ o("section", {
|
|
18
|
+
"aria-label": d["aria-label"],
|
|
19
|
+
"aria-busy": d.loading,
|
|
20
|
+
children: /* @__PURE__ */ o(i, {
|
|
21
|
+
columns: "repeat(auto-fit, minmax(min(100%, 220px), 1fr))",
|
|
22
|
+
gap: 12,
|
|
23
|
+
...d.grid,
|
|
24
|
+
children: d.items.map(({ key: e, ...t }) => /* @__PURE__ */ o(n.Metric, {
|
|
25
|
+
...t,
|
|
26
|
+
loading: d.loading ?? t.loading
|
|
27
|
+
}, e))
|
|
28
|
+
})
|
|
29
|
+
}),
|
|
30
|
+
f,
|
|
31
|
+
/* @__PURE__ */ s(r.Body, {
|
|
32
|
+
scroll: x,
|
|
33
|
+
...h,
|
|
34
|
+
children: [(m || p) && /* @__PURE__ */ o(r.Left, {
|
|
35
|
+
width: 240,
|
|
36
|
+
bordered: !1,
|
|
37
|
+
scroll: !1,
|
|
38
|
+
...m,
|
|
39
|
+
children: m?.children === void 0 ? p && /* @__PURE__ */ o(t, { ...p }) : m.children
|
|
40
|
+
}), /* @__PURE__ */ o(r.Main, {
|
|
41
|
+
scroll: x,
|
|
42
|
+
...g,
|
|
43
|
+
children: /* @__PURE__ */ s(a, {
|
|
44
|
+
direction: "column",
|
|
45
|
+
align: "stretch",
|
|
46
|
+
gap: 16,
|
|
47
|
+
children: [
|
|
48
|
+
_,
|
|
49
|
+
v,
|
|
50
|
+
b === void 0 ? g?.children : b
|
|
51
|
+
]
|
|
52
|
+
})
|
|
53
|
+
})]
|
|
54
|
+
}),
|
|
55
|
+
y
|
|
56
|
+
]
|
|
57
|
+
}), l = { DashboardSuite: c };
|
|
58
|
+
//#endregion
|
|
59
|
+
export { c as DashboardSuite, c as default, l as LayoutSuite };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=DashboardSuite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardSuite.js","names":[],"sources":["../../../src/components/LayoutSuite/DashboardSuite.tsx"],"sourcesContent":["import React from 'react';\nimport Page, { type PageProps, type PageBodyProps, type PageMainProps, type PageAsideProps } from '../Page';\nimport Card, { type CardMetricProps } from '../Card';\nimport NavigationList, { type NavigationListProps } from '../NavigationList';\nimport { Grid, Group, type LayoutGridProps } from '../Layout';\nimport { cn } from '../../utils/cn';\n\nexport type DashboardSuiteProps = PageProps & {\n header?: React.ReactNode;\n overview?: React.ReactNode;\n /** Persistent partial/stale/error feedback; data semantics remain with the caller. */\n notice?: React.ReactNode;\n metrics?: {\n 'aria-label': string;\n items: readonly (CardMetricProps & { key: React.Key })[];\n loading?: boolean;\n grid?: Omit<LayoutGridProps, 'children'>;\n };\n /** Cross-dashboard filters, above navigation and main content. */\n filters?: React.ReactNode;\n navigation?: NavigationListProps;\n /** Explicit children (including null) override the built-in NavigationList. */\n left?: PageAsideProps;\n body?: Omit<PageBodyProps, 'children'>;\n main?: PageMainProps;\n toolbar?: React.ReactNode;\n contentHeader?: React.ReactNode;\n footer?: React.ReactNode;\n};\n\n/** Controlled dashboard composition; no fetching, filtering or table dependency. */\nexport const DashboardSuite = ({\n header, overview, notice, metrics, filters, navigation, left, body, main,\n toolbar, contentHeader, footer, children, fullHeight = false, className, ...page\n}: DashboardSuiteProps) => (\n <Page {...page} fullHeight={fullHeight} className={cn('gap-4', className)}>\n {header}\n {overview}\n {notice}\n {metrics && metrics.items.length > 0 && (\n <section aria-label={metrics['aria-label']} aria-busy={metrics.loading}>\n <Grid columns=\"repeat(auto-fit, minmax(min(100%, 220px), 1fr))\" gap={12} {...metrics.grid}>\n {metrics.items.map(({ key, ...metric }) => (\n <Card.Metric key={key} {...metric} loading={metrics.loading ?? metric.loading} />\n ))}\n </Grid>\n </section>\n )}\n {filters}\n <Page.Body scroll={fullHeight} {...body}>\n {(left || navigation) && (\n <Page.Left width={240} bordered={false} scroll={false} {...left}>\n {left?.children !== undefined ? left.children : navigation && <NavigationList {...navigation} />}\n </Page.Left>\n )}\n <Page.Main scroll={fullHeight} {...main}>\n <Group direction=\"column\" align=\"stretch\" gap={16}>\n {toolbar}\n {contentHeader}\n {children !== undefined ? children : main?.children}\n </Group>\n </Page.Main>\n </Page.Body>\n {footer}\n </Page>\n);\n\n// lite exposes only the lightweight suite, without loading the Sidebar/router graph.\nexport const LayoutSuite = { DashboardSuite };\nexport default DashboardSuite;\n"],"mappings":";;;;;;;;AA+BA,IAAa,KAAkB,EAC3B,WAAQ,aAAU,WAAQ,YAAS,YAAS,eAAY,SAAM,SAAM,SACpE,YAAS,kBAAe,WAAQ,aAAU,gBAAa,IAAO,cAAW,GAAG,QAE5E,kBAAC,GAAD;CAAM,GAAI;CAAkB;CAAY,WAAW,EAAG,SAAS,CAAS;CAAxE,UAAA;EACK;EACA;EACA;EACA,KAAW,EAAQ,MAAM,SAAS,KAC/B,kBAAC,WAAD;GAAS,cAAY,EAAQ;GAAe,aAAW,EAAQ;GAC3D,UAAA,kBAAC,GAAD;IAAM,SAAQ;IAAkD,KAAK;IAAI,GAAI,EAAQ;IAChF,UAAA,EAAQ,MAAM,KAAK,EAAE,QAAK,GAAG,QAC1B,kBAAC,EAAK,QAAN;KAAuB,GAAI;KAAQ,SAAS,EAAQ,WAAW,EAAO;IAAU,GAA9D,CAA8D,CACnF;GACC,CAAA;EACD,CAAA;EAEZ;EACD,kBAAC,EAAK,MAAN;GAAW,QAAQ;GAAY,GAAI;GAAnC,UAAA,EACM,KAAQ,MACN,kBAAC,EAAK,MAAN;IAAW,OAAO;IAAK,UAAU;IAAO,QAAQ;IAAO,GAAI;IACtD,UAAA,GAAM,aAAa,KAAA,IAA4B,KAAc,kBAAC,GAAD,EAAgB,GAAI,EAAa,CAAA,IAA/D,EAAK;GAC9B,CAAA,GAEf,kBAAC,EAAK,MAAN;IAAW,QAAQ;IAAY,GAAI;IAC/B,UAAA,kBAAC,GAAD;KAAO,WAAU;KAAS,OAAM;KAAU,KAAK;KAA/C,UAAA;MACK;MACA;MACA,MAAa,KAAA,IAAuB,GAAM,WAAjB;KACvB;;GACA,CAAA,CACJ;;EACV;CACC;IAIG,IAAc,EAAE,kBAAe"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type PageProps, type PageBodyProps, type PageMainProps, type PageAsideProps, type PagePanelProps, type PageFooterProps, type PageFloatProps } from '../Page';
|
|
3
|
+
import type { PageHeaderProps } from '../PageHeader';
|
|
4
|
+
import Sidebar from '../../layouts/Sidebar';
|
|
5
|
+
import { DashboardSuite } from './DashboardSuite';
|
|
6
|
+
export { DashboardSuite } from './DashboardSuite';
|
|
7
|
+
export type { DashboardSuiteProps } from './DashboardSuite';
|
|
8
|
+
/** Sidebar 保持原有 API;panel 仅配置外层 Page.Left / Page.Right。 */
|
|
9
|
+
export type LayoutSuiteSidebarProps = Omit<React.ComponentProps<typeof Sidebar>, 'language' | 'isCollapsed' | 'side'> & {
|
|
10
|
+
language?: 'zh' | 'en';
|
|
11
|
+
isCollapsed?: boolean;
|
|
12
|
+
/** 独立启用区域边缘调宽,不要求 onToggle 或 onWidthChange。 */
|
|
13
|
+
resizable?: boolean;
|
|
14
|
+
panel?: Omit<PageAsideProps, 'children'>;
|
|
15
|
+
};
|
|
16
|
+
export type LayoutSuiteHeaderProps = PageHeaderProps & PagePanelProps;
|
|
17
|
+
export type LayoutSuiteBaseProps = PageProps & {
|
|
18
|
+
/** 可选三段式页头;Admin / Blog 仍要求配置 header。 */
|
|
19
|
+
header?: LayoutSuiteHeaderProps;
|
|
20
|
+
footer?: PageFooterProps;
|
|
21
|
+
/** body 不接收 children;主内容支持顶层 children 或 main.children。 */
|
|
22
|
+
body?: Omit<PageBodyProps, 'children'>;
|
|
23
|
+
main?: PageMainProps;
|
|
24
|
+
};
|
|
25
|
+
export type AdminSuiteProps = LayoutSuiteBaseProps & {
|
|
26
|
+
header: LayoutSuiteHeaderProps;
|
|
27
|
+
left: LayoutSuiteSidebarProps;
|
|
28
|
+
};
|
|
29
|
+
export type WikiSuiteProps = LayoutSuiteBaseProps & {
|
|
30
|
+
left?: LayoutSuiteSidebarProps;
|
|
31
|
+
right?: LayoutSuiteSidebarProps;
|
|
32
|
+
float?: PageFloatProps;
|
|
33
|
+
};
|
|
34
|
+
export type BlogSuiteProps = LayoutSuiteBaseProps & {
|
|
35
|
+
header: LayoutSuiteHeaderProps;
|
|
36
|
+
footer?: PageFooterProps;
|
|
37
|
+
};
|
|
38
|
+
export type BlankSuiteProps = LayoutSuiteBaseProps & {
|
|
39
|
+
float?: PageFloatProps;
|
|
40
|
+
};
|
|
41
|
+
/** 后台:必填页头和内置导航侧栏。Sidebar 需置于 TanStack Router 上下文中。 */
|
|
42
|
+
export declare const AdminSuite: (props: AdminSuiteProps) => React.JSX.Element;
|
|
43
|
+
/** 文档:可选双侧导航与浮窗。 */
|
|
44
|
+
export declare const WikiSuite: (props: WikiSuiteProps) => React.JSX.Element;
|
|
45
|
+
/** 博客:必填页头,可选页脚。 */
|
|
46
|
+
export declare const BlogSuite: (props: BlogSuiteProps) => React.JSX.Element;
|
|
47
|
+
/** 空白页:主内容与可选浮窗。 */
|
|
48
|
+
export declare const BlankSuite: (props: BlankSuiteProps) => React.JSX.Element;
|
|
49
|
+
export declare const LayoutSuite: {
|
|
50
|
+
AdminSuite: typeof AdminSuite;
|
|
51
|
+
WikiSuite: typeof WikiSuite;
|
|
52
|
+
BlogSuite: typeof BlogSuite;
|
|
53
|
+
BlankSuite: typeof BlankSuite;
|
|
54
|
+
DashboardSuite: typeof DashboardSuite;
|
|
55
|
+
};
|
|
56
|
+
export default LayoutSuite;
|