@ticatec/uniface-element 0.3.18 → 0.3.20

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.
@@ -0,0 +1,240 @@
1
+ # Split
2
+
3
+ A resizable splitter component that allows users to adjust the size of adjacent panels by dragging the divider. Perfect for creating resizable layouts with flexible panel sizing.
4
+
5
+ ## Features
6
+
7
+ - **Resizable Panels**: Drag to resize adjacent panels
8
+ - **Direction Support**: Horizontal and vertical orientations
9
+ - **Custom Width**: Set the divider width
10
+ - **Reverse Mode**: Optional reverse dragging direction
11
+ - **Fixed Mode**: Can be fixed (non-resizable)
12
+ - **Visual Feedback**: Cursor changes during drag operation
13
+ - **Minimum Size**: Enforces minimum panel size (5px)
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @ticatec/uniface-element
19
+ ```
20
+
21
+ ```typescript
22
+ import Split from '@ticatec/uniface-element/Split';
23
+ ```
24
+
25
+ ## Basic Usage
26
+
27
+ ```svelte
28
+ <script>
29
+ import Split from '@ticatec/uniface-element/Split';
30
+
31
+ let leftPanel;
32
+ let rightPanel;
33
+ </script>
34
+
35
+ <div style="display: flex; height: 300px;">
36
+ <div bind:this={leftPanel} style="flex: 0 0 200px; background: #f0f0f0;">
37
+ Left Panel
38
+ </div>
39
+ <Split bindingPanel={leftPanel} direction="horizontal" />
40
+ <div bind:this={rightPanel} style="flex: 1; background: #e0e0e0;">
41
+ Right Panel
42
+ </div>
43
+ </div>
44
+ ```
45
+
46
+ ## Props
47
+
48
+ | Prop | Type | Default | Description |
49
+ |------|------|---------|-------------|
50
+ | `direction` | `'horizontal' \| 'vertical'` | `'vertical'` | Splitter orientation |
51
+ | `width` | `number` | `2` | Width/thickness of the divider (px) |
52
+ | `bindingPanel` | `HTMLElement \| null` | `null` | Reference to the panel to resize |
53
+ | `reverse` | `boolean` | `false` | Reverse the drag direction |
54
+
55
+ ## Examples
56
+
57
+ ### Horizontal Split
58
+
59
+ ```svelte
60
+ <script>
61
+ import Split from '@ticatec/uniface-element/Split';
62
+
63
+ let panel1;
64
+ let panel2;
65
+ </script>
66
+
67
+ <div style="display: flex; height: 400px;">
68
+ <div bind:this={panel1} style="flex: 0 0 250px; padding: 16px; background: #f5f5f5;">
69
+ <h3>Left Panel</h3>
70
+ <p>Resize me by dragging the divider!</p>
71
+ </div>
72
+
73
+ <Split bindingPanel={panel1} direction="horizontal" width="4" />
74
+
75
+ <div style="flex: 1; padding: 16px; background: #e8e8e8;">
76
+ <h3>Right Panel</h3>
77
+ <p>This panel fills remaining space</p>
78
+ </div>
79
+ </div>
80
+ ```
81
+
82
+ ### Vertical Split
83
+
84
+ ```svelte
85
+ <script>
86
+ import Split from '@ticatec/uniface-element/Split';
87
+
88
+ let topPanel;
89
+ let bottomPanel;
90
+ </script>
91
+
92
+ <div style="display: flex; flex-direction: column; height: 400px;">
93
+ <div bind:this={topPanel} style="flex: 0 0 150px; padding: 16px; background: #f5f5f5;">
94
+ <h3>Top Panel</h3>
95
+ </div>
96
+
97
+ <Split bindingPanel={topPanel} direction="vertical" width="4" />
98
+
99
+ <div style="flex: 1; padding: 16px; background: #e8e8e8;">
100
+ <h3>Bottom Panel</h3>
101
+ </div>
102
+ </div>
103
+ ```
104
+
105
+ ### Custom Width
106
+
107
+ ```svelte
108
+ <script>
109
+ import Split from '@ticatec/uniface-element/Split';
110
+
111
+ let panel1;
112
+ let panel2;
113
+ </script>
114
+
115
+ <div style="display: flex; height: 300px;">
116
+ <div bind:this={panel1} style="flex: 0 0 200px; background: #f0f0f0;">
117
+ Panel 1
118
+ </div>
119
+
120
+ <!-- Thick divider -->
121
+ <Split bindingPanel={panel1} width="8" />
122
+
123
+ <div style="flex: 1; background: #e0e0e0;">
124
+ Panel 2
125
+ </div>
126
+ </div>
127
+ ```
128
+
129
+ ### Reverse Direction
130
+
131
+ ```svelte
132
+ <script>
133
+ import Split from '@ticatec/uniface-element/Split';
134
+
135
+ let panel1;
136
+ let panel2;
137
+ </script>
138
+
139
+ <div style="display: flex; height: 300px;">
140
+ <div style="flex: 1; background: #e0e0e0;">
141
+ Panel 1 (expands when panel 2 shrinks)
142
+ </div>
143
+
144
+ <!-- Reverse mode: drags in opposite direction -->
145
+ <Split bindingPanel={panel1} reverse />
146
+
147
+ <div bind:this={panel2} style="flex: 0 0 200px; background: #f0f0f0;">
148
+ Panel 2
149
+ </div>
150
+ </div>
151
+ ```
152
+
153
+ ### Fixed Divider
154
+
155
+ ```svelte
156
+ <script>
157
+ import Split from '@ticatec/uniface-element/Split';
158
+ </script>
159
+
160
+ <!-- Without bindingPanel, the divider is fixed (non-resizable) -->
161
+ <div style="display: flex; height: 300px;">
162
+ <div style="flex: 1; background: #f0f0f0;">
163
+ Panel 1
164
+ </div>
165
+
166
+ <Split /> <!-- Fixed divider -->
167
+
168
+ <div style="flex: 1; background: #e0e0e0;">
169
+ Panel 2
170
+ </div>
171
+ </div>
172
+ ```
173
+
174
+ ### Complete Resizable Layout
175
+
176
+ ```svelte
177
+ <script>
178
+ import Split from '@ticatec/uniface-element/Split';
179
+
180
+ let sidebar;
181
+ let mainContent;
182
+ let detailPanel;
183
+ </script>
184
+
185
+ <div style="display: flex; height: 100vh;">
186
+ <!-- Sidebar -->
187
+ <div bind:this={sidebar} style="flex: 0 0 250px; background: #2d3748; color: white; padding: 16px;">
188
+ <h3>Sidebar</h3>
189
+ <ul>
190
+ <li>Menu Item 1</li>
191
+ <li>Menu Item 2</li>
192
+ <li>Menu Item 3</li>
193
+ </ul>
194
+ </div>
195
+
196
+ <!-- Vertical split for sidebar -->
197
+ <Split bindingPanel={sidebar} direction="horizontal" width="4" />
198
+
199
+ <!-- Main content area with vertical split -->
200
+ <div style="flex: 1; display: flex; flex-direction: column;">
201
+ <!-- Top panel -->
202
+ <div bind:this={mainContent} style="flex: 0 0 60%; background: #f7fafc; padding: 16px;">
203
+ <h2>Main Content</h2>
204
+ <p>This is the main content area. Drag the divider below to resize.</p>
205
+ </div>
206
+
207
+ <!-- Horizontal split -->
208
+ <Split bindingPanel={mainContent} direction="vertical" width="4" />
209
+
210
+ <!-- Bottom panel -->
211
+ <div style="flex: 1; background: #edf2f7; padding: 16px;">
212
+ <h3>Details Panel</h3>
213
+ <p>Additional details and information</p>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ ```
218
+
219
+ ## Best Practices
220
+
221
+ 1. **Panel References**: Always bind the panel you want to resize using `bindingPanel`
222
+ 2. **Flex Layout**: Use flexbox for predictable resizing behavior
223
+ 3. **Initial Sizes**: Set reasonable initial sizes for resizable panels
224
+ 4. **Minimum Size**: The component enforces a 5px minimum panel size
225
+ 5. **User Feedback**: Cursor changes provide visual feedback during dragging
226
+ 6. **Fixed Dividers**: Don't provide `bindingPanel` for non-resizable dividers
227
+
228
+ ## Browser Support
229
+
230
+ - Modern browsers with full flexbox support
231
+ - Mouse events for drag functionality
232
+ - Touch devices (with touch event handling)
233
+
234
+ ## Notes
235
+
236
+ - The `bindingPanel` must be a valid HTML element reference
237
+ - Minimum panel size is enforced at 5px to prevent collapse
238
+ - Drag operation updates the panel's style directly
239
+ - Cursor automatically changes during drag operation
240
+ - The component uses `mousedown`, `mousemove`, and `mouseup` events
@@ -0,0 +1,240 @@
1
+ # Split 分割器
2
+
3
+ 一个可调整大小的分割器组件,允许用户通过拖动分割线来调整相邻面板的大小。非常适合创建具有灵活面板大小的可调整布局。
4
+
5
+ ## 特性
6
+
7
+ - **可调整面板**: 拖动以调整相邻面板的大小
8
+ - **方向支持**: 水平和垂直方向
9
+ - **自定义宽度**: 设置分割线的宽度
10
+ - **反向模式**: 可选的反向拖动方向
11
+ - **固定模式**: 可以是固定的(不可调整大小)
12
+ - **视觉反馈**: 拖动操作期间光标变化
13
+ - **最小尺寸**: 强制执行最小面板尺寸(5px)
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install @ticatec/uniface-element
19
+ ```
20
+
21
+ ```typescript
22
+ import Split from '@ticatec/uniface-element/Split';
23
+ ```
24
+
25
+ ## 基本用法
26
+
27
+ ```svelte
28
+ <script>
29
+ import Split from '@ticatec/uniface-element/Split';
30
+
31
+ let leftPanel;
32
+ let rightPanel;
33
+ </script>
34
+
35
+ <div style="display: flex; height: 300px;">
36
+ <div bind:this={leftPanel} style="flex: 0 0 200px; background: #f0f0f0;">
37
+ 左侧面板
38
+ </div>
39
+ <Split bindingPanel={leftPanel} direction="horizontal" />
40
+ <div bind:this={rightPanel} style="flex: 1; background: #e0e0e0;">
41
+ 右侧面板
42
+ </div>
43
+ </div>
44
+ ```
45
+
46
+ ## 属性
47
+
48
+ | 属性 | 类型 | 默认值 | 说明 |
49
+ |------|------|---------|-------------|
50
+ | `direction` | `'horizontal' \| 'vertical'` | `'vertical'` | 分割器方向 |
51
+ | `width` | `number` | `2` | 分割线的宽度/厚度(px) |
52
+ | `bindingPanel` | `HTMLElement \| null` | `null` | 要调整大小的面板的引用 |
53
+ | `reverse` | `boolean` | `false` | 反向拖动方向 |
54
+
55
+ ## 示例
56
+
57
+ ### 水平分割
58
+
59
+ ```svelte
60
+ <script>
61
+ import Split from '@ticatec/uniface-element/Split';
62
+
63
+ let panel1;
64
+ let panel2;
65
+ </script>
66
+
67
+ <div style="display: flex; height: 400px;">
68
+ <div bind:this={panel1} style="flex: 0 0 250px; padding: 16px; background: #f5f5f5;">
69
+ <h3>左侧面板</h3>
70
+ <p>通过拖动分割线调整我的大小!</p>
71
+ </div>
72
+
73
+ <Split bindingPanel={panel1} direction="horizontal" width="4" />
74
+
75
+ <div style="flex: 1; padding: 16px; background: #e8e8e8;">
76
+ <h3>右侧面板</h3>
77
+ <p>此面板填充剩余空间</p>
78
+ </div>
79
+ </div>
80
+ ```
81
+
82
+ ### 垂直分割
83
+
84
+ ```svelte
85
+ <script>
86
+ import Split from '@ticatec/uniface-element/Split';
87
+
88
+ let topPanel;
89
+ let bottomPanel;
90
+ </script>
91
+
92
+ <div style="display: flex; flex-direction: column; height: 400px;">
93
+ <div bind:this={topPanel} style="flex: 0 0 150px; padding: 16px; background: #f5f5f5;">
94
+ <h3>顶部面板</h3>
95
+ </div>
96
+
97
+ <Split bindingPanel={topPanel} direction="vertical" width="4" />
98
+
99
+ <div style="flex: 1; padding: 16px; background: #e8e8e8;">
100
+ <h3>底部面板</h3>
101
+ </div>
102
+ </div>
103
+ ```
104
+
105
+ ### 自定义宽度
106
+
107
+ ```svelte
108
+ <script>
109
+ import Split from '@ticatec/uniface-element/Split';
110
+
111
+ let panel1;
112
+ let panel2;
113
+ </script>
114
+
115
+ <div style="display: flex; height: 300px;">
116
+ <div bind:this={panel1} style="flex: 0 0 200px; background: #f0f0f0;">
117
+ 面板 1
118
+ </div>
119
+
120
+ <!-- 粗分割线 -->
121
+ <Split bindingPanel={panel1} width="8" />
122
+
123
+ <div style="flex: 1; background: #e0e0e0;">
124
+ 面板 2
125
+ </div>
126
+ </div>
127
+ ```
128
+
129
+ ### 反向方向
130
+
131
+ ```svelte
132
+ <script>
133
+ import Split from '@ticatec/uniface-element/Split';
134
+
135
+ let panel1;
136
+ let panel2;
137
+ </script>
138
+
139
+ <div style="display: flex; height: 300px;">
140
+ <div style="flex: 1; background: #e0e0e0;">
141
+ 面板 1(面板2缩小时展开)
142
+ </div>
143
+
144
+ <!-- 反向模式:向相反方向拖动 -->
145
+ <Split bindingPanel={panel1} reverse />
146
+
147
+ <div bind:this={panel2} style="flex: 0 0 200px; background: #f0f0f0;">
148
+ 面板 2
149
+ </div>
150
+ </div>
151
+ ```
152
+
153
+ ### 固定分割线
154
+
155
+ ```svelte
156
+ <script>
157
+ import Split from '@ticatec/uniface-element/Split';
158
+ </script>
159
+
160
+ <!-- 没有 bindingPanel 时,分割线是固定的(不可调整大小) -->
161
+ <div style="display: flex; height: 300px;">
162
+ <div style="flex: 1; background: #f0f0f0;">
163
+ 面板 1
164
+ </div>
165
+
166
+ <Split /> <!-- 固定分割线 -->
167
+
168
+ <div style="flex: 1; background: #e0e0e0;">
169
+ 面板 2
170
+ </div>
171
+ </div>
172
+ ```
173
+
174
+ ### 完整的可调整布局
175
+
176
+ ```svelte
177
+ <script>
178
+ import Split from '@ticatec/uniface-element/Split';
179
+
180
+ let sidebar;
181
+ let mainContent;
182
+ let detailPanel;
183
+ </script>
184
+
185
+ <div style="display: flex; height: 100vh;">
186
+ <!-- 侧边栏 -->
187
+ <div bind:this={sidebar} style="flex: 0 0 250px; background: #2d3748; color: white; padding: 16px;">
188
+ <h3>侧边栏</h3>
189
+ <ul>
190
+ <li>菜单项 1</li>
191
+ <li>菜单项 2</li>
192
+ <li>菜单项 3</li>
193
+ </ul>
194
+ </div>
195
+
196
+ <!-- 侧边栏的垂直分割 -->
197
+ <Split bindingPanel={sidebar} direction="horizontal" width="4" />
198
+
199
+ <!-- 主内容区域,带有垂直分割 -->
200
+ <div style="flex: 1; display: flex; flex-direction: column;">
201
+ <!-- 顶部面板 -->
202
+ <div bind:this={mainContent} style="flex: 0 0 60%; background: #f7fafc; padding: 16px;">
203
+ <h2>主要内容</h2>
204
+ <p>这是主内容区域。拖动下方的分割线来调整大小。</p>
205
+ </div>
206
+
207
+ <!-- 水平分割 -->
208
+ <Split bindingPanel={mainContent} direction="vertical" width="4" />
209
+
210
+ <!-- 底部面板 -->
211
+ <div style="flex: 1; background: #edf2f7; padding: 16px;">
212
+ <h3>详情面板</h3>
213
+ <p>额外的详细信息和数据</p>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ ```
218
+
219
+ ## 最佳实践
220
+
221
+ 1. **面板引用**: 始终使用 `bindingPanel` 绑定要调整大小的面板
222
+ 2. **Flex 布局**: 使用 flexbox 以获得可预测的调整大小行为
223
+ 3. **初始大小**: 为可调整大小的面板设置合理的初始大小
224
+ 4. **最小尺寸**: 组件强制执行 5px 的最小面板尺寸
225
+ 5. **用户反馈**: 光标变化在拖动期间提供视觉反馈
226
+ 6. **固定分割线**: 对于不可调整大小的分割线,不提供 `bindingPanel`
227
+
228
+ ## 浏览器支持
229
+
230
+ - 支持完整 flexbox 的现代浏览器
231
+ - 用于拖动功能的鼠标事件
232
+ - 触摸设备(带有触摸事件处理)
233
+
234
+ ## 注意事项
235
+
236
+ - `bindingPanel` 必须是有效的 HTML 元素引用
237
+ - 强制执行最小面板尺寸为 5px 以防止折叠
238
+ - 拖动操作直接更新面板的样式
239
+ - 光标在拖动操作期间自动变化
240
+ - 组件使用 `mousedown`、`mousemove` 和 `mouseup` 事件
@@ -83,49 +83,57 @@ import TreeNodes, { TreeNode, NodeViewOptions } from "@ticatec/uniface-element/T
83
83
 
