@ticatec/uniface-element 0.2.4 → 0.3.1
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.
- package/dist/accordion/README.md +169 -0
- package/dist/accordion/README_CN.md +176 -0
- package/dist/action-bar/README.md +275 -0
- package/dist/action-bar/README_CN.md +285 -0
- package/dist/app-layout/README.md +374 -0
- package/dist/app-layout/README_CN.md +381 -0
- package/dist/app-top-bar/README.md +357 -0
- package/dist/app-top-bar/README_CN.md +365 -0
- package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
- package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
- package/dist/base-calendar/CalendarBase.svelte +0 -3
- package/dist/box/README.md +385 -0
- package/dist/box/README_CN.md +393 -0
- package/dist/breadcrumbs/README.md +442 -0
- package/dist/breadcrumbs/README_CN.md +442 -0
- package/dist/button/Button.svelte +27 -7
- package/dist/button/Button.svelte.d.ts +3 -1
- package/dist/button/IconButton.svelte +26 -6
- package/dist/button/IconButton.svelte.d.ts +3 -1
- package/dist/button/IconButton_README.md +513 -0
- package/dist/button/IconButton_README_CN.md +513 -0
- package/dist/button/README.md +428 -0
- package/dist/button/README_CN.md +428 -0
- package/dist/button/TextButton.svelte +26 -6
- package/dist/button/TextButton.svelte.d.ts +3 -1
- package/dist/button/TextButton_README.md +571 -0
- package/dist/button/TextButton_README_CN.md +571 -0
- package/dist/card/README.md +666 -0
- package/dist/card/README_CN.md +666 -0
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
- package/dist/cascade-options-select/README.md +663 -2
- package/dist/cascade-options-select/README_CN.md +664 -0
- package/dist/checkbox/CheckBox.svelte +20 -6
- package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
- package/dist/checkbox/README.md +562 -0
- package/dist/checkbox/README_CN.md +727 -0
- package/dist/common-editor/NumberInput.svelte +39 -26
- package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
- package/dist/concise-data-table/ConciseListTable.svelte +133 -36
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
- package/dist/concise-data-table/DataCell.svelte +5 -6
- package/dist/concise-data-table/DataRow.svelte +22 -2
- package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
- package/dist/concise-data-table/README.md +606 -0
- package/dist/concise-data-table/README_CN.md +611 -0
- package/dist/context-menu/ContextMenu.svelte +138 -21
- package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
- package/dist/context-menu/ContextMenuItem.d.ts +20 -4
- package/dist/context-menu/README.md +551 -0
- package/dist/context-menu/README_CN.md +551 -0
- package/dist/criteria-field/CriteriaField.svelte +3 -5
- package/dist/criteria-field/README.md +532 -0
- package/dist/criteria-field/README_CN.md +532 -0
- package/dist/data-table/README.md +712 -0
- package/dist/data-table/README_CN.md +712 -0
- package/dist/date-picker/DatePicker.svelte +44 -7
- package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
- package/dist/date-picker/DateTimePicker.svelte +32 -8
- package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
- package/dist/date-picker/README.md +326 -0
- package/dist/date-picker/README_CN.md +316 -0
- package/dist/date-picker/ScrollBar.svelte +18 -8
- package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
- package/dist/date-picker/TimePanel.svelte +5 -5
- package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
- package/dist/date-range/README.md +374 -0
- package/dist/date-range/README_CN.md +374 -0
- package/dist/dialog/README.md +596 -0
- package/dist/dialog/README_CN.md +596 -0
- package/dist/drawer/README.md +679 -1
- package/dist/drawer/README_CN.md +679 -0
- package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
- package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
- package/dist/group-box/group-check-box/README.md +749 -0
- package/dist/group-box/group-check-box/README_CN.md +750 -0
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
- package/dist/group-box/group-radio-box/README.md +920 -0
- package/dist/group-box/group-radio-box/README_CN.md +920 -0
- package/dist/image-files/README.md +1346 -0
- package/dist/image-files/README_CN.md +1346 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
- package/dist/lib/forwardAllEvents.d.ts +3 -0
- package/dist/lib/forwardAllEvents.js +24 -0
- package/dist/list-box/README.md +579 -0
- package/dist/list-box/README_CN.md +682 -0
- package/dist/lookup-editor/LookupEditor.svelte +15 -3
- package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
- package/dist/lookup-editor/README.md +684 -0
- package/dist/lookup-editor/README_CN.md +684 -0
- package/dist/memo-editor/MemoEditor.svelte +77 -27
- package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
- package/dist/memo-editor/README.md +819 -0
- package/dist/memo-editor/README_CN.md +819 -0
- package/dist/message-box/README.md +398 -0
- package/dist/message-box/README_CN.md +398 -0
- package/dist/number-editor/NumberEditor.svelte +2 -2
- package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
- package/dist/number-editor/README.md +353 -22
- package/dist/number-editor/README_CN.md +357 -0
- package/dist/number-range/README.md +443 -0
- package/dist/number-range/README_CN.md +443 -0
- package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
- package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
- package/dist/options-multi-select/README.md +480 -0
- package/dist/options-multi-select/README_CN.md +480 -0
- package/dist/options-select/OptionsSelect.svelte +36 -5
- package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
- package/dist/options-select/README.md +632 -0
- package/dist/options-select/README_CN.md +632 -0
- package/dist/page/README.md +605 -0
- package/dist/page/README_CN.md +605 -0
- package/dist/pagination/README.md +946 -0
- package/dist/pagination/README_CN.md +946 -0
- package/dist/pagination-panel/README.md +1075 -0
- package/dist/pagination-panel/README_CN.md +1075 -0
- package/dist/popup-hint/README.md +841 -0
- package/dist/popup-hint/README_CN.md +840 -0
- package/dist/progress-bar/README.md +242 -0
- package/dist/progress-bar/README_CN.md +242 -0
- package/dist/progress-step-bar/README.md +316 -0
- package/dist/progress-step-bar/README_CN.md +316 -0
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
- package/dist/prompts-text-editor/README.md +329 -0
- package/dist/prompts-text-editor/README_CN.md +329 -0
- package/dist/property-editor/README.md +969 -0
- package/dist/property-editor/README_CN.md +969 -0
- package/dist/radio-button/README.md +372 -0
- package/dist/radio-button/README_CN.md +372 -0
- package/dist/radio-button/RadioButton.svelte +32 -3
- package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
- package/dist/search-box/README.md +425 -0
- package/dist/search-box/README_CN.md +424 -0
- package/dist/search-box/SearchBox.svelte +22 -6
- package/dist/search-box/SearchBox.svelte.d.ts +4 -1
- package/dist/tabs/README.md +919 -0
- package/dist/tabs/README_CN.md +920 -0
- package/dist/tag/README.md +922 -0
- package/dist/tag/README_CN.md +922 -0
- package/dist/text-editor/PasswordEditor.svelte +17 -2
- package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
- package/dist/text-editor/PasswordEditor_README.md +551 -0
- package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
- package/dist/text-editor/README.md +466 -0
- package/dist/text-editor/README_CN.md +466 -0
- package/dist/text-editor/TextEditor.svelte +51 -19
- package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
- package/dist/ticatec-uniface-web.css +2 -0
- package/dist/time-editor/README.md +498 -24
- package/dist/time-editor/README_CN.md +498 -0
- package/dist/time-editor/TimeEditor.svelte +7 -3
- package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
- package/dist/toast/README.md +667 -0
- package/dist/toast/README_CN.md +667 -0
- package/dist/transfer/README.md +795 -0
- package/dist/transfer/Transfer.svelte +6 -4
- package/dist/transfer/Transfer.svelte.d.ts +3 -1
- package/dist/tree-view/README.md +761 -0
- package/dist/tree-view/README_CN.md +761 -0
- package/dist/tree-view/TreeView.svelte +5 -3
- package/dist/tree-view/TreeView.svelte.d.ts +3 -1
- package/dist/unit-number-editor/README.md +546 -20
- package/dist/unit-number-editor/README_CN.md +525 -0
- package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
- package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
- package/docs/form-field/cn/README_CN.md +364 -0
- package/docs/form-field/en/README.md +364 -0
- package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
- package/docs/form-panel/flex-form/en/README.md +586 -0
- package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
- package/docs/form-panel/flex-row-form/en/README.md +787 -0
- package/docs/form-panel/grid-form/en/README.md +744 -0
- package/package.json +1 -1
- package/dist/drawer/README-CN.md +0 -1
package/dist/tree-view/README.md
CHANGED
|
@@ -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
|