dishui 0.0.81 → 0.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/components/Accordion/index.js +6 -6
  2. package/dist/components/Accordion/index.js.map +1 -1
  3. package/dist/components/Button/index.d.ts +1 -0
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/ButtonMenu/index.d.ts +28 -0
  6. package/dist/components/ButtonMenu/index.js +197 -0
  7. package/dist/components/ButtonMenu/index.js.map +1 -0
  8. package/dist/components/Card/index.d.ts +7 -4
  9. package/dist/components/Card/index.js +98 -65
  10. package/dist/components/Card/index.js.map +1 -1
  11. package/dist/components/Demo/index.d.ts +5 -0
  12. package/dist/components/Demo/index.js +131 -56
  13. package/dist/components/Demo/index.js.map +1 -1
  14. package/dist/components/Demo/source.d.ts +9 -0
  15. package/dist/components/Demo/source.js +32 -0
  16. package/dist/components/Demo/source.js.map +1 -0
  17. package/dist/components/EmptyState/index.js +4 -4
  18. package/dist/components/EmptyState/index.js.map +1 -1
  19. package/dist/components/Field/index.d.ts +8 -0
  20. package/dist/components/Field/index.js +43 -0
  21. package/dist/components/Field/index.js.map +1 -0
  22. package/dist/components/LayoutSuite/DashboardSuite.d.ts +35 -0
  23. package/dist/components/LayoutSuite/DashboardSuite.js +61 -0
  24. package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -0
  25. package/dist/components/LayoutSuite/index.d.ts +56 -0
  26. package/dist/components/LayoutSuite/index.js +101 -0
  27. package/dist/components/LayoutSuite/index.js.map +1 -0
  28. package/dist/components/List/index.js +5 -5
  29. package/dist/components/List/index.js.map +1 -1
  30. package/dist/components/Modal/focusScope.d.ts +1 -0
  31. package/dist/components/Modal/focusScope.js +81 -0
  32. package/dist/components/Modal/focusScope.js.map +1 -0
  33. package/dist/components/Modal/index.d.ts +4 -1
  34. package/dist/components/Modal/index.js +53 -48
  35. package/dist/components/Modal/index.js.map +1 -1
  36. package/dist/components/Page/Float.d.ts +14 -0
  37. package/dist/components/Page/Float2.js +154 -0
  38. package/dist/components/Page/Float2.js.map +1 -0
  39. package/dist/components/Page/index.d.ts +18 -5
  40. package/dist/components/Page/index.js +103 -34
  41. package/dist/components/Page/index.js.map +1 -1
  42. package/dist/components/Page/resize.d.ts +28 -0
  43. package/dist/components/Page/resize2.js +95 -0
  44. package/dist/components/Page/resize2.js.map +1 -0
  45. package/dist/components/PageHeader/index.d.ts +10 -3
  46. package/dist/components/PageHeader/index.js +46 -25
  47. package/dist/components/PageHeader/index.js.map +1 -1
  48. package/dist/components/PagePanel/index.d.ts +29 -0
  49. package/dist/components/PagePanel/index.js +99 -0
  50. package/dist/components/PagePanel/index.js.map +1 -0
  51. package/dist/components/Resizable/ResizeGrip.d.ts +5 -0
  52. package/dist/components/Resizable/ResizeGrip.js +14 -0
  53. package/dist/components/Resizable/ResizeGrip.js.map +1 -0
  54. package/dist/components/Resizable/index.js +57 -59
  55. package/dist/components/Resizable/index.js.map +1 -1
  56. package/dist/components/Resizable/useResize.d.ts +6 -0
  57. package/dist/components/Resizable/useResize.js +29 -28
  58. package/dist/components/Resizable/useResize.js.map +1 -1
  59. package/dist/components/SidebarToggleButton/index.d.ts +5 -3
  60. package/dist/components/SidebarToggleButton/index.js +24 -21
  61. package/dist/components/SidebarToggleButton/index.js.map +1 -1
  62. package/dist/components/Table/index.d.ts +10 -12
  63. package/dist/components/Table/index.js +25 -20
  64. package/dist/components/Table/index.js.map +1 -1
  65. package/dist/components/Text/index.d.ts +1 -1
  66. package/dist/components/Text/index.js +11 -10
  67. package/dist/components/Text/index.js.map +1 -1
  68. package/dist/components/Textarea/index.d.ts +14 -0
  69. package/dist/components/Textarea/index.js +44 -0
  70. package/dist/components/Textarea/index.js.map +1 -0
  71. package/dist/components/Tree/Tree.d.ts +2 -0
  72. package/dist/components/Tree/Tree.js +49 -40
  73. package/dist/components/Tree/Tree.js.map +1 -1
  74. package/dist/dishui.css +1 -1
  75. package/dist/index-nostyled.d.ts +9 -0
  76. package/dist/index.d.ts +11 -2
  77. package/dist/index.js +119 -113
  78. package/dist/layouts/Sidebar.d.ts +12 -1
  79. package/dist/layouts/Sidebar.js +121 -97
  80. package/dist/layouts/Sidebar.js.map +1 -1
  81. package/dist/lite.d.ts +10 -2
  82. package/dist/lite.js +17 -12
  83. package/dist/styles/themeStyles.js +6 -6
  84. package/dist/styles/themeStyles.js.map +1 -1
  85. package/dist/utils/menu.js +14 -16
  86. package/dist/utils/menu.js.map +1 -1
  87. package/package.json +3 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Textarea/index.tsx"],"sourcesContent":["import React, { forwardRef, useId } from 'react';\nimport './Textarea.css';\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n label?: React.ReactNode;\n description?: React.ReactNode;\n error?: React.ReactNode;\n wrapperClassName?: string;\n};\n\nconst hasContent = (node: React.ReactNode) => node !== undefined && node !== null && typeof node !== 'boolean' && node !== '';\n\nconst Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(function Textarea({\n label,\n description,\n error,\n wrapperClassName = '',\n className = '',\n id,\n 'aria-describedby': describedBy,\n 'aria-invalid': invalid,\n ...attributes\n}, ref) {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n const descriptionId = `${generatedId}-description`;\n const errorId = `${generatedId}-error`;\n const showDescription = hasContent(description);\n const showError = hasContent(error);\n const descriptionIds = [describedBy, showDescription ? descriptionId : undefined, showError ? errorId : undefined].filter(Boolean).join(' ') || undefined;\n\n return (\n <div className={`w-full space-y-2 ${wrapperClassName}`.trim()}>\n {hasContent(label) && <label htmlFor={fieldId} className=\"block text-sm font-medium\">{label}</label>}\n <textarea\n {...attributes}\n ref={ref}\n id={fieldId}\n aria-describedby={descriptionIds}\n aria-invalid={showError ? true : invalid}\n className={`textarea dishui-textarea w-full resize-y rounded-md border-strong bg-page p-3 text-sm text-primary placeholder:text-tertiary ${className}`.trim()}\n />\n {showDescription && <div id={descriptionId} className=\"text-xs leading-5 text-secondary\">{description}</div>}\n {showError && <div id={errorId} role=\"alert\" className=\"text-xs leading-5 text-error\">{error}</div>}\n </div>\n );\n});\n\nexport default Textarea;\n"],"mappings":";;;;AAUA,IAAM,KAAc,MAA0B,KAA+B,QAAQ,OAAO,KAAS,aAAa,MAAS,IAErH,IAAW,EAA+C,SAAkB,EAC9E,UACA,gBACA,UACA,sBAAmB,IACnB,eAAY,IACZ,OACA,oBAAoB,GACpB,gBAAgB,GAChB,GAAG,KACJ,GAAK;CACJ,IAAM,IAAc,EAAM,GACpB,IAAU,KAAM,GAChB,IAAgB,GAAG,EAAY,eAC/B,IAAU,GAAG,EAAY,SACzB,IAAkB,EAAW,CAAW,GACxC,IAAY,EAAW,CAAK,GAC5B,IAAiB;EAAC;EAAa,IAAkB,IAAgB,KAAA;EAAW,IAAY,IAAU,KAAA;CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA;CAEhJ,OACI,kBAAC,OAAD;EAAK,WAAW,oBAAoB,IAAmB,KAAK;EAA5D,UAAA;GACK,EAAW,CAAK,KAAK,kBAAC,SAAD;IAAO,SAAS;IAAS,WAAU;IAA6B,UAAA;GAAa,CAAA;GACnG,kBAAC,YAAD;IACI,GAAI;IACC;IACL,IAAI;IACJ,oBAAkB;IAClB,gBAAc,IAAY,KAAO;IACjC,WAAW,gIAAgI,IAAY,KAAK;GAC/J,CAAA;GACA,KAAmB,kBAAC,OAAD;IAAK,IAAI;IAAe,WAAU;IAAoC,UAAA;GAAiB,CAAA;GAC1G,KAAa,kBAAC,OAAD;IAAK,IAAI;IAAS,MAAK;IAAQ,WAAU;IAAgC,UAAA;GAAW,CAAA;EACjG;;AAEb,CAAC"}
@@ -62,6 +62,8 @@ export interface TreeProps {
62
62
  draggable?: boolean;
63
63
  /** 是否可选择(暂不实现) */
64
64
  checkable?: boolean;
65
+ /** Custom label content; depth is zero-based. The string label remains the search text and native title. */
66
+ renderLabel?: (node: TreeNode, depth: number) => React.ReactNode;
65
67
  /** 自定义渲染节点 */
66
68
  renderNode?: (node: TreeNode, defaultRender: React.ReactNode) => React.ReactNode;
67
69
  }
@@ -2,15 +2,15 @@ import { generateTreeActiveStyles as e } from "../../styles/themeStyles.js";
2
2
  import t, { useCallback as n, useMemo as r, useState as i } from "react";
3
3
  import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
4
4
  //#region src/components/Tree/Tree.tsx
5
- var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activeNodeId: f, defaultExpandedIds: p = [], showSearch: m = !0, searchPlaceholder: h = "Search...", showExpandAll: g = !0, expandAllText: _ = "Expand All", collapseAllText: v = "Collapse All", showIcon: y = !0, defaultIcon: b, expandIcon: x, collapseIcon: S, showLine: C = !1, maxHeight: w = "600px", className: T = "", title: E, titleIcon: D, showCount: O = !0, emptyText: k = "No data", noResultsText: A = "No results found", indent: j = 16, togglePosition: M = "left", renderNode: N }) => {
6
- let [P, F] = i(""), [I, L] = i(new Set(p));
5
+ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activeNodeId: f, defaultExpandedIds: p = [], showSearch: m = !0, searchPlaceholder: h = "Search...", showExpandAll: g = !0, expandAllText: _ = "Expand All", collapseAllText: v = "Collapse All", showIcon: y = !0, defaultIcon: b, expandIcon: x, collapseIcon: S, showLine: C = !1, maxHeight: w = "600px", className: T = "", title: E, titleIcon: D, showCount: O = !0, emptyText: k = "No data", noResultsText: A = "No results found", indent: j = 16, togglePosition: M = "left", renderLabel: N, renderNode: P }) => {
6
+ let [F, I] = i(""), [L, R] = i(new Set(p));
7
7
  t.useEffect(() => {
8
- p.length > 0 && L((e) => {
8
+ p.length > 0 && R((e) => {
9
9
  let t = new Set(e);
10
10
  return p.forEach((e) => t.add(e)), t;
11
11
  });
12
12
  }, [p]);
13
- let R = x || /* @__PURE__ */ o("svg", {
13
+ let z = x || /* @__PURE__ */ o("svg", {
14
14
  className: "w-3 h-3",
15
15
  fill: "none",
16
16
  viewBox: "0 0 24 24",
@@ -21,7 +21,7 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
21
21
  strokeWidth: 2,
22
22
  d: "M19 9l-7 7-7-7"
23
23
  })
24
- }), z = S || /* @__PURE__ */ o("svg", {
24
+ }), B = S || /* @__PURE__ */ o("svg", {
25
25
  className: "w-3 h-3",
26
26
  fill: "none",
27
27
  viewBox: "0 0 24 24",
@@ -32,7 +32,7 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
32
32
  strokeWidth: 2,
33
33
  d: "M9 5l7 7-7 7"
34
34
  })
35
- }), B = b || /* @__PURE__ */ o("svg", {
35
+ }), V = b || /* @__PURE__ */ o("svg", {
36
36
  className: "w-4 h-4",
37
37
  fill: "none",
38
38
  viewBox: "0 0 24 24",
@@ -43,36 +43,38 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
43
43
  strokeWidth: 2,
44
44
  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"
45
45
  })
46
- }), V = n((e) => e.reduce((e, t) => e + 1 + (t.children ? V(t.children) : 0), 0), []), H = r(() => V(c), [c, V]), U = n((e, t) => {
46
+ }), H = n((e) => e.reduce((e, t) => e + 1 + (t.children ? H(t.children) : 0), 0), []), U = r(() => H(c), [c, H]), W = n((e, t) => {
47
47
  if (!t) return e;
48
48
  let n = t.toLowerCase(), r = [];
49
49
  for (let i of e) {
50
- let e = i.label.toLowerCase().includes(n), a = i.children ? U(i.children, t) : [];
50
+ let e = i.label.toLowerCase().includes(n), a = i.children ? W(i.children, t) : [];
51
51
  (e || a.length > 0) && r.push({
52
52
  ...i,
53
53
  children: a.length > 0 ? a : i.children
54
54
  });
55
55
  }
56
56
  return r;
57
- }, []), W = r(() => U(c, P), [
57
+ }, []), G = r(() => W(c, F), [
58
58
  c,
59
- P,
60
- U
61
- ]), G = n((e) => {
62
- let t = new Set(I);
63
- t.has(e) ? (t.delete(e), d?.(e, !1)) : (t.add(e), d?.(e, !0)), L(t);
64
- }, [I, d]), K = n(() => {
59
+ F,
60
+ W
61
+ ]), K = n((e) => {
62
+ let t = new Set(L);
63
+ t.has(e) ? (t.delete(e), d?.(e, !1)) : (t.add(e), d?.(e, !0)), R(t);
64
+ }, [L, d]), q = n(() => {
65
65
  let e = /* @__PURE__ */ new Set(), t = (n) => {
66
66
  n.forEach((n) => {
67
67
  n.children && n.children.length > 0 && (e.add(n.id), t(n.children));
68
68
  });
69
69
  };
70
- t(c), L(e);
71
- }, [c]), q = n(() => {
72
- L(/* @__PURE__ */ new Set());
73
- }, []), J = n((e, t = 0, n = []) => {
74
- let r = e.children && e.children.length > 0, i = I.has(e.id), c = f === e.id, d = [...n, e.id], p = /* @__PURE__ */ s("div", {
70
+ t(c), R(e);
71
+ }, [c]), J = n(() => {
72
+ R(/* @__PURE__ */ new Set());
73
+ }, []), Y = n((e, t = 0, n = []) => {
74
+ let r = e.children && e.children.length > 0, i = L.has(e.id), c = f === e.id, d = [...n, e.id], p = /* @__PURE__ */ s("div", {
75
75
  "data-node-id": e.id,
76
+ "data-depth": t,
77
+ "data-level": t + 1,
76
78
  className: `tree-node ${c ? "tree-node-active" : ""} ${e.disabled ? "tree-node-disabled" : ""}`,
77
79
  style: { paddingLeft: `${t * j}px` },
78
80
  children: [/* @__PURE__ */ s("div", {
@@ -85,12 +87,15 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
85
87
  },
86
88
  children: [
87
89
  M === "left" && /* @__PURE__ */ o(a, { children: r ? /* @__PURE__ */ o("button", {
90
+ type: "button",
91
+ "aria-label": `${i ? "Collapse" : "Expand"} ${e.label}`,
92
+ "aria-expanded": i,
88
93
  className: `tree-node-toggle btn btn-xs btn-ghost btn-circle ${i ? "tree-node-toggle-expanded" : ""}`,
89
94
  onClick: (t) => {
90
- t.stopPropagation(), e.disabled || G(e.id);
95
+ t.stopPropagation(), e.disabled || K(e.id);
91
96
  },
92
97
  disabled: e.disabled,
93
- children: i ? R : z
98
+ children: i ? z : B
94
99
  }) : /* @__PURE__ */ o("span", {
95
100
  className: "tree-node-toggle-placeholder",
96
101
  style: {
@@ -101,12 +106,12 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
101
106
  }) }),
102
107
  y && /* @__PURE__ */ o("span", {
103
108
  className: "tree-node-icon",
104
- children: e.icon || B
109
+ children: e.icon || V
105
110
  }),
106
111
  /* @__PURE__ */ o("span", {
107
112
  className: "tree-node-label text-sm truncate flex-1",
108
113
  title: e.label,
109
- children: e.label
114
+ children: N ? N(e, t) : e.label
110
115
  }),
111
116
  e.meta?.count !== void 0 && e.meta?.count !== null ? /* @__PURE__ */ o("span", {
112
117
  className: "tree-node-count text-xs opacity-60",
@@ -120,34 +125,38 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
120
125
  ]
121
126
  }) : null,
122
127
  M === "right" && r && /* @__PURE__ */ o("button", {
128
+ type: "button",
129
+ "aria-label": `${i ? "Collapse" : "Expand"} ${e.label}`,
130
+ "aria-expanded": i,
123
131
  className: `tree-node-toggle tree-node-toggle-right btn btn-xs btn-ghost ${i ? "tree-node-toggle-expanded" : ""}`,
124
132
  onClick: (t) => {
125
- t.stopPropagation(), e.disabled || G(e.id);
133
+ t.stopPropagation(), e.disabled || K(e.id);
126
134
  },
127
135
  disabled: e.disabled,
128
- children: i ? R : z
136
+ children: i ? z : B
129
137
  })
130
138
  ]
131
139
  }), r && /* @__PURE__ */ o("div", {
132
140
  className: `tree-node-children ${i ? "tree-node-children-expanded" : "tree-node-children-collapsed"}`,
133
- children: e.children.map((e) => J(e, t + 1, d))
141
+ children: e.children.map((e) => Y(e, t + 1, d))
134
142
  })]
135
143
  }, e.id);
136
- return N ? N(e, p) : p;
144
+ return P ? P(e, p) : p;
137
145
  }, [
138
- I,
146
+ L,
139
147
  f,
140
148
  j,
141
149
  y,
142
150
  O,
143
151
  M,
144
- R,
145
152
  z,
146
153
  B,
154
+ V,
147
155
  l,
148
156
  u,
149
- G,
150
- N
157
+ K,
158
+ N,
159
+ P
151
160
  ]);
152
161
  return /* @__PURE__ */ s("div", {
153
162
  className: `tree-component bg-base-100 border border-base-300 rounded-lg p-2 ${T}`,
@@ -164,7 +173,7 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
164
173
  className: "text-xs opacity-60 ml-auto",
165
174
  children: [
166
175
  "(",
167
- H,
176
+ U,
168
177
  ")"
169
178
  ]
170
179
  })
@@ -173,31 +182,31 @@ var c = ({ data: c, onNodeClick: l, onNodeDoubleClick: u, onNodeToggle: d, activ
173
182
  m && /* @__PURE__ */ o("input", {
174
183
  type: "text",
175
184
  placeholder: h,
176
- value: P,
177
- onChange: (e) => F(e.target.value),
185
+ value: F,
186
+ onChange: (e) => I(e.target.value),
178
187
  className: "tree-search input input-sm input-bordered w-full mb-2"
179
188
  }),
180
189
  g && /* @__PURE__ */ s("div", {
181
190
  className: "tree-actions flex gap-1 mb-2",
182
191
  children: [/* @__PURE__ */ o("button", {
183
192
  className: "btn btn-xs btn-ghost",
184
- onClick: K,
193
+ onClick: q,
185
194
  children: _
186
195
  }), /* @__PURE__ */ o("button", {
187
196
  className: "btn btn-xs btn-ghost",
188
- onClick: q,
197
+ onClick: J,
189
198
  children: v
190
199
  })]
191
200
  }),
192
201
  /* @__PURE__ */ o("div", {
193
202
  className: "tree-content overflow-y-auto",
194
203
  style: { maxHeight: w },
195
- children: W.length === 0 ? /* @__PURE__ */ o("div", {
204
+ children: G.length === 0 ? /* @__PURE__ */ o("div", {
196
205
  className: "tree-empty text-center text-sm opacity-60 py-4",
197
- children: P ? A : k
206
+ children: F ? A : k
198
207
  }) : /* @__PURE__ */ o("div", {
199
208
  className: `tree-nodes ${C ? "tree-show-line" : ""}`,
200
- children: W.map((e) => J(e))
209
+ children: G.map((e) => Y(e))
201
210
  })
202
211
  }),
203
212
  /* @__PURE__ */ o("style", { children: `
@@ -1 +1 @@
1
- {"version":3,"file":"Tree.js","names":[],"sources":["../../../src/components/Tree/Tree.tsx"],"sourcesContent":["import React, { useState, useCallback, useMemo } from 'react';\nimport { generateTreeActiveStyles } from '../../styles/themeStyles';\n\n// ============= 类型定义 =============\n\nexport interface TreeNode {\n id: string | number;\n label: string;\n children?: TreeNode[];\n icon?: React.ReactNode;\n disabled?: boolean;\n meta?: Record<string, any>;\n}\n\nexport interface TreeProps {\n /** 树形数据 */\n data: TreeNode[];\n\n /** 节点点击回调 */\n onNodeClick?: (node: TreeNode, path: (string | number)[]) => void;\n\n /** 节点双击回调 */\n onNodeDoubleClick?: (node: TreeNode, path: (string | number)[]) => void;\n\n /** 节点展开/折叠回调 */\n onNodeToggle?: (nodeId: string | number, expanded: boolean) => void;\n\n /** 当前激活的节点 ID */\n activeNodeId?: string | number;\n\n /** 默认展开的节点 ID 列表 */\n defaultExpandedIds?: (string | number)[];\n\n /** 是否显示搜索框 */\n showSearch?: boolean;\n\n /** 搜索占位符 */\n searchPlaceholder?: string;\n\n /** 是否显示展开/折叠全部按钮 */\n showExpandAll?: boolean;\n\n /** 展开全部按钮文本 */\n expandAllText?: string;\n\n /** 折叠全部按钮文本 */\n collapseAllText?: string;\n\n /** 是否显示节点图标 */\n showIcon?: boolean;\n\n /** 默认图标 */\n defaultIcon?: React.ReactNode;\n\n /** 展开图标 */\n expandIcon?: React.ReactNode;\n\n /** 折叠图标 */\n collapseIcon?: React.ReactNode;\n\n /** 是否显示连接线 */\n showLine?: boolean;\n\n /** 最大高度 */\n maxHeight?: string;\n\n /** 自定义类名 */\n className?: string;\n\n /** 标题 */\n title?: string;\n\n /** 标题图标 */\n titleIcon?: React.ReactNode;\n\n /** 是否显示节点数量 */\n showCount?: boolean;\n\n /** 空状态文本 */\n emptyText?: string;\n\n /** 搜索无结果文本 */\n noResultsText?: string;\n\n /** 缩进宽度(像素) */\n indent?: number;\n\n /** 展开按钮位置:left(左侧)或 right(右侧) */\n togglePosition?: 'left' | 'right';\n\n /** 是否可拖拽(暂不实现) */\n draggable?: boolean;\n\n /** 是否可选择(暂不实现) */\n checkable?: boolean;\n\n /** 自定义渲染节点 */\n renderNode?: (node: TreeNode, defaultRender: React.ReactNode) => React.ReactNode;\n}\n\n// ============= Tree 组件 =============\n\nconst Tree: React.FC<TreeProps> = ({\n data,\n onNodeClick,\n onNodeDoubleClick,\n onNodeToggle,\n activeNodeId,\n defaultExpandedIds = [],\n showSearch = true,\n searchPlaceholder = 'Search...',\n showExpandAll = true,\n expandAllText = 'Expand All',\n collapseAllText = 'Collapse All',\n showIcon = true,\n defaultIcon,\n expandIcon,\n collapseIcon,\n showLine = false,\n maxHeight = '600px',\n className = '',\n title,\n titleIcon,\n showCount = true,\n emptyText = 'No data',\n noResultsText = 'No results found',\n indent = 16,\n togglePosition = 'left',\n renderNode,\n}) => {\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedIds, setExpandedIds] = useState<Set<string | number>>(\n new Set(defaultExpandedIds)\n );\n\n // 当 defaultExpandedIds 变化时,同步更新 expandedIds(用于异步加载的数据)\n React.useEffect(() => {\n if (defaultExpandedIds.length > 0) {\n setExpandedIds(prev => {\n const newSet = new Set(prev);\n defaultExpandedIds.forEach(id => newSet.add(id));\n return newSet;\n });\n }\n }, [defaultExpandedIds]);\n\n // 默认展开/折叠图标\n const defaultExpandIconEl = expandIcon || (\n <svg className=\"w-3 h-3\" 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 );\n\n const defaultCollapseIconEl = collapseIcon || (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n );\n\n // 默认节点图标\n const defaultIconEl = defaultIcon || (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n 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 />\n </svg>\n );\n\n // 统计节点总数\n const countNodes = useCallback((nodes: TreeNode[]): number => {\n return nodes.reduce((count, node) => {\n return count + 1 + (node.children ? countNodes(node.children) : 0);\n }, 0);\n }, []);\n\n const totalCount = useMemo(() => countNodes(data), [data, countNodes]);\n\n // 过滤节点(支持搜索)\n const filterNodes = useCallback((nodes: TreeNode[], query: string): TreeNode[] => {\n if (!query) return nodes;\n\n const lowerQuery = query.toLowerCase();\n const filtered: TreeNode[] = [];\n\n for (const node of nodes) {\n const matches = node.label.toLowerCase().includes(lowerQuery);\n const filteredChildren = node.children ? filterNodes(node.children, query) : [];\n\n if (matches || filteredChildren.length > 0) {\n filtered.push({\n ...node,\n children: filteredChildren.length > 0 ? filteredChildren : node.children,\n });\n }\n }\n\n return filtered;\n }, []);\n\n const filteredData = useMemo(\n () => filterNodes(data, searchQuery),\n [data, searchQuery, filterNodes]\n );\n\n // 切换节点展开/折叠\n const toggleNode = useCallback(\n (nodeId: string | number) => {\n const newExpanded = new Set(expandedIds);\n if (newExpanded.has(nodeId)) {\n newExpanded.delete(nodeId);\n onNodeToggle?.(nodeId, false);\n } else {\n newExpanded.add(nodeId);\n onNodeToggle?.(nodeId, true);\n }\n setExpandedIds(newExpanded);\n },\n [expandedIds, onNodeToggle]\n );\n\n // 展开所有节点\n const expandAll = useCallback(() => {\n const allIds = new Set<string | number>();\n const collectIds = (nodes: TreeNode[]) => {\n nodes.forEach((node) => {\n if (node.children && node.children.length > 0) {\n allIds.add(node.id);\n collectIds(node.children);\n }\n });\n };\n collectIds(data);\n setExpandedIds(allIds);\n }, [data]);\n\n // 折叠所有节点\n const collapseAll = useCallback(() => {\n setExpandedIds(new Set());\n }, []);\n\n // 渲染单个节点\n const renderTreeNode = useCallback(\n (node: TreeNode, depth: number = 0, path: (string | number)[] = []) => {\n const hasChildren = node.children && node.children.length > 0;\n const isExpanded = expandedIds.has(node.id);\n const isActive = activeNodeId === node.id;\n const currentPath = [...path, node.id];\n\n const nodeContent = (\n <div\n key={node.id}\n data-node-id={node.id}\n className={`tree-node ${isActive ? 'tree-node-active' : ''} ${node.disabled ? 'tree-node-disabled' : ''\n }`}\n style={{\n paddingLeft: `${depth * indent}px`,\n }}\n >\n <div\n className={`tree-node-content flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors ${isActive ? 'tree-node-content-active' : 'tree-node-content-inactive'\n } ${node.disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n onClick={() => {\n if (!node.disabled) {\n onNodeClick?.(node, currentPath);\n }\n }}\n onDoubleClick={() => {\n if (!node.disabled) {\n onNodeDoubleClick?.(node, currentPath);\n }\n }}\n >\n {/* 左侧展开按钮 */}\n {togglePosition === 'left' && (\n <>\n {hasChildren ? (\n <button\n className={`tree-node-toggle btn btn-xs btn-ghost btn-circle ${isExpanded ? 'tree-node-toggle-expanded' : ''\n }`}\n onClick={(e) => {\n e.stopPropagation();\n if (!node.disabled) {\n toggleNode(node.id);\n }\n }}\n disabled={node.disabled}\n >\n {isExpanded ? defaultExpandIconEl : defaultCollapseIconEl}\n </button>\n ) : (\n <span className=\"tree-node-toggle-placeholder\" style={{ width: '1.5rem', height: '1.5rem', flexShrink: 0 }}></span>\n )}\n </>\n )}\n\n {/* 节点图标 */}\n {showIcon && (\n <span className=\"tree-node-icon\">{node.icon || defaultIconEl}</span>\n )}\n\n {/* 节点标签 */}\n <span className=\"tree-node-label text-sm truncate flex-1\" title={node.label}>\n {node.label}\n </span>\n\n {/* 子节点数量(优先使用 meta.count,否则回退到子节点个数) */}\n {node.meta?.count !== undefined && node.meta?.count !== null ? (\n <span className=\"tree-node-count text-xs opacity-60\">\n {node.meta.count}\n </span>\n ) : hasChildren && showCount ? (\n <span className=\"tree-node-count text-xs opacity-60\">\n ({node.children!.length})\n </span>\n ) : null}\n\n {/* 右侧展开按钮 */}\n {togglePosition === 'right' && hasChildren && (\n <button\n className={`tree-node-toggle tree-node-toggle-right btn btn-xs btn-ghost ${isExpanded ? 'tree-node-toggle-expanded' : ''\n }`}\n onClick={(e) => {\n e.stopPropagation();\n if (!node.disabled) {\n toggleNode(node.id);\n }\n }}\n disabled={node.disabled}\n >\n {isExpanded ? defaultExpandIconEl : defaultCollapseIconEl}\n </button>\n )}\n </div>\n\n {/* 子节点 */}\n {hasChildren && (\n <div\n className={`tree-node-children ${isExpanded ? 'tree-node-children-expanded' : 'tree-node-children-collapsed'}`}\n >\n {node.children!.map((child) => renderTreeNode(child, depth + 1, currentPath))}\n </div>\n )}\n </div>\n );\n\n // 自定义渲染\n if (renderNode) {\n return renderNode(node, nodeContent);\n }\n\n return nodeContent;\n },\n [\n expandedIds,\n activeNodeId,\n indent,\n showIcon,\n showCount,\n togglePosition,\n defaultExpandIconEl,\n defaultCollapseIconEl,\n defaultIconEl,\n onNodeClick,\n onNodeDoubleClick,\n toggleNode,\n renderNode,\n ]\n );\n\n return (\n <div className={`tree-component bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n {title && (\n <div className=\"tree-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n {titleIcon}\n <span className=\"font-semibold\">{title}</span>\n {showCount && (\n <span className=\"text-xs opacity-60 ml-auto\">({totalCount})</span>\n )}\n </div>\n )}\n\n {/* 搜索框 */}\n {showSearch && (\n <input\n type=\"text\"\n placeholder={searchPlaceholder}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"tree-search input input-sm input-bordered w-full mb-2\"\n />\n )}\n\n {/* 操作按钮 */}\n {showExpandAll && (\n <div className=\"tree-actions flex gap-1 mb-2\">\n <button className=\"btn btn-xs btn-ghost\" onClick={expandAll}>\n {expandAllText}\n </button>\n <button className=\"btn btn-xs btn-ghost\" onClick={collapseAll}>\n {collapseAllText}\n </button>\n </div>\n )}\n\n {/* 树形列表 */}\n <div\n className=\"tree-content overflow-y-auto\"\n style={{ maxHeight }}\n >\n {filteredData.length === 0 ? (\n <div className=\"tree-empty text-center text-sm opacity-60 py-4\">\n {searchQuery ? noResultsText : emptyText}\n </div>\n ) : (\n <div className={`tree-nodes ${showLine ? 'tree-show-line' : ''}`}>\n {filteredData.map((node) => renderTreeNode(node))}\n </div>\n )}\n </div>\n\n <style>{`\n .tree-node {\n user-select: none;\n }\n \n /* 子节点容器基础样式 */\n .tree-node-children {\n margin-top: 2px;\n overflow: hidden;\n transform-origin: top;\n box-sizing: border-box;\n }\n \n /* 折叠状态 - 初始隐藏 */\n .tree-node-children-collapsed {\n max-height: 0;\n opacity: 0;\n transform: scaleY(0.8);\n border-left: none !important;\n }\n \n /* 展开状态 - 显示内容 */\n .tree-node-children-expanded {\n max-height: 5000px;\n opacity: 1;\n transform: scaleY(1);\n transition: \n max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1),\n transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n /* 不对 border 做动画 */\n box-sizing: border-box;\n }\n \n /* 连接线样式 - 在展开状态显示,使用多重选择器提高优先级 */\n .tree-component .tree-show-line .tree-node-children-expanded,\n .tree-show-line .tree-node-children.tree-node-children-expanded {\n border-left: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2)) !important;\n margin-left: 8px !important;\n padding-left: 8px !important;\n position: relative;\n }\n \n /* 左侧连接线圆点装饰 */\n .tree-show-line .tree-node-children-expanded::before {\n content: '';\n position: absolute;\n left: -3px;\n top: 0;\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background-color: var(--fallback-bc, oklch(var(--bc) / 0.3));\n }\n \n /* 折叠过渡 */\n .tree-node-children-collapsed {\n transition: \n max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1),\n transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n /* 展开/折叠按钮图标旋转动画 */\n .tree-node-toggle {\n z-index: 2;\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n .tree-node-toggle svg {\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n /* 折叠状态的图标 - 向右 */\n .tree-node-toggle:not(.tree-node-toggle-expanded) svg {\n transform: rotate(0deg);\n }\n \n /* 展开状态的图标 - 向下(已经是向下的,所以不需要额外旋转) */\n .tree-node-toggle-expanded svg {\n transform: rotate(0deg);\n }\n \n .tree-component {\n position: relative;\n z-index: 1;\n }\n \n .tree-node-disabled {\n cursor: not-allowed;\n }\n \n .tree-node-disabled .tree-node-content {\n pointer-events: none;\n }\n \n /* 节点内容悬停效果 */\n .tree-node-content {\n transition: background-color 0.15s ease;\n }\n \n /* 优化性能 - 告诉浏览器这些属性会变化 */\n .tree-node-children {\n will-change: max-height, opacity, transform;\n }\n \n /* 动画完成后移除 will-change 以节省资源 */\n .tree-node-children-expanded,\n .tree-node-children-collapsed {\n animation: remove-will-change 0.3s forwards;\n }\n \n @keyframes remove-will-change {\n to {\n will-change: auto;\n }\n }\n \n /* 活跃节点基础样式 */\n .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(0.5rem - 4px) !important;\n border-radius: 0.375rem !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateTreeActiveStyles()}\n \n /* 非活跃节点的悬停状态 */\n .tree-node-content-inactive:hover {\n background-color: oklch(var(--b2));\n }\n `}</style>\n </div>\n );\n};\n\nexport default Tree;\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tree.js","names":[],"sources":["../../../src/components/Tree/Tree.tsx"],"sourcesContent":["import React, { useState, useCallback, useMemo } from 'react';\nimport { generateTreeActiveStyles } from '../../styles/themeStyles';\n\n// ============= 类型定义 =============\n\nexport interface TreeNode {\n id: string | number;\n label: string;\n children?: TreeNode[];\n icon?: React.ReactNode;\n disabled?: boolean;\n meta?: Record<string, any>;\n}\n\nexport interface TreeProps {\n /** 树形数据 */\n data: TreeNode[];\n\n /** 节点点击回调 */\n onNodeClick?: (node: TreeNode, path: (string | number)[]) => void;\n\n /** 节点双击回调 */\n onNodeDoubleClick?: (node: TreeNode, path: (string | number)[]) => void;\n\n /** 节点展开/折叠回调 */\n onNodeToggle?: (nodeId: string | number, expanded: boolean) => void;\n\n /** 当前激活的节点 ID */\n activeNodeId?: string | number;\n\n /** 默认展开的节点 ID 列表 */\n defaultExpandedIds?: (string | number)[];\n\n /** 是否显示搜索框 */\n showSearch?: boolean;\n\n /** 搜索占位符 */\n searchPlaceholder?: string;\n\n /** 是否显示展开/折叠全部按钮 */\n showExpandAll?: boolean;\n\n /** 展开全部按钮文本 */\n expandAllText?: string;\n\n /** 折叠全部按钮文本 */\n collapseAllText?: string;\n\n /** 是否显示节点图标 */\n showIcon?: boolean;\n\n /** 默认图标 */\n defaultIcon?: React.ReactNode;\n\n /** 展开图标 */\n expandIcon?: React.ReactNode;\n\n /** 折叠图标 */\n collapseIcon?: React.ReactNode;\n\n /** 是否显示连接线 */\n showLine?: boolean;\n\n /** 最大高度 */\n maxHeight?: string;\n\n /** 自定义类名 */\n className?: string;\n\n /** 标题 */\n title?: string;\n\n /** 标题图标 */\n titleIcon?: React.ReactNode;\n\n /** 是否显示节点数量 */\n showCount?: boolean;\n\n /** 空状态文本 */\n emptyText?: string;\n\n /** 搜索无结果文本 */\n noResultsText?: string;\n\n /** 缩进宽度(像素) */\n indent?: number;\n\n /** 展开按钮位置:left(左侧)或 right(右侧) */\n togglePosition?: 'left' | 'right';\n\n /** 是否可拖拽(暂不实现) */\n draggable?: boolean;\n\n /** 是否可选择(暂不实现) */\n checkable?: boolean;\n\n /** Custom label content; depth is zero-based. The string label remains the search text and native title. */\n renderLabel?: (node: TreeNode, depth: number) => React.ReactNode;\n\n /** 自定义渲染节点 */\n renderNode?: (node: TreeNode, defaultRender: React.ReactNode) => React.ReactNode;\n}\n\n// ============= Tree 组件 =============\n\nconst Tree: React.FC<TreeProps> = ({\n data,\n onNodeClick,\n onNodeDoubleClick,\n onNodeToggle,\n activeNodeId,\n defaultExpandedIds = [],\n showSearch = true,\n searchPlaceholder = 'Search...',\n showExpandAll = true,\n expandAllText = 'Expand All',\n collapseAllText = 'Collapse All',\n showIcon = true,\n defaultIcon,\n expandIcon,\n collapseIcon,\n showLine = false,\n maxHeight = '600px',\n className = '',\n title,\n titleIcon,\n showCount = true,\n emptyText = 'No data',\n noResultsText = 'No results found',\n indent = 16,\n togglePosition = 'left',\n renderLabel,\n renderNode,\n}) => {\n const [searchQuery, setSearchQuery] = useState('');\n const [expandedIds, setExpandedIds] = useState<Set<string | number>>(\n new Set(defaultExpandedIds)\n );\n\n // 当 defaultExpandedIds 变化时,同步更新 expandedIds(用于异步加载的数据)\n React.useEffect(() => {\n if (defaultExpandedIds.length > 0) {\n setExpandedIds(prev => {\n const newSet = new Set(prev);\n defaultExpandedIds.forEach(id => newSet.add(id));\n return newSet;\n });\n }\n }, [defaultExpandedIds]);\n\n // 默认展开/折叠图标\n const defaultExpandIconEl = expandIcon || (\n <svg className=\"w-3 h-3\" 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 );\n\n const defaultCollapseIconEl = collapseIcon || (\n <svg className=\"w-3 h-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n );\n\n // 默认节点图标\n const defaultIconEl = defaultIcon || (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n 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 />\n </svg>\n );\n\n // 统计节点总数\n const countNodes = useCallback((nodes: TreeNode[]): number => {\n return nodes.reduce((count, node) => {\n return count + 1 + (node.children ? countNodes(node.children) : 0);\n }, 0);\n }, []);\n\n const totalCount = useMemo(() => countNodes(data), [data, countNodes]);\n\n // 过滤节点(支持搜索)\n const filterNodes = useCallback((nodes: TreeNode[], query: string): TreeNode[] => {\n if (!query) return nodes;\n\n const lowerQuery = query.toLowerCase();\n const filtered: TreeNode[] = [];\n\n for (const node of nodes) {\n const matches = node.label.toLowerCase().includes(lowerQuery);\n const filteredChildren = node.children ? filterNodes(node.children, query) : [];\n\n if (matches || filteredChildren.length > 0) {\n filtered.push({\n ...node,\n children: filteredChildren.length > 0 ? filteredChildren : node.children,\n });\n }\n }\n\n return filtered;\n }, []);\n\n const filteredData = useMemo(\n () => filterNodes(data, searchQuery),\n [data, searchQuery, filterNodes]\n );\n\n // 切换节点展开/折叠\n const toggleNode = useCallback(\n (nodeId: string | number) => {\n const newExpanded = new Set(expandedIds);\n if (newExpanded.has(nodeId)) {\n newExpanded.delete(nodeId);\n onNodeToggle?.(nodeId, false);\n } else {\n newExpanded.add(nodeId);\n onNodeToggle?.(nodeId, true);\n }\n setExpandedIds(newExpanded);\n },\n [expandedIds, onNodeToggle]\n );\n\n // 展开所有节点\n const expandAll = useCallback(() => {\n const allIds = new Set<string | number>();\n const collectIds = (nodes: TreeNode[]) => {\n nodes.forEach((node) => {\n if (node.children && node.children.length > 0) {\n allIds.add(node.id);\n collectIds(node.children);\n }\n });\n };\n collectIds(data);\n setExpandedIds(allIds);\n }, [data]);\n\n // 折叠所有节点\n const collapseAll = useCallback(() => {\n setExpandedIds(new Set());\n }, []);\n\n // 渲染单个节点\n const renderTreeNode = useCallback(\n (node: TreeNode, depth: number = 0, path: (string | number)[] = []) => {\n const hasChildren = node.children && node.children.length > 0;\n const isExpanded = expandedIds.has(node.id);\n const isActive = activeNodeId === node.id;\n const currentPath = [...path, node.id];\n\n const nodeContent = (\n <div\n key={node.id}\n data-node-id={node.id}\n data-depth={depth}\n data-level={depth + 1}\n className={`tree-node ${isActive ? 'tree-node-active' : ''} ${node.disabled ? 'tree-node-disabled' : ''\n }`}\n style={{\n paddingLeft: `${depth * indent}px`,\n }}\n >\n <div\n className={`tree-node-content flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors ${isActive ? 'tree-node-content-active' : 'tree-node-content-inactive'\n } ${node.disabled ? 'opacity-50 cursor-not-allowed' : ''}`}\n onClick={() => {\n if (!node.disabled) {\n onNodeClick?.(node, currentPath);\n }\n }}\n onDoubleClick={() => {\n if (!node.disabled) {\n onNodeDoubleClick?.(node, currentPath);\n }\n }}\n >\n {/* 左侧展开按钮 */}\n {togglePosition === 'left' && (\n <>\n {hasChildren ? (\n <button\n type=\"button\"\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.label}`}\n aria-expanded={isExpanded}\n className={`tree-node-toggle btn btn-xs btn-ghost btn-circle ${isExpanded ? 'tree-node-toggle-expanded' : ''\n }`}\n onClick={(e) => {\n e.stopPropagation();\n if (!node.disabled) {\n toggleNode(node.id);\n }\n }}\n disabled={node.disabled}\n >\n {isExpanded ? defaultExpandIconEl : defaultCollapseIconEl}\n </button>\n ) : (\n <span className=\"tree-node-toggle-placeholder\" style={{ width: '1.5rem', height: '1.5rem', flexShrink: 0 }}></span>\n )}\n </>\n )}\n\n {/* 节点图标 */}\n {showIcon && (\n <span className=\"tree-node-icon\">{node.icon || defaultIconEl}</span>\n )}\n\n {/* 节点标签 */}\n <span className=\"tree-node-label text-sm truncate flex-1\" title={node.label}>\n {renderLabel ? renderLabel(node, depth) : node.label}\n </span>\n\n {/* 子节点数量(优先使用 meta.count,否则回退到子节点个数) */}\n {node.meta?.count !== undefined && node.meta?.count !== null ? (\n <span className=\"tree-node-count text-xs opacity-60\">\n {node.meta.count}\n </span>\n ) : hasChildren && showCount ? (\n <span className=\"tree-node-count text-xs opacity-60\">\n ({node.children!.length})\n </span>\n ) : null}\n\n {/* 右侧展开按钮 */}\n {togglePosition === 'right' && hasChildren && (\n <button\n type=\"button\"\n aria-label={`${isExpanded ? 'Collapse' : 'Expand'} ${node.label}`}\n aria-expanded={isExpanded}\n className={`tree-node-toggle tree-node-toggle-right btn btn-xs btn-ghost ${isExpanded ? 'tree-node-toggle-expanded' : ''\n }`}\n onClick={(e) => {\n e.stopPropagation();\n if (!node.disabled) {\n toggleNode(node.id);\n }\n }}\n disabled={node.disabled}\n >\n {isExpanded ? defaultExpandIconEl : defaultCollapseIconEl}\n </button>\n )}\n </div>\n\n {/* 子节点 */}\n {hasChildren && (\n <div\n className={`tree-node-children ${isExpanded ? 'tree-node-children-expanded' : 'tree-node-children-collapsed'}`}\n >\n {node.children!.map((child) => renderTreeNode(child, depth + 1, currentPath))}\n </div>\n )}\n </div>\n );\n\n // 自定义渲染\n if (renderNode) {\n return renderNode(node, nodeContent);\n }\n\n return nodeContent;\n },\n [\n expandedIds,\n activeNodeId,\n indent,\n showIcon,\n showCount,\n togglePosition,\n defaultExpandIconEl,\n defaultCollapseIconEl,\n defaultIconEl,\n onNodeClick,\n onNodeDoubleClick,\n toggleNode,\n renderLabel,\n renderNode,\n ]\n );\n\n return (\n <div className={`tree-component bg-base-100 border border-base-300 rounded-lg p-2 ${className}`}>\n {/* 标题 */}\n {title && (\n <div className=\"tree-header flex items-center gap-2 px-2 py-1 mb-2 border-b border-base-300\">\n {titleIcon}\n <span className=\"font-semibold\">{title}</span>\n {showCount && (\n <span className=\"text-xs opacity-60 ml-auto\">({totalCount})</span>\n )}\n </div>\n )}\n\n {/* 搜索框 */}\n {showSearch && (\n <input\n type=\"text\"\n placeholder={searchPlaceholder}\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"tree-search input input-sm input-bordered w-full mb-2\"\n />\n )}\n\n {/* 操作按钮 */}\n {showExpandAll && (\n <div className=\"tree-actions flex gap-1 mb-2\">\n <button className=\"btn btn-xs btn-ghost\" onClick={expandAll}>\n {expandAllText}\n </button>\n <button className=\"btn btn-xs btn-ghost\" onClick={collapseAll}>\n {collapseAllText}\n </button>\n </div>\n )}\n\n {/* 树形列表 */}\n <div\n className=\"tree-content overflow-y-auto\"\n style={{ maxHeight }}\n >\n {filteredData.length === 0 ? (\n <div className=\"tree-empty text-center text-sm opacity-60 py-4\">\n {searchQuery ? noResultsText : emptyText}\n </div>\n ) : (\n <div className={`tree-nodes ${showLine ? 'tree-show-line' : ''}`}>\n {filteredData.map((node) => renderTreeNode(node))}\n </div>\n )}\n </div>\n\n <style>{`\n .tree-node {\n user-select: none;\n }\n \n /* 子节点容器基础样式 */\n .tree-node-children {\n margin-top: 2px;\n overflow: hidden;\n transform-origin: top;\n box-sizing: border-box;\n }\n \n /* 折叠状态 - 初始隐藏 */\n .tree-node-children-collapsed {\n max-height: 0;\n opacity: 0;\n transform: scaleY(0.8);\n border-left: none !important;\n }\n \n /* 展开状态 - 显示内容 */\n .tree-node-children-expanded {\n max-height: 5000px;\n opacity: 1;\n transform: scaleY(1);\n transition: \n max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1),\n transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n /* 不对 border 做动画 */\n box-sizing: border-box;\n }\n \n /* 连接线样式 - 在展开状态显示,使用多重选择器提高优先级 */\n .tree-component .tree-show-line .tree-node-children-expanded,\n .tree-show-line .tree-node-children.tree-node-children-expanded {\n border-left: 1px solid var(--fallback-bc, oklch(var(--bc) / 0.2)) !important;\n margin-left: 8px !important;\n padding-left: 8px !important;\n position: relative;\n }\n \n /* 左侧连接线圆点装饰 */\n .tree-show-line .tree-node-children-expanded::before {\n content: '';\n position: absolute;\n left: -3px;\n top: 0;\n width: 5px;\n height: 5px;\n border-radius: 50%;\n background-color: var(--fallback-bc, oklch(var(--bc) / 0.3));\n }\n \n /* 折叠过渡 */\n .tree-node-children-collapsed {\n transition: \n max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1),\n opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1),\n transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n /* 展开/折叠按钮图标旋转动画 */\n .tree-node-toggle {\n z-index: 2;\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n .tree-node-toggle svg {\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n }\n \n /* 折叠状态的图标 - 向右 */\n .tree-node-toggle:not(.tree-node-toggle-expanded) svg {\n transform: rotate(0deg);\n }\n \n /* 展开状态的图标 - 向下(已经是向下的,所以不需要额外旋转) */\n .tree-node-toggle-expanded svg {\n transform: rotate(0deg);\n }\n \n .tree-component {\n position: relative;\n z-index: 1;\n }\n \n .tree-node-disabled {\n cursor: not-allowed;\n }\n \n .tree-node-disabled .tree-node-content {\n pointer-events: none;\n }\n \n /* 节点内容悬停效果 */\n .tree-node-content {\n transition: background-color 0.15s ease;\n }\n \n /* 优化性能 - 告诉浏览器这些属性会变化 */\n .tree-node-children {\n will-change: max-height, opacity, transform;\n }\n \n /* 动画完成后移除 will-change 以节省资源 */\n .tree-node-children-expanded,\n .tree-node-children-collapsed {\n animation: remove-will-change 0.3s forwards;\n }\n \n @keyframes remove-will-change {\n to {\n will-change: auto;\n }\n }\n \n /* 活跃节点基础样式 */\n .tree-node-content-active {\n font-weight: 600 !important;\n padding-left: calc(0.5rem - 4px) !important;\n border-radius: 0.375rem !important;\n }\n \n /* 主题活跃状态样式 - 从共用配置生成 */\n ${generateTreeActiveStyles()}\n \n /* 非活跃节点的悬停状态 */\n .tree-node-content-inactive:hover {\n background-color: oklch(var(--b2));\n }\n `}</style>\n </div>\n );\n};\n\nexport default Tree;\n\n"],"mappings":"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"}