84
84
  ### TreeNode<T>
85
85
  ```typescript
86
- class TreeNode<T> {
87
- readonly item: T; // The actual data item
88
- readonly children: ReadonlyArray<TreeNode<T>>; // Child nodes (read-only)
89
- expand: boolean; // Whether node is expanded
90
- loading: boolean; // Whether node is loading (for lazy loading)
91
- parent: TreeNode<T> | null; // Parent node reference
86
+ class TreeNode<T> implements ITreeNode<T> {
87
+ readonly item: T; // The actual data item
88
+ get children(): Array<TreeNode<T>> | null; // Child nodes (shallow copy)
89
+ get level(): number; // Node level (root = 0)
90
+ expand: boolean; // Whether node is expanded
91
+ loading: boolean; // Whether node is loading (for lazy loading)
92
+ readonly parent: TreeNode<T> | null; // Parent node reference
92
93
 
93
94
  // Methods
94
- append(childItem: T): void; // Add a child node
95
- detach(): void; // Remove this node from parent
96
- moveTo(newParent: TreeNode<T>): void; // Move to different parent
97
- replace(newItem: T): void; // Replace node data
98
- removeChild(childId: any): void; // Remove specific child
99
- removeChildren(): void; // Remove all children
95
+ append(childItem: T | Array<T>): ITreeNode<T> | Array<ITreeNode<T>>; // Add child(ren)
96
+ detach(): void; // Remove this node from parent
97
+ moveTo(newParent: TreeNode<T>): TreeNode<T>; // Move to different parent
98
+ replace(newItem: T): void; // Replace node data
99
+ removeChildren(): void; // Remove all children
100
100
  }
101
101
  ```
