@skygraph/react 0.0.0-placeholder.0 → 0.4.0

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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Table-BqN2u5ma.d.cts +1015 -0
  3. package/dist/Table-IvijKCyd.d.ts +1015 -0
  4. package/dist/chunk-2OCEO636.js +91 -0
  5. package/dist/chunk-2OCEO636.js.map +1 -0
  6. package/dist/chunk-6SHHUUAE.js +1667 -0
  7. package/dist/chunk-6SHHUUAE.js.map +1 -0
  8. package/dist/chunk-BNMJSYI2.js +54 -0
  9. package/dist/chunk-BNMJSYI2.js.map +1 -0
  10. package/dist/chunk-DRBAZI46.js +57 -0
  11. package/dist/chunk-DRBAZI46.js.map +1 -0
  12. package/dist/chunk-GJDDPZH7.js +226 -0
  13. package/dist/chunk-GJDDPZH7.js.map +1 -0
  14. package/dist/chunk-KCFWFDSP.js +847 -0
  15. package/dist/chunk-KCFWFDSP.js.map +1 -0
  16. package/dist/chunk-MJAEAFPN.js +3791 -0
  17. package/dist/chunk-MJAEAFPN.js.map +1 -0
  18. package/dist/chunk-MLEBVELO.js +1412 -0
  19. package/dist/chunk-MLEBVELO.js.map +1 -0
  20. package/dist/chunk-SEQI65CF.js +61 -0
  21. package/dist/chunk-SEQI65CF.js.map +1 -0
  22. package/dist/chunk-ZJF6SJLP.js +200 -0
  23. package/dist/chunk-ZJF6SJLP.js.map +1 -0
  24. package/dist/common-CdpocIEz.d.cts +27 -0
  25. package/dist/common-CdpocIEz.d.ts +27 -0
  26. package/dist/datagrid-B6hg5yJh.d.cts +200 -0
  27. package/dist/datagrid-B6hg5yJh.d.ts +200 -0
  28. package/dist/datagrid.cjs +1052 -0
  29. package/dist/datagrid.cjs.map +1 -0
  30. package/dist/datagrid.d.cts +2 -0
  31. package/dist/datagrid.d.ts +2 -0
  32. package/dist/datagrid.js +10 -0
  33. package/dist/datagrid.js.map +1 -0
  34. package/dist/devtools.cjs +253 -0
  35. package/dist/devtools.cjs.map +1 -0
  36. package/dist/devtools.d.cts +29 -0
  37. package/dist/devtools.d.ts +29 -0
  38. package/dist/devtools.js +9 -0
  39. package/dist/devtools.js.map +1 -0
  40. package/dist/form.cjs +1723 -0
  41. package/dist/form.cjs.map +1 -0
  42. package/dist/form.d.cts +530 -0
  43. package/dist/form.d.ts +530 -0
  44. package/dist/form.js +49 -0
  45. package/dist/form.js.map +1 -0
  46. package/dist/index.cjs +22419 -0
  47. package/dist/index.cjs.map +1 -0
  48. package/dist/index.d.cts +3671 -0
  49. package/dist/index.d.ts +3671 -0
  50. package/dist/index.js +14087 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/table.cjs +4130 -0
  53. package/dist/table.cjs.map +1 -0
  54. package/dist/table.d.cts +31 -0
  55. package/dist/table.d.ts +31 -0
  56. package/dist/table.js +26 -0
  57. package/dist/table.js.map +1 -0
  58. package/dist/tree.cjs +1821 -0
  59. package/dist/tree.cjs.map +1 -0
  60. package/dist/tree.d.cts +348 -0
  61. package/dist/tree.d.ts +348 -0
  62. package/dist/tree.js +13 -0
  63. package/dist/tree.js.map +1 -0
  64. package/dist/virtual.cjs +145 -0
  65. package/dist/virtual.cjs.map +1 -0
  66. package/dist/virtual.d.cts +50 -0
  67. package/dist/virtual.d.ts +50 -0
  68. package/dist/virtual.js +11 -0
  69. package/dist/virtual.js.map +1 -0
  70. package/package.json +108 -18
  71. package/README.md +0 -12
  72. package/index.js +0 -3
