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