102
102
 
103
- ### NodeViewOptions<T>
103
+ ### ITreeNode<T>
104
104
  ```typescript
105
- class NodeViewOptions<T> {
106
- keyField: keyof T;
107
- textField: keyof T | ((data: T) => string);
108
- iconField?: keyof T | ((data: T) => string);
109
- cssClassField?: keyof T | ((data: T) => string);
110
- styleField?: keyof T | ((data: T) => Record<string, string>);
105
+ interface ITreeNode<T> {
106
+ expand: boolean; // Whether node is expanded
107
+ loading: boolean; // Whether node is loading
108
+ get level(): number; // Node level (root = 0)
109
+ get children(): Array<ITreeNode<T>> | null; // Child nodes (read-only)
110
+ get item(): T; // Node data
111
111
 
112
112
  // Methods
113
- getText(data: T): string;
114
- getIcon(data: T): string | undefined;
115
- getCssClass(data: T): string | undefined;
116
- getStyle(data: T): Record<string, string> | undefined;
117
- getKey(data: T): any;
113
+ append(childItem: T | Array<T>): ITreeNode<T> | Array<ITreeNode<T>>;
114
+ detach(): void;
115
+ moveTo(newParent: ITreeNode<T>): ITreeNode<T>;
116
+ replace(newItem: T): void;
117
+ removeChildren(): void;
118
118
  }
119
119
  ```
