@ticatec/uniface-element 0.2.3 → 0.3.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 (178) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/DialogBoard.svelte +1 -1
  70. package/dist/dialog/README.md +596 -0
  71. package/dist/dialog/README_CN.md +596 -0
  72. package/dist/drawer/README.md +679 -1
  73. package/dist/drawer/README_CN.md +679 -0
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  75. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  76. package/dist/group-box/group-check-box/README.md +749 -0
  77. package/dist/group-box/group-check-box/README_CN.md +750 -0
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  79. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  80. package/dist/group-box/group-radio-box/README.md +920 -0
  81. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  82. package/dist/image-files/README.md +1346 -0
  83. package/dist/image-files/README_CN.md +1346 -0
  84. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  85. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  86. package/dist/lib/forwardAllEvents.d.ts +3 -0
  87. package/dist/lib/forwardAllEvents.js +24 -0
  88. package/dist/list-box/README.md +579 -0
  89. package/dist/list-box/README_CN.md +682 -0
  90. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  91. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  92. package/dist/lookup-editor/README.md +684 -0
  93. package/dist/lookup-editor/README_CN.md +684 -0
  94. package/dist/memo-editor/MemoEditor.svelte +77 -27
  95. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  96. package/dist/memo-editor/README.md +819 -0
  97. package/dist/memo-editor/README_CN.md +819 -0
  98. package/dist/message-box/README.md +398 -0
  99. package/dist/message-box/README_CN.md +398 -0
  100. package/dist/number-editor/NumberEditor.svelte +2 -2
  101. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  102. package/dist/number-editor/README.md +353 -22
  103. package/dist/number-editor/README_CN.md +357 -0
  104. package/dist/number-range/README.md +443 -0
  105. package/dist/number-range/README_CN.md +443 -0
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  107. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  108. package/dist/options-multi-select/README.md +480 -0
  109. package/dist/options-multi-select/README_CN.md +480 -0
  110. package/dist/options-select/OptionsSelect.svelte +36 -5
  111. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  112. package/dist/options-select/README.md +632 -0
  113. package/dist/options-select/README_CN.md +632 -0
  114. package/dist/page/README.md +605 -0
  115. package/dist/page/README_CN.md +605 -0
  116. package/dist/pagination/README.md +946 -0
  117. package/dist/pagination/README_CN.md +946 -0
  118. package/dist/pagination-panel/README.md +1075 -0
  119. package/dist/pagination-panel/README_CN.md +1075 -0
  120. package/dist/popup-hint/README.md +841 -0
  121. package/dist/popup-hint/README_CN.md +840 -0
  122. package/dist/progress-bar/README.md +242 -0
  123. package/dist/progress-bar/README_CN.md +242 -0
  124. package/dist/progress-step-bar/README.md +316 -0
  125. package/dist/progress-step-bar/README_CN.md +316 -0
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  127. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  128. package/dist/prompts-text-editor/README.md +329 -0
  129. package/dist/prompts-text-editor/README_CN.md +329 -0
  130. package/dist/property-editor/README.md +969 -0
  131. package/dist/property-editor/README_CN.md +969 -0
  132. package/dist/radio-button/README.md +372 -0
  133. package/dist/radio-button/README_CN.md +372 -0
  134. package/dist/radio-button/RadioButton.svelte +32 -3
  135. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  136. package/dist/search-box/README.md +425 -0
  137. package/dist/search-box/README_CN.md +424 -0
  138. package/dist/search-box/SearchBox.svelte +22 -6
  139. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  140. package/dist/tabs/README.md +919 -0
  141. package/dist/tabs/README_CN.md +920 -0
  142. package/dist/tag/README.md +922 -0
  143. package/dist/tag/README_CN.md +922 -0
  144. package/dist/text-editor/PasswordEditor.svelte +17 -2
  145. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  146. package/dist/text-editor/PasswordEditor_README.md +551 -0
  147. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  148. package/dist/text-editor/README.md +466 -0
  149. package/dist/text-editor/README_CN.md +466 -0
  150. package/dist/text-editor/TextEditor.svelte +51 -19
  151. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  152. package/dist/ticatec-uniface-web.css +1 -0
  153. package/dist/time-editor/README.md +498 -24
  154. package/dist/time-editor/README_CN.md +498 -0
  155. package/dist/time-editor/TimeEditor.svelte +7 -3
  156. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  157. package/dist/toast/README.md +667 -0
  158. package/dist/toast/README_CN.md +667 -0
  159. package/dist/transfer/README.md +795 -0
  160. package/dist/transfer/Transfer.svelte +6 -4
  161. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  162. package/dist/tree-view/README.md +761 -0
  163. package/dist/tree-view/README_CN.md +761 -0
  164. package/dist/tree-view/TreeView.svelte +5 -3
  165. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  166. package/dist/unit-number-editor/README.md +546 -20
  167. package/dist/unit-number-editor/README_CN.md +525 -0
  168. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  169. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  170. package/docs/form-field/cn/README_CN.md +364 -0
  171. package/docs/form-field/en/README.md +364 -0
  172. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  173. package/docs/form-panel/flex-form/en/README.md +586 -0
  174. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  175. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  176. package/docs/form-panel/grid-form/en/README.md +744 -0
  177. package/package.json +1 -1
  178. package/dist/drawer/README-CN.md +0 -1
