dishui 0.0.64 → 0.0.65

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 (177) hide show
  1. package/dist/components/Badge/index.js +12 -9
  2. package/dist/components/Badge/index.js.map +1 -1
  3. package/dist/components/Button/index.js +43 -40
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/Card/index.d.ts +11 -0
  6. package/dist/components/Card/index.js +62 -37
  7. package/dist/components/Card/index.js.map +1 -1
  8. package/dist/components/Chart/Chart.js.map +1 -1
  9. package/dist/components/Checkbox/index.js +32 -30
  10. package/dist/components/Checkbox/index.js.map +1 -1
  11. package/dist/components/Demo/index.js.map +1 -1
  12. package/dist/components/EmptyState/index.d.ts +4 -1
  13. package/dist/components/EmptyState/index.js +3 -3
  14. package/dist/components/EmptyState/index.js.map +1 -1
  15. package/dist/components/FileUploader/DropZone.js.map +1 -1
  16. package/dist/components/FileUploader/FileItem.js.map +1 -1
  17. package/dist/components/FileUploader/FileUploader.js.map +1 -1
  18. package/dist/components/FileUploader/UploadQueue.js.map +1 -1
  19. package/dist/components/Input/index.js +30 -30
  20. package/dist/components/Input/index.js.map +1 -1
  21. package/dist/components/Label/index.js +41 -40
  22. package/dist/components/Label/index.js.map +1 -1
  23. package/dist/components/List/index.js +47 -32
  24. package/dist/components/List/index.js.map +1 -1
  25. package/dist/components/Markdown/Markdown.js +61 -57
  26. package/dist/components/Markdown/Markdown.js.map +1 -1
  27. package/dist/components/Markdown/markdownComponents.js +49 -49
  28. package/dist/components/Markdown/markdownComponents.js.map +1 -1
  29. package/dist/components/Modal/index.d.ts +7 -3
  30. package/dist/components/Modal/index.js +77 -65
  31. package/dist/components/Modal/index.js.map +1 -1
  32. package/dist/components/Page/index.d.ts +58 -0
  33. package/dist/components/Page/index.js +74 -0
  34. package/dist/components/Page/index.js.map +1 -0
  35. package/dist/components/PageHeader/index.js.map +1 -1
  36. package/dist/components/Select/index.js +0 -3
  37. package/dist/components/Select/index.js.map +1 -1
  38. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  39. package/dist/components/StatCard/index.d.ts +3 -1
  40. package/dist/components/StatCard/index.js +39 -11
  41. package/dist/components/StatCard/index.js.map +1 -1
  42. package/dist/components/Table/index.js +103 -85
  43. package/dist/components/Table/index.js.map +1 -1
  44. package/dist/components/Tabs/index.d.ts +19 -5
  45. package/dist/components/Tabs/index.js +32 -13
  46. package/dist/components/Tabs/index.js.map +1 -1
  47. package/dist/components/Tree/Tree.js.map +1 -1
  48. package/dist/components/pro/ArticleContextMenu/index.js.map +1 -1
  49. package/dist/components/pro/ArticleControl/ArticleControl2.js.map +1 -1
  50. package/dist/components/pro/CodeEditor/editors/CodeEditor.js +141 -134
  51. package/dist/components/pro/CodeEditor/editors/CodeEditor.js.map +1 -1
  52. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js +81 -78
  53. package/dist/components/pro/CodeEditor/editors/MarkdownEditor.js.map +1 -1
  54. package/dist/components/pro/CodeEditor/panels/FootnotePanel.js.map +1 -1
  55. package/dist/components/pro/CodeEditor/panels/HistoryPanel.js.map +1 -1
  56. package/dist/components/pro/CodeEditor/panels/OutlinePanel.js.map +1 -1
  57. package/dist/components/pro/CodeEditor/panels/TableOfContentsPanel.js.map +1 -1
  58. package/dist/components/pro/CodeEditor/panels/VariablePanel.js.map +1 -1
  59. package/dist/components/pro/CodeEditor/themes.js +59 -59
  60. package/dist/components/pro/CodeEditor/themes.js.map +1 -1
  61. package/dist/components/pro/DataTable/DataTable.js +49 -48
  62. package/dist/components/pro/DataTable/DataTable.js.map +1 -1
  63. package/dist/components/pro/DataTable/Filters.js +42 -42
  64. package/dist/components/pro/DataTable/Filters.js.map +1 -1
  65. package/dist/components/pro/DataTable/PivotPanel.js.map +1 -1
  66. package/dist/components/pro/DataTable/PivotView.js +35 -32
  67. package/dist/components/pro/DataTable/PivotView.js.map +1 -1
  68. package/dist/components/pro/DataTable/components/BulkActions.js.map +1 -1
  69. package/dist/components/pro/DataTable/components/ColumnSelector.js.map +1 -1
  70. package/dist/components/pro/DataTable/components/FilterBar.js.map +1 -1
  71. package/dist/components/pro/DataTable/components/TableBody.js.map +1 -1
  72. package/dist/components/pro/DataTable/components/TableHeader.js.map +1 -1
  73. package/dist/components/pro/DataTable/components/TablePagination.js.map +1 -1
  74. package/dist/components/pro/DataTable/components/TableToolbar.js.map +1 -1
  75. package/dist/components/pro/DataTable/pivotExtension.js.map +1 -1
  76. package/dist/components/pro/DataTable/rowDetailExtension.js.map +1 -1
  77. package/dist/components/pro/DataTable/tanstack-table.js +37 -37
  78. package/dist/components/pro/DataTable/tanstack-table.js.map +1 -1
  79. package/dist/components/pro/FileExplorer/Breadcrumb.js +53 -53
  80. package/dist/components/pro/FileExplorer/Breadcrumb.js.map +1 -1
  81. package/dist/components/pro/FileExplorer/CreateDialog.js.map +1 -1
  82. package/dist/components/pro/FileExplorer/FileExplorer.js.map +1 -1
  83. package/dist/components/pro/FileExplorer/FileIcon.js +22 -22
  84. package/dist/components/pro/FileExplorer/FileIcon.js.map +1 -1
  85. package/dist/components/pro/FileExplorer/GridView.js.map +1 -1
  86. package/dist/components/pro/FileExplorer/ListView.js.map +1 -1
  87. package/dist/components/pro/FileExplorer/Toolbar.js.map +1 -1
  88. package/dist/components/pro/Flow/Flow.js +496 -494
  89. package/dist/components/pro/Flow/Flow.js.map +1 -1
  90. package/dist/components/pro/Flow/FlowCanvas.js +916 -917
  91. package/dist/components/pro/Flow/FlowCanvas.js.map +1 -1
  92. package/dist/components/pro/Flow/context/FlowUIContext.js.map +1 -1
  93. package/dist/components/pro/Flow/edges/EdgeRenderer.js +59 -59
  94. package/dist/components/pro/Flow/edges/EdgeRenderer.js.map +1 -1
  95. package/dist/components/pro/Flow/hooks/useClipboard.js.map +1 -1
  96. package/dist/components/pro/Flow/hooks/useDeleteSelection.js.map +1 -1
  97. package/dist/components/pro/Flow/hooks/useEdgeMutations.js.map +1 -1
  98. package/dist/components/pro/Flow/hooks/useLayoutActions.js +9 -11
  99. package/dist/components/pro/Flow/hooks/useLayoutActions.js.map +1 -1
  100. package/dist/components/pro/Flow/hooks/useLineMutations.js.map +1 -1
  101. package/dist/components/pro/Flow/hooks/useMindMap.js.map +1 -1
  102. package/dist/components/pro/Flow/hooks/useNodeMutations.js.map +1 -1
  103. package/dist/components/pro/Flow/lines/FreehandTool.js +9 -9
  104. package/dist/components/pro/Flow/lines/FreehandTool.js.map +1 -1
  105. package/dist/components/pro/Flow/lines/LineRenderer.js +5 -5
  106. package/dist/components/pro/Flow/lines/LineRenderer.js.map +1 -1
  107. package/dist/components/pro/Flow/nodes/DataNodeView.js +113 -93
  108. package/dist/components/pro/Flow/nodes/DataNodeView.js.map +1 -1
  109. package/dist/components/pro/Flow/nodes/MediaContent.js.map +1 -1
  110. package/dist/components/pro/Flow/nodes/MediaOverlay.js.map +1 -1
  111. package/dist/components/pro/Flow/nodes/Model3DView.js +1 -1
  112. package/dist/components/pro/Flow/nodes/Model3DView.js.map +1 -1
  113. package/dist/components/pro/Flow/nodes/NodeRenderer.js +118 -118
  114. package/dist/components/pro/Flow/nodes/NodeRenderer.js.map +1 -1
  115. package/dist/components/pro/Flow/nodes/dataUtils.js.map +1 -1
  116. package/dist/components/pro/Flow/nodes/shapes.js +1 -3
  117. package/dist/components/pro/Flow/nodes/shapes.js.map +1 -1
  118. package/dist/components/pro/Flow/panels/AIPanel.js.map +1 -1
  119. package/dist/components/pro/Flow/panels/Breadcrumb.js.map +1 -1
  120. package/dist/components/pro/Flow/panels/ContextMenu.js.map +1 -1
  121. package/dist/components/pro/Flow/panels/DataInspectorSection.js.map +1 -1
  122. package/dist/components/pro/Flow/panels/ExpandableTextarea.js.map +1 -1
  123. package/dist/components/pro/Flow/panels/FlowPanelGroup.js.map +1 -1
  124. package/dist/components/pro/Flow/panels/FlowToolbar.js +97 -97
  125. package/dist/components/pro/Flow/panels/FlowToolbar.js.map +1 -1
  126. package/dist/components/pro/Flow/panels/InspectorPanel.js +57 -57
  127. package/dist/components/pro/Flow/panels/InspectorPanel.js.map +1 -1
  128. package/dist/components/pro/Flow/panels/OutlinePanel.js +26 -22
  129. package/dist/components/pro/Flow/panels/OutlinePanel.js.map +1 -1
  130. package/dist/components/pro/Flow/panels/PresentationMode.js +18 -16
  131. package/dist/components/pro/Flow/panels/PresentationMode.js.map +1 -1
  132. package/dist/components/pro/Flow/panels/ProjectTitle.js.map +1 -1
  133. package/dist/components/pro/Flow/panels/ShapePalette.js +109 -104
  134. package/dist/components/pro/Flow/panels/ShapePalette.js.map +1 -1
  135. package/dist/components/pro/Flow/panels/toolbarIcons.js.map +1 -1
  136. package/dist/components/pro/RichTextEditor/AIRewrite.js.map +1 -1
  137. package/dist/components/pro/RichTextEditor/BlockHandle.js.map +1 -1
  138. package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
  139. package/dist/components/pro/RichTextEditor/CommentDialog.js.map +1 -1
  140. package/dist/components/pro/RichTextEditor/CommentPanel.js.map +1 -1
  141. package/dist/components/pro/RichTextEditor/CommentPopover.js.map +1 -1
  142. package/dist/components/pro/RichTextEditor/ContextMenu.js.map +1 -1
  143. package/dist/components/pro/RichTextEditor/RichTextEditor.js.map +1 -1
  144. package/dist/components/pro/RichTextEditor/SlashMenu.js.map +1 -1
  145. package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
  146. package/dist/components/pro/RichTextEditor/Toolbar/FloatingDialogMenu.js.map +1 -1
  147. package/dist/components/pro/RichTextEditor/Toolbar/MarkdownTemplates.js.map +1 -1
  148. package/dist/components/pro/RichTextEditor/Toolbar/SelectDropdown.js.map +1 -1
  149. package/dist/components/pro/RichTextEditor/Toolbar/TableOpsMenu.js.map +1 -1
  150. package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
  151. package/dist/components/pro/RichTextEditor/extensions/CodeBlockView.js.map +1 -1
  152. package/dist/components/pro/RichTextEditor/extensions/FloatingDialog.js.map +1 -1
  153. package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
  154. package/dist/contexts/AppContext.js.map +1 -1
  155. package/dist/dishui.css +1 -1
  156. package/dist/hooks/useTableColumns.js +7 -8
  157. package/dist/hooks/useTableColumns.js.map +1 -1
  158. package/dist/index.d.ts +2 -0
  159. package/dist/index.js +227 -221
  160. package/dist/layouts/MainLayout.js +22 -22
  161. package/dist/layouts/MainLayout.js.map +1 -1
  162. package/dist/layouts/Navbar.js.map +1 -1
  163. package/dist/layouts/Sidebar.js +94 -73
  164. package/dist/layouts/Sidebar.js.map +1 -1
  165. package/dist/layouts/headbar/Headbar.js.map +1 -1
  166. package/dist/layouts/headbar/HeadbarLangSwitcher.js.map +1 -1
  167. package/dist/layouts/headbar/HeadbarSearch.js.map +1 -1
  168. package/dist/layouts/headbar/HeadbarThemeSwitcher.js +11 -11
  169. package/dist/layouts/headbar/HeadbarThemeSwitcher.js.map +1 -1
  170. package/dist/layouts/headbar/HeadbarTitle.js.map +1 -1
  171. package/dist/utils/i18n.js +10 -10
  172. package/dist/utils/i18n.js.map +1 -1
  173. package/dist/utils/menu.js.map +1 -1
  174. package/dist/utils/routerBuilder.js +17 -15
  175. package/dist/utils/routerBuilder.js.map +1 -1
  176. package/dist/utils/themes.js.map +1 -1
  177. package/package.json +7 -7