120
120
 
121
- ### LazyLoader
121
+ ### TreeLazyLoader
122
122
  ```typescript
123
- interface LazyLoader {
124
- isBranch: (node: TreeNode<any>) => boolean; // Check if node can have children
125
- load: (node: TreeNode<any>) => Promise<Array<TreeNode<any>>>; // Load children
123
+ interface TreeLazyLoader {
124
+ isBranch: (node: ITreeNode<any>) => boolean; // Check if node can have children
125
+ load: (node: ITreeNode<any>) => Promise<Array<any>>; // Load children data
126
126
  }
127
127
  ```
128
128
 
129
+ ### LazyLoader (Deprecated)
130
+ ```typescript
131
+ /**
132
+ * @deprecated Use TreeLazyLoader instead. Will be removed in future versions.
133
+ */
134
+ type LazyLoader = TreeLazyLoader;
135
+ ```
136
+
129
137
  ### OnNodeSelectionChange
130
138
  ```typescript
131
139
  type OnNodeSelectionChange = (node: TreeNode<any>) => Promise<boolean>;
@@ -766,19 +774,25 @@ TreeNode is now a class with built-in methods for data manipulation:
766
774
  // Get a node and manipulate it directly
767
775
  const node = treeNodes.nodes[0];
768
776
 
769
- // Add a child node
777
+ // Add a child node (or array of children)
770
778
  node.append({
771
779
  id: 'new-child',
772
780
  name: 'New Child',
773
781
  parent: node.item.id
774
782
  });
775
783
 
784
+ // Or add multiple children at once
785
+ node.append([
786
+ { id: 'child1', name: 'Child 1', parent: node.item.id },
787
+ { id: 'child2', name: 'Child 2', parent: node.item.id }
788
+ ]);
789
+
776
790
  // Remove the node from tree
777
791
  node.detach();
778
792
 
779
- // Move node to different parent
793
+ // Move node to different parent (returns new node instance)
780
794
  const newParent = treeNodes.nodes[1];
781
- node.moveTo(newParent);
795
+ const movedNode = node.moveTo(newParent);
782
796
 
783
797
  // Replace node data
784
798
  node.replace({
@@ -787,15 +801,13 @@ node.replace({
787
801
  parent: node.item.parent
788
802
  });
789
803
 
790
- // Remove specific child
791
- node.removeChild('child-id');
792
-
793
804
  // Remove all children
794
805
  node.removeChildren();
795
806
 
796
- // Access properties (read-only)
807
+ // Access properties
797
808
  console.log(node.item); // Node data
798
- console.log(node.children); // Read-only child array
809
+ console.log(node.children); // Shallow copy of children array
810
+ console.log(node.level); // Node level (root = 0)
799
811
  console.log(node.expand); // Expanded state
800
812
  console.log(node.parent); // Parent node
801
813
  ```
