@ticatec/uniface-element 0.2.0 → 0.2.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/README.md +273 -1
- package/README_CN.md +341 -0
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/dialog/CommonDialog.svelte +6 -3
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +36 -10
- package/dist/dialog/Dialog.svelte.d.ts +4 -3
- package/dist/dialog/DialogBoard.svelte +11 -8
- package/dist/dialog/DialogWrapper.svelte +10 -0
- package/dist/dialog/DialogWrapper.svelte.d.ts +22 -0
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/docs/buttons/cn/ActionBar.md +459 -0
- package/docs/buttons/cn/Button.md +228 -0
- package/docs/buttons/cn/IconButton.md +294 -0
- package/docs/buttons/cn/README.md +600 -0
- package/docs/buttons/cn/TextButton.md +163 -0
- package/docs/buttons/en/ActionBar.md +459 -0
- package/docs/buttons/en/Button.md +228 -0
- package/docs/buttons/en/IconButton.md +294 -0
- package/docs/buttons/en/README.md +600 -0
- package/docs/buttons/en/TextButton.md +163 -0
- package/docs/containers/cn/accordion.md +622 -0
- package/docs/containers/cn/box.md +445 -0
- package/docs/containers/cn/card.md +404 -0
- package/docs/containers/cn/page.md +576 -0
- package/docs/containers/cn/tabs.md +686 -0
- package/docs/containers/en/accordion.md +622 -0
- package/docs/containers/en/box.md +445 -0
- package/docs/containers/en/card.md +404 -0
- package/docs/containers/en/page.md +576 -0
- package/docs/containers/en/tabs.md +686 -0
- package/docs/data-display/cn/concise-data-table.md +731 -0
- package/docs/data-display/cn/listbox.md +786 -0
- package/docs/data-display/cn/treeview.md +863 -0
- package/docs/data-display/en/concise-data-table.md +732 -0
- package/docs/data-display/en/listbox.md +786 -0
- package/docs/data-display/en/treeview.md +863 -0
- package/docs/data-table/cn/README.md +596 -0
- package/docs/data-table/en/README.md +596 -0
- package/docs/dialog/cn/README.md +767 -0
- package/docs/dialog/en/README.md +767 -0
- package/docs/form/cn/README.md +847 -0
- package/docs/form/en/README.md +847 -0
- package/docs/form-components/cn/README.md +495 -0
- package/docs/form-components/cn/attachmentfilesfield.md +757 -0
- package/docs/form-components/cn/cascade-options-select.md +374 -0
- package/docs/form-components/cn/checkbox.md +58 -0
- package/docs/form-components/cn/date-picker.md +138 -0
- package/docs/form-components/cn/datetime-picker.md +228 -0
- package/docs/form-components/cn/group-checkbox.md +405 -0
- package/docs/form-components/cn/group-radiobox.md +525 -0
- package/docs/form-components/cn/imagefilesfield.md +651 -0
- package/docs/form-components/cn/input-options-select.md +250 -0
- package/docs/form-components/cn/lookup-editor.md +406 -0
- package/docs/form-components/cn/memoeditor.md +409 -0
- package/docs/form-components/cn/number-editor.md +261 -0
- package/docs/form-components/cn/options-multi-select.md +177 -0
- package/docs/form-components/cn/options-select.md +83 -0
- package/docs/form-components/cn/passwordeditor.md +538 -0
- package/docs/form-components/cn/prompts-text-editor.md +241 -0
- package/docs/form-components/cn/radiobutton.md +84 -0
- package/docs/form-components/cn/switch.md +178 -0
- package/docs/form-components/cn/text-editor.md +142 -0
- package/docs/form-components/cn/time-editor.md +159 -0
- package/docs/form-components/cn/unit-number-editor.md +164 -0
- package/docs/form-components/en/README.md +463 -0
- package/docs/form-components/en/attachmentfilesfield.md +757 -0
- package/docs/form-components/en/cascade-options-select.md +358 -0
- package/docs/form-components/en/checkbox.md +59 -0
- package/docs/form-components/en/date-picker.md +138 -0
- package/docs/form-components/en/datetime-picker.md +228 -0
- package/docs/form-components/en/group-checkbox.md +395 -0
- package/docs/form-components/en/group-radiobox.md +498 -0
- package/docs/form-components/en/imagefilesfield.md +651 -0
- package/docs/form-components/en/input-options-select.md +239 -0
- package/docs/form-components/en/lookup-editor.md +389 -0
- package/docs/form-components/en/memoeditor.md +409 -0
- package/docs/form-components/en/number-editor.md +249 -0
- package/docs/form-components/en/options-multi-select.md +177 -0
- package/docs/form-components/en/options-select.md +83 -0
- package/docs/form-components/en/passwordeditor.md +538 -0
- package/docs/form-components/en/prompts-text-editor.md +241 -0
- package/docs/form-components/en/radiobutton.md +84 -0
- package/docs/form-components/en/switch.md +180 -0
- package/docs/form-components/en/text-editor.md +142 -0
- package/docs/form-components/en/time-editor.md +159 -0
- package/docs/form-components/en/unit-number-editor.md +164 -0
- package/docs/form-layout/cn/criteria-field.md +652 -0
- package/docs/form-layout/cn/flex-form.md +454 -0
- package/docs/form-layout/cn/flex-row-form.md +542 -0
- package/docs/form-layout/cn/form-field.md +923 -0
- package/docs/form-layout/cn/grid-form.md +676 -0
- package/docs/form-layout/en/criteria-field.md +652 -0
- package/docs/form-layout/en/flex-form.md +454 -0
- package/docs/form-layout/en/flex-row-form.md +542 -0
- package/docs/form-layout/en/form-field.md +923 -0
- package/docs/form-layout/en/grid-form.md +676 -0
- package/docs/global/cn/README.md +534 -0
- package/docs/global/en/README.md +534 -0
- package/docs/layout/cn/classiclayout.md +460 -0
- package/docs/layout/cn/headerlayout.md +524 -0
- package/docs/layout/cn/sidebarlayout.md +263 -0
- package/docs/layout/en/classiclayout.md +951 -0
- package/docs/layout/en/headerlayout.md +524 -0
- package/docs/layout/en/sidebarlayout.md +262 -0
- package/docs/misc/cn/README.md +1217 -0
- package/docs/misc/en/README.md +1217 -0
- package/docs/navigation/cn/breadcrumb.md +291 -0
- package/docs/navigation/cn/navigator.md +322 -0
- package/docs/navigation/cn/navigatormenu.md +512 -0
- package/docs/navigation/cn/progressbar.md +199 -0
- package/docs/navigation/cn/progressstepbar.md +299 -0
- package/docs/navigation/en/breadcrumb.md +291 -0
- package/docs/navigation/en/navigator.md +322 -0
- package/docs/navigation/en/navigatormenu.md +512 -0
- package/docs/navigation/en/progressbar.md +199 -0
- package/docs/navigation/en/progressstepbar.md +299 -0
- package/docs/search-filters/cn/daterange.md +1156 -0
- package/docs/search-filters/cn/numberrange.md +688 -0
- package/docs/search-filters/cn/searchbox.md +1582 -0
- package/docs/search-filters/en/daterange.md +1156 -0
- package/docs/search-filters/en/numberrange.md +688 -0
- package/docs/search-filters/en/searchbox.md +1582 -0
- package/package.json +38 -5
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# CascadeOptionsSelect Component
|
|
2
|
+
|
|
3
|
+
Cascade selector component supporting multi-level cascading selection.
|
|
4
|
+
|
|
5
|
+
## Type Definitions
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
type OnSelectOption = (item: any) => Promise<Array<any>>;
|
|
9
|
+
type IsLeafDetermine = (item: any) => boolean;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Properties
|
|
13
|
+
|
|
14
|
+
| Property | Type | Default | Description |
|
|
15
|
+
|----------|------|---------|-------------|
|
|
16
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Appearance variant |
|
|
17
|
+
| `disabled` | `boolean` | `false` | Whether disabled |
|
|
18
|
+
| `readonly` | `boolean` | `false` | Whether read-only |
|
|
19
|
+
| `compact` | `boolean` | `false` | Whether compact mode |
|
|
20
|
+
| `mandatory` | `boolean` | `false` | Whether required |
|
|
21
|
+
| `value` | `any` | `null` | Selected value |
|
|
22
|
+
| `keyField` | `string` | `'code'` | Value field name |
|
|
23
|
+
| `textField` | `string` | `'text'` | Display field name |
|
|
24
|
+
| `abbrField` | `string` | `'abbr'` | Abbreviation field name |
|
|
25
|
+
| `childrenField` | `string` | `'children'` | Children field name |
|
|
26
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
27
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode |
|
|
28
|
+
| `emptyText` | `string \| null` | `null` | Empty value display text |
|
|
29
|
+
| `checkLeaf` | `IsLeafDetermine \| null` | `null` | Leaf node determination function |
|
|
30
|
+
| `text` | `string` | `''` | Display text |
|
|
31
|
+
| `nodes` | `Array<any>` | `[]` | Root nodes array |
|
|
32
|
+
| `menu$height` | `number` | `150` | Dropdown menu height |
|
|
33
|
+
| `onSelect` | `OnSelectOption` | - | Option selection callback (async load children) |
|
|
34
|
+
| `box$style` | `string` | `''` | Option box style |
|
|
35
|
+
| `style` | `string` | `''` | Custom styles |
|
|
36
|
+
| `onChange` | `OnChangeHandler<any>` | - | Value change callback |
|
|
37
|
+
|
|
38
|
+
## Usage Examples
|
|
39
|
+
|
|
40
|
+
```svelte
|
|
41
|
+
<script lang="ts">
|
|
42
|
+
import CascadeOptionsSelect, { type OnSelectOption, type IsLeafDetermine } from '@ticatec/uniface-element/CascadeOptionsSelect';
|
|
43
|
+
|
|
44
|
+
interface CascadeNode {
|
|
45
|
+
code: string;
|
|
46
|
+
text: string;
|
|
47
|
+
abbr: string;
|
|
48
|
+
children?: CascadeNode[];
|
|
49
|
+
level?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let selectedRegion: string | null = null;
|
|
53
|
+
let selectedCategory: string | null = null;
|
|
54
|
+
|
|
55
|
+
// Regional cascade data
|
|
56
|
+
const regions: CascadeNode[] = [
|
|
57
|
+
{
|
|
58
|
+
code: 'ny',
|
|
59
|
+
text: 'New York',
|
|
60
|
+
abbr: 'NY',
|
|
61
|
+
children: [
|
|
62
|
+
{ code: 'manhattan', text: 'Manhattan', abbr: 'Manhattan' },
|
|
63
|
+
{ code: 'brooklyn', text: 'Brooklyn', abbr: 'Brooklyn' },
|
|
64
|
+
{ code: 'queens', text: 'Queens', abbr: 'Queens' }
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
code: 'ca',
|
|
69
|
+
text: 'California',
|
|
70
|
+
abbr: 'CA',
|
|
71
|
+
children: [
|
|
72
|
+
{ code: 'la', text: 'Los Angeles', abbr: 'LA' },
|
|
73
|
+
{ code: 'sf', text: 'San Francisco', abbr: 'SF' },
|
|
74
|
+
{ code: 'sd', text: 'San Diego', abbr: 'SD' }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
// Product category data (async loading)
|
|
80
|
+
const categories: CascadeNode[] = [
|
|
81
|
+
{ code: 'electronics', text: 'Electronics', abbr: 'Elec' },
|
|
82
|
+
{ code: 'clothing', text: 'Clothing', abbr: 'Cloth' },
|
|
83
|
+
{ code: 'books', text: 'Books', abbr: 'Books' }
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
// Async load subcategories
|
|
87
|
+
const loadSubCategories: OnSelectOption = async (item: CascadeNode) => {
|
|
88
|
+
// Simulate API call
|
|
89
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
90
|
+
|
|
91
|
+
const subcategories: Record<string, CascadeNode[]> = {
|
|
92
|
+
'electronics': [
|
|
93
|
+
{ code: 'phone', text: 'Mobile Phones', abbr: 'Phone', level: 2 },
|
|
94
|
+
{ code: 'computer', text: 'Computers', abbr: 'PC', level: 2 },
|
|
95
|
+
{ code: 'camera', text: 'Cameras', abbr: 'Camera', level: 2 }
|
|
96
|
+
],
|
|
97
|
+
'clothing': [
|
|
98
|
+
{ code: 'men', text: 'Men\'s Wear', abbr: 'Men', level: 2 },
|
|
99
|
+
{ code: 'women', text: 'Women\'s Wear', abbr: 'Women', level: 2 },
|
|
100
|
+
{ code: 'shoes', text: 'Shoes', abbr: 'Shoes', level: 2 }
|
|
101
|
+
],
|
|
102
|
+
'books': [
|
|
103
|
+
{ code: 'fiction', text: 'Fiction', abbr: 'Fiction', level: 2 },
|
|
104
|
+
{ code: 'technical', text: 'Technical Books', abbr: 'Tech', level: 2 },
|
|
105
|
+
{ code: 'education', text: 'Education', abbr: 'Edu', level: 2 }
|
|
106
|
+
]
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
return subcategories[item.code] || [];
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Determine if it's a leaf node
|
|
113
|
+
const isLeafNode: IsLeafDetermine = (item: CascadeNode) => {
|
|
114
|
+
// If it's a third-level node, it's a leaf node
|
|
115
|
+
return item.level === 3;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const handleRegionChange = (value: string): void => {
|
|
119
|
+
selectedRegion = value;
|
|
120
|
+
console.log('Selected region:', value);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const handleCategoryChange = (value: string): void => {
|
|
124
|
+
selectedCategory = value;
|
|
125
|
+
console.log('Selected category:', value);
|
|
126
|
+
};
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<!-- Regional cascade selection -->
|
|
130
|
+
<CascadeOptionsSelect
|
|
131
|
+
placeholder="Please select region"
|
|
132
|
+
nodes={regions}
|
|
133
|
+
keyField="code"
|
|
134
|
+
textField="text"
|
|
135
|
+
abbrField="abbr"
|
|
136
|
+
bind:value={selectedRegion}
|
|
137
|
+
onChange={handleRegionChange}
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<!-- Product category cascade selection (async loading) -->
|
|
141
|
+
<CascadeOptionsSelect
|
|
142
|
+
placeholder="Please select product category"
|
|
143
|
+
nodes={categories}
|
|
144
|
+
keyField="code"
|
|
145
|
+
textField="text"
|
|
146
|
+
abbrField="abbr"
|
|
147
|
+
onSelect={loadSubCategories}
|
|
148
|
+
checkLeaf={isLeafNode}
|
|
149
|
+
menu$height={200}
|
|
150
|
+
bind:value={selectedCategory}
|
|
151
|
+
onChange={handleCategoryChange}
|
|
152
|
+
/>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Advanced Usage
|
|
156
|
+
|
|
157
|
+
### Organization Structure Selection
|
|
158
|
+
```svelte
|
|
159
|
+
<script lang="ts">
|
|
160
|
+
interface OrgNode {
|
|
161
|
+
id: string;
|
|
162
|
+
name: string;
|
|
163
|
+
abbr: string;
|
|
164
|
+
type: 'company' | 'department' | 'team';
|
|
165
|
+
children?: OrgNode[];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let selectedOrg: string | null = null;
|
|
169
|
+
|
|
170
|
+
const orgStructure: OrgNode[] = [
|
|
171
|
+
{
|
|
172
|
+
id: 'company-1',
|
|
173
|
+
name: 'TechCorp Inc.',
|
|
174
|
+
abbr: 'TechCorp',
|
|
175
|
+
type: 'company',
|
|
176
|
+
children: [
|
|
177
|
+
{
|
|
178
|
+
id: 'dept-1',
|
|
179
|
+
name: 'Engineering',
|
|
180
|
+
abbr: 'Eng',
|
|
181
|
+
type: 'department',
|
|
182
|
+
children: [
|
|
183
|
+
{ id: 'team-1', name: 'Frontend Team', abbr: 'FE', type: 'team' },
|
|
184
|
+
{ id: 'team-2', name: 'Backend Team', abbr: 'BE', type: 'team' },
|
|
185
|
+
{ id: 'team-3', name: 'QA Team', abbr: 'QA', type: 'team' }
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: 'dept-2',
|
|
190
|
+
name: 'Product',
|
|
191
|
+
abbr: 'Product',
|
|
192
|
+
type: 'department',
|
|
193
|
+
children: [
|
|
194
|
+
{ id: 'team-4', name: 'Design Team', abbr: 'Design', type: 'team' },
|
|
195
|
+
{ id: 'team-5', name: 'Research Team', abbr: 'Research', type: 'team' }
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
// Dynamic loading of sub-organizations (simulate API fetch)
|
|
203
|
+
const loadSubOrgs: OnSelectOption = async (item: OrgNode) => {
|
|
204
|
+
console.log('Loading sub-organizations:', item);
|
|
205
|
+
|
|
206
|
+
// If already has children, return directly
|
|
207
|
+
if (item.children) {
|
|
208
|
+
return item.children;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Simulate API call
|
|
212
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
213
|
+
|
|
214
|
+
// Return different children based on type
|
|
215
|
+
if (item.type === 'company') {
|
|
216
|
+
return [
|
|
217
|
+
{ id: `dept-${Date.now()}`, name: 'New Department', abbr: 'New Dept', type: 'department' }
|
|
218
|
+
];
|
|
219
|
+
} else if (item.type === 'department') {
|
|
220
|
+
return [
|
|
221
|
+
{ id: `team-${Date.now()}`, name: 'New Team', abbr: 'New Team', type: 'team' }
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return [];
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Determine if it's a selectable final node
|
|
229
|
+
const isSelectableNode: IsLeafDetermine = (item: OrgNode) => {
|
|
230
|
+
return item.type === 'team'; // Only team level can be selected
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const handleOrgChange = (value: string): void => {
|
|
234
|
+
selectedOrg = value;
|
|
235
|
+
console.log('Selected organization:', value);
|
|
236
|
+
};
|
|
237
|
+
</script>
|
|
238
|
+
|
|
239
|
+
<CascadeOptionsSelect
|
|
240
|
+
placeholder="Please select organization"
|
|
241
|
+
nodes={orgStructure}
|
|
242
|
+
keyField="id"
|
|
243
|
+
textField="name"
|
|
244
|
+
abbrField="abbr"
|
|
245
|
+
onSelect={loadSubOrgs}
|
|
246
|
+
checkLeaf={isSelectableNode}
|
|
247
|
+
menu$height={250}
|
|
248
|
+
bind:value={selectedOrg}
|
|
249
|
+
onChange={handleOrgChange}
|
|
250
|
+
/>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Geographic Location Three-level Cascade
|
|
254
|
+
```svelte
|
|
255
|
+
<script lang="ts">
|
|
256
|
+
interface LocationNode {
|
|
257
|
+
code: string;
|
|
258
|
+
name: string;
|
|
259
|
+
level: number;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
let selectedLocation: string | null = null;
|
|
263
|
+
|
|
264
|
+
const states: LocationNode[] = [
|
|
265
|
+
{ code: 'NY', name: 'New York', level: 1 },
|
|
266
|
+
{ code: 'CA', name: 'California', level: 1 },
|
|
267
|
+
{ code: 'TX', name: 'Texas', level: 1 },
|
|
268
|
+
{ code: 'FL', name: 'Florida', level: 1 }
|
|
269
|
+
];
|
|
270
|
+
|
|
271
|
+
// Simulate geographic location API
|
|
272
|
+
const loadLocationChildren: OnSelectOption = async (item: LocationNode) => {
|
|
273
|
+
const response = await fetch(`/api/locations/${item.code}/children`);
|
|
274
|
+
const children = await response.json();
|
|
275
|
+
|
|
276
|
+
return children.map((child: any) => ({
|
|
277
|
+
code: child.code,
|
|
278
|
+
name: child.name,
|
|
279
|
+
level: item.level + 1
|
|
280
|
+
}));
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// County level is final selection
|
|
284
|
+
const isCountyLevel: IsLeafDetermine = (item: LocationNode) => {
|
|
285
|
+
return item.level === 3;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const handleLocationChange = (value: string): void => {
|
|
289
|
+
selectedLocation = value;
|
|
290
|
+
console.log('Selected location code:', value);
|
|
291
|
+
};
|
|
292
|
+
</script>
|
|
293
|
+
|
|
294
|
+
<CascadeOptionsSelect
|
|
295
|
+
placeholder="Please select State/City/County"
|
|
296
|
+
nodes={states}
|
|
297
|
+
keyField="code"
|
|
298
|
+
textField="name"
|
|
299
|
+
onSelect={loadLocationChildren}
|
|
300
|
+
checkLeaf={isCountyLevel}
|
|
301
|
+
bind:value={selectedLocation}
|
|
302
|
+
onChange={handleLocationChange}
|
|
303
|
+
/>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Best Practices
|
|
307
|
+
|
|
308
|
+
### 1. Async Loading Optimization
|
|
309
|
+
```typescript
|
|
310
|
+
// Use caching to avoid duplicate requests
|
|
311
|
+
const cache = new Map<string, any[]>();
|
|
312
|
+
|
|
313
|
+
const cachedLoader: OnSelectOption = async (item: any) => {
|
|
314
|
+
const cacheKey = item.code;
|
|
315
|
+
|
|
316
|
+
if (cache.has(cacheKey)) {
|
|
317
|
+
return cache.get(cacheKey)!;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const children = await fetchChildren(item.code);
|
|
321
|
+
cache.set(cacheKey, children);
|
|
322
|
+
|
|
323
|
+
return children;
|
|
324
|
+
};
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### 2. Error Handling
|
|
328
|
+
```typescript
|
|
329
|
+
const robustLoader: OnSelectOption = async (item: any) => {
|
|
330
|
+
try {
|
|
331
|
+
const response = await fetch(`/api/cascade/${item.code}`);
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
throw new Error(`HTTP ${response.status}`);
|
|
334
|
+
}
|
|
335
|
+
return await response.json();
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error('Failed to load children:', error);
|
|
338
|
+
return []; // Return empty array instead of throwing error
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### 3. Display Loading State
|
|
344
|
+
The component internally has loading state indication, showing loading animation when async loading children.
|
|
345
|
+
|
|
346
|
+
### 4. Set Appropriate Menu Height
|
|
347
|
+
```svelte
|
|
348
|
+
<!-- Adjust height based on number of levels -->
|
|
349
|
+
<CascadeOptionsSelect
|
|
350
|
+
menu$height={200} // 2-3 levels
|
|
351
|
+
nodes={shallowData}
|
|
352
|
+
/>
|
|
353
|
+
|
|
354
|
+
<CascadeOptionsSelect
|
|
355
|
+
menu$height={300} // 4-5 levels
|
|
356
|
+
nodes={deepData}
|
|
357
|
+
/>
|
|
358
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# CheckBox Component
|
|
2
|
+
|
|
3
|
+
Checkbox component for boolean value input.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
| Property | Type | Default | Description |
|
|
8
|
+
|----------|------|---------|-------------|
|
|
9
|
+
| `label` | `string \| null` | `null` | Label text |
|
|
10
|
+
| `readonly` | `boolean` | `false` | Whether read-only |
|
|
11
|
+
| `disabled` | `boolean` | `false` | Whether disabled |
|
|
12
|
+
| `value` | `boolean` | `false` | Checked state |
|
|
13
|
+
| `indeterminate` | `boolean` | `false` | Whether in indeterminate state |
|
|
14
|
+
| `style` | `string` | `''` | Custom styles |
|
|
15
|
+
| `compact` | `boolean` | `false` | Compact layout |
|
|
16
|
+
| `onClick` | `(event: MouseEvent) => void \| null` | `null` | Click event handler |
|
|
17
|
+
| `onChange` | `OnChangeHandler<boolean>` | - | Value change callback |
|
|
18
|
+
| `autoFocus` | `boolean` | `false` | Auto focus on mount |
|
|
19
|
+
|
|
20
|
+
## Usage Examples
|
|
21
|
+
|
|
22
|
+
```svelte
|
|
23
|
+
<script lang="ts">
|
|
24
|
+
import CheckBox from '@ticatec/uniface-element/Checkbox';
|
|
25
|
+
|
|
26
|
+
let agreeTerms = false;
|
|
27
|
+
let enableNotifications = true;
|
|
28
|
+
let partialSelection = false;
|
|
29
|
+
|
|
30
|
+
const handleAgreeChange = (checked: boolean) => {
|
|
31
|
+
agreeTerms = checked;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const handleNotificationChange = (checked: boolean) => {
|
|
35
|
+
enableNotifications = checked;
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<!-- Terms agreement -->
|
|
40
|
+
<CheckBox
|
|
41
|
+
label="I agree to the Terms of Service and Privacy Policy"
|
|
42
|
+
bind:value={agreeTerms}
|
|
43
|
+
onChange={handleAgreeChange}
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<!-- Notification settings -->
|
|
47
|
+
<CheckBox
|
|
48
|
+
label="Enable email notifications"
|
|
49
|
+
bind:value={enableNotifications}
|
|
50
|
+
onChange={handleNotificationChange}
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
<!-- Indeterminate state checkbox -->
|
|
54
|
+
<CheckBox
|
|
55
|
+
label="Partial selection state"
|
|
56
|
+
indeterminate={true}
|
|
57
|
+
bind:value={partialSelection}
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# DatePicker Component
|
|
2
|
+
|
|
3
|
+
Date picker component.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
| Property | Type | Default | Description |
|
|
8
|
+
|----------|------|---------|-------------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Appearance variant |
|
|
10
|
+
| `disabled` | `boolean` | `false` | Whether disabled |
|
|
11
|
+
| `readonly` | `boolean` | `false` | Whether read-only |
|
|
12
|
+
| `compact` | `boolean` | `false` | Whether compact mode |
|
|
13
|
+
| `mandatory` | `boolean` | `false` | Whether required |
|
|
14
|
+
| `value` | `any` | `null` | Date value |
|
|
15
|
+
| `style` | `string` | `''` | Custom styles |
|
|
16
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
17
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode |
|
|
18
|
+
| `min` | `UniDate` | `null` | Minimum date |
|
|
19
|
+
| `max` | `UniDate` | `null` | Maximum date |
|
|
20
|
+
| `onChange` | `OnChangeHandler<Date>` | - | Value change callback |
|
|
21
|
+
|
|
22
|
+
## Usage Examples
|
|
23
|
+
|
|
24
|
+
```svelte
|
|
25
|
+
<script lang="ts">
|
|
26
|
+
import DatePicker from '@ticatec/uniface-element/DatePicker';
|
|
27
|
+
|
|
28
|
+
let birthDate: any = null;
|
|
29
|
+
let startDate: any = new Date();
|
|
30
|
+
let endDate: any = null;
|
|
31
|
+
|
|
32
|
+
const handleBirthDateChange = (date: Date): void => {
|
|
33
|
+
birthDate = date;
|
|
34
|
+
console.log('Birth date:', date);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const handleStartDateChange = (date: Date): void => {
|
|
38
|
+
startDate = date;
|
|
39
|
+
console.log('Start date:', date);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const handleEndDateChange = (date: Date): void => {
|
|
43
|
+
endDate = date;
|
|
44
|
+
console.log('End date:', date);
|
|
45
|
+
};
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<!-- Basic date picker -->
|
|
49
|
+
<DatePicker
|
|
50
|
+
placeholder="Select date"
|
|
51
|
+
bind:value={birthDate}
|
|
52
|
+
onChange={handleBirthDateChange}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<!-- Start date with minimum -->
|
|
56
|
+
<DatePicker
|
|
57
|
+
placeholder="Select start date"
|
|
58
|
+
min={new Date()}
|
|
59
|
+
bind:value={startDate}
|
|
60
|
+
onChange={handleStartDateChange}
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
<!-- End date with range -->
|
|
64
|
+
<DatePicker
|
|
65
|
+
placeholder="Select end date"
|
|
66
|
+
min={startDate}
|
|
67
|
+
bind:value={endDate}
|
|
68
|
+
onChange={handleEndDateChange}
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Advanced Usage
|
|
73
|
+
|
|
74
|
+
### Date Range Selection
|
|
75
|
+
```svelte
|
|
76
|
+
<script lang="ts">
|
|
77
|
+
let startDate: any = null;
|
|
78
|
+
let endDate: any = null;
|
|
79
|
+
|
|
80
|
+
const handleStartChange = (date: Date) => {
|
|
81
|
+
startDate = date;
|
|
82
|
+
// Reset end date if it's before start date
|
|
83
|
+
if (endDate && new Date(endDate) < new Date(date)) {
|
|
84
|
+
endDate = null;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleEndChange = (date: Date) => {
|
|
89
|
+
endDate = date;
|
|
90
|
+
};
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<div class="date-range">
|
|
94
|
+
<DatePicker
|
|
95
|
+
placeholder="Start date"
|
|
96
|
+
bind:value={startDate}
|
|
97
|
+
onChange={handleStartChange}
|
|
98
|
+
/>
|
|
99
|
+
|
|
100
|
+
<DatePicker
|
|
101
|
+
placeholder="End date"
|
|
102
|
+
min={startDate}
|
|
103
|
+
bind:value={endDate}
|
|
104
|
+
onChange={handleEndChange}
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Best Practices
|
|
110
|
+
|
|
111
|
+
### 1. Set Reasonable Date Ranges
|
|
112
|
+
```svelte
|
|
113
|
+
<script lang="ts">
|
|
114
|
+
const today = new Date();
|
|
115
|
+
const futureDate = new Date();
|
|
116
|
+
futureDate.setDate(futureDate.getDate() + 1);
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<!-- Future dates only -->
|
|
120
|
+
<DatePicker
|
|
121
|
+
placeholder="Booking date"
|
|
122
|
+
min={futureDate}
|
|
123
|
+
/>
|
|
124
|
+
|
|
125
|
+
<!-- Past dates allowed -->
|
|
126
|
+
<DatePicker
|
|
127
|
+
placeholder="Birth date"
|
|
128
|
+
max={today}
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 2. Use Mandatory for Required Fields
|
|
133
|
+
```svelte
|
|
134
|
+
<DatePicker
|
|
135
|
+
mandatory={true}
|
|
136
|
+
placeholder="Required date field"
|
|
137
|
+
/>
|
|
138
|
+
```
|