package/dist/tree.cjs ADDED
@@ -0,0 +1,1821 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/tree.ts
31
+ var tree_exports = {};
32
+ __export(tree_exports, {
33
+ Tree: () => Tree,
34
+ TreeSelect: () => TreeSelect,
35
+ useTree: () => useTree
36
+ });
37
+ module.exports = __toCommonJS(tree_exports);
38
+
39
+ // src/components/complex/Tree/Tree.tsx
40
+ var import_react6 = require("react");
41
+
42
+ // src/hooks/useTree.ts
43
+ var import_react = require("react");
44
+ var import_core = require("@skygraph/core");
45
+ function useTree(options) {
46
+ const [{ core, tree }] = (0, import_react.useState)(() => {
47
+ const c = (0, import_core.createCore)();
48
+ const t = (0, import_core.createTree)(c, options);
49
+ if (options?.data) {
50
+ t.setData(options.data);
51
+ }
52
+ return { core: c, tree: t };
53
+ });
54
+ const [treeState, setTreeState] = (0, import_react.useState)(() => tree.getState());
55
+ const [flatNodes, setFlatNodes] = (0, import_react.useState)(() => tree.getFlatNodes());
56
+ const refresh = (0, import_react.useCallback)(() => {
57
+ setTreeState(tree.getState());
58
+ setFlatNodes(tree.getFlatNodes());
59
+ }, [tree]);
60
+ const expand = (0, import_react.useCallback)((key) => {
61
+ tree.expand(key);
62
+ refresh();
63
+ }, [tree, refresh]);
64
+ const collapse = (0, import_react.useCallback)((key) => {
65
+ tree.collapse(key);
66
+ refresh();
67
+ }, [tree, refresh]);
68
+ const toggleExpand = (0, import_react.useCallback)((key) => {
69
+ tree.toggleExpand(key);
70
+ refresh();
71
+ }, [tree, refresh]);
72
+ const setExpandedKeys = (0, import_react.useCallback)((keys) => {
73
+ tree.setExpandedKeys(keys);
74
+ refresh();
75
+ }, [tree, refresh]);
76
+ const expandAll = (0, import_react.useCallback)(() => {
77
+ tree.expandAll();
78
+ refresh();
79
+ }, [tree, refresh]);
80
+ const collapseAll = (0, import_react.useCallback)(() => {
81
+ tree.collapseAll();
82
+ refresh();
83
+ }, [tree, refresh]);
84
+ const check = (0, import_react.useCallback)((key) => {
85
+ tree.check(key);
86
+ refresh();
87
+ }, [tree, refresh]);
88
+ const uncheck = (0, import_react.useCallback)((key) => {
89
+ tree.uncheck(key);
90
+ refresh();
91
+ }, [tree, refresh]);
92
+ const toggleCheck = (0, import_react.useCallback)((key) => {
93
+ tree.toggleCheck(key);
94
+ refresh();
95
+ }, [tree, refresh]);
96
+ const setCheckedKeys = (0, import_react.useCallback)((keys) => {
97
+ tree.setCheckedKeys(keys);
98
+ refresh();
99
+ }, [tree, refresh]);
100
+ const select = (0, import_react.useCallback)((key, multiple) => {
101
+ tree.select(key, multiple);
102
+ refresh();
103
+ }, [tree, refresh]);
104
+ const deselect = (0, import_react.useCallback)((key) => {
105
+ tree.deselect(key);
106
+ refresh();
107
+ }, [tree, refresh]);
108
+ const setSelectedKeys = (0, import_react.useCallback)((keys) => {
109
+ tree.setSelectedKeys(keys);
110
+ refresh();
111
+ }, [tree, refresh]);
112
+ const markLoading = (0, import_react.useCallback)((key) => {
113
+ tree.markLoading(key);
114
+ refresh();
115
+ }, [tree, refresh]);
116
+ const markLoaded = (0, import_react.useCallback)((key) => {
117
+ tree.markLoaded(key);
118
+ refresh();
119
+ }, [tree, refresh]);
120
+ const addChildren = (0, import_react.useCallback)((parentKey, children) => {
121
+ tree.addChildren(parentKey, children);
122
+ refresh();
123
+ }, [tree, refresh]);
124
+ const moveNode = (0, import_react.useCallback)((dragKey, dropKey, position) => {
125
+ const result = tree.moveNode(dragKey, dropKey, position);
126
+ refresh();
127
+ return result;
128
+ }, [tree, refresh]);
129
+ const filterNodes = (0, import_react.useCallback)((predicate) => {
130
+ tree.filterNodes(predicate);
131
+ refresh();
132
+ }, [tree, refresh]);
133
+ const expandToLevel = (0, import_react.useCallback)((level) => {
134
+ const flat = tree.getFlatNodes();
135
+ const keys = [];
136
+ for (const item of flat) {
137
+ if (item.depth < level && !item.isLeaf) {
138
+ keys.push(item.key);
139
+ }
140
+ }
141
+ tree.expandAll();
142
+ const allFlat = tree.getFlatNodes();
143
+ const expandKeys = [];
144
+ for (const item of allFlat) {
145
+ if (item.depth < level && !item.isLeaf) {
146
+ expandKeys.push(item.key);
147
+ }
148
+ }
149
+ tree.setExpandedKeys(expandKeys);
150
+ refresh();
151
+ }, [tree, refresh]);
152
+ const checkAll = (0, import_react.useCallback)(() => {
153
+ const allKeys = tree.getAllKeys();
154
+ tree.setCheckedKeys(allKeys);
155
+ refresh();
156
+ }, [tree, refresh]);
157
+ const uncheckAll = (0, import_react.useCallback)(() => {
158
+ tree.setCheckedKeys([]);
159
+ refresh();
160
+ }, [tree, refresh]);
161
+ const getNodePath = (0, import_react.useCallback)((key) => {
162
+ const path = [];
163
+ let current = key;
164
+ while (current !== null) {
165
+ path.unshift(current);
166
+ current = tree.getParentKey(current);
167
+ }
168
+ return path;
169
+ }, [tree]);
170
+ return (0, import_react.useMemo)(() => ({
171
+ core,
172
+ tree,
173
+ treeState,
174
+ flatNodes,
175
+ expand,
176
+ collapse,
177
+ toggleExpand,
178
+ setExpandedKeys,
179
+ expandAll,
180
+ collapseAll,
181
+ expandToLevel,
182
+ check,
183
+ uncheck,
184
+ toggleCheck,
185
+ setCheckedKeys,
186
+ checkAll,
187
+ uncheckAll,
188
+ select,
189
+ deselect,
190
+ setSelectedKeys,
191
+ markLoading,
192
+ markLoaded,
193
+ addChildren,
194
+ moveNode,
195
+ filterNodes,
196
+ getNodePath,
197
+ refresh
198
+ }), [
199
+ core,
200
+ tree,
201
+ treeState,
202
+ flatNodes,
203
+ expand,
204
+ collapse,
205
+ toggleExpand,
206
+ setExpandedKeys,
207
+ expandAll,
208
+ collapseAll,
209
+ expandToLevel,
210
+ check,
211
+ uncheck,
212
+ toggleCheck,
213
+ setCheckedKeys,
214
+ checkAll,
215
+ uncheckAll,
216
+ select,
217
+ deselect,
218
+ setSelectedKeys,
219
+ markLoading,
220
+ markLoaded,
221
+ addChildren,
222
+ moveNode,
223
+ filterNodes,
224
+ getNodePath,
225
+ refresh
226
+ ]);
227
+ }
228
+
229
+ // src/components/complex/Tree/TreeNodeRow.tsx
230
+ var import_react5 = require("react");
231
+
232
+ // src/components/ui/Checkbox.tsx
233
+ var import_react4 = __toESM(require("react"), 1);
234
+
235
+ // src/components/ConfigProvider.tsx
236
+ var import_react2 = require("react");
237
+ var import_jsx_runtime = require("react/jsx-runtime");
238
+ var SgConfigContext = (0, import_react2.createContext)({});
239
+ function useConfig() {
240
+ return (0, import_react2.useContext)(SgConfigContext);
241
+ }
242
+
243
+ // src/components/ui/Spin.tsx
244
+ var import_react3 = __toESM(require("react"), 1);
245
+ var import_jsx_runtime2 = require("react/jsx-runtime");
246
+ function Spin({
247
+ spinning = true,
248
+ size: sizeProp,
249
+ delay,
250
+ tip,
251
+ fullscreen,
252
+ indicator,
253
+ children,
254
+ className,
255
+ style,
256
+ unstyled
257
+ }) {
258
+ const config = useConfig();
259
+ const resolvedSize = sizeProp ?? config.size ?? "middle";
260
+ const [visible, setVisible] = import_react3.default.useState(delay ? false : spinning);
261
+ import_react3.default.useEffect(() => {
262
+ if (!delay) {
263
+ setVisible(spinning);
264
+ return;
265
+ }
266
+ if (spinning) {
267
+ const timer = setTimeout(() => setVisible(true), delay);
268
+ return () => clearTimeout(timer);
269
+ }
270
+ setVisible(false);
271
+ }, [spinning, delay]);
272
+ if (!visible && !children) return null;
273
+ if (!visible && children) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
274
+ const spinSizeClass = resolvedSize === "middle" ? "default" : resolvedSize;
275
+ const spinClasses = unstyled ? className ?? "" : ["sg-spin", `sg-spin-${spinSizeClass}`, className].filter(Boolean).join(" ");
276
+ const spinElement = indicator ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
277
+ "span",
278
+ {
279
+ className: spinClasses,
280
+ style,
281
+ role: "status",
282
+ "aria-live": "polite",
283
+ "aria-label": config.locale?.spin?.loading ?? "Loading"
284
+ }
285
+ );
286
+ if (fullscreen) {
287
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: unstyled ? "" : "sg-spin-fullscreen", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: unstyled ? "" : "sg-spin-fullscreen-inner", children: [
288
+ spinElement,
289
+ tip && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
290
+ ] }) });
291
+ }
292
+ if (!children) {
293
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: unstyled ? "" : "sg-spin-standalone", style, children: [
294
+ spinElement,
295
+ tip && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
296
+ ] });
297
+ }
298
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: unstyled ? "" : "sg-spin-container", style, children: [
299
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: unstyled ? "" : "sg-spin-overlay", children: [
300
+ spinElement,
301
+ tip && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: unstyled ? "" : "sg-spin-tip", children: tip })
302
+ ] }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: visible ? unstyled ? "" : "sg-spin-blur" : "", children })
304
+ ] });
305
+ }
306
+
307
+ // src/components/ui/Checkbox.tsx
308
+ var import_jsx_runtime3 = require("react/jsx-runtime");
309
+ function Checkbox({
310
+ checked,
311
+ defaultChecked,
312
+ disabled: disabledProp,
313
+ loading,
314
+ indeterminate,
315
+ onChange,
316
+ children,
317
+ className,
318
+ style,
319
+ unstyled
320
+ }) {
321
+ const config = useConfig();
322
+ const disabled = disabledProp ?? config.disabled ?? false;
323
+ const inputRef = import_react4.default.useRef(null);
324
+ import_react4.default.useEffect(() => {
325
+ if (inputRef.current) {
326
+ inputRef.current.indeterminate = indeterminate ?? false;
327
+ }
328
+ }, [indeterminate]);
329
+ const wrapperClass = unstyled ? className ?? "" : [
330
+ "sg-checkbox",
331
+ disabled || loading ? "sg-checkbox-disabled" : "",
332
+ loading ? "sg-checkbox-loading" : "",
333
+ className
334
+ ].filter(Boolean).join(" ");
335
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: wrapperClass, style, children: [
336
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
337
+ "input",
338
+ {
339
+ ref: inputRef,
340
+ type: "checkbox",
341
+ "aria-checked": checked,
342
+ className: unstyled ? "" : "sg-checkbox-input",
343
+ checked,
344
+ defaultChecked,
345
+ disabled: disabled || loading,
346
+ onChange: (e) => onChange?.(e.target.checked)
347
+ }
348
+ ),
349
+ children && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: unstyled ? "" : "sg-checkbox-label", children }),
350
+ loading && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spin, { size: "small", unstyled })
351
+ ] });
352
+ }
353
+
354
+ // src/components/complex/Tree/TreeNodeRow.tsx
355
+ var import_jsx_runtime4 = require("react/jsx-runtime");
356
+ function TreeNodeRow(props) {
357
+ const {
358
+ node,
359
+ nodeKey,
360
+ depth,
361
+ isLeaf,
362
+ indentSize,
363
+ expanded,
364
+ checked,
365
+ halfChecked,
366
+ selected,
367
+ loading,
368
+ disabled,
369
+ focused,
370
+ checkable,
371
+ selectable,
372
+ showLine,
373
+ showLeafIcon,
374
+ showIcon,
375
+ blockNode,
376
+ directory,
377
+ globalIcon,
378
+ nodeIcon,
379
+ switcherIcon,
380
+ draggable,
381
+ dropPosition,
382
+ dragKey,
383
+ onExpand,
384
+ onCheck,
385
+ onSelect,
386
+ onDragStart,
387
+ onDragOver,
388
+ onDragLeave,
389
+ onDragEnd,
390
+ onDrop,
391
+ onRightClick,
392
+ onLoadData,
393
+ onFocusNode,
394
+ titleRender,
395
+ searchValue,
396
+ editable,
397
+ editing,
398
+ onEditStart,
399
+ onEditConfirm,
400
+ onEditCancel,
401
+ actions,
402
+ status,
403
+ lineIsLast,
404
+ lineParentIsLast,
405
+ unstyled,
406
+ nodeClassName,
407
+ nodeStyle
408
+ } = props;
409
+ const rowRef = (0, import_react5.useRef)(null);
410
+ const editInputRef = (0, import_react5.useRef)(null);
411
+ const [editValue, setEditValue] = (0, import_react5.useState)("");
412
+ (0, import_react5.useEffect)(() => {
413
+ if (editing) {
414
+ setEditValue(String(node.title ?? ""));
415
+ setTimeout(() => editInputRef.current?.focus(), 0);
416
+ }
417
+ }, [editing, node.title]);
418
+ (0, import_react5.useEffect)(() => {
419
+ if (focused && rowRef.current) {
420
+ rowRef.current.scrollIntoView?.({ block: "nearest" });
421
+ }
422
+ }, [focused]);
423
+ const handleSwitcherClick = (e) => {
424
+ e.stopPropagation();
425
+ if (isLeaf) return;
426
+ if (!expanded && loading) return;
427
+ onExpand(nodeKey);
428
+ if (!expanded && !isLeaf && onLoadData) {
429
+ onLoadData(node);
430
+ }
431
+ };
432
+ const handleCheckChange = () => {
433
+ if (disabled || node.disableCheckbox) return;
434
+ onCheck(nodeKey);
435
+ };
436
+ const handleSelect = () => {
437
+ if (disabled || node.selectable === false) return;
438
+ if (!selectable) return;
439
+ onSelect(nodeKey);
440
+ if (directory && !isLeaf) {
441
+ onExpand(nodeKey);
442
+ }
443
+ };
444
+ const handleClick = () => {
445
+ onFocusNode(nodeKey);
446
+ handleSelect();
447
+ };
448
+ const handleDoubleClick = () => {
449
+ if (editable && !editing) {
450
+ onEditStart(nodeKey);
451
+ }
452
+ };
453
+ const handleContextMenu = (e) => {
454
+ if (onRightClick) {
455
+ e.preventDefault();
456
+ onRightClick(e, node);
457
+ }
458
+ };
459
+ const handleEditKeyDown = (0, import_react5.useCallback)((e) => {
460
+ e.stopPropagation();
461
+ if (e.key === "Enter") {
462
+ onEditConfirm(nodeKey, editValue);
463
+ } else if (e.key === "Escape") {
464
+ onEditCancel(nodeKey);
465
+ }
466
+ }, [nodeKey, editValue, onEditConfirm, onEditCancel]);
467
+ const handleEditBlur = (0, import_react5.useCallback)(() => {
468
+ onEditConfirm(nodeKey, editValue);
469
+ }, [nodeKey, editValue, onEditConfirm]);
470
+ const renderHighlightedTitle = (title) => {
471
+ if (!searchValue) return title;
472
+ const index = title.toLowerCase().indexOf(searchValue.toLowerCase());
473
+ if (index === -1) return title;
474
+ const before = title.slice(0, index);
475
+ const match = title.slice(index, index + searchValue.length);
476
+ const after = title.slice(index + searchValue.length);
477
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
478
+ before,
479
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-highlight", children: match }),
480
+ after
481
+ ] });
482
+ };
483
+ const renderSwitcher = () => {
484
+ if (isLeaf) {
485
+ if (showLine) {
486
+ if (showLeafIcon === false) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-switcher sg-tree-switcher-noop" });
487
+ if (showLeafIcon && typeof showLeafIcon !== "boolean") {
488
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-switcher sg-tree-switcher-leaf-icon", children: showLeafIcon });
489
+ }
490
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-switcher sg-tree-switcher-leaf", children: "\u2500" });
491
+ }
492
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-switcher sg-tree-switcher-noop" });
493
+ }
494
+ if (loading) {
495
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-switcher sg-tree-switcher-loading", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Spin, { size: "small" }) });
496
+ }
497
+ let iconContent;
498
+ if (switcherIcon) {
499
+ iconContent = typeof switcherIcon === "function" ? switcherIcon({ expanded, loading, isLeaf }) : switcherIcon;
500
+ } else {
501
+ iconContent = /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
502
+ "svg",
503
+ {
504
+ className: `sg-tree-switcher-arrow${expanded ? " sg-tree-switcher-arrow-open" : ""}`,
505
+ width: "10",
506
+ height: "10",
507
+ viewBox: "0 0 10 10",
508
+ fill: "none",
509
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M3 2L7 5L3 8", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
510
+ }
511
+ );
512
+ }
513
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
514
+ "span",
515
+ {
516
+ className: `sg-tree-switcher${expanded ? " sg-tree-switcher-open" : " sg-tree-switcher-close"}`,
517
+ onClick: handleSwitcherClick,
518
+ children: iconContent
519
+ }
520
+ );
521
+ };
522
+ const renderIcon = () => {
523
+ if (!showIcon && !directory) return null;
524
+ const iconSource = nodeIcon ?? globalIcon;
525
+ let iconContent = null;
526
+ if (iconSource) {
527
+ iconContent = typeof iconSource === "function" ? iconSource({ expanded, selected }) : iconSource;
528
+ } else if (directory) {
529
+ iconContent = expanded ? "\u{1F4C2}" : "\u{1F4C1}";
530
+ }
531
+ if (!iconContent) return null;
532
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-icon", children: iconContent });
533
+ };
534
+ const renderTitle = () => {
535
+ if (editing) {
536
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
537
+ "input",
538
+ {
539
+ ref: editInputRef,
540
+ className: "sg-tree-edit-input",
541
+ value: editValue,
542
+ onChange: (e) => setEditValue(e.target.value),
543
+ onKeyDown: handleEditKeyDown,
544
+ onBlur: handleEditBlur,
545
+ onClick: (e) => e.stopPropagation()
546
+ }
547
+ );
548
+ }
549
+ if (titleRender) {
550
+ return titleRender(node, { expanded, selected, checked, halfChecked });
551
+ }
552
+ const titleText = String(node.title ?? nodeKey);
553
+ return renderHighlightedTitle(titleText);
554
+ };
555
+ const renderActions = () => {
556
+ if (!actions || actions.length === 0) return null;
557
+ const visibleActions = actions.filter((a) => !a.visible || a.visible(node));
558
+ if (visibleActions.length === 0) return null;
559
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "sg-tree-actions", onClick: (e) => e.stopPropagation(), children: visibleActions.map((action) => {
560
+ const isDisabled = action.disabled?.(node) ?? false;
561
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
562
+ "button",
563
+ {
564
+ className: `sg-tree-action-btn${action.danger ? " sg-tree-action-danger" : ""}${isDisabled ? " sg-tree-action-disabled" : ""}`,
565
+ title: action.title,
566
+ onClick: (e) => {
567
+ e.stopPropagation();
568
+ if (!isDisabled) action.onClick(node, nodeKey);
569
+ },
570
+ disabled: isDisabled,
571
+ type: "button",
572
+ children: action.icon ?? action.title ?? action.key
573
+ },
574
+ action.key
575
+ );
576
+ }) });
577
+ };
578
+ const renderIndentLines = () => {
579
+ if (!showLine) return null;
580
+ const lines = [];
581
+ for (let i = 0; i < depth; i++) {
582
+ const isParentLast = lineParentIsLast[i] ?? false;
583
+ lines.push(
584
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
585
+ "span",
586
+ {
587
+ className: `sg-tree-indent-line${isParentLast ? " sg-tree-indent-line-hidden" : ""}`,
588
+ style: { left: i * indentSize + indentSize / 2 }
589
+ },
590
+ i
591
+ )
592
+ );
593
+ }
594
+ if (depth > 0) {
595
+ lines.push(
596
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
597
+ "span",
598
+ {
599
+ className: `sg-tree-indent-branch${lineIsLast ? " sg-tree-indent-branch-last" : ""}`,
600
+ style: { left: (depth - 1) * indentSize + indentSize / 2 }
601
+ },
602
+ "branch"
603
+ )
604
+ );
605
+ }
606
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: lines });
607
+ };
608
+ const renderStatus = () => {
609
+ if (status === "default") return null;
610
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `sg-tree-status sg-tree-status-${status}` });
611
+ };
612
+ if (unstyled) {
613
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
614
+ "div",
615
+ {
616
+ ref: rowRef,
617
+ role: "treeitem",
618
+ "aria-expanded": isLeaf ? void 0 : expanded,
619
+ "aria-selected": selected,
620
+ "aria-checked": checkable ? checked : void 0,
621
+ "aria-level": depth + 1,
622
+ "data-key": nodeKey,
623
+ children: [
624
+ checkable && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
625
+ Checkbox,
626
+ {
627
+ checked,
628
+ indeterminate: halfChecked,
629
+ disabled: disabled || node.disableCheckbox,
630
+ onChange: handleCheckChange,
631
+ unstyled: true
632
+ }
633
+ ),
634
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { onClick: handleClick, children: renderTitle() })
635
+ ]
636
+ }
637
+ );
638
+ }
639
+ const isDragging = dragKey === nodeKey;
640
+ const rowCls = [
641
+ "sg-tree-node",
642
+ selected ? "sg-tree-node-selected" : "",
643
+ disabled ? "sg-tree-node-disabled" : "",
644
+ isLeaf ? "sg-tree-node-leaf" : "",
645
+ expanded ? "sg-tree-node-expanded" : "",
646
+ draggable ? "sg-tree-node-draggable" : "",
647
+ isDragging ? "sg-tree-node-dragging" : "",
648
+ dropPosition === 0 ? "sg-tree-node-drop-inner" : "",
649
+ dropPosition === -1 ? "sg-tree-node-drop-before" : "",
650
+ dropPosition === 1 ? "sg-tree-node-drop-after" : "",
651
+ showLine ? "sg-tree-node-show-line" : "",
652
+ blockNode ? "sg-tree-node-block" : "",
653
+ directory ? "sg-tree-node-directory" : "",
654
+ focused ? "sg-tree-node-focused" : "",
655
+ editing ? "sg-tree-node-editing" : "",
656
+ status !== "default" ? `sg-tree-node-status-${status}` : "",
657
+ nodeClassName
658
+ ].filter(Boolean).join(" ");
659
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
660
+ "div",
661
+ {
662
+ ref: rowRef,
663
+ className: rowCls,
664
+ style: { ...nodeStyle, paddingLeft: depth * indentSize },
665
+ role: "treeitem",
666
+ "aria-expanded": isLeaf ? void 0 : expanded,
667
+ "aria-selected": selected,
668
+ "aria-checked": checkable ? checked : void 0,
669
+ "aria-level": depth + 1,
670
+ "data-key": nodeKey,
671
+ draggable: draggable && !editing,
672
+ onDragStart: draggable ? (e) => onDragStart(e, nodeKey) : void 0,
673
+ onDragOver: draggable ? (e) => {
674
+ e.preventDefault();
675
+ onDragOver(e, nodeKey);
676
+ } : void 0,
677
+ onDragLeave: draggable ? (e) => onDragLeave(e, nodeKey) : void 0,
678
+ onDragEnd: draggable ? (e) => onDragEnd(e, nodeKey) : void 0,
679
+ onDrop: draggable ? (e) => {
680
+ e.preventDefault();
681
+ onDrop(e, nodeKey);
682
+ } : void 0,
683
+ onContextMenu: handleContextMenu,
684
+ onClick: handleClick,
685
+ onDoubleClick: editable ? handleDoubleClick : void 0,
686
+ children: [
687
+ renderIndentLines(),
688
+ renderSwitcher(),
689
+ checkable && node.checkable !== false && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
690
+ Checkbox,
691
+ {
692
+ checked,
693
+ indeterminate: halfChecked,
694
+ disabled: disabled || node.disableCheckbox,
695
+ onChange: handleCheckChange
696
+ }
697
+ ),
698
+ renderIcon(),
699
+ renderStatus(),
700
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
701
+ "span",
702
+ {
703
+ className: `sg-tree-title${selectable && !editing ? " sg-tree-title-selectable" : ""}`,
704
+ children: renderTitle()
705
+ }
706
+ ),
707
+ renderActions()
708
+ ]
709
+ }
710
+ );
711
+ }
712
+
713
+ // src/components/complex/Tree/types.ts
714
+ var DEFAULT_TREE_LOCALE = {
715
+ emptyText: "No data",
716
+ loadingText: "Loading...",
717
+ searchPlaceholder: "Search...",
718
+ expandAllText: "Expand All",
719
+ collapseAllText: "Collapse All",
720
+ checkAllText: "Check All",
721
+ uncheckAllText: "Uncheck All",
722
+ clearSearch: "Clear search"
723
+ };
724
+ var DEFAULT_INDENT = 24;
725
+ var NODE_HEIGHT = 28;
726
+
727
+ // src/components/complex/Tree/Tree.tsx
728
+ var import_jsx_runtime5 = require("react/jsx-runtime");
729
+ function Tree(props) {
730
+ const {
731
+ treeData,
732
+ fieldNames,
733
+ checkable = false,
734
+ checkStrictly = false,
735
+ checkedKeys: controlledCheckedKeys,
736
+ defaultCheckedKeys,
737
+ onCheck,
738
+ selectable = true,
739
+ multiple = false,
740
+ selectedKeys: controlledSelectedKeys,
741
+ defaultSelectedKeys,
742
+ onSelect,
743
+ expandedKeys: controlledExpandedKeys,
744
+ defaultExpandedKeys,
745
+ defaultExpandAll = false,
746
+ autoExpandParent = false,
747
+ onExpand,
748
+ draggable = false,
749
+ allowDrop,
750
+ onDragStart,
751
+ onDragOver,
752
+ onDragLeave,
753
+ onDragEnd,
754
+ onDrop,
755
+ loadData,
756
+ showLine = false,
757
+ showIcon = false,
758
+ icon: globalIcon,
759
+ switcherIcon,
760
+ blockNode = false,
761
+ height,
762
+ virtual = true,
763
+ disabled = false,
764
+ indentSize = DEFAULT_INDENT,
765
+ directory = false,
766
+ onRightClick,
767
+ // Search
768
+ showSearch = false,
769
+ searchValue: controlledSearchValue,
770
+ defaultSearchValue = "",
771
+ onSearch,
772
+ filterTreeNode,
773
+ highlightSearch = true,
774
+ // Keyboard
775
+ keyboard = true,
776
+ // Editable
777
+ editable = false,
778
+ onEdit,
779
+ onEditCancel,
780
+ // Custom render
781
+ titleRender,
782
+ // Actions
783
+ actions,
784
+ // Toolbar
785
+ showToolbar = false,
786
+ toolbarExtra,
787
+ // Animation
788
+ animated = true,
789
+ // Focus
790
+ autoFocus = false,
791
+ focusedKey: controlledFocusedKey,
792
+ onFocus: onFocusCallback,
793
+ // Scroll
794
+ scrollToKey,
795
+ // Status
796
+ nodeStatus,
797
+ locale,
798
+ className,
799
+ style,
800
+ unstyled
801
+ } = props;
802
+ const t = (0, import_react6.useMemo)(() => ({ ...DEFAULT_TREE_LOCALE, ...locale }), [locale]);
803
+ const showLineConfig = typeof showLine === "object" ? showLine : { showLeafIcon: false };
804
+ const isShowLine = !!showLine;
805
+ const {
806
+ tree,
807
+ treeState,
808
+ flatNodes,
809
+ toggleExpand,
810
+ setExpandedKeys,
811
+ expandAll,
812
+ collapseAll,
813
+ toggleCheck,
814
+ setCheckedKeys,
815
+ select,
816
+ setSelectedKeys,
817
+ markLoading,
818
+ markLoaded,
819
+ moveNode,
820
+ filterNodes,
821
+ refresh
822
+ } = useTree({
823
+ data: treeData,
824
+ fieldNames,
825
+ checkStrictly,
826
+ defaultExpandAll,
827
+ defaultExpandedKeys,
828
+ defaultCheckedKeys,
829
+ defaultSelectedKeys
830
+ });
831
+ const [internalSearchValue, setInternalSearchValue] = (0, import_react6.useState)(defaultSearchValue);
832
+ const searchValue = controlledSearchValue ?? internalSearchValue;
833
+ const handleSearchChange = (0, import_react6.useCallback)(
834
+ (value) => {
835
+ if (controlledSearchValue === void 0) {
836
+ setInternalSearchValue(value);
837
+ }
838
+ onSearch?.(value);
839
+ if (!value) {
840
+ filterNodes(null);
841
+ return;
842
+ }
843
+ const predicate = filterTreeNode ? (node) => filterTreeNode(node, value) : (node) => {
844
+ const title = String(node.title ?? "");
845
+ return title.toLowerCase().includes(value.toLowerCase());
846
+ };
847
+ filterNodes(predicate);
848
+ if (autoExpandParent) {
849
+ const filtered = tree.getFilteredKeys();
850
+ if (filtered) {
851
+ setExpandedKeys(filtered);
852
+ }
853
+ }
854
+ },
855
+ [
856
+ controlledSearchValue,
857
+ onSearch,
858
+ filterTreeNode,
859
+ filterNodes,
860
+ autoExpandParent,
861
+ tree,
862
+ setExpandedKeys
863
+ ]
864
+ );
865
+ (0, import_react6.useEffect)(() => {
866
+ if (controlledSearchValue !== void 0 && controlledSearchValue !== internalSearchValue) {
867
+ handleSearchChange(controlledSearchValue);
868
+ }
869
+ }, [controlledSearchValue]);
870
+ const prevDataRef = (0, import_react6.useRef)(treeData);
871
+ (0, import_react6.useEffect)(() => {
872
+ if (prevDataRef.current !== treeData) {
873
+ prevDataRef.current = treeData;
874
+ tree.setData(treeData);
875
+ refresh();
876
+ }
877
+ }, [treeData, tree, refresh]);
878
+ (0, import_react6.useEffect)(() => {
879
+ if (controlledExpandedKeys !== void 0) setExpandedKeys(controlledExpandedKeys);
880
+ }, [controlledExpandedKeys, setExpandedKeys]);
881
+ (0, import_react6.useEffect)(() => {
882
+ if (controlledCheckedKeys !== void 0) setCheckedKeys(controlledCheckedKeys);
883
+ }, [controlledCheckedKeys, setCheckedKeys]);
884
+ (0, import_react6.useEffect)(() => {
885
+ if (controlledSelectedKeys !== void 0) setSelectedKeys(controlledSelectedKeys);
886
+ }, [controlledSelectedKeys, setSelectedKeys]);
887
+ const [internalFocusedKey, setInternalFocusedKey] = (0, import_react6.useState)(null);
888
+ const focusedKey = controlledFocusedKey ?? internalFocusedKey;
889
+ const treeRef = (0, import_react6.useRef)(null);
890
+ const setFocusedKey = (0, import_react6.useCallback)(
891
+ (key) => {
892
+ setInternalFocusedKey(key);
893
+ if (key !== null) onFocusCallback?.(key);
894
+ },
895
+ [onFocusCallback]
896
+ );
897
+ (0, import_react6.useEffect)(() => {
898
+ if (autoFocus && flatNodes.length > 0 && focusedKey === null) {
899
+ setFocusedKey(flatNodes[0].key);
900
+ }
901
+ }, []);
902
+ const [editingKey, setEditingKey] = (0, import_react6.useState)(null);
903
+ const isNodeEditable = (0, import_react6.useCallback)(
904
+ (node) => {
905
+ if (typeof editable === "function") return editable(node);
906
+ return !!editable;
907
+ },
908
+ [editable]
909
+ );
910
+ const handleEditStart = (0, import_react6.useCallback)((key) => {
911
+ setEditingKey(key);
912
+ }, []);
913
+ const handleEditConfirm = (0, import_react6.useCallback)(
914
+ (key, value) => {
915
+ const node = tree.getNode(key);
916
+ if (node && onEdit) {
917
+ onEdit({ key, node, value, oldValue: String(node.title ?? "") });
918
+ }
919
+ setEditingKey(null);
920
+ },
921
+ [tree, onEdit]
922
+ );
923
+ const handleEditCancelInternal = (0, import_react6.useCallback)(
924
+ (key) => {
925
+ setEditingKey(null);
926
+ onEditCancel?.(key);
927
+ },
928
+ [onEditCancel]
929
+ );
930
+ const [dragKey, setDragKey] = (0, import_react6.useState)(null);
931
+ const [dropKey, setDropKey] = (0, import_react6.useState)(null);
932
+ const [dropPosition, setDropPosition] = (0, import_react6.useState)(0);
933
+ const handleExpand = (0, import_react6.useCallback)(
934
+ (key) => {
935
+ toggleExpand(key);
936
+ const node = tree.getNode(key);
937
+ if (node && onExpand) {
938
+ const newState = tree.getState();
939
+ const expanded = newState.expandedKeys.includes(key);
940
+ onExpand(newState.expandedKeys, { expanded, node });
941
+ }
942
+ },
943
+ [toggleExpand, tree, onExpand]
944
+ );
945
+ const handleCheck = (0, import_react6.useCallback)(
946
+ (key) => {
947
+ toggleCheck(key);
948
+ if (onCheck) {
949
+ const newState = tree.getState();
950
+ const node = tree.getNode(key);
951
+ const checkedNodes = newState.checkedKeys.map((ck) => tree.getNode(ck)).filter(Boolean);
952
+ onCheck(newState.checkedKeys, {
953
+ checked: newState.checkedKeys.includes(key),
954
+ node,
955
+ checkedNodes,
956
+ halfCheckedKeys: newState.halfCheckedKeys
957
+ });
958
+ }
959
+ },
960
+ [toggleCheck, tree, onCheck]
961
+ );
962
+ const handleSelect = (0, import_react6.useCallback)(
963
+ (key) => {
964
+ select(key, multiple);
965
+ if (onSelect) {
966
+ const newState = tree.getState();
967
+ const node = tree.getNode(key);
968
+ const selectedNodes = newState.selectedKeys.map((sk) => tree.getNode(sk)).filter(Boolean);
969
+ onSelect(newState.selectedKeys, {
970
+ selected: newState.selectedKeys.includes(key),
971
+ node,
972
+ selectedNodes
973
+ });
974
+ }
975
+ },
976
+ [select, multiple, tree, onSelect]
977
+ );
978
+ const handleLoadData = (0, import_react6.useCallback)(
979
+ (node) => {
980
+ if (!loadData) return;
981
+ const key = node.key;
982
+ if (treeState.loadedKeys.includes(key) || treeState.loadingKeys.includes(key)) return;
983
+ markLoading(key);
984
+ loadData(node).then(() => {
985
+ markLoaded(key);
986
+ });
987
+ },
988
+ [loadData, treeState.loadedKeys, treeState.loadingKeys, markLoading, markLoaded]
989
+ );
990
+ const handleDragStart = (0, import_react6.useCallback)(
991
+ (e, key) => {
992
+ setDragKey(key);
993
+ e.dataTransfer.effectAllowed = "move";
994
+ const node = tree.getNode(key);
995
+ if (node) onDragStart?.({ event: e, node });
996
+ },
997
+ [tree, onDragStart]
998
+ );
999
+ const handleDragOver = (0, import_react6.useCallback)(
1000
+ (e, key) => {
1001
+ e.preventDefault();
1002
+ setDropKey(key);
1003
+ const rect = e.currentTarget.getBoundingClientRect();
1004
+ const y = e.clientY - rect.top;
1005
+ const h = rect.height;
1006
+ let pos = 0;
1007
+ if (y < h * 0.25) pos = -1;
1008
+ else if (y > h * 0.75) pos = 1;
1009
+ setDropPosition(pos);
1010
+ const node = tree.getNode(key);
1011
+ if (node) onDragOver?.({ event: e, node });
1012
+ },
1013
+ [tree, onDragOver]
1014
+ );
1015
+ const handleDragLeave = (0, import_react6.useCallback)(
1016
+ (e, key) => {
1017
+ setDropKey(null);
1018
+ const node = tree.getNode(key);
1019
+ if (node) onDragLeave?.({ event: e, node });
1020
+ },
1021
+ [tree, onDragLeave]
1022
+ );
1023
+ const handleDragEnd = (0, import_react6.useCallback)(
1024
+ (e, key) => {
1025
+ setDragKey(null);
1026
+ setDropKey(null);
1027
+ const node = tree.getNode(key);
1028
+ if (node) onDragEnd?.({ event: e, node });
1029
+ },
1030
+ [tree, onDragEnd]
1031
+ );
1032
+ const handleDrop = (0, import_react6.useCallback)(
1033
+ (e, key) => {
1034
+ e.preventDefault();
1035
+ if (dragKey === null || dragKey === key) {
1036
+ setDragKey(null);
1037
+ setDropKey(null);
1038
+ return;
1039
+ }
1040
+ const dragNode = tree.getNode(dragKey);
1041
+ const dropNode = tree.getNode(key);
1042
+ if (!dragNode || !dropNode) return;
1043
+ if (allowDrop && !allowDrop({ dragNode, dropNode, dropPosition })) {
1044
+ setDragKey(null);
1045
+ setDropKey(null);
1046
+ return;
1047
+ }
1048
+ moveNode(dragKey, key, dropPosition);
1049
+ if (onDrop) {
1050
+ onDrop({ event: e, node: dropNode, dragNode, dropPosition });
1051
+ }
1052
+ setDragKey(null);
1053
+ setDropKey(null);
1054
+ },
1055
+ [dragKey, dropPosition, tree, allowDrop, moveNode, onDrop]
1056
+ );
1057
+ const handleRightClick = (0, import_react6.useCallback)(
1058
+ (e, node) => {
1059
+ onRightClick?.({ event: e, node });
1060
+ },
1061
+ [onRightClick]
1062
+ );
1063
+ const isDraggable = (node) => {
1064
+ if (typeof draggable === "function") return draggable(node);
1065
+ return !!draggable;
1066
+ };
1067
+ const containerRef = (0, import_react6.useRef)(null);
1068
+ const [scrollTop, setScrollTop] = (0, import_react6.useState)(0);
1069
+ const itemHeight = NODE_HEIGHT;
1070
+ const scrollToFocused = (0, import_react6.useCallback)(
1071
+ (key) => {
1072
+ const index = flatNodes.findIndex((item) => item.key === key);
1073
+ if (index === -1) return;
1074
+ const el = containerRef.current ?? treeRef.current;
1075
+ if (!el) return;
1076
+ const targetTop = index * itemHeight;
1077
+ const { scrollTop: st, clientHeight: ch } = el;
1078
+ if (targetTop < st) {
1079
+ el.scrollTop = targetTop;
1080
+ } else if (targetTop + itemHeight > st + ch) {
1081
+ el.scrollTop = targetTop + itemHeight - ch;
1082
+ }
1083
+ },
1084
+ [flatNodes, itemHeight]
1085
+ );
1086
+ const handleKeyDown = (0, import_react6.useCallback)(
1087
+ (e) => {
1088
+ if (!keyboard || disabled || editingKey !== null) return;
1089
+ const currentIndex = flatNodes.findIndex((item) => item.key === focusedKey);
1090
+ if (currentIndex === -1 && flatNodes.length === 0) return;
1091
+ const focusNode = (index) => {
1092
+ if (index >= 0 && index < flatNodes.length) {
1093
+ setFocusedKey(flatNodes[index].key);
1094
+ scrollToFocused(flatNodes[index].key);
1095
+ }
1096
+ };
1097
+ switch (e.key) {
1098
+ case "ArrowDown": {
1099
+ e.preventDefault();
1100
+ focusNode(currentIndex === -1 ? 0 : Math.min(currentIndex + 1, flatNodes.length - 1));
1101
+ break;
1102
+ }
1103
+ case "ArrowUp": {
1104
+ e.preventDefault();
1105
+ focusNode(currentIndex === -1 ? 0 : Math.max(currentIndex - 1, 0));
1106
+ break;
1107
+ }
1108
+ case "ArrowRight": {
1109
+ e.preventDefault();
1110
+ if (currentIndex === -1) break;
1111
+ const item = flatNodes[currentIndex];
1112
+ if (!item.isLeaf && !treeState.expandedKeys.includes(item.key)) {
1113
+ handleExpand(item.key);
1114
+ } else if (!item.isLeaf && treeState.expandedKeys.includes(item.key)) {
1115
+ focusNode(currentIndex + 1);
1116
+ }
1117
+ break;
1118
+ }
1119
+ case "ArrowLeft": {
1120
+ e.preventDefault();
1121
+ if (currentIndex === -1) break;
1122
+ const item = flatNodes[currentIndex];
1123
+ if (!item.isLeaf && treeState.expandedKeys.includes(item.key)) {
1124
+ handleExpand(item.key);
1125
+ } else if (item.parentKey !== null) {
1126
+ const parentIndex = flatNodes.findIndex((n) => n.key === item.parentKey);
1127
+ if (parentIndex !== -1) focusNode(parentIndex);
1128
+ }
1129
+ break;
1130
+ }
1131
+ case "Home": {
1132
+ e.preventDefault();
1133
+ focusNode(0);
1134
+ break;
1135
+ }
1136
+ case "End": {
1137
+ e.preventDefault();
1138
+ focusNode(flatNodes.length - 1);
1139
+ break;
1140
+ }
1141
+ case "Enter": {
1142
+ e.preventDefault();
1143
+ if (currentIndex === -1) break;
1144
+ const item = flatNodes[currentIndex];
1145
+ if (selectable) handleSelect(item.key);
1146
+ break;
1147
+ }
1148
+ case " ": {
1149
+ e.preventDefault();
1150
+ if (currentIndex === -1) break;
1151
+ const item = flatNodes[currentIndex];
1152
+ if (checkable) handleCheck(item.key);
1153
+ else if (!item.isLeaf) handleExpand(item.key);
1154
+ break;
1155
+ }
1156
+ case "*": {
1157
+ e.preventDefault();
1158
+ expandAll();
1159
+ break;
1160
+ }
1161
+ case "F2": {
1162
+ e.preventDefault();
1163
+ if (currentIndex === -1) break;
1164
+ const item = flatNodes[currentIndex];
1165
+ if (isNodeEditable(item.node)) {
1166
+ handleEditStart(item.key);
1167
+ }
1168
+ break;
1169
+ }
1170
+ }
1171
+ },
1172
+ [
1173
+ keyboard,
1174
+ disabled,
1175
+ editingKey,
1176
+ flatNodes,
1177
+ focusedKey,
1178
+ treeState.expandedKeys,
1179
+ handleExpand,
1180
+ handleCheck,
1181
+ handleSelect,
1182
+ expandAll,
1183
+ setFocusedKey,
1184
+ checkable,
1185
+ selectable,
1186
+ scrollToFocused,
1187
+ isNodeEditable,
1188
+ handleEditStart
1189
+ ]
1190
+ );
1191
+ const handleScroll = (0, import_react6.useCallback)(() => {
1192
+ if (containerRef.current) {
1193
+ setScrollTop(containerRef.current.scrollTop);
1194
+ }
1195
+ }, []);
1196
+ const useVirtual = virtual && height !== void 0 && flatNodes.length > 50;
1197
+ const VIRTUAL_OVERSCAN = 5;
1198
+ const visibleSlice = (0, import_react6.useMemo)(() => {
1199
+ if (!useVirtual || !height) {
1200
+ return { nodes: flatNodes, startIndex: 0 };
1201
+ }
1202
+ const rawStart = Math.floor(scrollTop / itemHeight);
1203
+ const startIndex = Math.max(0, rawStart - VIRTUAL_OVERSCAN);
1204
+ const visibleCount = Math.ceil(height / itemHeight) + VIRTUAL_OVERSCAN * 2;
1205
+ const endIndex = Math.min(flatNodes.length, startIndex + visibleCount);
1206
+ return { nodes: flatNodes.slice(startIndex, endIndex), startIndex };
1207
+ }, [flatNodes, useVirtual, height, scrollTop, itemHeight]);
1208
+ const visibleNodes = visibleSlice.nodes;
1209
+ const virtualOffset = visibleSlice.startIndex * itemHeight;
1210
+ const totalHeight = flatNodes.length * itemHeight;
1211
+ const virtualBottomPad = Math.max(
1212
+ 0,
1213
+ totalHeight - virtualOffset - visibleNodes.length * itemHeight
1214
+ );
1215
+ (0, import_react6.useEffect)(() => {
1216
+ if (scrollToKey !== void 0) {
1217
+ const index = flatNodes.findIndex((item) => item.key === scrollToKey);
1218
+ if (index !== -1) {
1219
+ scrollToFocused(scrollToKey);
1220
+ setFocusedKey(scrollToKey);
1221
+ }
1222
+ }
1223
+ }, [scrollToKey]);
1224
+ const handleExpandAll = (0, import_react6.useCallback)(() => {
1225
+ expandAll();
1226
+ if (onExpand) onExpand(tree.getState().expandedKeys, { expanded: true, node: treeData[0] });
1227
+ }, [expandAll, onExpand, tree, treeData]);
1228
+ const handleCollapseAll = (0, import_react6.useCallback)(() => {
1229
+ collapseAll();
1230
+ if (onExpand) onExpand([], { expanded: false, node: treeData[0] });
1231
+ }, [collapseAll, onExpand, treeData]);
1232
+ const handleCheckAll = (0, import_react6.useCallback)(() => {
1233
+ const allKeys = tree.getAllKeys();
1234
+ setCheckedKeys(allKeys);
1235
+ if (onCheck) {
1236
+ const allNodes = allKeys.map((k) => tree.getNode(k)).filter(Boolean);
1237
+ onCheck(allKeys, {
1238
+ checked: true,
1239
+ node: allNodes[0],
1240
+ checkedNodes: allNodes,
1241
+ halfCheckedKeys: []
1242
+ });
1243
+ }
1244
+ }, [tree, setCheckedKeys, onCheck]);
1245
+ const handleUncheckAll = (0, import_react6.useCallback)(() => {
1246
+ setCheckedKeys([]);
1247
+ if (onCheck) {
1248
+ onCheck([], { checked: false, node: treeData[0], checkedNodes: [], halfCheckedKeys: [] });
1249
+ }
1250
+ }, [setCheckedKeys, onCheck, treeData]);
1251
+ const siblingsMap = (0, import_react6.useMemo)(() => {
1252
+ if (!isShowLine) return null;
1253
+ const map = /* @__PURE__ */ new Map();
1254
+ function walk(list, depth, parentIsLast) {
1255
+ for (let i = 0; i < list.length; i++) {
1256
+ const node = list[i];
1257
+ const key = node.key;
1258
+ const isLast = i === list.length - 1;
1259
+ map.set(key, { isLast, parentIsLast: [...parentIsLast] });
1260
+ const children = node.children;
1261
+ if (children && children.length > 0) {
1262
+ walk(children, depth + 1, [...parentIsLast, isLast]);
1263
+ }
1264
+ }
1265
+ }
1266
+ walk(treeData, 0, []);
1267
+ return map;
1268
+ }, [treeData, isShowLine]);
1269
+ const renderNode = (item) => {
1270
+ const lineInfo = siblingsMap?.get(item.key);
1271
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1272
+ TreeNodeRow,
1273
+ {
1274
+ node: item.node,
1275
+ nodeKey: item.key,
1276
+ depth: item.depth,
1277
+ isLeaf: item.isLeaf,
1278
+ indentSize,
1279
+ expanded: treeState.expandedKeys.includes(item.key),
1280
+ checked: treeState.checkedKeys.includes(item.key),
1281
+ halfChecked: treeState.halfCheckedKeys.includes(item.key),
1282
+ selected: treeState.selectedKeys.includes(item.key),
1283
+ loading: treeState.loadingKeys.includes(item.key),
1284
+ disabled: disabled || !!item.node.disabled,
1285
+ focused: focusedKey === item.key,
1286
+ checkable,
1287
+ selectable,
1288
+ showLine: isShowLine,
1289
+ showLeafIcon: showLineConfig.showLeafIcon ?? false,
1290
+ showIcon: showIcon || directory,
1291
+ blockNode,
1292
+ directory,
1293
+ animated,
1294
+ globalIcon,
1295
+ nodeIcon: item.node.icon,
1296
+ switcherIcon,
1297
+ draggable: isDraggable(item.node),
1298
+ dropPosition: dropKey === item.key ? dropPosition : null,
1299
+ dragKey,
1300
+ t,
1301
+ onExpand: handleExpand,
1302
+ onCheck: handleCheck,
1303
+ onSelect: handleSelect,
1304
+ onDragStart: handleDragStart,
1305
+ onDragOver: handleDragOver,
1306
+ onDragLeave: handleDragLeave,
1307
+ onDragEnd: handleDragEnd,
1308
+ onDrop: handleDrop,
1309
+ onRightClick: onRightClick ? handleRightClick : void 0,
1310
+ onLoadData: loadData ? handleLoadData : void 0,
1311
+ nodeClassName: item.node.className,
1312
+ nodeStyle: item.node.style,
1313
+ titleRender,
1314
+ searchValue: highlightSearch ? searchValue : "",
1315
+ editable: isNodeEditable(item.node),
1316
+ editing: editingKey === item.key,
1317
+ onEditStart: handleEditStart,
1318
+ onEditConfirm: handleEditConfirm,
1319
+ onEditCancel: handleEditCancelInternal,
1320
+ actions,
1321
+ status: nodeStatus?.(item.node) ?? "default",
1322
+ lineIsLast: lineInfo?.isLast ?? false,
1323
+ lineParentIsLast: lineInfo?.parentIsLast ?? [],
1324
+ onFocusNode: setFocusedKey
1325
+ },
1326
+ item.key
1327
+ );
1328
+ };
1329
+ if (unstyled) {
1330
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1331
+ "div",
1332
+ {
1333
+ ref: treeRef,
1334
+ className,
1335
+ style,
1336
+ role: "tree",
1337
+ tabIndex: 0,
1338
+ onKeyDown: handleKeyDown,
1339
+ children: flatNodes.map((item) => renderNode(item))
1340
+ }
1341
+ );
1342
+ }
1343
+ const wrapperCls = [
1344
+ "sg-tree",
1345
+ isShowLine ? "sg-tree-show-line" : "",
1346
+ blockNode ? "sg-tree-block-node" : "",
1347
+ directory ? "sg-tree-directory" : "",
1348
+ disabled ? "sg-tree-disabled" : "",
1349
+ animated ? "sg-tree-animated" : "",
1350
+ className
1351
+ ].filter(Boolean).join(" ");
1352
+ const renderSearch = () => {
1353
+ if (!showSearch) return null;
1354
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sg-tree-search", children: [
1355
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1356
+ "input",
1357
+ {
1358
+ className: "sg-tree-search-input",
1359
+ type: "text",
1360
+ value: searchValue,
1361
+ onChange: (e) => handleSearchChange(e.target.value),
1362
+ placeholder: t.searchPlaceholder,
1363
+ "aria-label": t.searchPlaceholder
1364
+ }
1365
+ ),
1366
+ searchValue && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1367
+ "button",
1368
+ {
1369
+ className: "sg-tree-search-clear",
1370
+ onClick: () => handleSearchChange(""),
1371
+ "aria-label": t.clearSearch,
1372
+ type: "button",
1373
+ children: "\xD7"
1374
+ }
1375
+ )
1376
+ ] });
1377
+ };
1378
+ const renderToolbar = () => {
1379
+ if (!showToolbar) return null;
1380
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sg-tree-toolbar", children: [
1381
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "sg-tree-toolbar-actions", children: [
1382
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1383
+ "button",
1384
+ {
1385
+ className: "sg-tree-toolbar-btn",
1386
+ onClick: handleExpandAll,
1387
+ title: t.expandAllText,
1388
+ type: "button",
1389
+ children: "\u229E"
1390
+ }
1391
+ ),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1393
+ "button",
1394
+ {
1395
+ className: "sg-tree-toolbar-btn",
1396
+ onClick: handleCollapseAll,
1397
+ title: t.collapseAllText,
1398
+ type: "button",
1399
+ children: "\u229F"
1400
+ }
1401
+ ),
1402
+ checkable && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1403
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "sg-tree-toolbar-divider" }),
1404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1405
+ "button",
1406
+ {
1407
+ className: "sg-tree-toolbar-btn",
1408
+ onClick: handleCheckAll,
1409
+ title: t.checkAllText,
1410
+ type: "button",
1411
+ children: "\u2611"
1412
+ }
1413
+ ),
1414
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1415
+ "button",
1416
+ {
1417
+ className: "sg-tree-toolbar-btn",
1418
+ onClick: handleUncheckAll,
1419
+ title: t.uncheckAllText,
1420
+ type: "button",
1421
+ children: "\u2610"
1422
+ }
1423
+ )
1424
+ ] })
1425
+ ] }),
1426
+ toolbarExtra && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "sg-tree-toolbar-extra", children: toolbarExtra })
1427
+ ] });
1428
+ };
1429
+ const renderNodes = (list) => list.map((item) => renderNode(item));
1430
+ if (flatNodes.length === 0) {
1431
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: wrapperCls, style, role: "tree", children: [
1432
+ renderSearch(),
1433
+ renderToolbar(),
1434
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "sg-tree-empty", children: t.emptyText })
1435
+ ] });
1436
+ }
1437
+ if (useVirtual && height) {
1438
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: wrapperCls, style, children: [
1439
+ renderSearch(),
1440
+ renderToolbar(),
1441
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1442
+ "div",
1443
+ {
1444
+ ref: containerRef,
1445
+ className: "sg-tree-virtual-container",
1446
+ style: { height, overflow: "auto" },
1447
+ onScroll: handleScroll,
1448
+ onKeyDown: handleKeyDown,
1449
+ role: "tree",
1450
+ tabIndex: 0,
1451
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1452
+ "div",
1453
+ {
1454
+ style: {
1455
+ paddingTop: virtualOffset,
1456
+ paddingBottom: virtualBottomPad,
1457
+ boxSizing: "border-box"
1458
+ },
1459
+ children: renderNodes(visibleNodes)
1460
+ }
1461
+ )
1462
+ }
1463
+ )
1464
+ ] });
1465
+ }
1466
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1467
+ "div",
1468
+ {
1469
+ ref: treeRef,
1470
+ className: wrapperCls,
1471
+ style,
1472
+ role: "tree",
1473
+ tabIndex: 0,
1474
+ onKeyDown: handleKeyDown,
1475
+ children: [
1476
+ renderSearch(),
1477
+ renderToolbar(),
1478
+ renderNodes(visibleNodes)
1479
+ ]
1480
+ }
1481
+ );
1482
+ }
1483
+
1484
+ // src/components/complex/TreeSelect/TreeSelect.tsx
1485
+ var import_react7 = require("react");
1486
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1487
+ function toArray(val) {
1488
+ if (val === void 0) return [];
1489
+ return Array.isArray(val) ? val : [val];
1490
+ }
1491
+ function collectAllKeys(nodes) {
1492
+ const keys = [];
1493
+ const walk = (list) => {
1494
+ for (const n of list) {
1495
+ keys.push(n.key);
1496
+ if (n.children) walk(n.children);
1497
+ }
1498
+ };
1499
+ walk(nodes);
1500
+ return keys;
1501
+ }
1502
+ function findNode(nodes, key) {
1503
+ for (const n of nodes) {
1504
+ if (n.key === key) return n;
1505
+ if (n.children) {
1506
+ const found = findNode(n.children, key);
1507
+ if (found) return found;
1508
+ }
1509
+ }
1510
+ return void 0;
1511
+ }
1512
+ function getNodeLabel(node) {
1513
+ if (!node) return "";
1514
+ return node.title ?? String(node.key);
1515
+ }
1516
+ function filterTreeKeepMatches(nodes, predicate) {
1517
+ const result = [];
1518
+ for (const node of nodes) {
1519
+ const childResult = node.children ? filterTreeKeepMatches(node.children, predicate) : [];
1520
+ if (predicate(node) || childResult.length > 0) {
1521
+ result.push({
1522
+ ...node,
1523
+ children: childResult.length > 0 ? childResult : void 0
1524
+ });
1525
+ }
1526
+ }
1527
+ return result;
1528
+ }
1529
+ function getParentKeys(nodes, targetKey) {
1530
+ const parents = [];
1531
+ const walk = (list, path) => {
1532
+ for (const n of list) {
1533
+ if (n.key === targetKey) {
1534
+ parents.push(...path);
1535
+ return true;
1536
+ }
1537
+ if (n.children && walk(n.children, [...path, n.key])) return true;
1538
+ }
1539
+ return false;
1540
+ };
1541
+ walk(nodes, []);
1542
+ return parents;
1543
+ }
1544
+ function applyStrategy(checkedKeys, treeData, strategy) {
1545
+ if (strategy === "SHOW_ALL") return checkedKeys;
1546
+ const checkedSet = new Set(checkedKeys);
1547
+ if (strategy === "SHOW_CHILD") {
1548
+ return checkedKeys.filter((key) => {
1549
+ const node = findNode(treeData, key);
1550
+ return !node?.children || node.children.length === 0;
1551
+ });
1552
+ }
1553
+ if (strategy === "SHOW_PARENT") {
1554
+ return checkedKeys.filter((key) => {
1555
+ const parentKeys = getParentKeys(treeData, key);
1556
+ return !parentKeys.some((pk) => checkedSet.has(pk));
1557
+ });
1558
+ }
1559
+ return checkedKeys;
1560
+ }
1561
+ function TreeSelect(props) {
1562
+ const {
1563
+ treeData,
1564
+ value: controlledValue,
1565
+ defaultValue,
1566
+ onChange,
1567
+ fieldNames,
1568
+ multiple = false,
1569
+ treeCheckable = false,
1570
+ treeCheckStrictly = false,
1571
+ treeDefaultExpandAll = false,
1572
+ treeDefaultExpandedKeys,
1573
+ showSearch = false,
1574
+ filterTreeNode,
1575
+ placeholder = "Please select",
1576
+ allowClear = false,
1577
+ disabled = false,
1578
+ size = "middle",
1579
+ maxTagCount,
1580
+ dropdownStyle,
1581
+ treeLine = false,
1582
+ showCheckedStrategy = "SHOW_ALL",
1583
+ onSearch,
1584
+ className,
1585
+ style,
1586
+ unstyled
1587
+ } = props;
1588
+ const treeSelectLocale = useConfig().locale?.treeSelect;
1589
+ const searchPlaceholder = treeSelectLocale?.searchPlaceholder ?? "Search...";
1590
+ const noMatchesText = treeSelectLocale?.noMatches ?? "No matches";
1591
+ const isMultiple = multiple || treeCheckable;
1592
+ const [internalValue, setInternalValue] = (0, import_react7.useState)(
1593
+ () => toArray(controlledValue ?? defaultValue)
1594
+ );
1595
+ const [open, setOpen] = (0, import_react7.useState)(false);
1596
+ const [searchValue, setSearchValue] = (0, import_react7.useState)("");
1597
+ const wrapperRef = (0, import_react7.useRef)(null);
1598
+ const searchRef = (0, import_react7.useRef)(null);
1599
+ const currentValue = (0, import_react7.useMemo)(
1600
+ () => toArray(controlledValue ?? internalValue),
1601
+ [controlledValue, internalValue]
1602
+ );
1603
+ (0, import_react7.useEffect)(() => {
1604
+ if (controlledValue !== void 0) {
1605
+ setInternalValue(toArray(controlledValue));
1606
+ }
1607
+ }, [controlledValue]);
1608
+ (0, import_react7.useEffect)(() => {
1609
+ const handleClickOutside = (e) => {
1610
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
1611
+ setOpen(false);
1612
+ setSearchValue("");
1613
+ }
1614
+ };
1615
+ document.addEventListener("mousedown", handleClickOutside);
1616
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1617
+ }, []);
1618
+ (0, import_react7.useEffect)(() => {
1619
+ if (open && showSearch && searchRef.current) {
1620
+ searchRef.current.focus();
1621
+ }
1622
+ }, [open, showSearch]);
1623
+ const defaultFilter = (0, import_react7.useCallback)((input, node) => {
1624
+ const title = String(node.title ?? node.key).toLowerCase();
1625
+ return title.includes(input.toLowerCase());
1626
+ }, []);
1627
+ const filterFn = filterTreeNode ?? defaultFilter;
1628
+ const filteredTreeData = (0, import_react7.useMemo)(() => {
1629
+ if (!searchValue) return treeData;
1630
+ return filterTreeKeepMatches(treeData, (node) => filterFn(searchValue, node));
1631
+ }, [treeData, searchValue, filterFn]);
1632
+ const filteredExpandedKeys = (0, import_react7.useMemo)(() => {
1633
+ if (!searchValue) return void 0;
1634
+ return collectAllKeys(filteredTreeData);
1635
+ }, [searchValue, filteredTreeData]);
1636
+ const fireChange = (0, import_react7.useCallback)(
1637
+ (keys, triggerNode) => {
1638
+ setInternalValue(keys);
1639
+ const labels = keys.map((k) => getNodeLabel(findNode(treeData, k)));
1640
+ if (onChange) {
1641
+ const result = isMultiple ? keys : keys[0];
1642
+ onChange(result, labels, { triggerNode });
1643
+ }
1644
+ },
1645
+ [treeData, onChange, isMultiple]
1646
+ );
1647
+ const handleTreeSelect = (0, import_react7.useCallback)(
1648
+ (_selectedKeys, info) => {
1649
+ if (treeCheckable) return;
1650
+ const node = info.node;
1651
+ if (isMultiple) {
1652
+ const newKeys = info.selected ? [...currentValue, node.key] : currentValue.filter((k) => k !== node.key);
1653
+ fireChange(newKeys, node);
1654
+ } else {
1655
+ fireChange([node.key], node);
1656
+ setOpen(false);
1657
+ setSearchValue("");
1658
+ }
1659
+ },
1660
+ [treeCheckable, isMultiple, currentValue, fireChange]
1661
+ );
1662
+ const handleTreeCheck = (0, import_react7.useCallback)(
1663
+ (checkedKeys, info) => {
1664
+ const displayed = applyStrategy(checkedKeys, treeData, showCheckedStrategy);
1665
+ fireChange(displayed, info.node);
1666
+ },
1667
+ [treeData, showCheckedStrategy, fireChange]
1668
+ );
1669
+ const handleRemoveTag = (0, import_react7.useCallback)(
1670
+ (key, e) => {
1671
+ e.stopPropagation();
1672
+ if (disabled) return;
1673
+ const node = findNode(treeData, key) ?? { key };
1674
+ const newKeys = currentValue.filter((k) => k !== key);
1675
+ fireChange(newKeys, node);
1676
+ },
1677
+ [disabled, treeData, currentValue, fireChange]
1678
+ );
1679
+ const handleClear = (0, import_react7.useCallback)(
1680
+ (e) => {
1681
+ e.stopPropagation();
1682
+ if (disabled) return;
1683
+ const node = treeData[0] ?? { key: "" };
1684
+ fireChange([], node);
1685
+ setSearchValue("");
1686
+ },
1687
+ [disabled, treeData, fireChange]
1688
+ );
1689
+ const handleSearchChange = (0, import_react7.useCallback)(
1690
+ (e) => {
1691
+ const val = e.target.value;
1692
+ setSearchValue(val);
1693
+ onSearch?.(val);
1694
+ },
1695
+ [onSearch]
1696
+ );
1697
+ const handleTriggerClick = (0, import_react7.useCallback)(() => {
1698
+ if (disabled) return;
1699
+ setOpen((prev) => !prev);
1700
+ }, [disabled]);
1701
+ const displayedValues = (0, import_react7.useMemo)(() => {
1702
+ if (!isMultiple) return currentValue;
1703
+ return applyStrategy(currentValue, treeData, showCheckedStrategy);
1704
+ }, [isMultiple, currentValue, treeData, showCheckedStrategy]);
1705
+ const treeCheckedKeys = (0, import_react7.useMemo)(() => {
1706
+ if (!treeCheckable) return void 0;
1707
+ return currentValue;
1708
+ }, [treeCheckable, currentValue]);
1709
+ const treeSelectedKeys = (0, import_react7.useMemo)(() => {
1710
+ if (treeCheckable) return void 0;
1711
+ return currentValue;
1712
+ }, [treeCheckable, currentValue]);
1713
+ if (unstyled) {
1714
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: wrapperRef, className, style, children: [
1715
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { onClick: handleTriggerClick, children: [
1716
+ displayedValues.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: placeholder }),
1717
+ !isMultiple && displayedValues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: getNodeLabel(findNode(treeData, displayedValues[0])) }),
1718
+ isMultiple && displayedValues.map((key) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { children: [
1719
+ getNodeLabel(findNode(treeData, key)),
1720
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { onClick: (e) => handleRemoveTag(key, e), children: "\xD7" })
1721
+ ] }, String(key)))
1722
+ ] }),
1723
+ open && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1724
+ showSearch && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1725
+ "input",
1726
+ {
1727
+ ref: searchRef,
1728
+ value: searchValue,
1729
+ onChange: handleSearchChange,
1730
+ placeholder: searchPlaceholder
1731
+ }
1732
+ ),
1733
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1734
+ Tree,
1735
+ {
1736
+ treeData: filteredTreeData,
1737
+ fieldNames,
1738
+ checkable: treeCheckable,
1739
+ checkStrictly: treeCheckStrictly,
1740
+ checkedKeys: treeCheckedKeys,
1741
+ selectedKeys: treeSelectedKeys,
1742
+ multiple: isMultiple,
1743
+ defaultExpandAll: treeDefaultExpandAll,
1744
+ defaultExpandedKeys: treeDefaultExpandedKeys,
1745
+ expandedKeys: filteredExpandedKeys,
1746
+ showLine: treeLine,
1747
+ onSelect: handleTreeSelect,
1748
+ onCheck: handleTreeCheck,
1749
+ unstyled: true
1750
+ }
1751
+ )
1752
+ ] })
1753
+ ] });
1754
+ }
1755
+ const wrapperCls = [
1756
+ "sg-treeselect",
1757
+ `sg-treeselect-${size}`,
1758
+ open ? "sg-treeselect-open" : "",
1759
+ disabled ? "sg-treeselect-disabled" : "",
1760
+ isMultiple ? "sg-treeselect-multiple" : "",
1761
+ className
1762
+ ].filter(Boolean).join(" ");
1763
+ const visibleTags = maxTagCount !== void 0 && isMultiple ? displayedValues.slice(0, maxTagCount) : displayedValues;
1764
+ const hiddenCount = maxTagCount !== void 0 && isMultiple ? Math.max(0, displayedValues.length - maxTagCount) : 0;
1765
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: wrapperCls, style, ref: wrapperRef, children: [
1766
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "sg-treeselect-selector", onClick: handleTriggerClick, children: [
1767
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "sg-treeselect-selection-wrap", children: [
1768
+ displayedValues.length === 0 && !searchValue && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-placeholder", children: placeholder }),
1769
+ !isMultiple && displayedValues.length > 0 && !searchValue && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-selection-item", children: getNodeLabel(findNode(treeData, displayedValues[0])) }),
1770
+ isMultiple && visibleTags.map((key) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "sg-treeselect-tag", children: [
1771
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-tag-label", children: getNodeLabel(findNode(treeData, key)) }),
1772
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-tag-close", onClick: (e) => handleRemoveTag(key, e), children: "\xD7" })
1773
+ ] }, String(key))),
1774
+ hiddenCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "sg-treeselect-tag sg-treeselect-tag-rest", children: [
1775
+ "+",
1776
+ hiddenCount,
1777
+ "..."
1778
+ ] }),
1779
+ showSearch && open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1780
+ "input",
1781
+ {
1782
+ ref: searchRef,
1783
+ className: "sg-treeselect-search-input",
1784
+ value: searchValue,
1785
+ onChange: handleSearchChange,
1786
+ placeholder: displayedValues.length === 0 ? "" : ""
1787
+ }
1788
+ )
1789
+ ] }),
1790
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "sg-treeselect-actions", children: [
1791
+ allowClear && displayedValues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-clear", onClick: handleClear, children: "\xD7" }),
1792
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "sg-treeselect-arrow", children: open ? "\u25B2" : "\u25BC" })
1793
+ ] })
1794
+ ] }),
1795
+ open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "sg-treeselect-dropdown", style: dropdownStyle, children: filteredTreeData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "sg-treeselect-empty", children: noMatchesText }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1796
+ Tree,
1797
+ {
1798
+ treeData: filteredTreeData,
1799
+ fieldNames,
1800
+ checkable: treeCheckable,
1801
+ checkStrictly: treeCheckStrictly,
1802
+ checkedKeys: treeCheckedKeys,
1803
+ selectedKeys: treeSelectedKeys,
1804
+ multiple: isMultiple,
1805
+ defaultExpandAll: treeDefaultExpandAll,
1806
+ defaultExpandedKeys: treeDefaultExpandedKeys,
1807
+ expandedKeys: filteredExpandedKeys,
1808
+ showLine: treeLine,
1809
+ onSelect: handleTreeSelect,
1810
+ onCheck: handleTreeCheck
1811
+ }
1812
+ ) })
1813
+ ] });
1814
+ }
1815
+ // Annotate the CommonJS export names for ESM import in node:
1816
+ 0 && (module.exports = {
1817
+ Tree,
1818
+ TreeSelect,
1819
+ useTree
1820
+ });
1821
+ //# sourceMappingURL=tree.cjs.map