@@ -69,6 +69,7 @@ import TreeNodes, { type TreeNode } from "@ticatec/uniface-element/TreeNodes";
69
69
  | `textField` | `string \| GetText<any>` | 必需 | 节点文本的字段名称或获取文本的函数 |
70
70
  | `activeNode` | `any` | `null` | 当前选中的/活动节点 |
71
71
  | `style` | `string` | `""` | 附加 CSS 样式 |
72
+ | `title` | `string` | `undefined` | 可选的标题,显示在树视图顶部(固定位置,不滚动) |
72
73
  | `lazyLoader` | `LazyLoader \| null` | `null` | 延迟加载配置 |
73
74
  | `isVisible` | `NodeVisibleFun` | `null` | 判断节点可见性的函数 |
74
75
  | `onchange` | `OnNodeSelectionChange` | `null` | 节点选择更改时的回调函数 |
@@ -83,22 +84,57 @@ import TreeNodes, { type TreeNode } from "@ticatec/uniface-element/TreeNodes";
83
84
 
84
85
  ### TreeNode<T>
85
86
  ```typescript
86
- interface TreeNode<T> {
87
- item: T; // 实际数据项
88
- children?: Array<TreeNode<T>>; // 子节点
89
- expand?: boolean; // 节点是否展开
90
- parent?: TreeNode<T>; // 父节点引用
87
+ class TreeNode<T> implements ITreeNode<T> {
88
+ readonly item: T; // 节点的数据对象
89
+ get children(): Array<TreeNode<T>> | null; // 子节点(浅拷贝)
90
+ get level(): number; // 节点层级(根节点为 0)
91
+ expand: boolean; // 是否展开(显示子节点)
92
+ loading: boolean; // 是否正在加载(用于懒加载)
93
+ readonly parent: TreeNode<T> | null; // 父节点引用
94
+
95
+ // 方法
96
+ append(childItem: T | Array<T>): ITreeNode<T> | Array<ITreeNode<T>>; // 添加子节点
97
+ detach(): void; // 从父节点中分离
98
+ moveTo(newParent: TreeNode<T>): TreeNode<T>; // 移动到其他父节点
99
+ replace(newItem: T): void; // 替换节点数据
100
+ removeChildren(): void; // 删除所有子节点
91
101
  }
92
102
  ```
