dishui 0.0.104 → 0.0.106
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/.release-verified.json +2 -2
- package/dist/components/ChoicePicker/index.js +8 -6
- package/dist/components/ChoicePicker/index.js.map +1 -1
- package/dist/components/Column/index.d.ts +3 -2
- package/dist/components/Column/index.js +5 -17
- package/dist/components/Column/index.js.map +1 -1
- package/dist/components/ConfirmDialog/index.d.ts +20 -0
- package/dist/components/ConfirmDialog/index.js +84 -0
- package/dist/components/ConfirmDialog/index.js.map +1 -0
- package/dist/components/DateTimeInput/index.js +28 -26
- package/dist/components/DateTimeInput/index.js.map +1 -1
- package/dist/components/Input/index.js +1 -1
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/MultipleChoice/index.js +2 -1
- package/dist/components/MultipleChoice/index.js.map +1 -1
- package/dist/components/Row/index.d.ts +3 -2
- package/dist/components/Row/index.js +5 -17
- package/dist/components/Row/index.js.map +1 -1
- package/dist/components/Tab/index.js +80 -0
- package/dist/components/Tab/index.js.map +1 -0
- package/dist/components/Tabs/index.js +28 -33
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tabs/tabNavigation.d.ts +2 -0
- package/dist/components/Tabs/tabNavigation.js +14 -0
- package/dist/components/Tabs/tabNavigation.js.map +1 -0
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.d.ts +1 -1
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +25 -26
- package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
- package/dist/components/pro/FileExplorer/Breadcrumb.js +8 -11
- package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
- package/dist/components/pro/Flow/Flow.js +184 -182
- package/dist/components/pro/Flow/Flow.js.map +1 -1
- package/dist/components/pro/Flow/archify/convert.js +26 -26
- package/dist/components/pro/Flow/archify/convert.js.map +1 -1
- package/dist/components/pro/Flow/hooks/useLayoutActions.js +13 -11
- package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaContent.d.ts +2 -1
- package/dist/components/pro/Flow/nodes/MediaContent.js +15 -15
- package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
- package/dist/components/pro/Flow/nodes/MediaOverlay.js +8 -7
- package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js +73 -83
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +73 -49
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.d.ts +1 -0
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js +12 -14
- package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +113 -113
- package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
- package/dist/css.d.ts +1 -0
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +113 -111
- package/dist/layouts/Sidebar.js +201 -107
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/utils/flexLayout.d.ts +5 -0
- package/dist/utils/flexLayout.js +19 -0
- package/dist/utils/flexLayout.js.map +1 -0
- package/package.json +63 -57
package/dist/layouts/Sidebar.js
CHANGED
|
@@ -5,9 +5,58 @@ import r from "../components/Tree/Tree.js";
|
|
|
5
5
|
import { DesktopSidebarToggleButton as i } from "../components/SidebarToggleButton/index.js";
|
|
6
6
|
import { useEffect as a, useMemo as o, useRef as s, useState as c } from "react";
|
|
7
7
|
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
8
|
-
import {
|
|
8
|
+
import { createPortal as d } from "react-dom";
|
|
9
|
+
import { Link as f, useNavigate as p, useRouterState as m } from "@tanstack/react-router";
|
|
9
10
|
//#region src/layouts/Sidebar.tsx
|
|
10
|
-
var
|
|
11
|
+
var h = () => /* @__PURE__ */ u("svg", {
|
|
12
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
13
|
+
viewBox: "0 0 24 24",
|
|
14
|
+
fill: "none",
|
|
15
|
+
stroke: "currentColor",
|
|
16
|
+
strokeWidth: "1.8",
|
|
17
|
+
strokeLinecap: "round",
|
|
18
|
+
strokeLinejoin: "round",
|
|
19
|
+
children: [/* @__PURE__ */ l("rect", {
|
|
20
|
+
x: "4",
|
|
21
|
+
y: "4",
|
|
22
|
+
width: "16",
|
|
23
|
+
height: "16",
|
|
24
|
+
rx: "3"
|
|
25
|
+
}), /* @__PURE__ */ l("path", { d: "M8 9h8M8 13h8M8 17h5" })]
|
|
26
|
+
}), g = () => /* @__PURE__ */ u("svg", {
|
|
27
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
28
|
+
viewBox: "0 0 24 24",
|
|
29
|
+
fill: "none",
|
|
30
|
+
stroke: "currentColor",
|
|
31
|
+
strokeWidth: "1.8",
|
|
32
|
+
strokeLinecap: "round",
|
|
33
|
+
strokeLinejoin: "round",
|
|
34
|
+
children: [/* @__PURE__ */ l("rect", {
|
|
35
|
+
x: "3",
|
|
36
|
+
y: "3",
|
|
37
|
+
width: "18",
|
|
38
|
+
height: "18",
|
|
39
|
+
rx: "3"
|
|
40
|
+
}), /* @__PURE__ */ l("path", { d: "M9 3v18M9 10h12" })]
|
|
41
|
+
}), _ = () => /* @__PURE__ */ l("svg", {
|
|
42
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
43
|
+
viewBox: "0 0 24 24",
|
|
44
|
+
fill: "none",
|
|
45
|
+
stroke: "currentColor",
|
|
46
|
+
strokeWidth: "1.8",
|
|
47
|
+
strokeLinecap: "round",
|
|
48
|
+
children: /* @__PURE__ */ l("path", { d: "M12 5v14M5 12h14" })
|
|
49
|
+
}), v = (e, t, n, r) => {
|
|
50
|
+
let i = e.getBoundingClientRect(), a = t?.getBoundingClientRect() ?? i, o = a.left - 16, s = window.innerWidth - a.right - 16, c = n === "right" ? o >= 200 || o > s : s < 200 && o > s;
|
|
51
|
+
return {
|
|
52
|
+
target: e,
|
|
53
|
+
text: r,
|
|
54
|
+
top: Math.max(8, Math.min(i.top, window.innerHeight - 48)),
|
|
55
|
+
left: c ? a.left - 8 : a.right + 8,
|
|
56
|
+
maxWidth: Math.max(0, Math.min(320, c ? o : s)),
|
|
57
|
+
alignRight: c
|
|
58
|
+
};
|
|
59
|
+
}, y = [
|
|
11
60
|
{
|
|
12
61
|
size: "base",
|
|
13
62
|
weight: "semibold"
|
|
@@ -20,36 +69,36 @@ var m = [
|
|
|
20
69
|
size: "sm",
|
|
21
70
|
weight: "normal"
|
|
22
71
|
}
|
|
23
|
-
],
|
|
24
|
-
let [
|
|
72
|
+
], b = ({ isCollapsed: b, side: x = "left", language: S, items: C, levelText: w, getMenuItems: T, onWidthChange: E, initialWidth: D = 280, collapsedWidth: O = 64, onToggle: k, minWidth: A = 160, maxWidth: j = 400, workspace: M, primaryAction: N, footer: P }) => {
|
|
73
|
+
let [F, I] = c([]), [L, R] = c(""), [z, B] = c(() => Math.max(A, Math.min(D, j))), V = s(null), H = s(null), [U, W] = c(null), G = m({ select: (e) => e.location }), K = p();
|
|
25
74
|
a(() => {
|
|
26
|
-
|
|
75
|
+
B(Math.max(A, Math.min(D, j)));
|
|
27
76
|
}, [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
77
|
+
D,
|
|
78
|
+
A,
|
|
79
|
+
j
|
|
31
80
|
]);
|
|
32
|
-
let
|
|
33
|
-
let t = Math.max(
|
|
34
|
-
|
|
81
|
+
let q = (e) => {
|
|
82
|
+
let t = Math.max(A, Math.min(e, j));
|
|
83
|
+
B(t), E?.(t);
|
|
35
84
|
};
|
|
36
85
|
a(() => {
|
|
37
|
-
|
|
86
|
+
I(C === void 0 ? T ? T(S) : t(S) : C);
|
|
38
87
|
}, [
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
88
|
+
S,
|
|
89
|
+
C,
|
|
90
|
+
T
|
|
42
91
|
]), a(() => {
|
|
43
|
-
if (!
|
|
92
|
+
if (!L) return;
|
|
44
93
|
let e = setTimeout(() => {
|
|
45
|
-
|
|
94
|
+
H.current?.querySelector(b ? "[aria-current=\"page\"]" : ".tree-node-content-active")?.scrollIntoView({
|
|
46
95
|
block: "nearest",
|
|
47
96
|
behavior: window.matchMedia("(prefers-reduced-motion: reduce)").matches ? "instant" : "smooth"
|
|
48
97
|
});
|
|
49
98
|
}, 350);
|
|
50
99
|
return () => clearTimeout(e);
|
|
51
|
-
}, [
|
|
52
|
-
let e =
|
|
100
|
+
}, [L, b]), a(() => {
|
|
101
|
+
let e = H.current;
|
|
53
102
|
if (!e) return;
|
|
54
103
|
let t = (t) => {
|
|
55
104
|
if (e.scrollHeight <= e.clientHeight) return;
|
|
@@ -59,36 +108,42 @@ var m = [
|
|
|
59
108
|
e.scrollTop = r + n, e.scrollTop !== r && t.preventDefault();
|
|
60
109
|
};
|
|
61
110
|
return e.addEventListener("wheel", t, { passive: !1 }), () => e.removeEventListener("wheel", t);
|
|
62
|
-
}, [
|
|
63
|
-
let
|
|
111
|
+
}, [b]);
|
|
112
|
+
let J = (e, t) => {
|
|
113
|
+
W(v(e, V.current, x, t));
|
|
114
|
+
}, Y = (e) => {
|
|
115
|
+
document.activeElement !== e && W((t) => t?.target === e ? null : t);
|
|
116
|
+
}, X = (e) => {
|
|
117
|
+
e.matches(":hover") || W((t) => t?.target === e ? null : t);
|
|
118
|
+
};
|
|
119
|
+
a(() => {
|
|
120
|
+
if (!b) return;
|
|
121
|
+
let e = () => {
|
|
122
|
+
W((e) => e?.target.isConnected ? v(e.target, V.current, x, e.text) : null);
|
|
123
|
+
};
|
|
124
|
+
return window.addEventListener("resize", e), () => window.removeEventListener("resize", e);
|
|
125
|
+
}, [
|
|
126
|
+
b,
|
|
127
|
+
x,
|
|
128
|
+
V
|
|
129
|
+
]);
|
|
130
|
+
let Z = (e) => e.map((e) => ({
|
|
64
131
|
id: e.id,
|
|
65
132
|
label: e.label,
|
|
66
|
-
icon: e.icon
|
|
67
|
-
|
|
68
|
-
className: "h-4 w-4",
|
|
69
|
-
fill: "none",
|
|
70
|
-
viewBox: "0 0 24 24",
|
|
71
|
-
stroke: "currentColor",
|
|
72
|
-
children: /* @__PURE__ */ l("path", {
|
|
73
|
-
strokeLinecap: "round",
|
|
74
|
-
strokeLinejoin: "round",
|
|
75
|
-
strokeWidth: "2",
|
|
76
|
-
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
77
|
-
})
|
|
78
|
-
})),
|
|
79
|
-
children: e.children ? V(e.children, !1) : void 0,
|
|
133
|
+
icon: e.icon ?? /* @__PURE__ */ l(h, {}),
|
|
134
|
+
children: e.children ? Z(e.children) : void 0,
|
|
80
135
|
meta: { path: e.path }
|
|
81
|
-
})),
|
|
82
|
-
if (
|
|
136
|
+
})), Q = o(() => Z(F), [F]), ee = o(() => {
|
|
137
|
+
if (F.length === 0) return [];
|
|
83
138
|
let e = (t) => {
|
|
84
139
|
let n = [];
|
|
85
140
|
for (let r of t) r.children?.length && (n.push(r.id), n = [...n, ...e(r.children)]);
|
|
86
141
|
return n;
|
|
87
142
|
};
|
|
88
|
-
return e(
|
|
89
|
-
}, [
|
|
143
|
+
return e(F);
|
|
144
|
+
}, [F]);
|
|
90
145
|
a(() => {
|
|
91
|
-
let e =
|
|
146
|
+
let e = G.pathname, t = (n) => {
|
|
92
147
|
for (let r of n) {
|
|
93
148
|
if (r.path === e) return r.id;
|
|
94
149
|
if (r.children) {
|
|
@@ -97,12 +152,12 @@ var m = [
|
|
|
97
152
|
}
|
|
98
153
|
}
|
|
99
154
|
return null;
|
|
100
|
-
}, n = t(
|
|
101
|
-
|
|
102
|
-
}, [
|
|
103
|
-
let
|
|
155
|
+
}, n = t(F);
|
|
156
|
+
R(n ?? "");
|
|
157
|
+
}, [F, G.pathname]);
|
|
158
|
+
let te = (e) => {
|
|
104
159
|
if (e.meta?.path) {
|
|
105
|
-
|
|
160
|
+
R(e.id), K({ to: e.meta.path });
|
|
106
161
|
return;
|
|
107
162
|
}
|
|
108
163
|
if (e.children && e.children.length > 0) {
|
|
@@ -116,94 +171,131 @@ var m = [
|
|
|
116
171
|
}
|
|
117
172
|
return null;
|
|
118
173
|
}, n = t(e.children);
|
|
119
|
-
n ? (
|
|
120
|
-
} else
|
|
121
|
-
},
|
|
174
|
+
n ? (R(n.id), K({ to: n.meta.path })) : R(e.id);
|
|
175
|
+
} else R(e.id);
|
|
176
|
+
}, $ = (e, t = []) => e.flatMap((e) => {
|
|
122
177
|
let n = [...t, e.label];
|
|
123
178
|
return [...e.path ? [{
|
|
124
179
|
item: e,
|
|
125
180
|
trail: n.join(" / ")
|
|
126
|
-
}] : [],
|
|
127
|
-
}),
|
|
128
|
-
ref:
|
|
181
|
+
}] : [], ...$(e.children ?? [], n)];
|
|
182
|
+
}), ne = b ? /* @__PURE__ */ l("nav", {
|
|
183
|
+
ref: H,
|
|
129
184
|
className: "sidebar-rail",
|
|
130
|
-
"aria-label":
|
|
131
|
-
|
|
132
|
-
|
|
185
|
+
"aria-label": S === "zh" ? "侧边导航" : "Sidebar navigation",
|
|
186
|
+
onScroll: () => {
|
|
187
|
+
U?.target.isConnected && J(U.target, U.text);
|
|
188
|
+
},
|
|
189
|
+
children: F.map((e) => {
|
|
190
|
+
let t = $([e]);
|
|
133
191
|
return t.length > 0 ? /* @__PURE__ */ l("div", {
|
|
134
192
|
role: "group",
|
|
135
193
|
"aria-label": e.label,
|
|
136
194
|
className: "sidebar-rail-group",
|
|
137
|
-
children: t.map(({ item: e, trail: t }) => /* @__PURE__ */ l(
|
|
195
|
+
children: t.map(({ item: e, trail: t }) => /* @__PURE__ */ l(f, {
|
|
138
196
|
to: e.path,
|
|
139
197
|
className: "sidebar-rail-link",
|
|
140
198
|
"aria-label": t,
|
|
141
199
|
title: t,
|
|
142
|
-
"aria-current":
|
|
200
|
+
"aria-current": G.pathname === e.path ? "page" : void 0,
|
|
201
|
+
onMouseEnter: (e) => J(e.currentTarget, t),
|
|
202
|
+
onMouseLeave: (e) => Y(e.currentTarget),
|
|
203
|
+
onFocus: (e) => J(e.currentTarget, t),
|
|
204
|
+
onBlur: (e) => X(e.currentTarget),
|
|
143
205
|
children: /* @__PURE__ */ l("span", {
|
|
144
206
|
"aria-hidden": "true",
|
|
145
|
-
children: e.icon
|
|
207
|
+
children: e.icon ?? /* @__PURE__ */ l(h, {})
|
|
146
208
|
})
|
|
147
209
|
}, e.id))
|
|
148
210
|
}, e.id) : null;
|
|
149
211
|
})
|
|
150
212
|
}) : null;
|
|
151
213
|
return /* @__PURE__ */ u("div", {
|
|
152
|
-
ref:
|
|
214
|
+
ref: V,
|
|
153
215
|
className: "dishui-sidebar sidebar-container h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative",
|
|
154
|
-
style:
|
|
155
|
-
width:
|
|
156
|
-
maxWidth:
|
|
157
|
-
minWidth:
|
|
216
|
+
style: b ? { width: O } : {
|
|
217
|
+
width: z,
|
|
218
|
+
maxWidth: j,
|
|
219
|
+
minWidth: A
|
|
158
220
|
},
|
|
159
221
|
children: [
|
|
160
|
-
|
|
161
|
-
isCollapsed:
|
|
162
|
-
side:
|
|
163
|
-
onToggle:
|
|
164
|
-
sidebarWidth:
|
|
165
|
-
collapsedWidth:
|
|
166
|
-
onWidthChange:
|
|
167
|
-
minWidth:
|
|
168
|
-
maxWidth:
|
|
169
|
-
anchorRef:
|
|
222
|
+
k && /* @__PURE__ */ l(i, {
|
|
223
|
+
isCollapsed: b,
|
|
224
|
+
side: x,
|
|
225
|
+
onToggle: k,
|
|
226
|
+
sidebarWidth: z,
|
|
227
|
+
collapsedWidth: O,
|
|
228
|
+
onWidthChange: E ? q : void 0,
|
|
229
|
+
minWidth: A,
|
|
230
|
+
maxWidth: j,
|
|
231
|
+
anchorRef: V
|
|
170
232
|
}),
|
|
171
|
-
(
|
|
233
|
+
(M || N) && /* @__PURE__ */ u("div", {
|
|
172
234
|
className: "dishui-sidebar-ai-header",
|
|
173
|
-
children: [
|
|
235
|
+
children: [M && /* @__PURE__ */ u("button", {
|
|
174
236
|
type: "button",
|
|
175
237
|
className: "dishui-sidebar-ai-workspace",
|
|
176
|
-
onClick:
|
|
177
|
-
|
|
238
|
+
onClick: M.onClick,
|
|
239
|
+
"aria-label": b && typeof M.name == "string" ? M.name : void 0,
|
|
240
|
+
title: b && typeof M.name == "string" ? M.name : void 0,
|
|
241
|
+
onMouseEnter: (e) => {
|
|
242
|
+
b && typeof M.name == "string" && J(e.currentTarget, M.name);
|
|
243
|
+
},
|
|
244
|
+
onFocus: (e) => {
|
|
245
|
+
b && typeof M.name == "string" && J(e.currentTarget, M.name);
|
|
246
|
+
},
|
|
247
|
+
onMouseLeave: (e) => Y(e.currentTarget),
|
|
248
|
+
onBlur: (e) => X(e.currentTarget),
|
|
178
249
|
children: [/* @__PURE__ */ l("span", {
|
|
179
250
|
className: "dishui-sidebar-ai-avatar",
|
|
180
251
|
"aria-hidden": "true",
|
|
181
|
-
children:
|
|
182
|
-
}), !
|
|
252
|
+
children: M.icon ?? /* @__PURE__ */ l(g, {})
|
|
253
|
+
}), !b && /* @__PURE__ */ l("span", {
|
|
183
254
|
className: "dishui-sidebar-ai-workspace-name",
|
|
184
|
-
children:
|
|
255
|
+
children: M.name
|
|
185
256
|
})]
|
|
186
|
-
}),
|
|
257
|
+
}), N && /* @__PURE__ */ u("button", {
|
|
187
258
|
type: "button",
|
|
188
259
|
className: "dishui-sidebar-ai-action",
|
|
189
|
-
onClick:
|
|
190
|
-
|
|
260
|
+
onClick: N.onClick,
|
|
261
|
+
"aria-label": b && typeof N.label == "string" ? N.label : void 0,
|
|
262
|
+
title: b && typeof N.label == "string" ? N.label : void 0,
|
|
263
|
+
onMouseEnter: (e) => {
|
|
264
|
+
b && typeof N.label == "string" && J(e.currentTarget, N.label);
|
|
265
|
+
},
|
|
266
|
+
onFocus: (e) => {
|
|
267
|
+
b && typeof N.label == "string" && J(e.currentTarget, N.label);
|
|
268
|
+
},
|
|
269
|
+
onMouseLeave: (e) => Y(e.currentTarget),
|
|
270
|
+
onBlur: (e) => X(e.currentTarget),
|
|
191
271
|
children: [/* @__PURE__ */ l("span", {
|
|
192
272
|
"aria-hidden": "true",
|
|
193
|
-
children:
|
|
194
|
-
}), !
|
|
273
|
+
children: N.icon ?? /* @__PURE__ */ l(_, {})
|
|
274
|
+
}), !b && /* @__PURE__ */ l("span", { children: N.label })]
|
|
195
275
|
})]
|
|
196
276
|
}),
|
|
197
|
-
|
|
277
|
+
ne,
|
|
278
|
+
b && U?.target.isConnected && d(/* @__PURE__ */ l("div", {
|
|
279
|
+
className: "dishui-sidebar-rail-tooltip",
|
|
280
|
+
role: "tooltip",
|
|
281
|
+
"aria-hidden": "true",
|
|
282
|
+
style: {
|
|
283
|
+
top: U.top,
|
|
284
|
+
left: U.left,
|
|
285
|
+
maxWidth: U.maxWidth,
|
|
286
|
+
transform: U.alignRight ? "translateX(-100%)" : void 0
|
|
287
|
+
},
|
|
288
|
+
children: U.text
|
|
289
|
+
}), document.body),
|
|
198
290
|
/* @__PURE__ */ l("div", {
|
|
199
|
-
hidden:
|
|
200
|
-
style:
|
|
201
|
-
ref:
|
|
291
|
+
hidden: b,
|
|
292
|
+
style: b ? { display: "none" } : void 0,
|
|
293
|
+
ref: b ? void 0 : H,
|
|
202
294
|
className: "sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent",
|
|
203
295
|
children: /* @__PURE__ */ l(r, {
|
|
204
|
-
data:
|
|
205
|
-
activeNodeId:
|
|
206
|
-
defaultExpandedIds:
|
|
296
|
+
data: Q,
|
|
297
|
+
activeNodeId: L,
|
|
298
|
+
defaultExpandedIds: ee,
|
|
207
299
|
showSearch: !1,
|
|
208
300
|
showExpandAll: !1,
|
|
209
301
|
showIcon: !0,
|
|
@@ -212,20 +304,20 @@ var m = [
|
|
|
212
304
|
indent: 1,
|
|
213
305
|
togglePosition: "right",
|
|
214
306
|
maxHeight: "100%",
|
|
215
|
-
className: `sidebar-tree${
|
|
307
|
+
className: `sidebar-tree${w === void 0 ? "" : " sidebar-tree-level-text"}`,
|
|
216
308
|
renderLabel: (t, n) => {
|
|
217
|
-
let r = Math.min(n, 2), i =
|
|
309
|
+
let r = Math.min(n, 2), i = w?.[r], a = y[r];
|
|
218
310
|
return /* @__PURE__ */ u(e, {
|
|
219
311
|
size: i?.size ?? a.size,
|
|
220
312
|
weight: i?.weight ?? a.weight,
|
|
221
|
-
color:
|
|
313
|
+
color: L === t.id ? "inherit" : i?.color ?? "inherit",
|
|
222
314
|
style: {
|
|
223
|
-
...
|
|
315
|
+
...w === void 0 ? {
|
|
224
316
|
fontSize: "inherit",
|
|
225
317
|
lineHeight: "inherit",
|
|
226
318
|
fontWeight: "inherit"
|
|
227
319
|
} : {},
|
|
228
|
-
...r === 2 && i?.color === void 0 &&
|
|
320
|
+
...r === 2 && i?.color === void 0 && L !== t.id ? { color: "var(--sidebar-level-muted)" } : {}
|
|
229
321
|
},
|
|
230
322
|
children: [t.label, typeof t.id == "string" && t.id.startsWith("ai-") && /* @__PURE__ */ l("span", {
|
|
231
323
|
className: "dishui-sidebar-ai-native-badge",
|
|
@@ -233,12 +325,12 @@ var m = [
|
|
|
233
325
|
})]
|
|
234
326
|
});
|
|
235
327
|
},
|
|
236
|
-
onNodeClick:
|
|
328
|
+
onNodeClick: te
|
|
237
329
|
})
|
|
238
330
|
}),
|
|
239
|
-
|
|
331
|
+
P && !b && /* @__PURE__ */ l("div", {
|
|
240
332
|
className: "dishui-sidebar-ai-footer",
|
|
241
|
-
children:
|
|
333
|
+
children: P
|
|
242
334
|
}),
|
|
243
335
|
/* @__PURE__ */ l("style", { children: `
|
|
244
336
|
.sidebar-container {
|
|
@@ -252,7 +344,9 @@ var m = [
|
|
|
252
344
|
.sidebar-rail-group { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; margin-bottom: 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 10px; }
|
|
253
345
|
.sidebar-rail-link { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 36px; min-height: 36px; flex-shrink: 0; border-radius: 6px; color: var(--sidebar-level-muted); text-decoration: none; transition: background-color 150ms, color 150ms; }
|
|
254
346
|
.sidebar-rail-link > span { display: flex; align-items: center; justify-content: center; }
|
|
255
|
-
.sidebar-rail-link svg { width:
|
|
347
|
+
.sidebar-rail-link svg { width: 16px; height: 16px; }
|
|
348
|
+
.dishui-sidebar-ai-avatar svg, .dishui-sidebar-ai-action svg { width: 18px; height: 18px; }
|
|
349
|
+
.dishui-sidebar-rail-tooltip { position: fixed; z-index: 1000; padding: 6px 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 6px; background: var(--color-base-100); color: var(--color-base-content); box-shadow: 0 2px 8px color-mix(in oklab, var(--color-base-content) 15%, transparent); font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; max-height: calc(100vh - 16px); overflow-y: auto; pointer-events: none; }
|
|
256
350
|
.sidebar-rail-link:hover { background: var(--color-base-300); }
|
|
257
351
|
.sidebar-rail-link[aria-current="page"] { color: var(--color-primary); background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-200)); box-shadow: inset 2px 0 var(--color-primary); }
|
|
258
352
|
.sidebar-rail-link:focus-visible { outline: 2px solid var(--dishui-ring, var(--color-primary)); outline-offset: -2px; }
|
|
@@ -314,8 +408,8 @@ var m = [
|
|
|
314
408
|
|
|
315
409
|
/* 图标样式 */
|
|
316
410
|
.sidebar-tree .tree-node-icon {
|
|
317
|
-
width:
|
|
318
|
-
height:
|
|
411
|
+
width: 20px;
|
|
412
|
+
height: 20px;
|
|
319
413
|
display: flex;
|
|
320
414
|
align-items: center;
|
|
321
415
|
justify-content: center;
|
|
@@ -324,14 +418,14 @@ var m = [
|
|
|
324
418
|
}
|
|
325
419
|
|
|
326
420
|
.sidebar-tree .tree-node-icon svg {
|
|
327
|
-
width:
|
|
328
|
-
height:
|
|
421
|
+
width: 20px;
|
|
422
|
+
height: 20px;
|
|
329
423
|
}
|
|
330
424
|
|
|
331
425
|
/* 子节点图标稍小 */
|
|
332
426
|
.sidebar-tree .tree-node-children .tree-node-icon svg {
|
|
333
|
-
width:
|
|
334
|
-
height:
|
|
427
|
+
width: 18px;
|
|
428
|
+
height: 18px;
|
|
335
429
|
opacity: 0.8;
|
|
336
430
|
}
|
|
337
431
|
|
|
@@ -391,6 +485,6 @@ var m = [
|
|
|
391
485
|
});
|
|
392
486
|
};
|
|
393
487
|
//#endregion
|
|
394
|
-
export {
|
|
488
|
+
export { b as default };
|
|
395
489
|
|
|
396
490
|
//# sourceMappingURL=Sidebar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.js","names":[],"sources":["../../src/layouts/Sidebar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useMemo } from 'react';\nimport { Link, useNavigate, useRouterState } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { getMenuItems as defaultGetMenuItems } from '../utils/menu';\nimport { Tree, TreeNode } from '../components/Tree';\nimport { generateSidebarActiveStyles } from '../styles/themeStyles';\nimport { DesktopSidebarToggleButton } from '../components/SidebarToggleButton';\nimport Text, { type TextProps } from '../components/Text';\n\nexport type SidebarLevelText = Pick<TextProps, 'size' | 'weight' | 'color'>;\n\nexport type SidebarHeader = {\n name: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nexport type SidebarAction = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nconst DEFAULT_LEVEL_TEXT = [\n { size: 'base', weight: 'semibold' },\n { size: 'sm', weight: 'medium' },\n { size: 'sm', weight: 'normal' },\n] as const satisfies readonly SidebarLevelText[];\n\n// 组件属性\nexport type SidebarProps = {\n isCollapsed: boolean;\n /** 侧栏所在侧,控制内侧 pill 的位置与调宽方向。 */\n side?: 'left' | 'right';\n language: 'zh' | 'en';\n items?: MenuItem[];\n /**\n * Opt-in typography for levels 1–3; deeper nodes reuse level 3.\n * Omitted: preserve legacy Sidebar/LayoutSuite typography. When supplied,\n * missing values default to base/sm/sm and semibold/medium/normal.\n * Levels 3+ default to theme-adaptive neutral gray, even without levelText.\n * Explicit colors retain Text semantics (secondary may be a theme accent).\n * Selected labels always inherit the active row color.\n */\n levelText?: readonly [SidebarLevelText?, SidebarLevelText?, SidebarLevelText?];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n onWidthChange?: (width: number) => void;\n initialWidth?: number;\n collapsedWidth?: number;\n /**\n * 折叠 / 展开切换回调。传入后,侧边栏会在其边缘渲染统一的悬浮 pill 控制条\n * (点击折叠、拖拽调节宽度),无需再在外层单独渲染 SidebarToggleButtons。\n */\n onToggle?: () => void;\n /** 拖拽调节宽度的最小值(px) */\n minWidth?: number;\n /** 拖拽调节宽度的最大值(px) */\n maxWidth?: number;\n /** Optional AI-style workspace header shown above the tree. */\n workspace?: SidebarHeader;\n /** Optional primary sidebar action, such as “New chat”. */\n primaryAction?: SidebarAction;\n /** Optional footer rendered below the scrollable multi-level menu. */\n footer?: React.ReactNode;\n};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n side = 'left',\n language,\n items: propItems,\n levelText,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n onToggle,\n minWidth = 160,\n maxWidth = 400,\n workspace,\n primaryAction,\n footer,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [sidebarWidth, setSidebarWidth] = useState(() => Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n const sidebarRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const routerState = useRouterState({ select: (s: { location: { pathname: string } }) => s.location });\n const navigate = useNavigate();\n\n // 当 initialWidth 改变时,更新侧边栏宽度\n useEffect(() => {\n setSidebarWidth(Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n }, [initialWidth, minWidth, maxWidth]);\n\n // 统一的宽度变更处理:同步内部状态并通知父组件。\n // pill 拖拽与外部同步都通过此入口,避免必须回传 initialWidth 才能生效。\n const handleInternalWidthChange = (width: number) => {\n const next = Math.max(minWidth, Math.min(width, maxWidth));\n setSidebarWidth(next);\n onWidthChange?.(next);\n };\n\n // 当语言改变或传入items prop时,更新菜单项\n useEffect(() => {\n if (propItems !== undefined) {\n setItems(propItems);\n } else if (getMenuItems) {\n setItems(getMenuItems(language));\n } else {\n setItems(defaultGetMenuItems(language));\n }\n }, [language, propItems, getMenuItems]);\n\n // 活跃节点变化时,自动滚动到可见区域(菜单过长时保证当前页可见)。\n // 延迟 350ms:Tree 展开动画(max-height 0.3s)期间布局仍在变化,立即\n // scrollIntoView 会计算到动画中途的位置而滚动不到位。\n useEffect(() => {\n if (!activeNodeId) return;\n const t = setTimeout(() => {\n scrollRef.current\n ?.querySelector(isCollapsed ? '[aria-current=\"page\"]' : '.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId, isCollapsed]);\n\n // 兜底:确保鼠标悬停在菜单任意位置都能滚轮滚动。\n // 部分浏览器/嵌套滚动场景下原生滚轮可能不作用于该容器,这里用非被动\n // 监听手动滚动;成功滚动后 preventDefault,避免浏览器默认行为造成双重滚动。\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n if (el.scrollHeight <= el.clientHeight) return;\n const dy = e.deltaMode === 1 ? e.deltaY * 16 : e.deltaY; // 行模式 → 像素\n if (dy === 0) return;\n const before = el.scrollTop;\n el.scrollTop = before + dy;\n if (el.scrollTop !== before) e.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [isCollapsed]);\n\n // 将 MenuItem 转换为 TreeNode\n const convertToTreeNodes = (menuItems: MenuItem[], isTopLevel: boolean = true): TreeNode[] => {\n return menuItems.map(item => ({\n id: item.id,\n label: item.label,\n icon: item.icon || (!isTopLevel ? (\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n ) : undefined),\n children: item.children ? convertToTreeNodes(item.children, false) : undefined,\n meta: {\n path: item.path,\n },\n }));\n };\n\n // 转换后的树形数据\n const treeData = useMemo(() => convertToTreeNodes(items, true), [items]);\n\n // 获取默认展开的节点ID(默认全部展开)\n const defaultExpandedIds = useMemo(() => {\n if (items.length === 0) return [];\n\n // 收集所有有子节点的项的ID,使其默认全展开\n const collectAllExpandableIds = (menuItems: MenuItem[]): string[] => {\n let result: string[] = [];\n for (const item of menuItems) {\n if (item.children?.length) {\n result.push(item.id);\n result = [...result, ...collectAllExpandableIds(item.children)];\n }\n }\n return result;\n };\n\n return collectAllExpandableIds(items);\n }, [items]);\n\n // 更新活跃节点ID\n useEffect(() => {\n const currentPath = routerState.pathname;\n const findNodeByPath = (menuItems: MenuItem[]): string | null => {\n for (const item of menuItems) {\n if (item.path === currentPath) {\n return item.id;\n }\n if (item.children) {\n const found = findNodeByPath(item.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const nodeId = findNodeByPath(items);\n setActiveNodeId(nodeId ?? '');\n }, [items, routerState.pathname]);\n\n\n\n // 处理节点点击\n const handleNodeClick = (node: TreeNode) => {\n // 如果节点有路径,直接导航\n if (node.meta?.path) {\n setActiveNodeId(node.id);\n navigate({ to: node.meta.path });\n return;\n }\n\n // 如果没有路径但有子节点,寻找第一个有路径的后代节点\n if (node.children && node.children.length > 0) {\n const findFirstPath = (nodes: TreeNode[]): TreeNode | null => {\n for (const n of nodes) {\n if (n.meta?.path) return n;\n if (n.children && n.children.length > 0) {\n const found = findFirstPath(n.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const firstNodeWithPath = findFirstPath(node.children);\n if (firstNodeWithPath) {\n setActiveNodeId(firstNodeWithPath.id);\n navigate({ to: firstNodeWithPath.meta!.path });\n } else {\n // 全都没有路径则激活当前节点\n setActiveNodeId(node.id);\n }\n } else {\n setActiveNodeId(node.id);\n }\n };\n\n const collectLinks = (nodes: MenuItem[], parents: string[] = []): { item: MenuItem; trail: string }[] =>\n nodes.flatMap(item => {\n const trail = [...parents, item.label];\n return [\n ...(item.path ? [{ item, trail: trail.join(' / ') }] : []),\n ...collectLinks(item.children ?? [], trail),\n ];\n });\n\n /* Keep Tree mounted so rail toggles do not reset the user's expanded branches. */\n const rail = isCollapsed ? (\n <nav ref={scrollRef} className=\"sidebar-rail\" aria-label={language === 'zh' ? '侧边导航' : 'Sidebar navigation'}>\n {items.map(group => {\n const links = collectLinks([group]);\n return links.length > 0 ? (\n <div key={group.id} role=\"group\" aria-label={group.label} className=\"sidebar-rail-group\">\n {links.map(({ item, trail }) => (\n <Link\n key={item.id}\n to={item.path!}\n className=\"sidebar-rail-link\"\n aria-label={trail}\n title={trail}\n aria-current={routerState.pathname === item.path ? 'page' : undefined}\n >\n <span aria-hidden=\"true\">{item.icon || <span>{item.label.charAt(0)}</span>}</span>\n </Link>\n ))}\n </div>\n ) : null;\n })}\n </nav>\n ) : null;\n\n return (\n <div\n ref={sidebarRef}\n className=\"dishui-sidebar sidebar-container h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative\"\n style={isCollapsed ? { width: collapsedWidth } : { width: sidebarWidth, maxWidth, minWidth }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\n side={side}\n onToggle={onToggle}\n sidebarWidth={sidebarWidth}\n collapsedWidth={collapsedWidth}\n onWidthChange={onWidthChange ? handleInternalWidthChange : undefined}\n minWidth={minWidth}\n maxWidth={maxWidth}\n anchorRef={sidebarRef}\n />\n )}\n {(workspace || primaryAction) && (\n <div className=\"dishui-sidebar-ai-header\">\n {workspace && (\n <button type=\"button\" className=\"dishui-sidebar-ai-workspace\" onClick={workspace.onClick} title={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}>\n <span className=\"dishui-sidebar-ai-avatar\" aria-hidden=\"true\">{workspace.icon ?? (typeof workspace.name === 'string' ? workspace.name.charAt(0).toUpperCase() : '•')}</span>\n {!isCollapsed && <span className=\"dishui-sidebar-ai-workspace-name\">{workspace.name}</span>}\n </button>\n )}\n {primaryAction && (\n <button type=\"button\" className=\"dishui-sidebar-ai-action\" onClick={primaryAction.onClick} title={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}>\n <span aria-hidden=\"true\">{primaryAction.icon ?? '+'}</span>\n {!isCollapsed && <span>{primaryAction.label}</span>}\n </button>\n )}\n </div>\n )}\n {rail}\n <div hidden={isCollapsed} style={isCollapsed ? { display: 'none' } : undefined} ref={isCollapsed ? undefined : scrollRef} className=\"sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent\">\n <Tree\n data={treeData}\n activeNodeId={activeNodeId}\n defaultExpandedIds={defaultExpandedIds}\n showSearch={false}\n showExpandAll={false}\n showIcon={true}\n showCount={false}\n showLine={true}\n indent={1}\n togglePosition=\"right\"\n maxHeight=\"100%\"\n className={`sidebar-tree${levelText !== undefined ? ' sidebar-tree-level-text' : ''}`}\n renderLabel={(node, depth) => {\n const level = Math.min(depth, 2);\n const text = levelText?.[level];\n const defaults = DEFAULT_LEVEL_TEXT[level];\n return (\n <Text\n size={text?.size ?? defaults.size}\n weight={text?.weight ?? defaults.weight}\n color={activeNodeId === node.id ? 'inherit' : text?.color ?? 'inherit'}\n style={{\n ...(levelText === undefined ? { fontSize: 'inherit', lineHeight: 'inherit', fontWeight: 'inherit' } : {}),\n ...(level === 2 && text?.color === undefined && activeNodeId !== node.id\n ? { color: 'var(--sidebar-level-muted)' } : {}),\n }}\n >\n {node.label}\n {typeof node.id === 'string' && node.id.startsWith('ai-') && (\n <span className=\"dishui-sidebar-ai-native-badge\">AI</span>\n )}\n </Text>\n );\n }}\n onNodeClick={handleNodeClick}\n />\n </div>\n {footer && !isCollapsed && <div className=\"dishui-sidebar-ai-footer\">{footer}</div>}\n\n <style>{`\n .sidebar-container {\n --sidebar-level-muted: oklch(from color-mix(in oklab, var(--color-base-content) 76%, var(--color-base-200)) l 0 0);\n }\n /* LayoutSuite uses semantic surfaces even in colorful themes. Match its text luminance. */\n .dishui-layout-suite-sidebar > .sidebar-container {\n --sidebar-level-muted: oklch(from var(--dishui-text-tertiary) l 0 0);\n }\n .sidebar-rail { min-height: 0; height: 100%; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 6px; }\n .sidebar-rail-group { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; margin-bottom: 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 10px; }\n .sidebar-rail-link { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 36px; min-height: 36px; flex-shrink: 0; border-radius: 6px; color: var(--sidebar-level-muted); text-decoration: none; transition: background-color 150ms, color 150ms; }\n .sidebar-rail-link > span { display: flex; align-items: center; justify-content: center; }\n .sidebar-rail-link svg { width: 18px; height: 18px; }\n .sidebar-rail-link:hover { background: var(--color-base-300); }\n .sidebar-rail-link[aria-current=\"page\"] { color: var(--color-primary); background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-200)); box-shadow: inset 2px 0 var(--color-primary); }\n .sidebar-rail-link:focus-visible { outline: 2px solid var(--dishui-ring, var(--color-primary)); outline-offset: -2px; }\n @media (prefers-reduced-motion: reduce) { .sidebar-rail-link { transition: none; } }\n /* Sidebar Tree 自定义样式 */\n .sidebar-tree {\n background: transparent;\n border: none;\n padding: 0.5rem;\n }\n \n .sidebar-tree .tree-node-content {\n padding: 0.5rem 1rem;\n border-radius: var(--dishui-radius-sm);\n transition: background-color var(--dishui-duration-normal) var(--dishui-ease-out), color var(--dishui-duration-normal) var(--dishui-ease-out), transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n /* 活跃状态 - 为每个主题设置匹配的配色 */\n .sidebar-tree .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(1rem - 4px) !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateSidebarActiveStyles()}\n \n /* 悬停状态 */\n .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {\n background-color: var(--color-base-200);\n }\n \n /* 右侧展开按钮样式 */\n .sidebar-tree .tree-node-toggle-right {\n width: auto;\n height: auto;\n min-width: auto;\n min-height: auto;\n padding: 0.25rem;\n opacity: 0.6;\n transition: opacity var(--dishui-duration-normal) var(--dishui-ease-out), background-color var(--dishui-duration-normal) var(--dishui-ease-out);\n border-radius: var(--dishui-radius-xs);\n }\n \n .sidebar-tree .tree-node-toggle-right:hover {\n opacity: 1;\n background-color: var(--color-base-300);\n }\n \n /* 右侧按钮图标旋转 */\n .sidebar-tree .tree-node-toggle-right svg {\n width: 1rem;\n height: 1rem;\n transition: transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n .sidebar-tree .tree-node-toggle-right.tree-node-toggle-expanded svg {\n transform: rotate(90deg);\n }\n \n /* 图标样式 */\n .sidebar-tree .tree-node-icon {\n width: 1.25rem;\n height: 1.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.2s ease;\n }\n \n .sidebar-tree .tree-node-icon svg {\n width: 1.25rem;\n height: 1.25rem;\n }\n \n /* 子节点图标稍小 */\n .sidebar-tree .tree-node-children .tree-node-icon svg {\n width: 1rem;\n height: 1rem;\n opacity: 0.8;\n }\n \n /* Preserve the legacy all-level appearance only when typography is not configured. */\n .sidebar-tree:not(.sidebar-tree-level-text) .tree-node-label {\n font-size: 1rem;\n line-height: 1.4rem;\n font-weight: 500;\n }\n \n /* 连接线样式 - 强制显示!向右移动并加粗,增加整体左边距 */\n /* 使用双重选择器增加优先级,避免被其他 Tree 组件样式覆盖 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded,\n .sidebar-tree.sidebar-tree .tree-node-children.tree-node-children-expanded,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded,\n div.sidebar-tree .tree-node-children.tree-node-children-expanded {\n border-left: 3px solid rgba(128, 128, 128, 0.35) !important;\n margin-left: 24px !important;\n padding-left: 8px !important;\n box-sizing: border-box !important;\n }\n \n /* 隐藏 Tree 组件的圆点装饰 - 避免与 Sidebar 样式冲突 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded::before,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded::before {\n display: none !important;\n }\n \n /* 隐藏 Tree 组件的标题和操作按钮 */\n .sidebar-tree .tree-header,\n .sidebar-tree .tree-search,\n .sidebar-tree .tree-actions {\n display: none;\n }\n \n /* 移除内边距 */\n .sidebar-tree > div:first-child {\n padding: 0;\n }\n \n /* 子节点动画优化 - 减小间距 */\n .sidebar-tree .tree-node-children {\n margin-top: 0.125rem !important;\n }\n \n /* 一级菜单项间距 */\n .sidebar-tree > div > .tree-nodes > .tree-node {\n margin-bottom: 0.375rem;\n }\n \n /* 二级菜单项间距 */\n .sidebar-tree .tree-node-children > .tree-node {\n margin-bottom: 0.125rem;\n }\n `}</style>\n </div>\n );\n};\n\nexport default Sidebar; "],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Sidebar.js","names":[],"sources":["../../src/layouts/Sidebar.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Link, useNavigate, useRouterState } from '@tanstack/react-router';\nimport { MenuItem } from '../types/menu';\nimport { getMenuItems as defaultGetMenuItems } from '../utils/menu';\nimport { Tree, TreeNode } from '../components/Tree';\nimport { generateSidebarActiveStyles } from '../styles/themeStyles';\nimport { DesktopSidebarToggleButton } from '../components/SidebarToggleButton';\nimport Text, { type TextProps } from '../components/Text';\n\nexport type SidebarLevelText = Pick<TextProps, 'size' | 'weight' | 'color'>;\n\nexport type SidebarHeader = {\n name: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nexport type SidebarAction = {\n label: React.ReactNode;\n icon?: React.ReactNode;\n onClick?: () => void;\n};\n\nconst DefaultMenuIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"3\" />\n <path d=\"M8 9h8M8 13h8M8 17h5\" />\n </svg>\n);\n\nconst DefaultWorkspaceIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"3\" />\n <path d=\"M9 3v18M9 10h12\" />\n </svg>\n);\n\nconst DefaultActionIcon = () => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\" strokeLinecap=\"round\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n);\n\ntype RailTooltip = { target: HTMLElement; text: string; top: number; left: number; maxWidth: number; alignRight: boolean };\n\nconst getRailTooltip = (target: HTMLElement, sidebarElement: HTMLElement | null, side: 'left' | 'right', text: string): RailTooltip => {\n const rect = target.getBoundingClientRect();\n const sidebar = sidebarElement?.getBoundingClientRect() ?? rect;\n const spaceLeft = sidebar.left - 16;\n const spaceRight = window.innerWidth - sidebar.right - 16;\n const alignRight = side === 'right' ? spaceLeft >= 200 || spaceLeft > spaceRight : spaceRight < 200 && spaceLeft > spaceRight;\n return {\n target,\n text,\n top: Math.max(8, Math.min(rect.top, window.innerHeight - 48)),\n left: alignRight ? sidebar.left - 8 : sidebar.right + 8,\n maxWidth: Math.max(0, Math.min(320, alignRight ? spaceLeft : spaceRight)),\n alignRight,\n };\n};\n\nconst DEFAULT_LEVEL_TEXT = [\n { size: 'base', weight: 'semibold' },\n { size: 'sm', weight: 'medium' },\n { size: 'sm', weight: 'normal' },\n] as const satisfies readonly SidebarLevelText[];\n\n// 组件属性\nexport type SidebarProps = {\n isCollapsed: boolean;\n /** 侧栏所在侧,控制内侧 pill 的位置与调宽方向。 */\n side?: 'left' | 'right';\n language: 'zh' | 'en';\n items?: MenuItem[];\n /**\n * Opt-in typography for levels 1–3; deeper nodes reuse level 3.\n * Omitted: preserve legacy Sidebar/LayoutSuite typography. When supplied,\n * missing values default to base/sm/sm and semibold/medium/normal.\n * Levels 3+ default to theme-adaptive neutral gray, even without levelText.\n * Explicit colors retain Text semantics (secondary may be a theme accent).\n * Selected labels always inherit the active row color.\n */\n levelText?: readonly [SidebarLevelText?, SidebarLevelText?, SidebarLevelText?];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n onWidthChange?: (width: number) => void;\n initialWidth?: number;\n collapsedWidth?: number;\n /**\n * 折叠 / 展开切换回调。传入后,侧边栏会在其边缘渲染统一的悬浮 pill 控制条\n * (点击折叠、拖拽调节宽度),无需再在外层单独渲染 SidebarToggleButtons。\n */\n onToggle?: () => void;\n /** 拖拽调节宽度的最小值(px) */\n minWidth?: number;\n /** 拖拽调节宽度的最大值(px) */\n maxWidth?: number;\n /** Optional AI-style workspace header shown above the tree. */\n workspace?: SidebarHeader;\n /** Optional primary sidebar action, such as “New chat”. */\n primaryAction?: SidebarAction;\n /** Optional footer rendered below the scrollable multi-level menu. */\n footer?: React.ReactNode;\n};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n side = 'left',\n language,\n items: propItems,\n levelText,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n onToggle,\n minWidth = 160,\n maxWidth = 400,\n workspace,\n primaryAction,\n footer,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [sidebarWidth, setSidebarWidth] = useState(() => Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n const sidebarRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const [railTooltip, setRailTooltip] = useState<RailTooltip | null>(null);\n const routerState = useRouterState({ select: (s: { location: { pathname: string } }) => s.location });\n const navigate = useNavigate();\n\n // 当 initialWidth 改变时,更新侧边栏宽度\n useEffect(() => {\n setSidebarWidth(Math.max(minWidth, Math.min(initialWidth, maxWidth)));\n }, [initialWidth, minWidth, maxWidth]);\n\n // 统一的宽度变更处理:同步内部状态并通知父组件。\n // pill 拖拽与外部同步都通过此入口,避免必须回传 initialWidth 才能生效。\n const handleInternalWidthChange = (width: number) => {\n const next = Math.max(minWidth, Math.min(width, maxWidth));\n setSidebarWidth(next);\n onWidthChange?.(next);\n };\n\n // 当语言改变或传入items prop时,更新菜单项\n useEffect(() => {\n if (propItems !== undefined) {\n setItems(propItems);\n } else if (getMenuItems) {\n setItems(getMenuItems(language));\n } else {\n setItems(defaultGetMenuItems(language));\n }\n }, [language, propItems, getMenuItems]);\n\n // 活跃节点变化时,自动滚动到可见区域(菜单过长时保证当前页可见)。\n // 延迟 350ms:Tree 展开动画(max-height 0.3s)期间布局仍在变化,立即\n // scrollIntoView 会计算到动画中途的位置而滚动不到位。\n useEffect(() => {\n if (!activeNodeId) return;\n const t = setTimeout(() => {\n scrollRef.current\n ?.querySelector(isCollapsed ? '[aria-current=\"page\"]' : '.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'instant' : 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId, isCollapsed]);\n\n // 兜底:确保鼠标悬停在菜单任意位置都能滚轮滚动。\n // 部分浏览器/嵌套滚动场景下原生滚轮可能不作用于该容器,这里用非被动\n // 监听手动滚动;成功滚动后 preventDefault,避免浏览器默认行为造成双重滚动。\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n if (el.scrollHeight <= el.clientHeight) return;\n const dy = e.deltaMode === 1 ? e.deltaY * 16 : e.deltaY; // 行模式 → 像素\n if (dy === 0) return;\n const before = el.scrollTop;\n el.scrollTop = before + dy;\n if (el.scrollTop !== before) e.preventDefault();\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [isCollapsed]);\n\n const showRailTooltip = (target: HTMLElement, text: string) => {\n setRailTooltip(getRailTooltip(target, sidebarRef.current, side, text));\n };\n\n const hideTooltipOnMouseLeave = (target: HTMLElement) => {\n if (document.activeElement !== target) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n const hideTooltipOnBlur = (target: HTMLElement) => {\n if (!target.matches(':hover')) setRailTooltip(current => current?.target === target ? null : current);\n };\n\n useEffect(() => {\n if (!isCollapsed) return;\n const update = () => {\n setRailTooltip(current => current?.target.isConnected\n ? getRailTooltip(current.target, sidebarRef.current, side, current.text)\n : null);\n };\n window.addEventListener('resize', update);\n return () => window.removeEventListener('resize', update);\n }, [isCollapsed, side, sidebarRef]);\n\n // 将 MenuItem 转换为 TreeNode\n const convertToTreeNodes = (menuItems: MenuItem[]): TreeNode[] => {\n return menuItems.map(item => ({\n id: item.id,\n label: item.label,\n icon: item.icon ?? <DefaultMenuIcon />,\n children: item.children ? convertToTreeNodes(item.children) : undefined,\n meta: {\n path: item.path,\n },\n }));\n };\n\n // 转换后的树形数据\n const treeData = useMemo(() => convertToTreeNodes(items), [items]);\n\n // 获取默认展开的节点ID(默认全部展开)\n const defaultExpandedIds = useMemo(() => {\n if (items.length === 0) return [];\n\n // 收集所有有子节点的项的ID,使其默认全展开\n const collectAllExpandableIds = (menuItems: MenuItem[]): string[] => {\n let result: string[] = [];\n for (const item of menuItems) {\n if (item.children?.length) {\n result.push(item.id);\n result = [...result, ...collectAllExpandableIds(item.children)];\n }\n }\n return result;\n };\n\n return collectAllExpandableIds(items);\n }, [items]);\n\n // 更新活跃节点ID\n useEffect(() => {\n const currentPath = routerState.pathname;\n const findNodeByPath = (menuItems: MenuItem[]): string | null => {\n for (const item of menuItems) {\n if (item.path === currentPath) {\n return item.id;\n }\n if (item.children) {\n const found = findNodeByPath(item.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const nodeId = findNodeByPath(items);\n setActiveNodeId(nodeId ?? '');\n }, [items, routerState.pathname]);\n\n\n\n // 处理节点点击\n const handleNodeClick = (node: TreeNode) => {\n // 如果节点有路径,直接导航\n if (node.meta?.path) {\n setActiveNodeId(node.id);\n navigate({ to: node.meta.path });\n return;\n }\n\n // 如果没有路径但有子节点,寻找第一个有路径的后代节点\n if (node.children && node.children.length > 0) {\n const findFirstPath = (nodes: TreeNode[]): TreeNode | null => {\n for (const n of nodes) {\n if (n.meta?.path) return n;\n if (n.children && n.children.length > 0) {\n const found = findFirstPath(n.children);\n if (found) return found;\n }\n }\n return null;\n };\n\n const firstNodeWithPath = findFirstPath(node.children);\n if (firstNodeWithPath) {\n setActiveNodeId(firstNodeWithPath.id);\n navigate({ to: firstNodeWithPath.meta!.path });\n } else {\n // 全都没有路径则激活当前节点\n setActiveNodeId(node.id);\n }\n } else {\n setActiveNodeId(node.id);\n }\n };\n\n const collectLinks = (nodes: MenuItem[], parents: string[] = []): { item: MenuItem; trail: string }[] =>\n nodes.flatMap(item => {\n const trail = [...parents, item.label];\n return [\n ...(item.path ? [{ item, trail: trail.join(' / ') }] : []),\n ...collectLinks(item.children ?? [], trail),\n ];\n });\n\n /* Keep Tree mounted so rail toggles do not reset the user's expanded branches. */\n const rail = isCollapsed ? (\n <nav ref={scrollRef} className=\"sidebar-rail\" aria-label={language === 'zh' ? '侧边导航' : 'Sidebar navigation'} onScroll={() => {\n if (railTooltip?.target.isConnected) showRailTooltip(railTooltip.target, railTooltip.text);\n }}>\n {items.map(group => {\n const links = collectLinks([group]);\n return links.length > 0 ? (\n <div key={group.id} role=\"group\" aria-label={group.label} className=\"sidebar-rail-group\">\n {links.map(({ item, trail }) => (\n <Link\n key={item.id}\n to={item.path!}\n className=\"sidebar-rail-link\"\n aria-label={trail}\n title={trail}\n aria-current={routerState.pathname === item.path ? 'page' : undefined}\n onMouseEnter={event => showRailTooltip(event.currentTarget, trail)}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onFocus={event => showRailTooltip(event.currentTarget, trail)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{item.icon ?? <DefaultMenuIcon />}</span>\n </Link>\n ))}\n </div>\n ) : null;\n })}\n </nav>\n ) : null;\n\n return (\n <div\n ref={sidebarRef}\n className=\"dishui-sidebar sidebar-container h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative\"\n style={isCollapsed ? { width: collapsedWidth } : { width: sidebarWidth, maxWidth, minWidth }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\n side={side}\n onToggle={onToggle}\n sidebarWidth={sidebarWidth}\n collapsedWidth={collapsedWidth}\n onWidthChange={onWidthChange ? handleInternalWidthChange : undefined}\n minWidth={minWidth}\n maxWidth={maxWidth}\n anchorRef={sidebarRef}\n />\n )}\n {(workspace || primaryAction) && (\n <div className=\"dishui-sidebar-ai-header\">\n {workspace && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-workspace\"\n onClick={workspace.onClick}\n aria-label={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n title={isCollapsed && typeof workspace.name === 'string' ? workspace.name : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onFocus={event => { if (isCollapsed && typeof workspace.name === 'string') showRailTooltip(event.currentTarget, workspace.name); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span className=\"dishui-sidebar-ai-avatar\" aria-hidden=\"true\">{workspace.icon ?? <DefaultWorkspaceIcon />}</span>\n {!isCollapsed && <span className=\"dishui-sidebar-ai-workspace-name\">{workspace.name}</span>}\n </button>\n )}\n {primaryAction && (\n <button\n type=\"button\"\n className=\"dishui-sidebar-ai-action\"\n onClick={primaryAction.onClick}\n aria-label={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n title={isCollapsed && typeof primaryAction.label === 'string' ? primaryAction.label : undefined}\n onMouseEnter={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onFocus={event => { if (isCollapsed && typeof primaryAction.label === 'string') showRailTooltip(event.currentTarget, primaryAction.label); }}\n onMouseLeave={event => hideTooltipOnMouseLeave(event.currentTarget)}\n onBlur={event => hideTooltipOnBlur(event.currentTarget)}\n >\n <span aria-hidden=\"true\">{primaryAction.icon ?? <DefaultActionIcon />}</span>\n {!isCollapsed && <span>{primaryAction.label}</span>}\n </button>\n )}\n </div>\n )}\n {rail}\n {isCollapsed && railTooltip?.target.isConnected && createPortal(\n <div className=\"dishui-sidebar-rail-tooltip\" role=\"tooltip\" aria-hidden=\"true\" style={{ top: railTooltip.top, left: railTooltip.left, maxWidth: railTooltip.maxWidth, transform: railTooltip.alignRight ? 'translateX(-100%)' : undefined }}>\n {railTooltip.text}\n </div>,\n document.body,\n )}\n <div hidden={isCollapsed} style={isCollapsed ? { display: 'none' } : undefined} ref={isCollapsed ? undefined : scrollRef} className=\"sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent\">\n <Tree\n data={treeData}\n activeNodeId={activeNodeId}\n defaultExpandedIds={defaultExpandedIds}\n showSearch={false}\n showExpandAll={false}\n showIcon={true}\n showCount={false}\n showLine={true}\n indent={1}\n togglePosition=\"right\"\n maxHeight=\"100%\"\n className={`sidebar-tree${levelText !== undefined ? ' sidebar-tree-level-text' : ''}`}\n renderLabel={(node, depth) => {\n const level = Math.min(depth, 2);\n const text = levelText?.[level];\n const defaults = DEFAULT_LEVEL_TEXT[level];\n return (\n <Text\n size={text?.size ?? defaults.size}\n weight={text?.weight ?? defaults.weight}\n color={activeNodeId === node.id ? 'inherit' : text?.color ?? 'inherit'}\n style={{\n ...(levelText === undefined ? { fontSize: 'inherit', lineHeight: 'inherit', fontWeight: 'inherit' } : {}),\n ...(level === 2 && text?.color === undefined && activeNodeId !== node.id\n ? { color: 'var(--sidebar-level-muted)' } : {}),\n }}\n >\n {node.label}\n {typeof node.id === 'string' && node.id.startsWith('ai-') && (\n <span className=\"dishui-sidebar-ai-native-badge\">AI</span>\n )}\n </Text>\n );\n }}\n onNodeClick={handleNodeClick}\n />\n </div>\n {footer && !isCollapsed && <div className=\"dishui-sidebar-ai-footer\">{footer}</div>}\n\n <style>{`\n .sidebar-container {\n --sidebar-level-muted: oklch(from color-mix(in oklab, var(--color-base-content) 76%, var(--color-base-200)) l 0 0);\n }\n /* LayoutSuite uses semantic surfaces even in colorful themes. Match its text luminance. */\n .dishui-layout-suite-sidebar > .sidebar-container {\n --sidebar-level-muted: oklch(from var(--dishui-text-tertiary) l 0 0);\n }\n .sidebar-rail { min-height: 0; height: 100%; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; padding: 6px; }\n .sidebar-rail-group { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 4px 2px; margin-bottom: 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 10px; }\n .sidebar-rail-link { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 36px; min-height: 36px; flex-shrink: 0; border-radius: 6px; color: var(--sidebar-level-muted); text-decoration: none; transition: background-color 150ms, color 150ms; }\n .sidebar-rail-link > span { display: flex; align-items: center; justify-content: center; }\n .sidebar-rail-link svg { width: 16px; height: 16px; }\n .dishui-sidebar-ai-avatar svg, .dishui-sidebar-ai-action svg { width: 18px; height: 18px; }\n .dishui-sidebar-rail-tooltip { position: fixed; z-index: 1000; padding: 6px 8px; border: 1px solid var(--dishui-border-hairline, var(--color-base-300)); border-radius: 6px; background: var(--color-base-100); color: var(--color-base-content); box-shadow: 0 2px 8px color-mix(in oklab, var(--color-base-content) 15%, transparent); font-size: 12px; line-height: 1.4; overflow-wrap: anywhere; max-height: calc(100vh - 16px); overflow-y: auto; pointer-events: none; }\n .sidebar-rail-link:hover { background: var(--color-base-300); }\n .sidebar-rail-link[aria-current=\"page\"] { color: var(--color-primary); background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-200)); box-shadow: inset 2px 0 var(--color-primary); }\n .sidebar-rail-link:focus-visible { outline: 2px solid var(--dishui-ring, var(--color-primary)); outline-offset: -2px; }\n @media (prefers-reduced-motion: reduce) { .sidebar-rail-link { transition: none; } }\n /* Sidebar Tree 自定义样式 */\n .sidebar-tree {\n background: transparent;\n border: none;\n padding: 0.5rem;\n }\n \n .sidebar-tree .tree-node-content {\n padding: 0.5rem 1rem;\n border-radius: var(--dishui-radius-sm);\n transition: background-color var(--dishui-duration-normal) var(--dishui-ease-out), color var(--dishui-duration-normal) var(--dishui-ease-out), transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n /* 活跃状态 - 为每个主题设置匹配的配色 */\n .sidebar-tree .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(1rem - 4px) !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateSidebarActiveStyles()}\n \n /* 悬停状态 */\n .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {\n background-color: var(--color-base-200);\n }\n \n /* 右侧展开按钮样式 */\n .sidebar-tree .tree-node-toggle-right {\n width: auto;\n height: auto;\n min-width: auto;\n min-height: auto;\n padding: 0.25rem;\n opacity: 0.6;\n transition: opacity var(--dishui-duration-normal) var(--dishui-ease-out), background-color var(--dishui-duration-normal) var(--dishui-ease-out);\n border-radius: var(--dishui-radius-xs);\n }\n \n .sidebar-tree .tree-node-toggle-right:hover {\n opacity: 1;\n background-color: var(--color-base-300);\n }\n \n /* 右侧按钮图标旋转 */\n .sidebar-tree .tree-node-toggle-right svg {\n width: 1rem;\n height: 1rem;\n transition: transform var(--dishui-duration-normal) var(--dishui-ease-out);\n }\n \n .sidebar-tree .tree-node-toggle-right.tree-node-toggle-expanded svg {\n transform: rotate(90deg);\n }\n \n /* 图标样式 */\n .sidebar-tree .tree-node-icon {\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: color 0.2s ease;\n }\n \n .sidebar-tree .tree-node-icon svg {\n width: 20px;\n height: 20px;\n }\n \n /* 子节点图标稍小 */\n .sidebar-tree .tree-node-children .tree-node-icon svg {\n width: 18px;\n height: 18px;\n opacity: 0.8;\n }\n \n /* Preserve the legacy all-level appearance only when typography is not configured. */\n .sidebar-tree:not(.sidebar-tree-level-text) .tree-node-label {\n font-size: 1rem;\n line-height: 1.4rem;\n font-weight: 500;\n }\n \n /* 连接线样式 - 强制显示!向右移动并加粗,增加整体左边距 */\n /* 使用双重选择器增加优先级,避免被其他 Tree 组件样式覆盖 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded,\n .sidebar-tree.sidebar-tree .tree-node-children.tree-node-children-expanded,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded,\n div.sidebar-tree .tree-node-children.tree-node-children-expanded {\n border-left: 3px solid rgba(128, 128, 128, 0.35) !important;\n margin-left: 24px !important;\n padding-left: 8px !important;\n box-sizing: border-box !important;\n }\n \n /* 隐藏 Tree 组件的圆点装饰 - 避免与 Sidebar 样式冲突 */\n .sidebar-tree.sidebar-tree .tree-show-line .tree-node-children-expanded::before,\n div.sidebar-tree .tree-show-line .tree-node-children-expanded::before {\n display: none !important;\n }\n \n /* 隐藏 Tree 组件的标题和操作按钮 */\n .sidebar-tree .tree-header,\n .sidebar-tree .tree-search,\n .sidebar-tree .tree-actions {\n display: none;\n }\n \n /* 移除内边距 */\n .sidebar-tree > div:first-child {\n padding: 0;\n }\n \n /* 子节点动画优化 - 减小间距 */\n .sidebar-tree .tree-node-children {\n margin-top: 0.125rem !important;\n }\n \n /* 一级菜单项间距 */\n .sidebar-tree > div > .tree-nodes > .tree-node {\n margin-bottom: 0.375rem;\n }\n \n /* 二级菜单项间距 */\n .sidebar-tree .tree-node-children > .tree-node {\n margin-bottom: 0.125rem;\n }\n `}</style>\n </div>\n );\n};\n\nexport default Sidebar; "],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type FlexAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch';
|
|
2
|
+
export type FlexJustify = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
|
|
3
|
+
export declare const FLEX_ALIGN_CLASS: Record<FlexAlign, string>;
|
|
4
|
+
export declare const FLEX_JUSTIFY_CLASS: Record<FlexJustify, string>;
|
|
5
|
+
export declare const flexGap: (value: number | string | undefined) => string | undefined;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/utils/flexLayout.ts
|
|
2
|
+
var e = {
|
|
3
|
+
start: "items-start",
|
|
4
|
+
center: "items-center",
|
|
5
|
+
end: "items-end",
|
|
6
|
+
baseline: "items-baseline",
|
|
7
|
+
stretch: "items-stretch"
|
|
8
|
+
}, t = {
|
|
9
|
+
start: "justify-start",
|
|
10
|
+
center: "justify-center",
|
|
11
|
+
end: "justify-end",
|
|
12
|
+
between: "justify-between",
|
|
13
|
+
around: "justify-around",
|
|
14
|
+
evenly: "justify-evenly"
|
|
15
|
+
}, n = (e) => typeof e == "number" ? `${e}px` : e;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { e as FLEX_ALIGN_CLASS, t as FLEX_JUSTIFY_CLASS, n as flexGap };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=flexLayout.js.map
|