dishui 0.0.72 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/components/Button/index.d.ts +4 -4
  2. package/dist/components/Button/index.js +18 -17
  3. package/dist/components/Button/index.js.map +1 -1
  4. package/dist/components/Card/Metric.d.ts +17 -0
  5. package/dist/components/Card/Metric2.js +50 -0
  6. package/dist/components/Card/Metric2.js.map +1 -0
  7. package/dist/components/Card/index.d.ts +3 -0
  8. package/dist/components/Card/index.js +118 -117
  9. package/dist/components/Card/index.js.map +1 -1
  10. package/dist/components/Group/index.d.ts +2 -0
  11. package/dist/components/GroupButton/index.d.ts +16 -0
  12. package/dist/components/GroupButton/index.js +41 -0
  13. package/dist/components/GroupButton/index.js.map +1 -0
  14. package/dist/components/GroupedTable/index.d.ts +38 -0
  15. package/dist/components/GroupedTable/index.js +92 -0
  16. package/dist/components/GroupedTable/index.js.map +1 -0
  17. package/dist/components/Layout/index.d.ts +4 -2
  18. package/dist/components/Layout/index.js +1 -1
  19. package/dist/components/Layout/index.js.map +1 -1
  20. package/dist/components/NavigationList/index.d.ts +17 -0
  21. package/dist/components/NavigationList/index.js +48 -0
  22. package/dist/components/NavigationList/index.js.map +1 -0
  23. package/dist/components/Section/index.d.ts +28 -0
  24. package/dist/components/Section/index.js +58 -0
  25. package/dist/components/Section/index.js.map +1 -0
  26. package/dist/components/Select/index.d.ts +2 -0
  27. package/dist/components/Select/index.js +83 -82
  28. package/dist/components/Select/index.js.map +1 -1
  29. package/dist/components/SidebarToggleButton/index.d.ts +16 -1
  30. package/dist/components/SidebarToggleButton/index.js +90 -30
  31. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  32. package/dist/components/Skeleton/index.d.ts +7 -0
  33. package/dist/components/Skeleton/index.js +21 -0
  34. package/dist/components/Skeleton/index.js.map +1 -0
  35. package/dist/components/Tree/Tree.js +5 -2
  36. package/dist/components/Tree/Tree.js.map +1 -1
  37. package/dist/components/pro/RichTextEditor/AIRewrite.js +114 -72
  38. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  39. package/dist/components/pro/RichTextEditor/BlockHandle.js +315 -196
  40. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  41. package/dist/components/pro/RichTextEditor/BubbleToolbar.d.ts +1 -1
  42. package/dist/components/pro/RichTextEditor/BubbleToolbar.js +156 -39
  43. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  44. package/dist/components/pro/RichTextEditor/CommentPanel.d.ts +2 -1
  45. package/dist/components/pro/RichTextEditor/CommentPanel.js +100 -81
  46. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  47. package/dist/components/pro/RichTextEditor/CommentPopover.d.ts +2 -1
  48. package/dist/components/pro/RichTextEditor/CommentPopover.js +92 -68
  49. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  50. package/dist/components/pro/RichTextEditor/RichTextEditor.js +24 -22
  51. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  52. package/dist/components/pro/RichTextEditor/SearchReplace.d.ts +7 -0
  53. package/dist/components/pro/RichTextEditor/SlashMenu.js +132 -73
  54. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  55. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -0
  56. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +9 -9
  57. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  58. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js +8 -13
  59. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  60. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js +22 -3
  61. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  62. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.d.ts +1 -1
  63. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +346 -313
  64. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  65. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js +120 -146
  66. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  67. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js +2 -2
  68. package/dist/components/pro/RichTextEditor/extensions/CommentMark.js.map +1 -1
  69. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js +178 -163
  70. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  71. package/dist/components/pro/RichTextEditor/extensions/FontSize.js +8 -5
  72. package/dist/components/pro/RichTextEditor/extensions/FontSize.js.map +1 -1
  73. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.d.ts +6 -0
  74. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js +85 -74
  75. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  76. package/dist/components/pro/RichTextEditor/searchUtils.d.ts +23 -0
  77. package/dist/contexts/AppContext.js +47 -45
  78. package/dist/contexts/AppContext.js.map +1 -1
  79. package/dist/dishui.css +1 -1
  80. package/dist/index-nostyled.d.ts +11 -1
  81. package/dist/index.d.ts +11 -1
  82. package/dist/index.js +119 -114
  83. package/dist/layouts/MainLayout.js +9 -10
  84. package/dist/layouts/MainLayout.js.map +1 -1
  85. package/dist/layouts/Sidebar.d.ts +9 -0
  86. package/dist/layouts/Sidebar.js +99 -80
  87. package/dist/layouts/Sidebar.js.map +1 -1
  88. package/dist/layouts/headbar/Headbar.d.ts +1 -1
  89. package/dist/layouts/headbar/Headbar.js +2 -2
  90. package/dist/layouts/headbar/Headbar.js.map +1 -1
  91. package/dist/lite.d.ts +19 -1
  92. package/dist/lite.js +17 -8
  93. package/dist/styles/themeStyles.js +6 -6
  94. package/dist/styles/themeStyles.js.map +1 -1
  95. package/dist/utils/i18n.d.ts +3 -0
  96. package/dist/utils/i18n.js +78 -0
  97. package/dist/utils/i18n.js.map +1 -1
  98. package/dist/utils/menu.js +23 -6
  99. package/dist/utils/menu.js.map +1 -1
  100. package/package.json +8 -2
@@ -1,31 +1,36 @@
1
1
  import { generateSidebarActiveStyles as e } from "../styles/themeStyles.js";
2
2
  import t from "../components/Tree/Tree.js";
3
3
  import { getMenuItems as n } from "../utils/menu.js";