93
103
 
94
- ### LazyLoader
104
+ ### ITreeNode<T>
95
105
  ```typescript
96
- interface LazyLoader {
97
- isBranch: (node: TreeNode<any>) => boolean; // 判断节点是否可有子节点
98
- load: (node: TreeNode<any>) => Promise<Array<TreeNode<any>>>; // 加载子节点
106
+ interface ITreeNode<T> {
107
+ expand: boolean; // 是否展开
108
+ loading: boolean; // 是否正在加载
109
+ get level(): number; // 节点层级(根节点为 0)
110
+ get children(): Array<ITreeNode<T>> | null; // 子节点(只读)
111
+ get item(): T; // 节点数据
112
+
113
+ // 方法
114
+ append(childItem: T | Array<T>): ITreeNode<T> | Array<ITreeNode<T>>;
115
+ detach(): void;
116
+ moveTo(newParent: ITreeNode<T>): ITreeNode<T>;
117
+ replace(newItem: T): void;
118
+ removeChildren(): void;
99
119
  }
100
120
  ```
101
121
 
122
+ ### TreeLazyLoader
123
+ ```typescript
124
+ interface TreeLazyLoader {
125
+ isBranch: (node: ITreeNode<any>) => boolean; // 判断节点是否可为分支
126
+ load: (node: ITreeNode<any>) => Promise<Array<any>>; // 加载子节点数据
127
+ }
128
+ ```
129
+
130
+ ### LazyLoader (已弃用)
131
+ ```typescript
132
+ /**
133
+ * @deprecated 使用 TreeLazyLoader 代替。LazyLoader 已弃用,将在未来版本中移除。
134
+ */
135
+ type LazyLoader = TreeLazyLoader;
136
+ ```
137
+
102
138
  ### OnNodeSelectionChange
103
139
  ```typescript
104
140
  type OnNodeSelectionChange = (node: TreeNode<any>) => Promise<boolean>;