@@ -0,0 +1,761 @@
1
+ # TreeView
2
+
3
+ A hierarchical tree view component for displaying nested data structures. Features expandable/collapsible nodes, lazy loading, context menus, and customizable node display. Perfect for file explorers, organizational charts, and hierarchical data navigation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ticatec/uniface-element
9
+ ```
10
+
11
+ ## Import
12
+
13
+ ```typescript
14
+ import TreeView, { type LazyLoader, type NodeVisibleFun, type OnNodeSelectionChange } from "@ticatec/uniface-element/TreeView";
15
+ import TreeNodes, { type TreeNode } from "@ticatec/uniface-element/TreeNodes";
16
+ ```
17
+
18
+ ## Basic Usage
19
+
20
+ ```svelte
21
+ <script>
22
+ import TreeView from "@ticatec/uniface-element/TreeView";
23
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
24
+
25
+ let activeNode = null;
26
+
27
+ // Sample data
28
+ const data = [
29
+ { id: 1, name: "Documents", parent: null },
30
+ { id: 2, name: "Projects", parent: null },
31
+ { id: 3, name: "Project A", parent: 2 },
32
+ { id: 4, name: "Project B", parent: 2 },
33
+ { id: 5, name: "file1.txt", parent: 3 },
34
+ { id: 6, name: "file2.txt", parent: 3 }
35
+ ];
36
+
37
+ // Create tree structure
38
+ const treeNodes = new TreeNodes({
39
+ keyField: 'id',
40
+ textField: 'name',
41
+ parentKeyField: 'parent',
42
+ checkIsRoot: (item) => item.parent === null,
43
+ checkIsDirectory: (node) => node.children != null
44
+ });
45
+
46
+ treeNodes.setData(data);
47
+
48
+ function handleSelectionChange(node) {
49
+ console.log('Selected node:', node);
50
+ return true; // Allow selection
51
+ }
52
+ </script>
53
+
54
+ <TreeView
55
+ nodes={treeNodes.nodes}
56
+ textField="name"
57
+ bind:activeNode
58
+ onchange={handleSelectionChange}
59
+ checkIsDirectory={node => node.children != null}
60
+ />
61
+ ```
62
+
63
+ ## Props
64
+
65
+ | Prop | Type | Default | Description |
66
+ |------|------|---------|-------------|
67
+ | `nodes` | `Array<TreeNode<any>>` | Required | Array of tree nodes to display |
68
+ | `textField` | `string \| GetText<any>` | Required | Field name or function to get node text |
69
+ | `activeNode` | `any` | `null` | Currently selected/active node |
70
+ | `style` | `string` | `""` | Additional CSS styles |
71
+ | `lazyLoader` | `LazyLoader \| null` | `null` | Lazy loading configuration |
72
+ | `isVisible` | `NodeVisibleFun` | `null` | Function to determine node visibility |
73
+ | `onchange` | `OnNodeSelectionChange` | `null` | Callback when node selection changes |
74
+ | `onfocus` | `((event: FocusEvent) => void) \| null` | `null` | Callback when tree gains focus |
75
+ | `onblur` | `((event: FocusEvent) => void) \| null` | `null` | Callback when tree loses focus |
76
+ | `onContextMenu` | `OnContextMenu` | `null` | Right-click context menu handler |
77
+ | `checkIsDirectory` | `CheckIsDirectory<any>` | Required | Function to check if node is a directory |
78
+ | `class` | `string` | `""` | CSS class name |
79
+
80
+ ## Type Definitions
81
+
82
+ ### TreeNode<T>
83
+ ```typescript
84
+ interface TreeNode<T> {
85
+ item: T; // The actual data item
86
+ children?: Array<TreeNode<T>>; // Child nodes
87
+ expand?: boolean; // Whether node is expanded
88
+ parent?: TreeNode<T>; // Parent node reference
89
+ }
90
+ ```
91
+
92
+ ### LazyLoader
93
+ ```typescript
94
+ interface LazyLoader {
95
+ isBranch: (node: TreeNode<any>) => boolean; // Check if node can have children
96
+ load: (node: TreeNode<any>) => Promise<Array<TreeNode<any>>>; // Load children
97
+ }
98
+ ```
99
+
100
+ ### OnNodeSelectionChange
101
+ ```typescript
102
+ type OnNodeSelectionChange = (node: TreeNode<any>) => Promise<boolean>;
103
+ ```
104
+
105
+ ### NodeVisibleFun
106
+ ```typescript
107
+ type NodeVisibleFun = (node: TreeNode<any>) => boolean;
108
+ ```
109
+
110
+ ## Examples
111
+
112
+ ### File System Tree
113
+
114
+ ```svelte
115
+ <script>
116
+ import TreeView from "@ticatec/uniface-element/TreeView";
117
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
118
+
119
+ let activeNode = null;
120
+
121
+ const fileSystemData = [
122
+ { id: 1, name: "=� Documents", type: "folder", parent: null },
123
+ { id: 2, name: "=� Pictures", type: "folder", parent: null },
124
+ { id: 3, name: "=� Work", type: "folder", parent: 1 },
125
+ { id: 4, name: "=� Personal", type: "folder", parent: 1 },
126
+ { id: 5, name: "=� resume.pdf", type: "file", parent: 3 },
127
+ { id: 6, name: "=� cover-letter.doc", type: "file", parent: 3 },
128
+ { id: 7, name: "=� vacation.jpg", type: "file", parent: 2 },
129
+ { id: 8, name: "=� family.png", type: "file", parent: 2 }
130
+ ];
131
+
132
+ const fileTree = new TreeNodes({
133
+ keyField: 'id',
134
+ textField: 'name',
135
+ parentKeyField: 'parent',
136
+ checkIsRoot: (item) => item.parent === null,
137
+ checkIsDirectory: (node) => node.item.type === 'folder',
138
+ expendDepth: 1 // Expand first level by default
139
+ });
140
+
141
+ fileTree.setData(fileSystemData);
142
+
143
+ function handleFileSelection(node) {
144
+ console.log('Selected file:', node.item.name);
145
+ return true;
146
+ }
147
+
148
+ function isDirectory(node) {
149
+ return node.item.type === 'folder';
150
+ }
151
+ </script>
152
+
153
+ <div class="file-explorer">
154
+ <h3>File Explorer</h3>
155
+ <TreeView
156
+ nodes={fileTree.nodes}
157
+ textField="name"
158
+ bind:activeNode
159
+ onchange={handleFileSelection}
160
+ checkIsDirectory={isDirectory}
161
+ />
162
+ </div>
163
+
164
+ <style>
165
+ .file-explorer {
166
+ width: 300px;
167
+ border: 1px solid #ddd;
168
+ border-radius: 4px;
169
+ padding: 16px;
170
+ }
171
+
172
+ h3 {
173
+ margin: 0 0 12px 0;
174
+ font-size: 16px;
175
+ }
176
+ </style>
177
+ ```
178
+
179
+ ### Organization Chart
180
+
181
+ ```svelte
182
+ <script>
183
+ import TreeView from "@ticatec/uniface-element/TreeView";
184
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
185
+
186
+ let selectedEmployee = null;
187
+
188
+ const orgData = [
189
+ { id: 1, name: "CEO - John Smith", position: "Chief Executive Officer", manager: null },
190
+ { id: 2, name: "CTO - Jane Doe", position: "Chief Technology Officer", manager: 1 },
191
+ { id: 3, name: "CFO - Bob Wilson", position: "Chief Financial Officer", manager: 1 },
192
+ { id: 4, name: "Dev Manager - Alice Brown", position: "Development Manager", manager: 2 },
193
+ { id: 5, name: "QA Manager - Charlie Davis", position: "QA Manager", manager: 2 },
194
+ { id: 6, name: "Developer - Eve Johnson", position: "Senior Developer", manager: 4 },
195
+ { id: 7, name: "Developer - Frank Miller", position: "Junior Developer", manager: 4 },
196
+ { id: 8, name: "QA Engineer - Grace Lee", position: "QA Engineer", manager: 5 }
197
+ ];
198
+
199
+ const orgChart = new TreeNodes({
200
+ keyField: 'id',
201
+ textField: 'name',
202
+ parentKeyField: 'manager',
203
+ checkIsRoot: (item) => item.manager === null,
204
+ checkIsDirectory: (node) => node.children && node.children.length > 0,
205
+ expendDepth: 2
206
+ });
207
+
208
+ orgChart.setData(orgData);
209
+
210
+ function handleEmployeeSelection(node) {
211
+ selectedEmployee = node.item;
212
+ return true;
213
+ }
214
+
215
+ function isManager(node) {
216
+ return node.children && node.children.length > 0;
217
+ }
218
+ </script>
219
+
220
+ <div class="org-chart">
221
+ <h3>Organization Chart</h3>
222
+ <TreeView
223
+ nodes={orgChart.nodes}
224
+ textField="name"
225
+ onchange={handleEmployeeSelection}
226
+ checkIsDirectory={isManager}
227
+ />
228
+
229
+ {#if selectedEmployee}
230
+ <div class="employee-details">
231
+ <h4>Employee Details</h4>
232
+ <p><strong>Name:</strong> {selectedEmployee.name}</p>
233
+ <p><strong>Position:</strong> {selectedEmployee.position}</p>
234
+ </div>
235
+ {/if}
236
+ </div>
237
+
238
+ <style>
239
+ .org-chart {
240
+ width: 400px;
241
+ border: 1px solid #ddd;
242
+ border-radius: 4px;
243
+ padding: 16px;
244
+ }
245
+
246
+ .employee-details {
247
+ margin-top: 16px;
248
+ padding: 12px;
249
+ background: #f8f9fa;
250
+ border-radius: 4px;
251
+ }
252
+
253
+ .employee-details h4 {
254
+ margin: 0 0 8px 0;
255
+ }
256
+
257
+ .employee-details p {
258
+ margin: 4px 0;
259
+ }
260
+ </style>
261
+ ```
262
+
263
+ ### With Lazy Loading
264
+
265
+ ```svelte
266
+ <script>
267
+ import TreeView from "@ticatec/uniface-element/TreeView";
268
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
269
+
270
+ let activeNode = null;
271
+
272
+ // Initial root nodes
273
+ const initialData = [
274
+ { id: 1, name: "Folder A", hasChildren: true },
275
+ { id: 2, name: "Folder B", hasChildren: true },
276
+ { id: 3, name: "File 1.txt", hasChildren: false }
277
+ ];
278
+
279
+ const treeNodes = new TreeNodes({
280
+ keyField: 'id',
281
+ textField: 'name',
282
+ parentKeyField: 'parent',
283
+ checkIsRoot: (item) => !item.parent,
284
+ checkIsDirectory: (node) => node.item.hasChildren
285
+ });
286
+
287
+ treeNodes.setData(initialData);
288
+
289
+ // Lazy loader configuration
290
+ const lazyLoader = {
291
+ isBranch: (node) => node.item.hasChildren,
292
+
293
+ load: async (node) => {
294
+ // Simulate API call
295
+ await new Promise(resolve => setTimeout(resolve, 1000));
296
+
297
+ // Generate child nodes
298
+ const children = [];
299
+ for (let i = 1; i <= 3; i++) {
300
+ children.push({
301
+ id: `${node.item.id}-${i}`,
302
+ name: `${node.item.name} - Child ${i}`,
303
+ parent: node.item.id,
304
+ hasChildren: Math.random() > 0.7 // 30% chance of having children
305
+ });
306
+ }
307
+
308
+ return children.map(child => ({ item: child, children: null }));
309
+ }
310
+ };
311
+
312
+ function handleSelection(node) {
313
+ console.log('Selected:', node.item.name);
314
+ return true;
315
+ }
316
+
317
+ function isDirectory(node) {
318
+ return node.item.hasChildren;
319
+ }
320
+ </script>
321
+
322
+ <div class="lazy-tree">
323
+ <h3>Lazy Loading Tree</h3>
324
+ <TreeView
325
+ nodes={treeNodes.nodes}
326
+ textField="name"
327
+ bind:activeNode
328
+ {lazyLoader}
329
+ onchange={handleSelection}
330
+ checkIsDirectory={isDirectory}
331
+ />
332
+ </div>
333
+
334
+ <style>
335
+ .lazy-tree {
336
+ width: 300px;
337
+ border: 1px solid #ddd;
338
+ border-radius: 4px;
339
+ padding: 16px;
340
+ }
341
+ </style>
342
+ ```
343
+
344
+ ### With Context Menu
345
+
346
+ ```svelte
347
+ <script>
348
+ import TreeView from "@ticatec/uniface-element/TreeView";
349
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
350
+ import ContextMenu from "@ticatec/uniface-element/ContextMenu";
351
+
352
+ let activeNode = null;
353
+ let contextMenu;
354
+
355
+ const menuData = [
356
+ { id: 1, name: "Root Folder", type: "folder", parent: null },
357
+ { id: 2, name: "Subfolder", type: "folder", parent: 1 },
358
+ { id: 3, name: "document.txt", type: "file", parent: 2 }
359
+ ];
360
+
361
+ const menuTree = new TreeNodes({
362
+ keyField: 'id',
363
+ textField: 'name',
364
+ parentKeyField: 'parent',
365
+ checkIsRoot: (item) => item.parent === null,
366
+ checkIsDirectory: (node) => node.item.type === 'folder'
367
+ });
368
+
369
+ menuTree.setData(menuData);
370
+
371
+ function handleContextMenu(event, node) {
372
+ const isFolder = node.item.type === 'folder';
373
+
374
+ const menuItems = [
375
+ {
376
+ text: "Open",
377
+ action: () => console.log('Open:', node.item.name)
378
+ },
379
+ {
380
+ text: "Rename",
381
+ action: () => console.log('Rename:', node.item.name)
382
+ },
383
+ ...(isFolder ? [{
384
+ text: "Add File",
385
+ action: () => console.log('Add file to:', node.item.name)
386
+ }] : []),
387
+ {
388
+ text: "Delete",
389
+ action: () => console.log('Delete:', node.item.name)
390
+ }
391
+ ];
392
+
393
+ contextMenu.show(event, menuItems);
394
+ }
395
+
396
+ function isDirectory(node) {
397
+ return node.item.type === 'folder';
398
+ }
399
+ </script>
400
+
401
+ <div class="context-tree">
402
+ <h3>Right-click for Context Menu</h3>
403
+ <TreeView
404
+ nodes={menuTree.nodes}
405
+ textField="name"
406
+ bind:activeNode
407
+ onContextMenu={handleContextMenu}
408
+ checkIsDirectory={isDirectory}
409
+ />
410
+ </div>
411
+
412
+ <ContextMenu bind:this={contextMenu} />
413
+
414
+ <style>
415
+ .context-tree {
416
+ width: 300px;
417
+ border: 1px solid #ddd;
418
+ border-radius: 4px;
419
+ padding: 16px;
420
+ }
421
+ </style>
422
+ ```
423
+
424
+ ### With Custom Visibility Filter
425
+
426
+ ```svelte
427
+ <script>
428
+ import TreeView from "@ticatec/uniface-element/TreeView";
429
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
430
+
431
+ let activeNode = null;
432
+ let showHidden = false;
433
+
434
+ const fileData = [
435
+ { id: 1, name: "public", hidden: false, parent: null },
436
+ { id: 2, name: ".env", hidden: true, parent: null },
437
+ { id: 3, name: "index.js", hidden: false, parent: 1 },
438
+ { id: 4, name: ".gitignore", hidden: true, parent: 1 },
439
+ { id: 5, name: "config.json", hidden: false, parent: 1 }
440
+ ];
441
+
442
+ const fileTree = new TreeNodes({
443
+ keyField: 'id',
444
+ textField: 'name',
445
+ parentKeyField: 'parent',
446
+ checkIsRoot: (item) => item.parent === null,
447
+ checkIsDirectory: (node) => node.children && node.children.length > 0
448
+ });
449
+
450
+ fileTree.setData(fileData);
451
+
452
+ function isVisible(node) {
453
+ return showHidden || !node.item.hidden;
454
+ }
455
+
456
+ function isDirectory(node) {
457
+ return node.children && node.children.length > 0;
458
+ }
459
+ </script>
460
+
461
+ <div class="filtered-tree">
462
+ <div class="controls">
463
+ <label>
464
+ <input type="checkbox" bind:checked={showHidden} />
465
+ Show hidden files
466
+ </label>
467
+ </div>
468
+
469
+ <TreeView
470
+ nodes={fileTree.nodes}
471
+ textField="name"
472
+ bind:activeNode
473
+ {isVisible}
474
+ checkIsDirectory={isDirectory}
475
+ />
476
+ </div>
477
+
478
+ <style>
479
+ .filtered-tree {
480
+ width: 300px;
481
+ border: 1px solid #ddd;
482
+ border-radius: 4px;
483
+ padding: 16px;
484
+ }
485
+
486
+ .controls {
487
+ margin-bottom: 12px;
488
+ }
489
+
490
+ label {
491
+ display: flex;
492
+ align-items: center;
493
+ gap: 8px;
494
+ font-size: 14px;
495
+ }
496
+ </style>
497
+ ```
498
+
499
+ ### With Event Handlers
500
+
501
+ ```svelte
502
+ <script>
503
+ import TreeView from "@ticatec/uniface-element/TreeView";
504
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
505
+
506
+ let activeNode = null;
507
+ let isFocused = false;
508
+ let selectionLog = [];
509
+
510
+ const eventData = [
511
+ { id: 1, name: "Node 1", parent: null },
512
+ { id: 2, name: "Node 2", parent: null },
513
+ { id: 3, name: "Child 1", parent: 1 },
514
+ { id: 4, name: "Child 2", parent: 1 }
515
+ ];
516
+
517
+ const eventTree = new TreeNodes({
518
+ keyField: 'id',
519
+ textField: 'name',
520
+ parentKeyField: 'parent',
521
+ checkIsRoot: (item) => item.parent === null,
522
+ checkIsDirectory: (node) => node.children && node.children.length > 0
523
+ });
524
+
525
+ eventTree.setData(eventData);
526
+
527
+ function handleSelectionChange(node) {
528
+ selectionLog = [...selectionLog, `Selected: ${node.item.name} at ${new Date().toLocaleTimeString()}`];
529
+ return true;
530
+ }
531
+
532
+ function handleFocus(event) {
533
+ console.log('Tree focused');
534
+ isFocused = true;
535
+ }
536
+
537
+ function handleBlur(event) {
538
+ console.log('Tree blurred');
539
+ isFocused = false;
540
+ }
541
+
542
+ function isDirectory(node) {
543
+ return node.children && node.children.length > 0;
544
+ }
545
+ </script>
546
+
547
+ <div class="event-tree">
548
+ <h3>Event Handling Demo</h3>
549
+ <p>Tree is {isFocused ? 'focused' : 'not focused'}</p>
550
+
551
+ <TreeView
552
+ nodes={eventTree.nodes}
553
+ textField="name"
554
+ bind:activeNode
555
+ onchange={handleSelectionChange}
556
+ onfocus={handleFocus}
557
+ onblur={handleBlur}
558
+ checkIsDirectory={isDirectory}
559
+ />
560
+
561
+ <div class="log">
562
+ <h4>Selection Log:</h4>
563
+ {#each selectionLog.slice(-5) as entry}
564
+ <p>{entry}</p>
565
+ {/each}
566
+ </div>
567
+ </div>
568
+
569
+ <style>
570
+ .event-tree {
571
+ width: 400px;
572
+ border: 1px solid #ddd;
573
+ border-radius: 4px;
574
+ padding: 16px;
575
+ }
576
+
577
+ .log {
578
+ margin-top: 16px;
579
+ padding: 12px;
580
+ background: #f8f9fa;
581
+ border-radius: 4px;
582
+ max-height: 150px;
583
+ overflow-y: auto;
584
+ }
585
+
586
+ .log h4 {
587
+ margin: 0 0 8px 0;
588
+ font-size: 14px;
589
+ }
590
+
591
+ .log p {
592
+ margin: 2px 0;
593
+ font-size: 12px;
594
+ font-family: monospace;
595
+ }
596
+ </style>
597
+ ```
598
+
599
+ ### Geographic Hierarchy
600
+
601
+ ```svelte
602
+ <script>
603
+ import TreeView from "@ticatec/uniface-element/TreeView";
604
+ import TreeNodes from "@ticatec/uniface-element/TreeNodes";
605
+
606
+ let activeLocation = null;
607
+
608
+ const locationData = [
609
+ { code: "CN", name: "China", type: "country", parent: null },
610
+ { code: "US", name: "United States", type: "country", parent: null },
611
+ { code: "CN-BJ", name: "Beijing", type: "province", parent: "CN" },
612
+ { code: "CN-SH", name: "Shanghai", type: "province", parent: "CN" },
613
+ { code: "US-CA", name: "California", type: "state", parent: "US" },
614
+ { code: "US-NY", name: "New York", type: "state", parent: "US" },
615
+ { code: "CN-BJ-HD", name: "Haidian District", type: "district", parent: "CN-BJ" },
616
+ { code: "CN-BJ-CY", name: "Chaoyang District", type: "district", parent: "CN-BJ" },
617
+ { code: "US-CA-SF", name: "San Francisco", type: "city", parent: "US-CA" },
618
+ { code: "US-CA-LA", name: "Los Angeles", type: "city", parent: "US-CA" }
619
+ ];
620
+
621
+ const locationTree = new TreeNodes({
622
+ keyField: 'code',
623
+ textField: 'name',
624
+ parentKeyField: 'parent',
625
+ checkIsRoot: (item) => item.parent === null,
626
+ checkIsDirectory: (node) => {
627
+ const hasChildren = locationData.some(loc => loc.parent === node.item.code);
628
+ return hasChildren;
629
+ },
630
+ expendDepth: 1
631
+ });
632
+
633
+ locationTree.setData(locationData);
634
+
635
+ function handleLocationSelection(node) {
636
+ activeLocation = node.item;
637
+ return true;
638
+ }
639
+
640
+ function isDirectory(node) {
641
+ return locationData.some(loc => loc.parent === node.item.code);
642
+ }
643
+
644
+ function getLocationIcon(type) {
645
+ switch (type) {
646
+ case 'country': return '<
647
+ case 'province':
648
+ case 'state': return '<�';
649
+ case 'district':
650
+ case 'city': return '<�';
651
+ default: return '=�';
652
+ }
653
+ }
654
+
655
+ function displayLocationName(item) {
656
+ return `${getLocationIcon(item.type)} ${item.name}`;
657
+ }
658
+ </script>
659
+
660
+ <div class="location-tree">
661
+ <h3>Geographic Hierarchy</h3>
662
+ <TreeView
663
+ nodes={locationTree.nodes}
664
+ textField={displayLocationName}
665
+ onchange={handleLocationSelection}
666
+ checkIsDirectory={isDirectory}
667
+ />
668
+
669
+ {#if activeLocation}
670
+ <div class="location-details">
671
+ <h4>Selected Location</h4>
672
+ <p><strong>Name:</strong> {activeLocation.name}</p>
673
+ <p><strong>Code:</strong> {activeLocation.code}</p>
674
+ <p><strong>Type:</strong> {activeLocation.type}</p>
675
+ </div>
676
+ {/if}
677
+ </div>
678
+
679
+ <style>
680
+ .location-tree {
681
+ width: 350px;
682
+ border: 1px solid #ddd;
683
+ border-radius: 4px;
684
+ padding: 16px;
685
+ }
686
+
687
+ .location-details {
688
+ margin-top: 16px;
689
+ padding: 12px;
690
+ background: #f8f9fa;
691
+ border-radius: 4px;
692
+ }
693
+
694
+ .location-details h4 {
695
+ margin: 0 0 8px 0;
696
+ }
697
+
698
+ .location-details p {
699
+ margin: 4px 0;
700
+ }
701
+ </style>
702
+ ```
703
+
704
+ ## Features
705
+
706
+ - **Hierarchical Display**: Clean tree structure with expandable/collapsible nodes
707
+ - **Lazy Loading**: Load child nodes on demand for large datasets
708
+ - **Context Menus**: Right-click support for custom actions
709
+ - **Keyboard Navigation**: Full keyboard accessibility support
710
+ - **Custom Visibility**: Filter nodes based on custom criteria
711
+ - **Selection Management**: Track and control node selection
712
+ - **Event Handling**: Comprehensive event system for interactions
713
+ - **Flexible Data**: Support for any data structure with configurable mapping
714
+
715
+ ## Node Management
716
+
717
+ The TreeView component works with the `TreeNodes` utility class to manage hierarchical data:
718
+
719
+ ```typescript
720
+ const treeNodes = new TreeNodes({
721
+ keyField: 'id', // Unique identifier field
722
+ textField: 'name', // Display text field
723
+ parentKeyField: 'parent', // Parent reference field
724
+ checkIsRoot: (item) => item.parent === null,
725
+ checkIsDirectory: (node) => node.children != null,
726
+ expendDepth: 1 // Initial expansion depth
727
+ });
728
+
729
+ treeNodes.setData(flatData); // Convert flat data to tree structure
730
+ ```
731
+
732
+ ## Accessibility
733
+
734
+ - Keyboard navigation with arrow keys and Enter
735
+ - Proper ARIA attributes for screen readers
736
+ - Focus management and visual indicators
737
+ - Semantic HTML structure
738
+ - Tab navigation support
739
+
740
+ ## Best Practices
741
+
742
+ 1. **Data Structure**: Use consistent field names across your data
743
+ 2. **Performance**: Implement lazy loading for large datasets
744
+ 3. **Visibility**: Use the `isVisible` prop to filter nodes efficiently
745
+ 4. **Selection**: Always return a boolean from selection change handlers
746
+ 5. **Context Menus**: Provide contextually relevant menu items
747
+ 6. **Accessibility**: Ensure proper keyboard navigation support
748
+
749
+ ## Browser Support
750
+
751
+ - Modern browsers with full event support
752
+ - Compatible with Svelte 5+
753
+ - Keyboard navigation support
754
+ - Touch-friendly interface
755
+ - Full TypeScript support
756
+
757
+ ## Related Components
758
+
759
+ - `TreeNodes` - Tree data structure utility
760
+ - `ContextMenu` - Right-click context menu component
761
+ - `LazyLoader` - Async data loading interface