4
- import { useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
5
- import { jsx as s, jsxs as c } from "react/jsx-runtime";
6
- import { useNavigate as l, useRouterState as u } from "@tanstack/react-router";
4
+ import { DesktopSidebarToggleButton as r } from "../components/SidebarToggleButton/index.js";
5
+ import { useEffect as i, useMemo as a, useRef as o, useState as s } from "react";
6
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
7
+ import { useNavigate as u, useRouterState as d } from "@tanstack/react-router";
7
8
  //#region src/layouts/Sidebar.tsx
8
- var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange: h, initialWidth: g = 280, collapsedWidth: _ = 64 }) => {
9
- let [v, y] = o([]), [b, x] = o(""), [S, C] = o(!1), [w, T] = o(g), E = a(null), D = a(null), O = a(null), k = u({ select: (e) => e.location }), A = l();
10
- r(() => {
11
- T(g);
12
- }, [g]), r(() => {
13
- y(p === void 0 ? m ? m(f) : n(f) : p);
9
+ var f = ({ isCollapsed: f, language: p, items: m, getMenuItems: h, onWidthChange: g, initialWidth: _ = 280, collapsedWidth: v = 64, onToggle: y, minWidth: b = 160, maxWidth: x = 400 }) => {
10
+ let [S, C] = s([]), [w, T] = s(""), [E, D] = s(!1), [O, k] = s(_), A = o(null), j = o(null), M = d({ select: (e) => e.location }), N = u();
11
+ i(() => {
12
+ k(_);
13
+ }, [_]);
14
+ let P = (e) => {
15
+ k(e), g?.(e);
16
+ };
17
+ i(() => {
18
+ C(m === void 0 ? h ? h(p) : n(p) : m);
14
19
  }, [
15
- f,
16
20
  p,
17
- m
18
- ]), r(() => {
19
- if (!b) return;
21
+ m,
22
+ h
23
+ ]), i(() => {
24
+ if (!w) return;
20
25
  let e = setTimeout(() => {
21
- D.current?.querySelector(".tree-node-content-active")?.scrollIntoView({
26
+ j.current?.querySelector(".tree-node-content-active")?.scrollIntoView({
22
27
  block: "nearest",
23
28
  behavior: "smooth"
24
29
  });
25
30
  }, 350);
26
31
  return () => clearTimeout(e);
27
- }, [b]), r(() => {
28
- let e = D.current;
32
+ }, [w]), i(() => {
33
+ let e = j.current;
29
34
  if (!e) return;
30
35
  let t = (t) => {
31
36
  if (e.scrollHeight <= e.clientHeight) return;
@@ -36,35 +41,35 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
36
41
  };
37
42
  return e.addEventListener("wheel", t, { passive: !1 }), () => e.removeEventListener("wheel", t);
38
43
  }, []);
39
- let j = (e, t = !0) => e.map((e) => ({
44
+ let F = (e, t = !0) => e.map((e) => ({
40
45
  id: e.id,
41
46
  label: e.label,
42
- icon: e.icon || (t ? void 0 : /* @__PURE__ */ s("svg", {
47
+ icon: e.icon || (t ? void 0 : /* @__PURE__ */ c("svg", {
43
48
  xmlns: "http://www.w3.org/2000/svg",
44
49
  className: "h-4 w-4",
45
50
  fill: "none",
46
51
  viewBox: "0 0 24 24",
47
52
  stroke: "currentColor",
48
- children: /* @__PURE__ */ s("path", {
53
+ children: /* @__PURE__ */ c("path", {
49
54
  strokeLinecap: "round",
50
55
  strokeLinejoin: "round",
51
56
  strokeWidth: "2",
52
57
  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"
53
58
  })
54
59
  })),
55
- children: e.children ? j(e.children, !1) : void 0,
60
+ children: e.children ? F(e.children, !1) : void 0,
56
61
  meta: { path: e.path }
57
- })), M = i(() => j(v, !0), [v]), N = i(() => {
58
- if (v.length === 0) return [];
62
+ })), I = a(() => F(S, !0), [S]), L = a(() => {
63
+ if (S.length === 0) return [];
59
64
  let e = (t) => {
60
65
  let n = [];
61
66
  for (let r of t) r.children?.length && (n.push(r.id), n = [...n, ...e(r.children)]);
62
67
  return n;
63
68
  };
64
- return e(v);
65
- }, [v]);
66
- return r(() => {
67
- let e = k.pathname, t = (n) => {
69
+ return e(S);
70
+ }, [S]);
71
+ return i(() => {
72
+ let e = M.pathname, t = (n) => {
68
73
  for (let r of n) {
69
74
  if (r.path === e) return r.id;
70
75
  if (r.children) {
@@ -73,74 +78,93 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
73
78
  }
74
79
  }
75
80
  return null;
76
- }, n = t(v);
77
- n && x(n);
78
- }, [v, k.pathname]), r(() => {
79
- let e = (e) => {
80
- C(!0), document.body.style.userSelect = "none", document.body.style.cursor = "ew-resize", e.preventDefault();
81
- }, t = () => {
82
- C(!1), document.body.style.userSelect = "", document.body.style.cursor = "";
83
- }, n = (e) => {
84
- if (S && E.current) {
85
- let t = e.clientX, n = Math.max(160, Math.min(t, 400));
86
- T(n), h && h(n);
81
+ }, n = t(S);
82
+ n && T(n);
83
+ }, [S, M.pathname]), i(() => {
84
+ let e = () => {
85
+ D(!1), document.body.style.userSelect = "", document.body.style.cursor = "";
86
+ }, t = (e) => {
87
+ if (E && A.current) {
88
+ let t = A.current.getBoundingClientRect().left, n = e.clientX - t, r = Math.max(160, Math.min(n, 400));
89
+ k(r), g && g(r);
87
90
  }
88
- }, r = O.current;
89
- return r && r.addEventListener("mousedown", e), document.addEventListener("mouseup", t), document.addEventListener("mousemove", n), () => {
90
- r && r.removeEventListener("mousedown", e), document.removeEventListener("mouseup", t), document.removeEventListener("mousemove", n);
91
+ };
92
+ return document.addEventListener("mouseup", e), document.addEventListener("mousemove", t), () => {
93
+ document.removeEventListener("mouseup", e), document.removeEventListener("mousemove", t);
91
94
  };
92
95
  }, [
93
- S,
94
- h,
95
- E
96
- ]), d ? /* @__PURE__ */ s("div", {
97
- className: "h-full bg-base-200 overflow-y-auto overflow-x-hidden shadow-lg transition-all duration-300 ease-in-out",
98
- style: { width: `${_}px` },
99
- children: /* @__PURE__ */ s("ul", {
100
- className: "flex flex-col p-2 gap-1",
101
- children: v.map((e) => /* @__PURE__ */ s("li", { children: e.path ? /* @__PURE__ */ s("button", {
102
- onClick: () => A({ to: e.path }),
96
+ E,
97
+ g,
98
+ A
99
+ ]), f ? /* @__PURE__ */ l("div", {
100
+ ref: A,
101
+ className: "blade-sidebar h-full bg-base-200 overflow-visible transition-all duration-200 ease-in-out relative",
102
+ style: { width: `${v}px` },
103
+ children: [y && /* @__PURE__ */ c(r, {
104
+ isCollapsed: f,
105
+ onToggle: y,
106
+ sidebarWidth: O,
107
+ collapsedWidth: v,
108
+ onWidthChange: g ? P : void 0,
109
+ minWidth: b,
110
+ maxWidth: x,
111
+ anchorRef: A
112
+ }), /* @__PURE__ */ c("ul", {
113
+ className: "flex flex-col p-2 gap-1 h-full overflow-y-auto overflow-x-hidden",
114
+ children: S.map((e) => /* @__PURE__ */ c("li", { children: e.path ? /* @__PURE__ */ c("button", {
115
+ onClick: () => N({ to: e.path }),
116
+ "aria-label": e.label,
103
117
  className: "flex justify-center items-center rounded-lg hover:bg-base-300 transition-colors w-full",
104
118
  style: {
105
119
  WebkitTapHighlightColor: "transparent",
106
- height: `${Math.min(_ - 16, 40)}px`,
107
- width: `${Math.min(_ - 16, 40)}px`,
120
+ height: `${Math.min(v - 16, 40)}px`,
121
+ width: `${Math.min(v - 16, 40)}px`,
108
122
  margin: "0 auto"
109
123
  },
110
- children: e.icon || /* @__PURE__ */ s("span", {
124
+ children: e.icon || /* @__PURE__ */ c("span", {
111
125
  className: "text-sm",
112
126
  children: e.label.charAt(0)
113
127
  })
114
- }) : /* @__PURE__ */ s("div", {
128
+ }) : /* @__PURE__ */ c("div", {
115
129
  className: "flex justify-center items-center",
116
130
  style: {
117
131
  WebkitTapHighlightColor: "transparent",
118
- height: `${Math.min(_ - 16, 40)}px`,
119
- width: `${Math.min(_ - 16, 40)}px`,
132
+ height: `${Math.min(v - 16, 40)}px`,
133
+ width: `${Math.min(v - 16, 40)}px`,
120
134
  margin: "0 auto"
121
135
  },
122
- children: e.icon || /* @__PURE__ */ s("span", {
136
+ children: e.icon || /* @__PURE__ */ c("span", {
123
137
  className: "text-sm",
124
138
  children: e.label.charAt(0)
125
139
  })
126
140
  }) }, e.id))
127
- })
128
- }) : /* @__PURE__ */ c("div", {
129
- ref: E,
130
- className: "h-full bg-base-200 overflow-hidden flex flex-col transition-all duration-300 ease-in-out relative",
141
+ })]
142
+ }) : /* @__PURE__ */ l("div", {
143
+ ref: A,
144
+ className: "blade-sidebar h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative",
131
145
  style: {
132
- width: `${w}px`,
146
+ width: `${O}px`,
133
147
  maxWidth: "400px",
134
148
  minWidth: "160px"
135
149
  },
136
150
  children: [
137
- /* @__PURE__ */ s("div", {
138
- ref: D,
151
+ y && /* @__PURE__ */ c(r, {
152
+ isCollapsed: f,
153
+ onToggle: y,
154
+ sidebarWidth: O,
155
+ collapsedWidth: v,
156
+ onWidthChange: g ? P : void 0,
157
+ minWidth: b,
158
+ maxWidth: x,
159
+ anchorRef: A
160
+ }),
161
+ /* @__PURE__ */ c("div", {
162
+ ref: j,
139
163
  className: "sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent",
140
- children: /* @__PURE__ */ s(t, {
141
- data: M,
142
- activeNodeId: b,
143
- defaultExpandedIds: N,
164
+ children: /* @__PURE__ */ c(t, {
165
+ data: I,
166
+ activeNodeId: w,
167
+ defaultExpandedIds: L,
144
168
  showSearch: !1,
145
169
  showExpandAll: !1,
146
170
  showIcon: !0,
@@ -152,7 +176,7 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
152
176
  className: "sidebar-tree",
153
177
  onNodeClick: (e) => {
154
178
  if (e.meta?.path) {
155
- x(e.id), A({ to: e.meta.path });
179
+ T(e.id), N({ to: e.meta.path });
156
180
  return;
157
181
  }
158
182
  if (e.children && e.children.length > 0) {
@@ -166,17 +190,12 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
166
190
  }
167
191
  return null;
168
192
  }, n = t(e.children);
169
- n ? (x(n.id), A({ to: n.meta.path })) : x(e.id);
170
- } else x(e.id);
193
+ n ? (T(n.id), N({ to: n.meta.path })) : T(e.id);
194
+ } else T(e.id);
171
195
  }
172
196
  })
173
197
  }),
174
- /* @__PURE__ */ s("div", {
175
- ref: O,
176
- className: "absolute top-0 right-0 w-2 h-full cursor-ew-resize hover:bg-primary hover:opacity-50 transition-all z-50",
177
- style: { right: "-1px" }
178
- }),
179
- /* @__PURE__ */ s("style", { children: `
198
+ /* @__PURE__ */ c("style", { children: `
180
199
  /* Sidebar Tree 自定义样式 */
181
200
  .sidebar-tree {
182
201
  background: transparent;
@@ -201,7 +220,7 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
201
220
 
202
221
  /* 悬停状态 */
203
222
  .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {
204
- background-color: oklch(var(--b2));
223
+ background-color: var(--color-base-200);
205
224
  }
206
225
 
207
226
  /* 右侧展开按钮样式 */
@@ -218,7 +237,7 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
218
237
 
219
238
  .sidebar-tree .tree-node-toggle-right:hover {
220
239
  opacity: 1;
221
- background-color: var(--fallback-b3, oklch(var(--b3) / 0.5));
240
+ background-color: var(--color-base-300);
222
241
  }
223
242
 
224
243
  /* 右侧按钮图标旋转 */
@@ -317,6 +336,6 @@ var d = ({ isCollapsed: d, language: f, items: p, getMenuItems: m, onWidthChange
317
336
  });
318
337
  };
319
338
  //#endregion
320
- export { d as default };
339
+ export { f as default };
321
340
 
322
341
  //# 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 { 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';\n\n// 组件属性\ntype SidebarProps = {\n isCollapsed: boolean;\n language: 'zh' | 'en';\n items?: MenuItem[];\n getMenuItems?: (language: 'zh' | 'en') => MenuItem[];\n onWidthChange?: (width: number) => void;\n initialWidth?: number;\n collapsedWidth?: number;\n};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n language,\n items: propItems,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [isDragging, setIsDragging] = useState(false);\n const [sidebarWidth, setSidebarWidth] = useState(initialWidth); // 使用传入的初始宽度\n const sidebarRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const resizeHandleRef = 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(initialWidth);\n }, [initialWidth]);\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('.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId]);\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 }, []);\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 if (nodeId) {\n setActiveNodeId(nodeId);\n }\n }, [items, routerState.pathname]);\n\n // 处理拖动调整宽度\n useEffect(() => {\n const handleMouseDown = (e: MouseEvent) => {\n setIsDragging(true);\n document.body.style.userSelect = 'none';\n document.body.style.cursor = 'ew-resize';\n e.preventDefault(); // 防止文本选择\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (isDragging && sidebarRef.current) {\n const newWidth = e.clientX;\n // 最小宽度160px,最大宽度400px\n const clampedWidth = Math.max(160, Math.min(newWidth, 400));\n setSidebarWidth(clampedWidth);\n if (onWidthChange) {\n onWidthChange(clampedWidth);\n }\n }\n };\n\n const resizeHandle = resizeHandleRef.current;\n if (resizeHandle) {\n resizeHandle.addEventListener('mousedown', handleMouseDown);\n }\n\n document.addEventListener('mouseup', handleMouseUp);\n document.addEventListener('mousemove', handleMouseMove);\n\n return () => {\n if (resizeHandle) {\n resizeHandle.removeEventListener('mousedown', handleMouseDown);\n }\n document.removeEventListener('mouseup', handleMouseUp);\n document.removeEventListener('mousemove', handleMouseMove);\n };\n }, [isDragging, onWidthChange, sidebarRef]);\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 if (isCollapsed) {\n return (\n <div\n className=\"h-full bg-base-200 overflow-y-auto overflow-x-hidden shadow-lg transition-all duration-300 ease-in-out\"\n style={{ width: `${collapsedWidth}px` }}\n >\n <ul className=\"flex flex-col p-2 gap-1\">\n {items.map(item => (\n <li key={item.id}>\n {item.path ? (\n <button\n onClick={() => navigate({ to: item.path! })}\n className=\"flex justify-center items-center rounded-lg hover:bg-base-300 transition-colors w-full\"\n style={{\n WebkitTapHighlightColor: 'transparent',\n height: `${Math.min(collapsedWidth - 16, 40)}px`,\n width: `${Math.min(collapsedWidth - 16, 40)}px`,\n margin: '0 auto'\n }}\n >\n {item.icon || <span className=\"text-sm\">{item.label.charAt(0)}</span>}\n </button>\n ) : (\n <div\n className=\"flex justify-center items-center\"\n style={{\n WebkitTapHighlightColor: 'transparent',\n height: `${Math.min(collapsedWidth - 16, 40)}px`,\n width: `${Math.min(collapsedWidth - 16, 40)}px`,\n margin: '0 auto'\n }}\n >\n {item.icon || <span className=\"text-sm\">{item.label.charAt(0)}</span>}\n </div>\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n }\n\n return (\n <div\n ref={sidebarRef}\n className=\"h-full bg-base-200 overflow-hidden flex flex-col transition-all duration-300 ease-in-out relative\"\n style={{ width: `${sidebarWidth}px`, maxWidth: '400px', minWidth: '160px' }}\n >\n <div ref={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\"\n onNodeClick={handleNodeClick}\n />\n </div>\n\n {/* 调整大小的手柄 */}\n <div\n ref={resizeHandleRef}\n className=\"absolute top-0 right-0 w-2 h-full cursor-ew-resize hover:bg-primary hover:opacity-50 transition-all z-50\"\n style={{ right: '-1px' }}\n ></div>\n\n <style>{`\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: 0.5rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\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: oklch(var(--b2));\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: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n border-radius: 0.25rem;\n }\n \n .sidebar-tree .tree-node-toggle-right:hover {\n opacity: 1;\n background-color: var(--fallback-b3, oklch(var(--b3) / 0.5));\n }\n \n /* 右侧按钮图标旋转 */\n .sidebar-tree .tree-node-toggle-right svg {\n width: 1rem;\n height: 1rem;\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\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 /* 标签样式 - 增大字体和行高 */\n .sidebar-tree .tree-node-label {\n font-size: 0.9375rem;\n line-height: 1.4rem;\n font-weight: 450;\n }\n \n /* 一级菜单标签更大 */\n .sidebar-tree > div > .tree-nodes > .tree-node .tree-node-label {\n font-size: 1rem;\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 { 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';\n\n// 组件属性\ntype SidebarProps = {\n isCollapsed: boolean;\n language: 'zh' | 'en';\n items?: MenuItem[];\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};\n\nconst Sidebar: React.FC<SidebarProps> = ({\n isCollapsed,\n language,\n items: propItems,\n getMenuItems,\n onWidthChange,\n initialWidth = 280,\n collapsedWidth = 64,\n onToggle,\n minWidth = 160,\n maxWidth = 400,\n}) => {\n const [items, setItems] = useState<MenuItem[]>([]);\n const [activeNodeId, setActiveNodeId] = useState<string | number>('');\n const [isDragging, setIsDragging] = useState(false);\n const [sidebarWidth, setSidebarWidth] = useState(initialWidth); // 使用传入的初始宽度\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(initialWidth);\n }, [initialWidth]);\n\n // 统一的宽度变更处理:同步内部状态并通知父组件。\n // pill 拖拽与外部同步都通过此入口,避免必须回传 initialWidth 才能生效。\n const handleInternalWidthChange = (width: number) => {\n setSidebarWidth(width);\n onWidthChange?.(width);\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('.tree-node-content-active')\n ?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }, 350);\n return () => clearTimeout(t);\n }, [activeNodeId]);\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 }, []);\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 if (nodeId) {\n setActiveNodeId(nodeId);\n }\n }, [items, routerState.pathname]);\n\n // 处理拖动调整宽度\n useEffect(() => {\n const handleMouseUp = () => {\n setIsDragging(false);\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n };\n\n const handleMouseMove = (e: MouseEvent) => {\n if (isDragging && sidebarRef.current) {\n // 宽度 = 指针位置 - 侧边栏左边缘(适配侧边栏内嵌于页面中的情况)。\n const sidebarLeft = sidebarRef.current.getBoundingClientRect().left;\n const newWidth = e.clientX - sidebarLeft;\n const clampedWidth = Math.max(160, Math.min(newWidth, 400));\n setSidebarWidth(clampedWidth);\n if (onWidthChange) {\n onWidthChange(clampedWidth);\n }\n }\n };\n\n document.addEventListener('mouseup', handleMouseUp);\n document.addEventListener('mousemove', handleMouseMove);\n\n return () => {\n document.removeEventListener('mouseup', handleMouseUp);\n document.removeEventListener('mousemove', handleMouseMove);\n };\n }, [isDragging, onWidthChange, sidebarRef]);\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 if (isCollapsed) {\n return (\n <div\n ref={sidebarRef}\n className=\"blade-sidebar h-full bg-base-200 overflow-visible transition-all duration-200 ease-in-out relative\"\n style={{ width: `${collapsedWidth}px` }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\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 <ul className=\"flex flex-col p-2 gap-1 h-full overflow-y-auto overflow-x-hidden\">\n {items.map(item => (\n <li key={item.id}>\n {item.path ? (\n <button\n onClick={() => navigate({ to: item.path! })}\n aria-label={item.label}\n className=\"flex justify-center items-center rounded-lg hover:bg-base-300 transition-colors w-full\"\n style={{\n WebkitTapHighlightColor: 'transparent',\n height: `${Math.min(collapsedWidth - 16, 40)}px`,\n width: `${Math.min(collapsedWidth - 16, 40)}px`,\n margin: '0 auto'\n }}\n >\n {item.icon || <span className=\"text-sm\">{item.label.charAt(0)}</span>}\n </button>\n ) : (\n <div\n className=\"flex justify-center items-center\"\n style={{\n WebkitTapHighlightColor: 'transparent',\n height: `${Math.min(collapsedWidth - 16, 40)}px`,\n width: `${Math.min(collapsedWidth - 16, 40)}px`,\n margin: '0 auto'\n }}\n >\n {item.icon || <span className=\"text-sm\">{item.label.charAt(0)}</span>}\n </div>\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n }\n\n return (\n <div\n ref={sidebarRef}\n className=\"blade-sidebar h-full bg-base-200 overflow-visible flex flex-col transition-colors duration-200 ease-in-out relative\"\n style={{ width: `${sidebarWidth}px`, maxWidth: '400px', minWidth: '160px' }}\n >\n {onToggle && (\n <DesktopSidebarToggleButton\n isCollapsed={isCollapsed}\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 <div ref={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\"\n onNodeClick={handleNodeClick}\n />\n </div>\n\n <style>{`\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: 0.5rem;\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\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: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n border-radius: 0.25rem;\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 0.3s cubic-bezier(0.4, 0, 0.2, 1);\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 /* 标签样式 - 增大字体和行高 */\n .sidebar-tree .tree-node-label {\n font-size: 0.9375rem;\n line-height: 1.4rem;\n font-weight: 450;\n }\n \n /* 一级菜单标签更大 */\n .sidebar-tree > div > .tree-nodes > .tree-node .tree-node-label {\n font-size: 1rem;\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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"}
@@ -6,7 +6,7 @@ export type HeadbarProps = {
6
6
  middle?: React.ReactNode;
7
7
  /** 右侧插槽内容 */
8
8
  right?: React.ReactNode;
9
- /** 高度(像素),默认 64 */
9
+ /** 高度(像素),默认 52 */
10
10
  height?: number;
11
11
  /** 自定义 className */
12
12
  className?: string;
@@ -1,8 +1,8 @@
1
1
  import "react";
2
2
  import { jsx as e, jsxs as t } from "react/jsx-runtime";
3
3
  //#region src/layouts/headbar/Headbar.tsx
4
- var n = ({ left: n, middle: r, right: i, height: a = 64, className: o }) => /* @__PURE__ */ t("div", {
5
- className: `navbar bg-base-100 shadow-md ${o || ""}`,
4
+ var n = ({ left: n, middle: r, right: i, height: a = 52, className: o }) => /* @__PURE__ */ t("div", {
5
+ className: `navbar bg-base-100 border-b border-base-300 ${o || ""}`,
6
6
  style: {
7
7
  height: `${a}px`,
8
8
  minHeight: `${a}px`,
@@ -1 +1 @@
1
- {"version":3,"file":"Headbar.js","names":[],"sources":["../../../src/layouts/headbar/Headbar.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarProps = {\n /** 左侧插槽内容 */\n left?: React.ReactNode;\n /** 中间插槽内容 */\n middle?: React.ReactNode;\n /** 右侧插槽内容 */\n right?: React.ReactNode;\n /** 高度(像素),默认 64 */\n height?: number;\n /** 自定义 className */\n className?: string;\n};\n\n/**\n * Headbar - 纯布局容器,提供 left / middle / right 三个插槽。\n * 不包含任何业务逻辑,所有内容通过 props 注入。\n */\nconst Headbar: React.FC<HeadbarProps> = ({\n left,\n middle,\n right,\n height = 64,\n className,\n}) => {\n return (\n <div\n className={`navbar bg-base-100 shadow-md ${className || ''}`}\n style={{\n height: `${height}px`,\n minHeight: `${height}px`,\n maxHeight: `${height}px`,\n }}\n >\n <div className=\"navbar-start\">{left}</div>\n <div className=\"navbar-center hidden lg:flex\">{middle}</div>\n <div className=\"navbar-end\">{right}</div>\n </div>\n );\n};\n\nexport default Headbar;\n"],"mappings":";;;AAmBA,IAAM,KAAmC,EACvC,SACA,WACA,UACA,YAAS,IACT,mBAGE,kBAAC,OAAD;CACE,WAAW,gCAAgC,KAAa;CACxD,OAAO;EACL,QAAQ,GAAG,EAAO;EAClB,WAAW,GAAG,EAAO;EACrB,WAAW,GAAG,EAAO;CACvB;CANF,UAAA;EAQE,kBAAC,OAAD;GAAK,WAAU;GAAgB,UAAA;EAAU,CAAA;EACzC,kBAAC,OAAD;GAAK,WAAU;GAAgC,UAAA;EAAY,CAAA;EAC3D,kBAAC,OAAD;GAAK,WAAU;GAAc,UAAA;EAAW,CAAA;CACrC"}
1
+ {"version":3,"file":"Headbar.js","names":[],"sources":["../../../src/layouts/headbar/Headbar.tsx"],"sourcesContent":["import React from 'react';\n\nexport type HeadbarProps = {\n /** 左侧插槽内容 */\n left?: React.ReactNode;\n /** 中间插槽内容 */\n middle?: React.ReactNode;\n /** 右侧插槽内容 */\n right?: React.ReactNode;\n /** 高度(像素),默认 52 */\n height?: number;\n /** 自定义 className */\n className?: string;\n};\n\n/**\n * Headbar - 纯布局容器,提供 left / middle / right 三个插槽。\n * 不包含任何业务逻辑,所有内容通过 props 注入。\n */\nconst Headbar: React.FC<HeadbarProps> = ({\n left,\n middle,\n right,\n height = 52,\n className,\n}) => {\n return (\n <div\n className={`navbar bg-base-100 border-b border-base-300 ${className || ''}`}\n style={{\n height: `${height}px`,\n minHeight: `${height}px`,\n maxHeight: `${height}px`,\n }}\n >\n <div className=\"navbar-start\">{left}</div>\n <div className=\"navbar-center hidden lg:flex\">{middle}</div>\n <div className=\"navbar-end\">{right}</div>\n </div>\n );\n};\n\nexport default Headbar;\n"],"mappings":";;;AAmBA,IAAM,KAAmC,EACvC,SACA,WACA,UACA,YAAS,IACT,mBAGE,kBAAC,OAAD;CACE,WAAW,+CAA+C,KAAa;CACvE,OAAO;EACL,QAAQ,GAAG,EAAO;EAClB,WAAW,GAAG,EAAO;EACrB,WAAW,GAAG,EAAO;CACvB;CANF,UAAA;EAQE,kBAAC,OAAD;GAAK,WAAU;GAAgB,UAAA;EAAU,CAAA;EACzC,kBAAC,OAAD;GAAK,WAAU;GAAgC,UAAA;EAAY,CAAA;EAC3D,kBAAC,OAAD;GAAK,WAAU;GAAc,UAAA;EAAW,CAAA;CACrC"}
package/dist/lite.d.ts CHANGED
@@ -5,7 +5,25 @@ export type { BadgeProps } from './components/Badge';
5
5
  export { default as Input } from './components/Input';
6
6
  export type { InputProps } from './components/Input';
7
7
  export { default as Card } from './components/Card';
8
- export type { CardProps } from './components/Card';
8
+ export type { CardProps, CardMetricProps, CardMetricItem } from './components/Card';
9
+ export { default as GroupButton } from './components/GroupButton';
10
+ export type { GroupButtonProps, GroupButtonOption } from './components/GroupButton';
11
+ export { default as GroupedTable } from './components/GroupedTable';
12
+ export type { GroupedTableProps, GroupedTableColumn, GroupedTableGroup } from './components/GroupedTable';
13
+ export { default as NavigationList } from './components/NavigationList';
14
+ export type { NavigationListProps, NavigationListItem } from './components/NavigationList';
15
+ export { Tree } from './components/Tree';
16
+ export type { TreeNode, TreeProps } from './components/Tree';
17
+ export { default as Skeleton } from './components/Skeleton';
18
+ export type { SkeletonProps } from './components/Skeleton';
19
+ export { default as Section } from './components/Section';
20
+ export type { SectionProps, SectionSlotProps } from './components/Section';
21
+ export { default as Text } from './components/Text';
22
+ export type { TextProps } from './components/Text';
23
+ export { default as Page } from './components/Page';
24
+ export type { PageProps, PageBodyProps, PageAsideProps, PageMainProps } from './components/Page';
25
+ export { default as EmptyState } from './components/EmptyState';
26
+ export type { EmptyStateProps } from './components/EmptyState';
9
27
  export { default as Layout, Container, Grid, GridItem, Flex, Group, Space } from './components/Layout';
10
28
  export type { LayoutCompound, LayoutContainerProps, LayoutGridProps, LayoutGridItemProps, LayoutFlexProps, LayoutGroupProps, LayoutSpaceProps, LayoutGap, LayoutMaxWidth, LayoutAlign, LayoutJustify, GridColumns, GridPlacement, } from './components/Layout';
11
29
  export { default as Label } from './components/Label';
package/dist/lite.js CHANGED
@@ -1,9 +1,18 @@
1
1
  import e from "./components/Button/index.js";
2
- import t from "./components/Badge/index.js";
3
- import n from "./components/Input/index.js";
4
- import r from "./components/Label/index.js";
5
- import i from "./components/Checkbox/index.js";
6
- import a from "./components/Select/index.js";
7
- import o from "./components/Card/index.js";
8
- import s, { Container as c, Flex as l, Grid as u, GridItem as d, Group as f, Space as p } from "./components/Layout/index.js";
9
- export { t as Badge, e as Button, o as Card, i as Checkbox, c as Container, l as Flex, u as Grid, d as GridItem, f as Group, n as Input, r as Label, s as Layout, a as Select, p as Space };
2
+ import t from "./components/GroupButton/index.js";
3
+ import n from "./components/Skeleton/index.js";
4
+ import r from "./components/GroupedTable/index.js";
5
+ import i from "./components/NavigationList/index.js";
6
+ import a from "./components/Section/index.js";
7
+ import o from "./components/Badge/index.js";
8
+ import s from "./components/Input/index.js";
9
+ import c from "./components/Label/index.js";
10
+ import l from "./components/Checkbox/index.js";
11
+ import u from "./components/Select/index.js";
12
+ import d from "./components/Card/index.js";
13
+ import f from "./components/Page/index.js";
14
+ import p from "./components/EmptyState/index.js";
15
+ import m, { Container as h, Flex as g, Grid as _, GridItem as v, Group as y, Space as b } from "./components/Layout/index.js";
16
+ import x from "./components/Text/index.js";
17
+ import S from "./components/Tree/Tree.js";
18
+ export { o as Badge, e as Button, d as Card, l as Checkbox, h as Container, p as EmptyState, g as Flex, _ as Grid, v as GridItem, y as Group, t as GroupButton, r as GroupedTable, s as Input, c as Label, m as Layout, i as NavigationList, f as Page, a as Section, u as Select, n as Skeleton, b as Space, x as Text, S as Tree };
@@ -1,14 +1,14 @@
1
1
  //#region src/styles/themeStyles.ts
2
2
  var e = {
3
3
  light: {
4
- backgroundColor: "rgba(23, 23, 23, 0.06)",
5
- borderColor: "rgb(23, 23, 23)",
6
- textColor: "rgb(23, 23, 23)"
4
+ backgroundColor: "var(--blade-accent)",
5
+ borderColor: "var(--blade-accent)",
6
+ textColor: "var(--blade-accent-fg)"
7
7
  },
8
8
  dark: {
9
- backgroundColor: "rgba(250, 250, 250, 0.12)",
10
- borderColor: "rgb(250, 250, 250)",
11
- textColor: "rgb(250, 250, 250)"
9
+ backgroundColor: "var(--blade-accent)",
10
+ borderColor: "var(--blade-accent)",
11
+ textColor: "var(--blade-accent-fg)"
12
12
  },
13
13
  cursor: {
14
14
  backgroundColor: "rgba(96, 165, 250, 0.16)",
@@ -1 +1 @@
1
- {"version":3,"file":"themeStyles.js","names":[],"sources":["../../src/styles/themeStyles.ts"],"sourcesContent":["// 共用主题样式配置\n// 用于 Tree 组件和 Sidebar 组件的活跃状态样式\n\nexport interface ThemeActiveStyle {\n backgroundColor: string;\n borderColor: string;\n textColor: string;\n}\n\n// 主题配色映射\nexport const themeActiveStyles: Record<string, ThemeActiveStyle> = {\n light: {\n backgroundColor: 'rgba(23, 23, 23, 0.06)',\n borderColor: 'rgb(23, 23, 23)',\n textColor: 'rgb(23, 23, 23)',\n },\n dark: {\n backgroundColor: 'rgba(250, 250, 250, 0.12)',\n borderColor: 'rgb(250, 250, 250)',\n textColor: 'rgb(250, 250, 250)',\n },\n cursor: {\n backgroundColor: 'rgba(96, 165, 250, 0.16)',\n borderColor: 'rgb(96, 165, 250)',\n textColor: 'rgb(147, 197, 253)',\n },\n retro: {\n backgroundColor: 'rgba(239, 68, 68, 0.15)',\n borderColor: 'rgb(239, 68, 68)',\n textColor: 'rgb(239, 68, 68)',\n },\n cyberpunk: {\n backgroundColor: 'rgba(255, 221, 0, 0.18)',\n borderColor: 'rgb(255, 221, 0)',\n textColor: 'rgb(255, 221, 0)',\n },\n matrix: {\n backgroundColor: 'rgba(0, 255, 65, 0.15)',\n borderColor: 'rgb(0, 255, 65)',\n textColor: 'rgb(0, 255, 65)',\n },\n oceanblue: {\n backgroundColor: 'rgba(6, 95, 212, 0.18)',\n borderColor: 'rgb(6, 95, 212)',\n textColor: 'rgb(6, 95, 212)',\n },\n eyecare: {\n backgroundColor: 'rgba(34, 139, 34, 0.18)',\n borderColor: 'rgb(34, 139, 34)',\n textColor: 'rgb(34, 139, 34)',\n },\n ghibli: {\n backgroundColor: 'rgba(249, 115, 22, 0.18)',\n borderColor: 'rgb(249, 115, 22)',\n textColor: 'rgb(249, 115, 22)',\n },\n pinkgirl: {\n backgroundColor: 'rgba(236, 72, 153, 0.15)',\n borderColor: 'rgb(236, 72, 153)',\n textColor: 'rgb(236, 72, 153)',\n },\n mintgirl: {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n borderColor: 'rgb(52, 211, 153)',\n textColor: 'rgb(52, 211, 153)',\n },\n\n wuxing: {\n backgroundColor: 'rgba(180, 120, 60, 0.15)',\n borderColor: 'rgb(180, 120, 60)',\n textColor: 'rgb(140, 90, 40)',\n },\n jukebox: {\n backgroundColor: 'rgba(147, 51, 234, 0.18)',\n borderColor: 'rgb(147, 51, 234)',\n textColor: 'rgb(167, 139, 250)',\n },\n};\n\n// 生成 Tree 组件的主题活跃状态 CSS\nexport const generateTreeActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n color: ${style.textColor} !important;\n }\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-icon,\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-label {\n color: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n// 生成 Sidebar 组件的主题活跃状态 CSS\nexport const generateSidebarActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n }\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-label,\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-icon svg {\n color: ${style.textColor} !important;\n stroke: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n"],"mappings":";AAUA,IAAa,IAAsD;CACjE,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,MAAM;EACJ,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CAEA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;AACF,GAGa,UACJ,OAAO,QAAQ,CAAiB,CAAC,CACrC,KAAK,CAAC,GAAO,OAAW;aAChB,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAM,MAAM,CAAC,EAAE;uBACrC,EAAM;8BACC,EAAM,gBAAgB;mCACjB,EAAM,YAAY;mBAClC,EAAM,UAAU;;uBAEZ,EAAM;uBACN,EAAM;mBACV,EAAM,UAAU;UACzB,CAAC,CACN,KAAK,IAAI,GAID,UACJ,OAAO,QAAQ,CAAiB,CAAC,CACrC,KAAK,CAAC,GAAO,OAAW;aAChB,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAM,MAAM,CAAC,EAAE;uBACrC,EAAM;8BACC,EAAM,gBAAgB;mCACjB,EAAM,YAAY;;uBAE9B,EAAM;uBACN,EAAM;mBACV,EAAM,UAAU;oBACf,EAAM,UAAU;UAC1B,CAAC,CACN,KAAK,IAAI"}
1
+ {"version":3,"file":"themeStyles.js","names":[],"sources":["../../src/styles/themeStyles.ts"],"sourcesContent":["// 共用主题样式配置\n// 用于 Tree 组件和 Sidebar 组件的活跃状态样式\n\nexport interface ThemeActiveStyle {\n backgroundColor: string;\n borderColor: string;\n textColor: string;\n}\n\n// 主题配色映射\nexport const themeActiveStyles: Record<string, ThemeActiveStyle> = {\n light: {\n backgroundColor: 'var(--blade-accent)',\n borderColor: 'var(--blade-accent)',\n textColor: 'var(--blade-accent-fg)',\n },\n dark: {\n backgroundColor: 'var(--blade-accent)',\n borderColor: 'var(--blade-accent)',\n textColor: 'var(--blade-accent-fg)',\n },\n cursor: {\n backgroundColor: 'rgba(96, 165, 250, 0.16)',\n borderColor: 'rgb(96, 165, 250)',\n textColor: 'rgb(147, 197, 253)',\n },\n retro: {\n backgroundColor: 'rgba(239, 68, 68, 0.15)',\n borderColor: 'rgb(239, 68, 68)',\n textColor: 'rgb(239, 68, 68)',\n },\n cyberpunk: {\n backgroundColor: 'rgba(255, 221, 0, 0.18)',\n borderColor: 'rgb(255, 221, 0)',\n textColor: 'rgb(255, 221, 0)',\n },\n matrix: {\n backgroundColor: 'rgba(0, 255, 65, 0.15)',\n borderColor: 'rgb(0, 255, 65)',\n textColor: 'rgb(0, 255, 65)',\n },\n oceanblue: {\n backgroundColor: 'rgba(6, 95, 212, 0.18)',\n borderColor: 'rgb(6, 95, 212)',\n textColor: 'rgb(6, 95, 212)',\n },\n eyecare: {\n backgroundColor: 'rgba(34, 139, 34, 0.18)',\n borderColor: 'rgb(34, 139, 34)',\n textColor: 'rgb(34, 139, 34)',\n },\n ghibli: {\n backgroundColor: 'rgba(249, 115, 22, 0.18)',\n borderColor: 'rgb(249, 115, 22)',\n textColor: 'rgb(249, 115, 22)',\n },\n pinkgirl: {\n backgroundColor: 'rgba(236, 72, 153, 0.15)',\n borderColor: 'rgb(236, 72, 153)',\n textColor: 'rgb(236, 72, 153)',\n },\n mintgirl: {\n backgroundColor: 'rgba(52, 211, 153, 0.15)',\n borderColor: 'rgb(52, 211, 153)',\n textColor: 'rgb(52, 211, 153)',\n },\n\n wuxing: {\n backgroundColor: 'rgba(180, 120, 60, 0.15)',\n borderColor: 'rgb(180, 120, 60)',\n textColor: 'rgb(140, 90, 40)',\n },\n jukebox: {\n backgroundColor: 'rgba(147, 51, 234, 0.18)',\n borderColor: 'rgb(147, 51, 234)',\n textColor: 'rgb(167, 139, 250)',\n },\n};\n\n// 生成 Tree 组件的主题活跃状态 CSS\nexport const generateTreeActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n color: ${style.textColor} !important;\n }\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-icon,\n [data-theme=\"${theme}\"] .tree-node-content-active .tree-node-label {\n color: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n// 生成 Sidebar 组件的主题活跃状态 CSS\nexport const generateSidebarActiveStyles = (): string => {\n return Object.entries(themeActiveStyles)\n .map(([theme, style]) => `\n /* ${theme.charAt(0).toUpperCase() + theme.slice(1)} 主题 */\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active {\n background-color: ${style.backgroundColor} !important;\n border-left: 4px solid ${style.borderColor} !important;\n }\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-label,\n [data-theme=\"${theme}\"] .sidebar-tree .tree-node-content-active .tree-node-icon svg {\n color: ${style.textColor} !important;\n stroke: ${style.textColor} !important;\n }`)\n .join('\\n');\n};\n\n"],"mappings":";AAUA,IAAa,IAAsD;CACjE,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,MAAM;EACJ,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,WAAW;EACT,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,UAAU;EACR,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CAEA,QAAQ;EACN,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;CACA,SAAS;EACP,iBAAiB;EACjB,aAAa;EACb,WAAW;CACb;AACF,GAGa,UACJ,OAAO,QAAQ,CAAiB,CAAC,CACrC,KAAK,CAAC,GAAO,OAAW;aAChB,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAM,MAAM,CAAC,EAAE;uBACrC,EAAM;8BACC,EAAM,gBAAgB;mCACjB,EAAM,YAAY;mBAClC,EAAM,UAAU;;uBAEZ,EAAM;uBACN,EAAM;mBACV,EAAM,UAAU;UACzB,CAAC,CACN,KAAK,IAAI,GAID,UACJ,OAAO,QAAQ,CAAiB,CAAC,CACrC,KAAK,CAAC,GAAO,OAAW;aAChB,EAAM,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,EAAM,MAAM,CAAC,EAAE;uBACrC,EAAM;8BACC,EAAM,gBAAgB;mCACjB,EAAM,YAAY;;uBAE9B,EAAM;uBACN,EAAM;mBACV,EAAM,UAAU;oBACf,EAAM,UAAU;UAC1B,CAAC,CACN,KAAK,IAAI"}
@@ -20,6 +20,9 @@ export type Translations = {
20
20
  children: Record<string, MenuItem>;
21
21
  };
22
22
  charts: MenuItem;
23
+ showcase: Omit<MenuItem, 'children'> & {
24
+ children: Record<string, MenuItem>;
25
+ };
23
26
  };
24
27
  };
25
28
  };