@@ -1,25 +1,25 @@
1
- import S from "./Sidebar.js";
2
- import v from "./headbar/Headbar.js";
3
- import { SidebarToggleButtons as y } from "../components/SidebarToggleButton/index.js";
4
- import { useAppContext as N } from "../contexts/AppContext.js";
5
- import R, { useRef as j, useState as r } from "react";
1
+ import v from "./Sidebar.js";
2
+ import y from "./headbar/Headbar.js";
3
+ import { SidebarToggleButtons as N } from "../components/SidebarToggleButton/index.js";
4
+ import { useAppContext as R } from "../contexts/AppContext.js";
5
+ import j, { useRef as w, useState as r } from "react";
6
6
  import { jsx as e, jsxs as n } from "react/jsx-runtime";
7
- import { Outlet as w } from "@tanstack/react-router";
8
- var q = ({ children: m, headbarLeft: i, headbarMiddle: f, headbarRight: c }) => {
9
- const [s, h] = r(!1), { title: I, language: p, theme: u, menuItems: g, getMenuItems: b, themes: M, sidebarWidth: t, sidebarCollapsedWidth: l } = N(), [o, a] = r(t || 280), x = j(null);
10
- R.useEffect(() => {
7
+ import { Outlet as I } from "@tanstack/react-router";
8
+ var z = ({ children: m, headbarLeft: i, headbarMiddle: f, headbarRight: c }) => {
9
+ const [s, h] = r(!1), { title: M, language: p, theme: u, menuItems: g, getMenuItems: b, themes: T, sidebarWidth: t, sidebarCollapsedWidth: o } = R(), [l, a] = r(t || 280), x = w(null);
10
+ j.useEffect(() => {
11
11
  t && a(t);
12
12
  }, [t]);
13
13
  const d = () => {
14
14
  h(!s);
15
- }, W = (C) => {
16
- a(C);
17
- };
15
+ }, W = (S) => {
16
+ a(S);
17
+ }, C = typeof i == "function" ? i(d) : i;
18
18
  return /* @__PURE__ */ n("div", {
19
19
  className: "min-h-screen flex flex-col bg-base-100",
20
20
  "data-theme": u,
21
- children: [/* @__PURE__ */ e(v, {
22
- left: typeof i == "function" ? i(d) : i,
21
+ children: [/* @__PURE__ */ e(y, {
22
+ left: C,
23
23
  middle: f,
24
24
  right: c
25
25
  }), /* @__PURE__ */ n("div", {
@@ -28,32 +28,32 @@ var q = ({ children: m, headbarLeft: i, headbarMiddle: f, headbarRight: c }) =>
28
28
  /* @__PURE__ */ e("div", {
29
29
  className: "flex-shrink-0",
30
30
  ref: x,
31
- children: /* @__PURE__ */ e(S, {
31
+ children: /* @__PURE__ */ e(v, {
32
32
  isCollapsed: s,
33
33
  language: p,
34
34
  items: g,
35
35
  getMenuItems: b,
36
36
  onWidthChange: W,
37
- initialWidth: t || o,
38
- collapsedWidth: l || 64
37
+ initialWidth: t || l,
38
+ collapsedWidth: o || 64
39
39
  })
40
40
  }),
41
41
  /* @__PURE__ */ e("main", {
42
42
  className: "flex-1 overflow-y-auto px-6 py-4",
43
- children: m || /* @__PURE__ */ e(w, {})
43
+ children: m || /* @__PURE__ */ e(I, {})
44
44
  }),
45
- /* @__PURE__ */ e(y, {
45
+ /* @__PURE__ */ e(N, {
46
46
  isCollapsed: s,
47
47
  onToggle: d,
48
- sidebarWidth: o,
49
- collapsedWidth: l || 64
48
+ sidebarWidth: l,
49
+ collapsedWidth: o || 64
50
50
  })
51
51
  ]
52
52
  })]
53
53
  });
54
54
  };
55
55
  export {
56
- q as default
56
+ z as default
57
57
  };
58
58
 
59
59
  //# sourceMappingURL=MainLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MainLayout.js","names":[],"sources":["../../src/layouts/MainLayout.tsx"],"sourcesContent":["import React, { useState, useRef } from 'react';\nimport { Headbar, HeadbarTitle, HeadbarLangSwitcher, HeadbarThemeSwitcher } from './headbar';\nimport Sidebar from './Sidebar';\nimport { useAppContext } from '../contexts/AppContext';\nimport { Outlet } from '@tanstack/react-router';\nimport { SidebarToggleButtons } from '../components/SidebarToggleButton';\n\ninterface MainLayoutProps {\n children?: React.ReactNode;\n /** Headbar 左侧插槽 */\n headbarLeft?: React.ReactNode | ((toggleSidebar: () => void) => React.ReactNode);\n /** Headbar 中间插槽 */\n headbarMiddle?: React.ReactNode;\n /** Headbar 右侧插槽 */\n headbarRight?: React.ReactNode;\n}\n\nconst MainLayout: React.FC<MainLayoutProps> = ({ children, headbarLeft, headbarMiddle, headbarRight }) => {\n const [sidebarCollapsed, setSidebarCollapsed] = useState(false);\n const { title, language, theme, menuItems, getMenuItems, themes, sidebarWidth: configSidebarWidth, sidebarCollapsedWidth } = useAppContext();\n const [sidebarWidth, setSidebarWidth] = useState(configSidebarWidth || 280); // 默认侧边栏宽度\n const sidebarRef = useRef<HTMLDivElement>(null);\n\n // 当配置的 sidebarWidth 改变时,更新本地 state\n React.useEffect(() => {\n if (configSidebarWidth) {\n setSidebarWidth(configSidebarWidth);\n }\n }, [configSidebarWidth]);\n\n const toggleSidebar = () => {\n setSidebarCollapsed(!sidebarCollapsed);\n };\n\n // 当侧边栏宽度变化时更新状态\n const handleSidebarWidthChange = (width: number) => {\n setSidebarWidth(width);\n };\n\n const resolvedLeft = typeof headbarLeft === 'function'\n ? headbarLeft(toggleSidebar)\n : headbarLeft;\n\n return (\n <div className=\"min-h-screen flex flex-col bg-base-100\" data-theme={theme}>\n <Headbar\n left={resolvedLeft}\n middle={headbarMiddle}\n right={headbarRight}\n />\n\n <div className=\"flex flex-1 overflow-hidden\">\n <div className=\"flex-shrink-0\" ref={sidebarRef}>\n <Sidebar\n isCollapsed={sidebarCollapsed}\n language={language}\n items={menuItems}\n getMenuItems={getMenuItems}\n onWidthChange={handleSidebarWidthChange}\n initialWidth={configSidebarWidth || sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n\n <main className=\"flex-1 overflow-y-auto px-6 py-4\">\n {children || <Outlet />}\n </main>\n\n {/* 悬浮侧边栏切换按钮 */}\n <SidebarToggleButtons\n isCollapsed={sidebarCollapsed}\n onToggle={toggleSidebar}\n sidebarWidth={sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n </div>\n );\n};\n\nexport default MainLayout; "],"mappings":";;;;;;;AAiBA,IAAM,IAAA,CAAyC,EAAE,UAAA,GAAU,aAAA,GAAa,eAAA,GAAe,cAAA,EAAA,MAAmB;AACxG,QAAM,CAAC,GAAkB,CAAA,IAAuB,EAAS,EAAK,GACxD,EAAE,OAAA,GAAO,UAAA,GAAU,OAAA,GAAO,WAAA,GAAW,cAAA,GAAc,QAAA,GAAQ,cAAc,GAAoB,uBAAA,EAAA,IAA0B,EAAc,GACrI,CAAC,GAAc,CAAA,IAAmB,EAAS,KAAsB,GAAG,GACpE,IAAa,EAAuB,IAAI;AAG9C,EAAA,EAAM,UAAA,MAAgB;AACpB,IAAI,KACF,EAAgB,CAAkB;AAAA,EAEtC,GAAG,CAAC,CAAkB,CAAC;AAEvB,QAAM,IAAA,MAAsB;AAC1B,IAAA,EAAoB,CAAC,CAAgB;AAAA,EACvC,GAGM,IAAA,CAA4B,MAAkB;AAClD,IAAA,EAAgB,CAAK;AAAA,EACvB;AAMA,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IAAyC,cAAY;AAAA,cAApE,CACE,gBAAA,EAAC,GAAD;AAAA,MACE,MAPe,OAAO,KAAgB,aACxC,EAAY,CAAa,IACzB;AAAA,MAME,QAAQ;AAAA,MACR,OAAO;AAAA,IACR,CAAA,GAED,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAf;AAAA,QACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAgB,KAAK;AAAA,oBAClC,gBAAA,EAAC,GAAD;AAAA,YACE,aAAa;AAAA,YACH,UAAA;AAAA,YACV,OAAO;AAAA,YACO,cAAA;AAAA,YACd,eAAe;AAAA,YACf,cAAc,KAAsB;AAAA,YACpC,gBAAgB,KAAyB;AAAA,UAC1C,CAAA;AAAA,QACE,CAAA;AAAA,QAEL,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,oBACb,KAAY,gBAAA,EAAC,GAAD,CAAS,CAAA;AAAA,QAClB,CAAA;AAAA,QAGN,gBAAA,EAAC,GAAD;AAAA,UACE,aAAa;AAAA,UACb,UAAU;AAAA,UACI,cAAA;AAAA,UACd,gBAAgB,KAAyB;AAAA,QAC1C,CAAA;AAAA,MACE;AAAA,MACF;AAAA;AAET"}
1
+ {"version":3,"file":"MainLayout.js","names":[],"sources":["../../src/layouts/MainLayout.tsx"],"sourcesContent":["import React, { useState, useRef } from 'react';\nimport { Headbar, HeadbarTitle, HeadbarLangSwitcher, HeadbarThemeSwitcher } from './headbar';\nimport Sidebar from './Sidebar';\nimport { useAppContext } from '../contexts/AppContext';\nimport { Outlet } from '@tanstack/react-router';\nimport { SidebarToggleButtons } from '../components/SidebarToggleButton';\n\ninterface MainLayoutProps {\n children?: React.ReactNode;\n /** Headbar 左侧插槽 */\n headbarLeft?: React.ReactNode | ((toggleSidebar: () => void) => React.ReactNode);\n /** Headbar 中间插槽 */\n headbarMiddle?: React.ReactNode;\n /** Headbar 右侧插槽 */\n headbarRight?: React.ReactNode;\n}\n\nconst MainLayout: React.FC<MainLayoutProps> = ({ children, headbarLeft, headbarMiddle, headbarRight }) => {\n const [sidebarCollapsed, setSidebarCollapsed] = useState(false);\n const { title, language, theme, menuItems, getMenuItems, themes, sidebarWidth: configSidebarWidth, sidebarCollapsedWidth } = useAppContext();\n const [sidebarWidth, setSidebarWidth] = useState(configSidebarWidth || 280); // 默认侧边栏宽度\n const sidebarRef = useRef<HTMLDivElement>(null);\n\n // 当配置的 sidebarWidth 改变时,更新本地 state\n React.useEffect(() => {\n if (configSidebarWidth) {\n setSidebarWidth(configSidebarWidth);\n }\n }, [configSidebarWidth]);\n\n const toggleSidebar = () => {\n setSidebarCollapsed(!sidebarCollapsed);\n };\n\n // 当侧边栏宽度变化时更新状态\n const handleSidebarWidthChange = (width: number) => {\n setSidebarWidth(width);\n };\n\n const resolvedLeft = typeof headbarLeft === 'function'\n ? headbarLeft(toggleSidebar)\n : headbarLeft;\n\n return (\n <div className=\"min-h-screen flex flex-col bg-base-100\" data-theme={theme}>\n <Headbar\n left={resolvedLeft}\n middle={headbarMiddle}\n right={headbarRight}\n />\n\n <div className=\"flex flex-1 overflow-hidden\">\n <div className=\"flex-shrink-0\" ref={sidebarRef}>\n <Sidebar\n isCollapsed={sidebarCollapsed}\n language={language}\n items={menuItems}\n getMenuItems={getMenuItems}\n onWidthChange={handleSidebarWidthChange}\n initialWidth={configSidebarWidth || sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n\n <main className=\"flex-1 overflow-y-auto px-6 py-4\">\n {children || <Outlet />}\n </main>\n\n {/* 悬浮侧边栏切换按钮 */}\n <SidebarToggleButtons\n isCollapsed={sidebarCollapsed}\n onToggle={toggleSidebar}\n sidebarWidth={sidebarWidth}\n collapsedWidth={sidebarCollapsedWidth || 64}\n />\n </div>\n </div>\n );\n};\n\nexport default MainLayout; "],"mappings":";;;;;;;AAiBA,IAAM,IAAA,CAAyC,EAAE,UAAA,GAAU,aAAA,GAAa,eAAA,GAAe,cAAA,EAAA,MAAmB;AACxG,QAAM,CAAC,GAAkB,CAAA,IAAuB,EAAS,EAAK,GACxD,EAAE,OAAA,GAAO,UAAA,GAAU,OAAA,GAAO,WAAA,GAAW,cAAA,GAAc,QAAA,GAAQ,cAAc,GAAoB,uBAAA,EAAA,IAA0B,EAAc,GACrI,CAAC,GAAc,CAAA,IAAmB,EAAS,KAAsB,GAAG,GACpE,IAAa,EAAuB,IAAI;AAG9C,EAAA,EAAM,UAAA,MAAgB;AACpB,IAAI,KACF,EAAgB,CAAkB;AAAA,EAEtC,GAAG,CAAC,CAAkB,CAAC;AAEvB,QAAM,IAAA,MAAsB;AAC1B,IAAA,EAAoB,CAAC,CAAgB;AAAA,EACvC,GAGM,IAAA,CAA4B,MAAkB;AAClD,IAAA,EAAgB,CAAK;AAAA,EACvB,GAEM,IAAe,OAAO,KAAgB,aACxC,EAAY,CAAa,IACzB;AAEJ,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IAAyC,cAAY;AAAA,IAApE,UAAA,CACE,gBAAA,EAAC,GAAD;AAAA,MACE,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,OAAO;AAAA,IACR,CAAA,GAED,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAf,UAAA;AAAA,QACE,gBAAA,EAAC,OAAD;AAAA,UAAK,WAAU;AAAA,UAAgB,KAAK;AAAA,UAClC,UAAA,gBAAA,EAAC,GAAD;AAAA,YACE,aAAa;AAAA,YACH,UAAA;AAAA,YACV,OAAO;AAAA,YACO,cAAA;AAAA,YACd,eAAe;AAAA,YACf,cAAc,KAAsB;AAAA,YACpC,gBAAgB,KAAyB;AAAA,UAC1C,CAAA;AAAA,QACE,CAAA;AAAA,QAEL,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,UACb,UAAA,KAAY,gBAAA,EAAC,GAAD,CAAS,CAAA;AAAA,QAClB,CAAA;AAAA,QAGN,gBAAA,EAAC,GAAD;AAAA,UACE,aAAa;AAAA,UACb,UAAU;AAAA,UACI,cAAA;AAAA,UACd,gBAAgB,KAAyB;AAAA,QAC1C,CAAA;AAAA,MACE;AAAA,IACF,CAAA,CAAA;AAAA;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"Navbar.js","names":[],"sources":["../../src/layouts/Navbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { ThemeType, useAppContext } from '../contexts/AppContext';\nimport { getTranslations } from '../utils/i18n';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../utils/themes';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\ntype NavbarProps = {\n onToggleSidebar: () => void;\n searchConfig?: SearchConfig;\n themes?: ThemeConfig[];\n height?: number; // Navbar 高度(像素)\n};\n\nconst Navbar: React.FC<NavbarProps> = ({ onToggleSidebar, searchConfig, themes: propThemes, height = 64 }) => {\n const { title = 'DiShUI', language, setLanguage, theme, setTheme } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n // 获取主题配置:优先使用 propThemes,否则使用默认的\n const themes = propThemes || defaultGetThemes();\n\n // 获取当前主题\n const currentTheme = themes.find(t => t.id === theme) || themes[0];\n\n // 搜索是否启用\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n // 使用外部提供的搜索函数\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n return (\n <div className=\"navbar bg-base-100 shadow-md\" style={{ height: `${height}px`, minHeight: `${height}px`, maxHeight: `${height}px` }}>\n <div className=\"navbar-start\">\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" className=\"inline-block w-5 h-5 stroke-current\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path>\n </svg>\n </button>\n </div>\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">{title}</a>\n </div>\n\n {isSearchEnabled && (\n <div className=\"navbar-center hidden lg:flex\">\n <button\n className=\"btn btn-ghost gap-2\"\n onClick={toggleSearch}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} ({searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n </div>\n )}\n\n <div className=\"navbar-end\">\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\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=\"M19 9l-7 7-7-7\" />\n </svg>\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\">\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\">\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n\n {/* 搜索对话框 */}\n {isSearchEnabled && (\n <dialog ref={modalRef} className=\"modal modal-bottom sm:modal-middle\" onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}>\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchConfig?.placeholder?.[language] || t.navbar.searchPlaceholder}\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 absolute top-3 right-3 opacity-50\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">{result.description}</div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>ESC</button>\n </form>\n </div>\n </div>\n </dialog>\n )}\n </div>\n );\n};\n\nexport default Navbar; "],"mappings":"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"}
1
+ {"version":3,"file":"Navbar.js","names":[],"sources":["../../src/layouts/Navbar.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { ThemeType, useAppContext } from '../contexts/AppContext';\nimport { getTranslations } from '../utils/i18n';\nimport { ThemeConfig, getThemes as defaultGetThemes } from '../utils/themes';\n\nexport type SearchResult = {\n title: string;\n path: string;\n description: string;\n};\n\nexport type SearchConfig = {\n enabled: boolean;\n searchFunction?: (term: string, language: 'zh' | 'en') => SearchResult[];\n placeholder?: { zh: string; en: string };\n shortcut?: string;\n};\n\ntype NavbarProps = {\n onToggleSidebar: () => void;\n searchConfig?: SearchConfig;\n themes?: ThemeConfig[];\n height?: number; // Navbar 高度(像素)\n};\n\nconst Navbar: React.FC<NavbarProps> = ({ onToggleSidebar, searchConfig, themes: propThemes, height = 64 }) => {\n const { title = 'DiShUI', language, setLanguage, theme, setTheme } = useAppContext();\n const t = getTranslations(language);\n\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchTerm, setSearchTerm] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDialogElement>(null);\n\n // 获取主题配置:优先使用 propThemes,否则使用默认的\n const themes = propThemes || defaultGetThemes();\n\n // 获取当前主题\n const currentTheme = themes.find(t => t.id === theme) || themes[0];\n\n // 搜索是否启用\n const isSearchEnabled = searchConfig?.enabled ?? true;\n\n const toggleSearch = () => {\n setIsSearchOpen(!isSearchOpen);\n if (!isSearchOpen && modalRef.current) {\n modalRef.current.showModal();\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n } else if (modalRef.current) {\n modalRef.current.close();\n }\n };\n\n const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearchTerm(value);\n // 使用外部提供的搜索函数\n const searchFn = searchConfig?.searchFunction;\n if (searchFn) {\n setSearchResults(searchFn(value, language));\n }\n };\n\n useEffect(() => {\n if (!isSearchEnabled) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key === 'k') {\n e.preventDefault();\n toggleSearch();\n }\n\n if (e.key === 'Escape' && isSearchOpen) {\n toggleSearch();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isSearchOpen, isSearchEnabled]);\n\n // 当语言改变时,更新搜索结果\n useEffect(() => {\n if (searchTerm && isSearchEnabled && searchConfig?.searchFunction) {\n setSearchResults(searchConfig.searchFunction(searchTerm, language));\n }\n }, [language, searchConfig, isSearchEnabled, searchTerm]);\n\n return (\n <div className=\"navbar bg-base-100 shadow-md\" style={{ height: `${height}px`, minHeight: `${height}px`, maxHeight: `${height}px` }}>\n <div className=\"navbar-start\">\n <div className=\"flex-none lg:hidden\">\n <button className=\"btn btn-square btn-ghost\" onClick={onToggleSidebar}>\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" className=\"inline-block w-5 h-5 stroke-current\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path>\n </svg>\n </button>\n </div>\n <a href=\"/\" className=\"btn btn-ghost normal-case text-xl\">{title}</a>\n </div>\n\n {isSearchEnabled && (\n <div className=\"navbar-center hidden lg:flex\">\n <button\n className=\"btn btn-ghost gap-2\"\n onClick={toggleSearch}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n {searchConfig?.placeholder?.[language] || t.navbar.search} ({searchConfig?.shortcut || t.navbar.searchShortcut})\n </button>\n </div>\n )}\n\n <div className=\"navbar-end\">\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\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=\"M19 9l-7 7-7-7\" />\n </svg>\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\">\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost\">\n {currentTheme.icon}\n </label>\n <ul tabIndex={0} className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-52 mt-4\">\n {themes.map((themeOption) => (\n <li key={themeOption.id}>\n <a\n className={theme === themeOption.id ? 'active' : ''}\n onClick={() => setTheme(themeOption.id)}\n >\n <span className=\"mr-2\">{themeOption.icon}</span>\n {language === 'zh' ? themeOption.name.zh : themeOption.name.en}\n </a>\n </li>\n ))}\n </ul>\n </div>\n </div>\n\n {/* 搜索对话框 */}\n {isSearchEnabled && (\n <dialog ref={modalRef} className=\"modal modal-bottom sm:modal-middle\" onClick={(e) => {\n if (e.target === modalRef.current) toggleSearch();\n }}>\n <div className=\"modal-box bg-base-100\">\n <div className=\"relative mb-4\">\n <input\n ref={searchInputRef}\n type=\"text\"\n placeholder={searchConfig?.placeholder?.[language] || t.navbar.searchPlaceholder}\n className=\"input input-bordered w-full pr-10\"\n value={searchTerm}\n onChange={handleSearch}\n />\n <svg xmlns=\"http://www.w3.org/2000/svg\" className=\"h-5 w-5 absolute top-3 right-3 opacity-50\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n </div>\n\n <div className=\"search-results max-h-80 overflow-y-auto\">\n {searchResults.length > 0 ? (\n <ul className=\"menu bg-base-100 rounded-box\">\n {searchResults.map((result, index) => (\n <li key={index}>\n <a\n href={result.path}\n className=\"flex flex-col items-start\"\n onClick={() => toggleSearch()}\n >\n <div className=\"font-medium\">{result.title}</div>\n <div className=\"text-sm opacity-70\">{result.description}</div>\n </a>\n </li>\n ))}\n </ul>\n ) : searchTerm ? (\n <div className=\"py-4 text-center text-base-content/70\">\n {t.navbar.noResults}\n </div>\n ) : null}\n </div>\n\n <div className=\"modal-action\">\n <form method=\"dialog\">\n <button className=\"btn\" onClick={toggleSearch}>ESC</button>\n </form>\n </div>\n </div>\n </dialog>\n )}\n </div>\n );\n};\n\nexport default Navbar; "],"mappings":"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"}
@@ -1,144 +1,165 @@
1
- import { generateSidebarActiveStyles as D } from "../styles/themeStyles.js";
1
+ import { generateSidebarActiveStyles as C } from "../styles/themeStyles.js";
2
2
  import P from "../components/Tree/Tree.js";
3
- import { getMenuItems as R } from "../utils/menu.js";
4
- import { useEffect as c, useMemo as E, useRef as L, useState as h } from "react";
5
- import { jsx as n, jsxs as $ } from "react/jsx-runtime";
6
- import { useNavigate as B, useRouterState as V } from "@tanstack/react-router";
7
- var K = ({ isCollapsed: T, language: m, items: u, getMenuItems: f, onWidthChange: b, initialWidth: g = 280, collapsedWidth: s = 64 }) => {
8
- const [a, p] = h([]), [j, l] = h(""), [w, y] = h(!1), [A, N] = h(g), v = L(null), k = L(null), z = V({ select: (e) => e.location }), x = B();
9
- c(() => {
10
- N(g);
11
- }, [g]), c(() => {
12
- p(u !== void 0 ? u : f ? f(m) : R(m));
3
+ import { getMenuItems as $ } from "../utils/menu.js";
4
+ import { useEffect as d, useMemo as H, useRef as N, useState as h } from "react";
5
+ import { jsx as i, jsxs as V } from "react/jsx-runtime";
6
+ import { useNavigate as W, useRouterState as B } from "@tanstack/react-router";
7
+ var K = ({ isCollapsed: I, language: u, items: m, getMenuItems: f, onWidthChange: b, initialWidth: p = 280, collapsedWidth: l = 64 }) => {
8
+ const [a, g] = h([]), [v, c] = h(""), [k, T] = h(!1), [j, M] = h(p), w = N(null), x = N(null), S = N(null), z = B({ select: (e) => e.location }), y = W();
9
+ d(() => {
10
+ M(p);
11
+ }, [p]), d(() => {
12
+ g(m !== void 0 ? m : f ? f(u) : $(u));
13
13
  }, [
14
- m,
15
14
  u,
15
+ m,
16
16
  f
17
- ]);
18
- const M = (e, i = !0) => e.map((t) => ({
17
+ ]), d(() => {
18
+ if (!v) return;
19
+ const e = setTimeout(() => {
20
+ x.current?.querySelector(".tree-node-content-active")?.scrollIntoView({
21
+ block: "nearest",
22
+ behavior: "smooth"
23
+ });
24
+ }, 350);
25
+ return () => clearTimeout(e);
26
+ }, [v]), d(() => {
27
+ const e = x.current;
28
+ if (!e) return;
29
+ const n = (t) => {
30
+ if (e.scrollHeight <= e.clientHeight) return;
31
+ const o = t.deltaMode === 1 ? t.deltaY * 16 : t.deltaY;
32
+ if (o === 0) return;
33
+ const r = e.scrollTop;
34
+ e.scrollTop = r + o, e.scrollTop !== r && t.preventDefault();
35
+ };
36
+ return e.addEventListener("wheel", n, { passive: !1 }), () => e.removeEventListener("wheel", n);
37
+ }, []);
38
+ const E = (e, n = !0) => e.map((t) => ({
19
39
  id: t.id,
20
40
  label: t.label,
21
- icon: t.icon || (i ? void 0 : /* @__PURE__ */ n("svg", {
41
+ icon: t.icon || (n ? void 0 : /* @__PURE__ */ i("svg", {
22
42
  xmlns: "http://www.w3.org/2000/svg",
23
43
  className: "h-4 w-4",
24
44
  fill: "none",
25
45
  viewBox: "0 0 24 24",
26
46
  stroke: "currentColor",
27
- children: /* @__PURE__ */ n("path", {
47
+ children: /* @__PURE__ */ i("path", {
28
48
  strokeLinecap: "round",
29
49
  strokeLinejoin: "round",
30
50
  strokeWidth: "2",
31
51
  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"
32
52
  })
33
53
  })),
34
- children: t.children ? M(t.children, !1) : void 0,
54
+ children: t.children ? E(t.children, !1) : void 0,
35
55
  meta: { path: t.path }
36
- })), H = E(() => M(a, !0), [a]), I = E(() => {
56
+ })), A = H(() => E(a, !0), [a]), D = H(() => {
37
57
  if (a.length === 0) return [];
38
- const e = (i) => {
58
+ const e = (n) => {
39
59
  let t = [];
40
- for (const o of i) o.children?.length && (t.push(o.id), t = [...t, ...e(o.children)]);
60
+ for (const o of n) o.children?.length && (t.push(o.id), t = [...t, ...e(o.children)]);
41
61
  return t;
42
62
  };
43
63
  return e(a);
44
64
  }, [a]);
45
- c(() => {
46
- const e = z.pathname, i = (o) => {
65
+ d(() => {
66
+ const e = z.pathname, n = (o) => {
47
67
  for (const r of o) {
48
68
  if (r.path === e) return r.id;
49
69
  if (r.children) {
50
- const d = i(r.children);
51
- if (d) return d;
70
+ const s = n(r.children);
71
+ if (s) return s;
52
72
  }
53
73
  }
54
74
  return null;
55
- }, t = i(a);
56
- t && l(t);
57
- }, [a, z.pathname]), c(() => {
75
+ }, t = n(a);
76
+ t && c(t);
77
+ }, [a, z.pathname]), d(() => {
58
78
  const e = (r) => {
59
- y(!0), document.body.style.userSelect = "none", document.body.style.cursor = "ew-resize", r.preventDefault();
60
- }, i = () => {
61
- y(!1), document.body.style.userSelect = "", document.body.style.cursor = "";
79
+ T(!0), document.body.style.userSelect = "none", document.body.style.cursor = "ew-resize", r.preventDefault();
80
+ }, n = () => {
81
+ T(!1), document.body.style.userSelect = "", document.body.style.cursor = "";
62
82
  }, t = (r) => {
63
- if (w && v.current) {
64
- const d = r.clientX, S = Math.max(160, Math.min(d, 400));
65
- N(S), b && b(S);
83
+ if (k && w.current) {
84
+ const s = r.clientX, L = Math.max(160, Math.min(s, 400));
85
+ M(L), b && b(L);
66
86
  }
67
- }, o = k.current;
68
- return o && o.addEventListener("mousedown", e), document.addEventListener("mouseup", i), document.addEventListener("mousemove", t), () => {
69
- o && o.removeEventListener("mousedown", e), document.removeEventListener("mouseup", i), document.removeEventListener("mousemove", t);
87
+ }, o = S.current;
88
+ return o && o.addEventListener("mousedown", e), document.addEventListener("mouseup", n), document.addEventListener("mousemove", t), () => {
89
+ o && o.removeEventListener("mousedown", e), document.removeEventListener("mouseup", n), document.removeEventListener("mousemove", t);
70
90
  };
71
91
  }, [
72
- w,
92
+ k,
73
93
  b,
74
- v
94
+ w
75
95
  ]);
76
- const C = (e) => {
96
+ const R = (e) => {
77
97
  if (e.meta?.path) {
78
- l(e.id), x({ to: e.meta.path });
98
+ c(e.id), y({ to: e.meta.path });
79
99
  return;
80
100
  }
81
101
  if (e.children && e.children.length > 0) {
82
- const i = (o) => {
102
+ const n = (o) => {
83
103
  for (const r of o) {
84
104
  if (r.meta?.path) return r;
85
105
  if (r.children && r.children.length > 0) {
86
- const d = i(r.children);
87
- if (d) return d;
106
+ const s = n(r.children);
107
+ if (s) return s;
88
108
  }
89
109
  }
90
110
  return null;
91
- }, t = i(e.children);
92
- t ? (l(t.id), x({ to: t.meta.path })) : l(e.id);
93
- } else l(e.id);
111
+ }, t = n(e.children);
112
+ t ? (c(t.id), y({ to: t.meta.path })) : c(e.id);
113
+ } else c(e.id);
94
114
  };
95
- return T ? /* @__PURE__ */ n("div", {
96
- className: "h-full bg-base-200 overflow-hidden shadow-lg transition-all duration-300 ease-in-out",
97
- style: { width: `${s}px` },
98
- children: /* @__PURE__ */ n("ul", {
115
+ return I ? /* @__PURE__ */ i("div", {
116
+ className: "h-full bg-base-200 overflow-y-auto overflow-x-hidden shadow-lg transition-all duration-300 ease-in-out",
117
+ style: { width: `${l}px` },
118
+ children: /* @__PURE__ */ i("ul", {
99
119
  className: "flex flex-col p-2 gap-1",
100
- children: a.map((e) => /* @__PURE__ */ n("li", { children: e.path ? /* @__PURE__ */ n("button", {
101
- onClick: () => x({ to: e.path }),
120
+ children: a.map((e) => /* @__PURE__ */ i("li", { children: e.path ? /* @__PURE__ */ i("button", {
121
+ onClick: () => y({ to: e.path }),
102
122
  className: "flex justify-center items-center rounded-lg hover:bg-base-300 transition-colors w-full",
103
123
  style: {
104
124
  WebkitTapHighlightColor: "transparent",
105
- height: `${Math.min(s - 16, 40)}px`,
106
- width: `${Math.min(s - 16, 40)}px`,
125
+ height: `${Math.min(l - 16, 40)}px`,
126
+ width: `${Math.min(l - 16, 40)}px`,
107
127
  margin: "0 auto"
108
128
  },
109
- children: e.icon || /* @__PURE__ */ n("span", {
129
+ children: e.icon || /* @__PURE__ */ i("span", {
110
130
  className: "text-sm",
111
131
  children: e.label.charAt(0)
112
132
  })
113
- }) : /* @__PURE__ */ n("div", {
133
+ }) : /* @__PURE__ */ i("div", {
114
134
  className: "flex justify-center items-center",
115
135
  style: {
116
136
  WebkitTapHighlightColor: "transparent",
117
- height: `${Math.min(s - 16, 40)}px`,
118
- width: `${Math.min(s - 16, 40)}px`,
137
+ height: `${Math.min(l - 16, 40)}px`,
138
+ width: `${Math.min(l - 16, 40)}px`,
119
139
  margin: "0 auto"
120
140
  },
121
- children: e.icon || /* @__PURE__ */ n("span", {
141
+ children: e.icon || /* @__PURE__ */ i("span", {
122
142
  className: "text-sm",
123
143
  children: e.label.charAt(0)
124
144
  })
125
145
  }) }, e.id))
126
146
  })
127
- }) : /* @__PURE__ */ $("div", {
128
- ref: v,
147
+ }) : /* @__PURE__ */ V("div", {
148
+ ref: w,
129
149
  className: "h-full bg-base-200 overflow-hidden flex flex-col transition-all duration-300 ease-in-out relative",
130
150
  style: {
131
- width: `${A}px`,
151
+ width: `${j}px`,
132
152
  maxWidth: "400px",
133
153
  minWidth: "160px"
134
154
  },
135
155
  children: [
136
- /* @__PURE__ */ n("div", {
137
- className: "overflow-y-auto flex-grow hide-scrollbar",
138
- children: /* @__PURE__ */ n(P, {
139
- data: H,
140
- activeNodeId: j,
141
- defaultExpandedIds: I,
156
+ /* @__PURE__ */ i("div", {
157
+ ref: x,
158
+ className: "sidebar-scroll min-h-0 flex-grow overflow-y-auto scrollbar-thin scrollbar-thumb-base-300 scrollbar-track-transparent",
159
+ children: /* @__PURE__ */ i(P, {
160
+ data: A,
161
+ activeNodeId: v,
162
+ defaultExpandedIds: D,
142
163
  showSearch: !1,
143
164
  showExpandAll: !1,
144
165
  showIcon: !0,
@@ -148,15 +169,15 @@ var K = ({ isCollapsed: T, language: m, items: u, getMenuItems: f, onWidthChange
148
169
  togglePosition: "right",
149
170
  maxHeight: "100%",
150
171
  className: "sidebar-tree",
151
- onNodeClick: C
172
+ onNodeClick: R
152
173
  })
153
174
  }),
154
- /* @__PURE__ */ n("div", {
155
- ref: k,
175
+ /* @__PURE__ */ i("div", {
176
+ ref: S,
156
177
  className: "absolute top-0 right-0 w-2 h-full cursor-ew-resize hover:bg-primary hover:opacity-50 transition-all z-50",
157
178
  style: { right: "-1px" }
158
179
  }),
159
- /* @__PURE__ */ n("style", { children: `
180
+ /* @__PURE__ */ i("style", { children: `
160
181
  /* Sidebar Tree 自定义样式 */
161
182
  .sidebar-tree {
162
183
  background: transparent;
@@ -177,7 +198,7 @@ var K = ({ isCollapsed: T, language: m, items: u, getMenuItems: f, onWidthChange
177
198
  }
178
199
 
179
200
  /* 主题活跃状态样式 - 从共用配置生成 */
180
- ${D()}
201
+ ${C()}
181
202
 
182
203
  /* 悬停状态 */
183
204
  .sidebar-tree .tree-node-content:hover:not(.tree-node-active .tree-node-content):not(.tree-node-content-active) {
@@ -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 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 // 将 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-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 className=\"overflow-y-auto flex-grow hide-scrollbar\">\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":";;;;;;AAkBA,IAAM,IAAA,CAAmC,EACvC,aAAA,GACA,UAAA,GACA,OAAO,GACP,cAAA,GACA,eAAA,GACA,cAAA,IAAe,KACf,gBAAA,IAAiB,GAAA,MACb;AACJ,QAAM,CAAC,GAAO,CAAA,IAAY,EAAqB,CAAC,CAAC,GAC3C,CAAC,GAAc,CAAA,IAAmB,EAA0B,EAAE,GAC9D,CAAC,GAAY,CAAA,IAAiB,EAAS,EAAK,GAC5C,CAAC,GAAc,CAAA,IAAmB,EAAS,CAAY,GACvD,IAAa,EAAuB,IAAI,GACxC,IAAkB,EAAuB,IAAI,GAC7C,IAAc,EAAe,EAAE,QAAA,CAAS,MAA0C,EAAE,SAAS,CAAC,GAC9F,IAAW,EAAY;AAG7B,EAAA,EAAA,MAAgB;AACd,IAAA,EAAgB,CAAY;AAAA,EAC9B,GAAG,CAAC,CAAY,CAAC,GAGjB,EAAA,MAAgB;AACd,IACE,EADE,MAAc,SACP,IACA,IACA,EAAa,CAAQ,IAErB,EAAoB,CAAQ,CAJnB;AAAA,EAMtB,GAAG;AAAA,IAAC;AAAA,IAAU;AAAA,IAAW;AAAA,EAAY,CAAC;AAGtC,QAAM,IAAA,CAAsB,GAAuB,IAAsB,OAChE,EAAU,IAAA,CAAI,OAAS;AAAA,IAC5B,IAAI,EAAK;AAAA,IACT,OAAO,EAAK;AAAA,IACZ,MAAM,EAAK,SAAU,IAIjB,SAHF,gBAAA,EAAC,OAAD;AAAA,MAAK,OAAM;AAAA,MAA6B,WAAU;AAAA,MAAU,MAAK;AAAA,MAAO,SAAQ;AAAA,MAAY,QAAO;AAAA,gBACjG,gBAAA,EAAC,QAAD;AAAA,QAAM,eAAc;AAAA,QAAQ,gBAAe;AAAA,QAAQ,aAAY;AAAA,QAAI,GAAE;AAAA,MAAwH,CAAA;AAAA,IAC1L,CAAA;AAAA,IAEP,UAAU,EAAK,WAAW,EAAmB,EAAK,UAAU,EAAK,IAAI;AAAA,IACrE,MAAM,EACJ,MAAM,EAAK,KACb;AAAA,EACF,EAAE,GAIE,IAAW,EAAA,MAAc,EAAmB,GAAO,EAAI,GAAG,CAAC,CAAK,CAAC,GAGjE,IAAqB,EAAA,MAAc;AACvC,QAAI,EAAM,WAAW,EAAG,QAAO,CAAC;AAGhC,UAAM,IAAA,CAA2B,MAAoC;AACnE,UAAI,IAAmB,CAAC;AACxB,iBAAW,KAAQ,EACjB,CAAI,EAAK,UAAU,WACjB,EAAO,KAAK,EAAK,EAAE,GACnB,IAAS,CAAC,GAAG,GAAQ,GAAG,EAAwB,EAAK,QAAQ,CAAC;AAGlE,aAAO;AAAA,IACT;AAEA,WAAO,EAAwB,CAAK;AAAA,EACtC,GAAG,CAAC,CAAK,CAAC;AAGV,EAAA,EAAA,MAAgB;AACd,UAAM,IAAc,EAAY,UAC1B,IAAA,CAAkB,MAAyC;AAC/D,iBAAW,KAAQ,GAAW;AAC5B,YAAI,EAAK,SAAS,EAChB,QAAO,EAAK;AAEd,YAAI,EAAK,UAAU;AACjB,gBAAM,IAAQ,EAAe,EAAK,QAAQ;AAC1C,cAAI,EAAO,QAAO;AAAA,QACpB;AAAA,MACF;AACA,aAAO;AAAA,IACT,GAEM,IAAS,EAAe,CAAK;AACnC,IAAI,KACF,EAAgB,CAAM;AAAA,EAE1B,GAAG,CAAC,GAAO,EAAY,QAAQ,CAAC,GAGhC,EAAA,MAAgB;AACd,UAAM,IAAA,CAAmB,MAAkB;AACzC,MAAA,EAAc,EAAI,GAClB,SAAS,KAAK,MAAM,aAAa,QACjC,SAAS,KAAK,MAAM,SAAS,aAC7B,EAAE,eAAe;AAAA,IACnB,GAEM,IAAA,MAAsB;AAC1B,MAAA,EAAc,EAAK,GACnB,SAAS,KAAK,MAAM,aAAa,IACjC,SAAS,KAAK,MAAM,SAAS;AAAA,IAC/B,GAEM,IAAA,CAAmB,MAAkB;AACzC,UAAI,KAAc,EAAW,SAAS;AACpC,cAAM,IAAW,EAAE,SAEb,IAAe,KAAK,IAAI,KAAK,KAAK,IAAI,GAAU,GAAG,CAAC;AAC1D,QAAA,EAAgB,CAAY,GACxB,KACF,EAAc,CAAY;AAAA,MAE9B;AAAA,IACF,GAEM,IAAe,EAAgB;AACrC,WAAI,KACF,EAAa,iBAAiB,aAAa,CAAe,GAG5D,SAAS,iBAAiB,WAAW,CAAa,GAClD,SAAS,iBAAiB,aAAa,CAAe,GAEtD,MAAa;AACX,MAAI,KACF,EAAa,oBAAoB,aAAa,CAAe,GAE/D,SAAS,oBAAoB,WAAW,CAAa,GACrD,SAAS,oBAAoB,aAAa,CAAe;AAAA,IAC3D;AAAA,EACF,GAAG;AAAA,IAAC;AAAA,IAAY;AAAA,IAAe;AAAA,EAAU,CAAC;AAG1C,QAAM,IAAA,CAAmB,MAAmB;AAE1C,QAAI,EAAK,MAAM,MAAM;AACnB,MAAA,EAAgB,EAAK,EAAE,GACvB,EAAS,EAAE,IAAI,EAAK,KAAK,KAAK,CAAC;AAC/B;AAAA,IACF;AAGA,QAAI,EAAK,YAAY,EAAK,SAAS,SAAS,GAAG;AAC7C,YAAM,IAAA,CAAiB,MAAuC;AAC5D,mBAAW,KAAK,GAAO;AACrB,cAAI,EAAE,MAAM,KAAM,QAAO;AACzB,cAAI,EAAE,YAAY,EAAE,SAAS,SAAS,GAAG;AACvC,kBAAM,IAAQ,EAAc,EAAE,QAAQ;AACtC,gBAAI,EAAO,QAAO;AAAA,UACpB;AAAA,QACF;AACA,eAAO;AAAA,MACT,GAEM,IAAoB,EAAc,EAAK,QAAQ;AACrD,MAAI,KACF,EAAgB,EAAkB,EAAE,GACpC,EAAS,EAAE,IAAI,EAAkB,KAAM,KAAK,CAAC,KAG7C,EAAgB,EAAK,EAAE;AAAA,IAE3B,MACE,CAAA,EAAgB,EAAK,EAAE;AAAA,EAE3B;AAEA,SAAI,IAEA,gBAAA,EAAC,OAAD;AAAA,IACE,WAAU;AAAA,IACV,OAAO,EAAE,OAAO,GAAG,CAAA,KAAmB;AAAA,cAEtC,gBAAA,EAAC,MAAD;AAAA,MAAI,WAAU;AAAA,gBACX,EAAM,IAAA,CAAI,MACT,gBAAA,EAAC,MAAD,EAAA,UACG,EAAK,OACJ,gBAAA,EAAC,UAAD;AAAA,QACE,SAAA,MAAe,EAAS,EAAE,IAAI,EAAK,KAAM,CAAC;AAAA,QAC1C,WAAU;AAAA,QACV,OAAO;AAAA,UACL,yBAAyB;AAAA,UACzB,QAAQ,GAAG,KAAK,IAAI,IAAiB,IAAI,EAAE,CAAA;AAAA,UAC3C,OAAO,GAAG,KAAK,IAAI,IAAiB,IAAI,EAAE,CAAA;AAAA,UAC1C,QAAQ;AAAA,QACV;AAAA,kBAEC,EAAK,QAAQ,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,oBAAW,EAAK,MAAM,OAAO,CAAC;AAAA,QAAQ,CAAA;AAAA,MAC9D,CAAA,IAER,gBAAA,EAAC,OAAD;AAAA,QACE,WAAU;AAAA,QACV,OAAO;AAAA,UACL,yBAAyB;AAAA,UACzB,QAAQ,GAAG,KAAK,IAAI,IAAiB,IAAI,EAAE,CAAA;AAAA,UAC3C,OAAO,GAAG,KAAK,IAAI,IAAiB,IAAI,EAAE,CAAA;AAAA,UAC1C,QAAQ;AAAA,QACV;AAAA,kBAEC,EAAK,QAAQ,gBAAA,EAAC,QAAD;AAAA,UAAM,WAAU;AAAA,oBAAW,EAAK,MAAM,OAAO,CAAC;AAAA,QAAQ,CAAA;AAAA,MACjE,CAAA,EAEL,GA3BK,EAAK,EA2BV,CACL;AAAA,IACC,CAAA;AAAA,EACD,CAAA,IAKP,gBAAA,EAAC,OAAD;AAAA,IACE,KAAK;AAAA,IACL,WAAU;AAAA,IACV,OAAO;AAAA,MAAE,OAAO,GAAG,CAAA;AAAA,MAAkB,UAAU;AAAA,MAAS,UAAU;AAAA,IAAQ;AAAA,cAH5E;AAAA,MAKE,gBAAA,EAAC,OAAD;AAAA,QAAK,WAAU;AAAA,kBACb,gBAAA,EAAC,GAAD;AAAA,UACE,MAAM;AAAA,UACQ,cAAA;AAAA,UACM,oBAAA;AAAA,UACpB,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,UAAU;AAAA,UACV,WAAW;AAAA,UACX,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,gBAAe;AAAA,UACf,WAAU;AAAA,UACV,WAAU;AAAA,UACV,aAAa;AAAA,QACd,CAAA;AAAA,MACE,CAAA;AAAA,MAGL,gBAAA,EAAC,OAAD;AAAA,QACE,KAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO,EAAE,OAAO,OAAO;AAAA,MACnB,CAAA;AAAA,MAEN,gBAAA,EAAC,SAAD,EAAA,UAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAqBJ,EAA4B,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAmHvB,CAAA;AAAA,IACN;AAAA;AAET"}
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 +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,IAAA,CAAmC,EACvC,MAAA,GACA,QAAA,GACA,OAAA,GACA,QAAA,IAAS,IACT,WAAA,EAAA,MAGE,gBAAA,EAAC,OAAD;AAAA,EACE,WAAW,gCAAgC,KAAa,EAAA;AAAA,EACxD,OAAO;AAAA,IACL,QAAQ,GAAG,CAAA;AAAA,IACX,WAAW,GAAG,CAAA;AAAA,IACd,WAAW,GAAG,CAAA;AAAA,EAChB;AAAA,YANF;AAAA,IAQE,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAgB;AAAA,IAAU,CAAA;AAAA,IACzC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAgC;AAAA,IAAY,CAAA;AAAA,IAC3D,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,gBAAc;AAAA,IAAW,CAAA;AAAA,EACrC"}
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,IAAA,CAAmC,EACvC,MAAA,GACA,QAAA,GACA,OAAA,GACA,QAAA,IAAS,IACT,WAAA,EAAA,MAGE,gBAAA,EAAC,OAAD;AAAA,EACE,WAAW,gCAAgC,KAAa,EAAA;AAAA,EACxD,OAAO;AAAA,IACL,QAAQ,GAAG,CAAA;AAAA,IACX,WAAW,GAAG,CAAA;AAAA,IACd,WAAW,GAAG,CAAA;AAAA,EAChB;AAAA,EANF,UAAA;AAAA,IAQE,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAgB,UAAA;AAAA,IAAU,CAAA;AAAA,IACzC,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAgC,UAAA;AAAA,IAAY,CAAA;AAAA,IAC3D,gBAAA,EAAC,OAAD;AAAA,MAAK,WAAU;AAAA,MAAc,UAAA;AAAA,IAAW,CAAA;AAAA,EACrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"HeadbarLangSwitcher.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarLangSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\n\n/**\n * HeadbarLangSwitcher - 语言切换下拉菜单\n */\nconst HeadbarLangSwitcher: React.FC = () => {\n const { language, setLanguage } = useAppContext();\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\"\n >\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n );\n};\n\nexport default HeadbarLangSwitcher;\n"],"mappings":";;;AAMA,IAAM,IAAA,MAAsC;AAC1C,QAAM,EAAE,UAAA,GAAU,aAAA,EAAA,IAAgB,EAAc;AAEhD,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,cAAf,CACE,gBAAA,EAAC,SAAD;AAAA,MAAO,UAAU;AAAA,MAAG,WAAU;AAAA,gBAA9B,CACG,MAAa,OAAO,OAAO,WAC5B,gBAAA,EAAC,OAAD;AAAA,QACE,OAAM;AAAA,QACN,WAAU;AAAA,QACV,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,QAAO;AAAA,kBAEP,gBAAA,EAAC,QAAD;AAAA,UACE,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,aAAY;AAAA,UACZ,GAAE;AAAA,QACH,CAAA;AAAA,MACE,CAAA,CACA;AAAA,QACP,gBAAA,EAAC,MAAD;AAAA,MACE,UAAU;AAAA,MACV,WAAU;AAAA,gBAFZ,CAIE,gBAAA,EAAC,MAAD,EAAA,UACE,gBAAA,EAAC,KAAD;AAAA,QACE,WAAW,MAAa,OAAO,WAAW;AAAA,QAC1C,SAAA,MAAe,EAAY,IAAI;AAAA,kBAChC;AAAA,MAEE,CAAA,EACD,CAAA,GACJ,gBAAA,EAAC,MAAD,EAAA,UACE,gBAAA,EAAC,KAAD;AAAA,QACE,WAAW,MAAa,OAAO,WAAW;AAAA,QAC1C,SAAA,MAAe,EAAY,IAAI;AAAA,kBAChC;AAAA,MAEE,CAAA,EACD,CAAA,CACF;AAAA,MACD;AAAA;AAET"}
1
+ {"version":3,"file":"HeadbarLangSwitcher.js","names":[],"sources":["../../../src/layouts/headbar/HeadbarLangSwitcher.tsx"],"sourcesContent":["import React from 'react';\nimport { useAppContext } from '../../contexts/AppContext';\n\n/**\n * HeadbarLangSwitcher - 语言切换下拉菜单\n */\nconst HeadbarLangSwitcher: React.FC = () => {\n const { language, setLanguage } = useAppContext();\n\n return (\n <div className=\"dropdown dropdown-end\">\n <label tabIndex={0} className=\"btn btn-ghost gap-1\">\n {language === 'zh' ? '中文' : 'English'}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n d=\"M19 9l-7 7-7-7\"\n />\n </svg>\n </label>\n <ul\n tabIndex={0}\n className=\"menu dropdown-content p-2 shadow bg-base-100 rounded-box w-40 mt-4\"\n >\n <li>\n <a\n className={language === 'zh' ? 'active' : ''}\n onClick={() => setLanguage('zh')}\n >\n 中文\n </a>\n </li>\n <li>\n <a\n className={language === 'en' ? 'active' : ''}\n onClick={() => setLanguage('en')}\n >\n English\n </a>\n </li>\n </ul>\n </div>\n );\n};\n\nexport default HeadbarLangSwitcher;\n"],"mappings":";;;AAMA,IAAM,IAAA,MAAsC;AAC1C,QAAM,EAAE,UAAA,GAAU,aAAA,EAAA,IAAgB,EAAc;AAEhD,SACE,gBAAA,EAAC,OAAD;AAAA,IAAK,WAAU;AAAA,IAAf,UAAA,CACE,gBAAA,EAAC,SAAD;AAAA,MAAO,UAAU;AAAA,MAAG,WAAU;AAAA,MAA9B,UAAA,CACG,MAAa,OAAO,OAAO,WAC5B,gBAAA,EAAC,OAAD;AAAA,QACE,OAAM;AAAA,QACN,WAAU;AAAA,QACV,MAAK;AAAA,QACL,SAAQ;AAAA,QACR,QAAO;AAAA,QAEP,UAAA,gBAAA,EAAC,QAAD;AAAA,UACE,eAAc;AAAA,UACd,gBAAe;AAAA,UACf,aAAY;AAAA,UACZ,GAAE;AAAA,QACH,CAAA;AAAA,MACE,CAAA,CACA;AAAA,IACP,CAAA,GAAA,gBAAA,EAAC,MAAD;AAAA,MACE,UAAU;AAAA,MACV,WAAU;AAAA,MAFZ,UAAA,CAIE,gBAAA,EAAC,MAAD,EAAA,UACE,gBAAA,EAAC,KAAD;AAAA,QACE,WAAW,MAAa,OAAO,WAAW;AAAA,QAC1C,SAAA,MAAe,EAAY,IAAI;AAAA,QAChC,UAAA;AAAA,MAEE,CAAA,EACD,CAAA,GACJ,gBAAA,EAAC,MAAD,EAAA,UACE,gBAAA,EAAC,KAAD;AAAA,QACE,WAAW,MAAa,OAAO,WAAW;AAAA,QAC1C,SAAA,MAAe,EAAY,IAAI;AAAA,QAChC,UAAA;AAAA,MAEE,CAAA,EACD,CAAA,CACF;AAAA,IACD,CAAA,CAAA;AAAA;AAET"}