@ticatec/uniface-element 0.2.4 → 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 (176) 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/README.md +596 -0
  70. package/dist/dialog/README_CN.md +596 -0
  71. package/dist/drawer/README.md +679 -1
  72. package/dist/drawer/README_CN.md +679 -0
  73. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  75. package/dist/group-box/group-check-box/README.md +749 -0
  76. package/dist/group-box/group-check-box/README_CN.md +750 -0
  77. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  79. package/dist/group-box/group-radio-box/README.md +920 -0
  80. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  81. package/dist/image-files/README.md +1346 -0
  82. package/dist/image-files/README_CN.md +1346 -0
  83. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  84. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  85. package/dist/lib/forwardAllEvents.d.ts +3 -0
  86. package/dist/lib/forwardAllEvents.js +24 -0
  87. package/dist/list-box/README.md +579 -0
  88. package/dist/list-box/README_CN.md +682 -0
  89. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  90. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  91. package/dist/lookup-editor/README.md +684 -0
  92. package/dist/lookup-editor/README_CN.md +684 -0
  93. package/dist/memo-editor/MemoEditor.svelte +77 -27
  94. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  95. package/dist/memo-editor/README.md +819 -0
  96. package/dist/memo-editor/README_CN.md +819 -0
  97. package/dist/message-box/README.md +398 -0
  98. package/dist/message-box/README_CN.md +398 -0
  99. package/dist/number-editor/NumberEditor.svelte +2 -2
  100. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  101. package/dist/number-editor/README.md +353 -22
  102. package/dist/number-editor/README_CN.md +357 -0
  103. package/dist/number-range/README.md +443 -0
  104. package/dist/number-range/README_CN.md +443 -0
  105. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  107. package/dist/options-multi-select/README.md +480 -0
  108. package/dist/options-multi-select/README_CN.md +480 -0
  109. package/dist/options-select/OptionsSelect.svelte +36 -5
  110. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  111. package/dist/options-select/README.md +632 -0
  112. package/dist/options-select/README_CN.md +632 -0
  113. package/dist/page/README.md +605 -0
  114. package/dist/page/README_CN.md +605 -0
  115. package/dist/pagination/README.md +946 -0
  116. package/dist/pagination/README_CN.md +946 -0
  117. package/dist/pagination-panel/README.md +1075 -0
  118. package/dist/pagination-panel/README_CN.md +1075 -0
  119. package/dist/popup-hint/README.md +841 -0
  120. package/dist/popup-hint/README_CN.md +840 -0
  121. package/dist/progress-bar/README.md +242 -0
  122. package/dist/progress-bar/README_CN.md +242 -0
  123. package/dist/progress-step-bar/README.md +316 -0
  124. package/dist/progress-step-bar/README_CN.md +316 -0
  125. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  127. package/dist/prompts-text-editor/README.md +329 -0
  128. package/dist/prompts-text-editor/README_CN.md +329 -0
  129. package/dist/property-editor/README.md +969 -0
  130. package/dist/property-editor/README_CN.md +969 -0
  131. package/dist/radio-button/README.md +372 -0
  132. package/dist/radio-button/README_CN.md +372 -0
  133. package/dist/radio-button/RadioButton.svelte +32 -3
  134. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  135. package/dist/search-box/README.md +425 -0
  136. package/dist/search-box/README_CN.md +424 -0
  137. package/dist/search-box/SearchBox.svelte +22 -6
  138. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  139. package/dist/tabs/README.md +919 -0
  140. package/dist/tabs/README_CN.md +920 -0
  141. package/dist/tag/README.md +922 -0
  142. package/dist/tag/README_CN.md +922 -0
  143. package/dist/text-editor/PasswordEditor.svelte +17 -2
  144. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  145. package/dist/text-editor/PasswordEditor_README.md +551 -0
  146. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  147. package/dist/text-editor/README.md +466 -0
  148. package/dist/text-editor/README_CN.md +466 -0
  149. package/dist/text-editor/TextEditor.svelte +51 -19
  150. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  151. package/dist/time-editor/README.md +498 -24
  152. package/dist/time-editor/README_CN.md +498 -0
  153. package/dist/time-editor/TimeEditor.svelte +7 -3
  154. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  155. package/dist/toast/README.md +667 -0
  156. package/dist/toast/README_CN.md +667 -0
  157. package/dist/transfer/README.md +795 -0
  158. package/dist/transfer/Transfer.svelte +6 -4
  159. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  160. package/dist/tree-view/README.md +761 -0
  161. package/dist/tree-view/README_CN.md +761 -0
  162. package/dist/tree-view/TreeView.svelte +5 -3
  163. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  164. package/dist/unit-number-editor/README.md +546 -20
  165. package/dist/unit-number-editor/README_CN.md +525 -0
  166. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  167. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  168. package/docs/form-field/cn/README_CN.md +364 -0
  169. package/docs/form-field/en/README.md +364 -0
  170. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  171. package/docs/form-panel/flex-form/en/README.md +586 -0
  172. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  173. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  174. package/docs/form-panel/grid-form/en/README.md +744 -0
  175. package/package.json +1 -1
  176. package/dist/drawer/README-CN.md +0 -1
@@ -1,3 +1,664 @@
1
- # 级联选择
1
+ # CascadeOptionSelect Component
2
2
 
3
- 用于多级选择,通常选择类似于层级结构。
3
+ A hierarchical dropdown component for selecting options from nested data structures. Perfect for location selectors (country/state/city), category hierarchies, organizational structures, and any multi-level selection scenarios.
4
+
5
+ ## Features
6
+
7
+ - **Hierarchical Selection**: Navigate through nested option levels
8
+ - **Dynamic Loading**: Async loading of child options via callbacks
9
+ - **Flexible Data Structure**: Configurable field mapping for different data formats
10
+ - **Leaf Detection**: Custom logic to determine selectable end nodes
11
+ - **Display Modes**: Edit and display modes for different UI contexts
12
+ - **Keyboard & Focus Support**: Full keyboard navigation and focus management
13
+ - **Loading States**: Built-in loading indicators for async operations
14
+ - **Customizable Styling**: Flexible appearance options and variants
15
+ - **Clean/Mandatory Options**: Optional clear functionality and required selection
16
+
17
+ ## Basic Usage
18
+
19
+ ```svelte
20
+ <script>
21
+ import CascadeOptionSelect from '@ticatec/uniface-element/CascadeOptionSelect';
22
+
23
+ const locationData = [
24
+ {
25
+ code: 'US',
26
+ text: 'United States',
27
+ abbr: 'US',
28
+ children: [
29
+ {
30
+ code: 'CA',
31
+ text: 'California',
32
+ abbr: 'CA',
33
+ children: [
34
+ { code: 'SF', text: 'San Francisco', abbr: 'SF' },
35
+ { code: 'LA', text: 'Los Angeles', abbr: 'LA' }
36
+ ]
37
+ }
38
+ ]
39
+ }
40
+ ];
41
+
42
+ let selectedValue = null;
43
+
44
+ const handleChange = (value) => {
45
+ console.log('Selected:', value);
46
+ selectedValue = value;
47
+ };
48
+ </script>
49
+
50
+ <CascadeOptionSelect
51
+ nodes={locationData}
52
+ bind:value={selectedValue}
53
+ onchange={handleChange}
54
+ placeholder="Select location..."
55
+ />
56
+ ```
57
+
58
+ ## Props
59
+
60
+ | Prop | Type | Default | Description |
61
+ |------|------|---------|-------------|
62
+ | `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual variant style |
63
+ | `disabled` | `boolean` | `false` | Whether the component is disabled |
64
+ | `readonly` | `boolean` | `false` | Whether the component is read-only |
65
+ | `compact` | `boolean` | `false` | Compact display mode |
66
+ | `mandatory` | `boolean` | `false` | Whether selection is required (disables clear) |
67
+ | `value` | `any` | `null` | Selected value (key field value) |
68
+ | `keyField` | `string` | `'code'` | Field name for option keys/values |
69
+ | `textField` | `string` | `'text'` | Field name for option display text |
70
+ | `abbrField` | `string` | `'abbr'` | Field name for abbreviated text in dropdown |
71
+ | `childrenField` | `string` | `'children'` | Field name for child options |
72
+ | `style` | `string` | `''` | Custom CSS styles |
73
+ | `placeholder` | `string` | `''` | Placeholder text |
74
+ | `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display or edit mode |
75
+ | `emptyText` | `string \| null` | `null` | Text to show when no selection |
76
+ | `checkLeaf` | `IsLeafDetermine \| null` | `null` | Function to determine if item is selectable leaf |
77
+ | `text` | `string` | `''` | Display text (automatically managed) |
78
+ | `nodes` | `Array<any>` | `[]` | Root level options array |
79
+ | `menu$height` | `number` | `150` | Dropdown menu height in pixels |
80
+ | `onSelect` | `OnSelectOption` | - | Async function to load child options |
81
+ | `box$style` | `string` | `''` | Custom styles for option boxes |
82
+ | `onchange` | `OnChangeHandler<any>` | - | Change event handler |
83
+ | `onfocus` | `(() => void) \| null` | `null` | Focus event handler |
84
+ | `onblur` | `(() => void) \| null` | `null` | Blur event handler |
85
+
86
+ ## Type Definitions
87
+
88
+ ```typescript
89
+ // Function to load child options asynchronously
90
+ type OnSelectOption = (item: any) => Promise<Array<any>>;
91
+
92
+ // Function to determine if an item is a selectable leaf node
93
+ type IsLeafDetermine = (item: any) => boolean;
94
+
95
+ // Change event handler
96
+ type OnChangeHandler<T> = (value: T) => void;
97
+ ```
98
+
99
+ ## Static Data Example
100
+
101
+ ```svelte
102
+ <script>
103
+ const categories = [
104
+ {
105
+ code: 'electronics',
106
+ text: 'Electronics',
107
+ abbr: 'Electronics',
108
+ children: [
109
+ {
110
+ code: 'computers',
111
+ text: 'Computers',
112
+ abbr: 'Computers',
113
+ children: [
114
+ { code: 'laptops', text: 'Laptops', abbr: 'Laptops' },
115
+ { code: 'desktops', text: 'Desktops', abbr: 'Desktops' }
116
+ ]
117
+ },
118
+ {
119
+ code: 'phones',
120
+ text: 'Mobile Phones',
121
+ abbr: 'Phones',
122
+ children: [
123
+ { code: 'smartphones', text: 'Smartphones', abbr: 'Smartphones' },
124
+ { code: 'basic-phones', text: 'Basic Phones', abbr: 'Basic' }
125
+ ]
126
+ }
127
+ ]
128
+ }
129
+ ];
130
+
131
+ let selectedCategory = null;
132
+ </script>
133
+
134
+ <CascadeOptionSelect
135
+ nodes={categories}
136
+ bind:value={selectedCategory}
137
+ placeholder="Select category..."
138
+ onchange={(value) => console.log('Selected category:', value)}
139
+ />
140
+ ```
141
+
142
+ ## Dynamic Loading Example
143
+
144
+ ```svelte
145
+ <script>
146
+ const loadRegions = async (country) => {
147
+ // Simulate API call
148
+ const response = await fetch(`/api/regions?country=${country.code}`);
149
+ return await response.json();
150
+ };
151
+
152
+ const loadCities = async (region) => {
153
+ const response = await fetch(`/api/cities?region=${region.code}`);
154
+ return await response.json();
155
+ };
156
+
157
+ const dynamicLoader = async (item) => {
158
+ // Determine what type of data to load based on the item
159
+ if (!item.children) {
160
+ if (item.type === 'country') {
161
+ return await loadRegions(item);
162
+ } else if (item.type === 'region') {
163
+ return await loadCities(item);
164
+ }
165
+ }
166
+ return item.children || [];
167
+ };
168
+
169
+ const countries = [
170
+ { code: 'US', text: 'United States', abbr: 'US', type: 'country' },
171
+ { code: 'CA', text: 'Canada', abbr: 'CA', type: 'country' },
172
+ { code: 'UK', text: 'United Kingdom', abbr: 'UK', type: 'country' }
173
+ ];
174
+
175
+ let selectedLocation = null;
176
+ </script>
177
+
178
+ <CascadeOptionSelect
179
+ nodes={countries}
180
+ bind:value={selectedLocation}
181
+ onSelect={dynamicLoader}
182
+ placeholder="Select location..."
183
+ onchange={(value) => console.log('Selected location:', value)}
184
+ />
185
+ ```
186
+
187
+ ## Custom Field Mapping
188
+
189
+ ```svelte
190
+ <script>
191
+ // Data with different field names
192
+ const orgData = [
193
+ {
194
+ id: 'corp',
195
+ name: 'Corporation',
196
+ short: 'Corp',
197
+ divisions: [
198
+ {
199
+ id: 'tech',
200
+ name: 'Technology Division',
201
+ short: 'Tech',
202
+ departments: [
203
+ { id: 'dev', name: 'Development', short: 'Dev' },
204
+ { id: 'qa', name: 'Quality Assurance', short: 'QA' }
205
+ ]
206
+ }
207
+ ]
208
+ }
209
+ ];
210
+
211
+ let selectedOrg = null;
212
+ </script>
213
+
214
+ <CascadeOptionSelect
215
+ nodes={orgData}
216
+ bind:value={selectedOrg}
217
+ keyField="id"
218
+ textField="name"
219
+ abbrField="short"
220
+ childrenField="divisions"
221
+ placeholder="Select organization..."
222
+ />
223
+ ```
224
+
225
+ ## Leaf Detection Example
226
+
227
+ ```svelte
228
+ <script>
229
+ const menuData = [
230
+ {
231
+ code: 'file',
232
+ text: 'File',
233
+ abbr: 'File',
234
+ isLeaf: false,
235
+ children: [
236
+ { code: 'new', text: 'New File', abbr: 'New', isLeaf: true },
237
+ { code: 'open', text: 'Open File', abbr: 'Open', isLeaf: true },
238
+ { code: 'save', text: 'Save File', abbr: 'Save', isLeaf: true }
239
+ ]
240
+ }
241
+ ];
242
+
243
+ const checkIfLeaf = (item) => {
244
+ return item.isLeaf === true;
245
+ };
246
+
247
+ let selectedMenuItem = null;
248
+ </script>
249
+
250
+ <CascadeOptionSelect
251
+ nodes={menuData}
252
+ bind:value={selectedMenuItem}
253
+ checkLeaf={checkIfLeaf}
254
+ placeholder="Select menu item..."
255
+ />
256
+ ```
257
+
258
+ ## Different Variants
259
+
260
+ ```svelte
261
+ <!-- Default variant -->
262
+ <CascadeOptionSelect
263
+ nodes={data}
264
+ placeholder="Default style"
265
+ />
266
+
267
+ <!-- Plain variant -->
268
+ <CascadeOptionSelect
269
+ nodes={data}
270
+ variant="plain"
271
+ placeholder="Plain style"
272
+ />
273
+
274
+ <!-- Outlined variant -->
275
+ <CascadeOptionSelect
276
+ nodes={data}
277
+ variant="outlined"
278
+ placeholder="Outlined style"
279
+ />
280
+
281
+ <!-- Filled variant -->
282
+ <CascadeOptionSelect
283
+ nodes={data}
284
+ variant="filled"
285
+ placeholder="Filled style"
286
+ />
287
+ ```
288
+
289
+ ## Event Handling
290
+
291
+ ```svelte
292
+ <script>
293
+ let currentValue = null;
294
+ let focusCount = 0;
295
+
296
+ const handleChange = (value) => {
297
+ console.log('Value changed to:', value);
298
+ currentValue = value;
299
+ };
300
+
301
+ const handleFocus = () => {
302
+ console.log('Component focused');
303
+ focusCount++;
304
+ };
305
+
306
+ const handleBlur = () => {
307
+ console.log('Component blurred');
308
+ };
309
+ </script>
310
+
311
+ <CascadeOptionSelect
312
+ nodes={data}
313
+ bind:value={currentValue}
314
+ onchange={handleChange}
315
+ onfocus={handleFocus}
316
+ onblur={handleBlur}
317
+ placeholder="Event handling example"
318
+ />
319
+
320
+ <p>Current value: {currentValue}</p>
321
+ <p>Focus count: {focusCount}</p>
322
+ ```
323
+
324
+ ## Advanced Examples
325
+
326
+ ### Location Selector with API Integration
327
+
328
+ ```svelte
329
+ <script>
330
+ import { onMount } from 'svelte';
331
+
332
+ let countries = [];
333
+ let selectedLocation = null;
334
+
335
+ onMount(async () => {
336
+ // Load initial countries
337
+ const response = await fetch('/api/countries');
338
+ countries = await response.json();
339
+ });
340
+
341
+ const loadLocationChildren = async (location) => {
342
+ let endpoint = '';
343
+
344
+ if (location.type === 'country') {
345
+ endpoint = `/api/states?country=${location.code}`;
346
+ } else if (location.type === 'state') {
347
+ endpoint = `/api/cities?state=${location.code}`;
348
+ }
349
+
350
+ if (endpoint) {
351
+ const response = await fetch(endpoint);
352
+ return await response.json();
353
+ }
354
+
355
+ return [];
356
+ };
357
+
358
+ const isLocationLeaf = (location) => {
359
+ return location.type === 'city';
360
+ };
361
+ </script>
362
+
363
+ <div class="location-selector">
364
+ <label>Select Location:</label>
365
+ <CascadeOptionSelect
366
+ nodes={countries}
367
+ bind:value={selectedLocation}
368
+ onSelect={loadLocationChildren}
369
+ checkLeaf={isLocationLeaf}
370
+ placeholder="Country / State / City"
371
+ mandatory={true}
372
+ variant="outlined"
373
+ />
374
+ </div>
375
+ ```
376
+
377
+ ### Product Category Navigator
378
+
379
+ ```svelte
380
+ <script>
381
+ const productCategories = [
382
+ {
383
+ code: 'electronics',
384
+ text: 'Electronics',
385
+ abbr: 'Electronics',
386
+ children: [
387
+ {
388
+ code: 'computers',
389
+ text: 'Computers & Accessories',
390
+ abbr: 'Computers',
391
+ children: [
392
+ { code: 'laptops', text: 'Laptops', abbr: 'Laptops' },
393
+ { code: 'desktops', text: 'Desktop Computers', abbr: 'Desktops' },
394
+ { code: 'accessories', text: 'Computer Accessories', abbr: 'Accessories' }
395
+ ]
396
+ },
397
+ {
398
+ code: 'mobile',
399
+ text: 'Mobile Devices',
400
+ abbr: 'Mobile',
401
+ children: [
402
+ { code: 'smartphones', text: 'Smartphones', abbr: 'Phones' },
403
+ { code: 'tablets', text: 'Tablets', abbr: 'Tablets' },
404
+ { code: 'wearables', text: 'Wearable Technology', abbr: 'Wearables' }
405
+ ]
406
+ }
407
+ ]
408
+ },
409
+ {
410
+ code: 'clothing',
411
+ text: 'Clothing & Fashion',
412
+ abbr: 'Clothing',
413
+ children: [
414
+ {
415
+ code: 'mens',
416
+ text: "Men's Clothing",
417
+ abbr: "Men's",
418
+ children: [
419
+ { code: 'shirts', text: 'Shirts', abbr: 'Shirts' },
420
+ { code: 'pants', text: 'Pants', abbr: 'Pants' },
421
+ { code: 'shoes', text: 'Shoes', abbr: 'Shoes' }
422
+ ]
423
+ }
424
+ ]
425
+ }
426
+ ];
427
+
428
+ let selectedCategory = null;
429
+
430
+ $: if (selectedCategory) {
431
+ console.log('Browse products in category:', selectedCategory);
432
+ }
433
+ </script>
434
+
435
+ <div class="category-navigator">
436
+ <h3>Browse Products</h3>
437
+ <CascadeOptionSelect
438
+ nodes={productCategories}
439
+ bind:value={selectedCategory}
440
+ placeholder="Select category to browse..."
441
+ variant="filled"
442
+ menu$height={200}
443
+ />
444
+ </div>
445
+ ```
446
+
447
+ ### Organization Hierarchy Selector
448
+
449
+ ```svelte
450
+ <script>
451
+ const organizationData = [
452
+ {
453
+ code: 'headquarters',
454
+ text: 'Headquarters',
455
+ abbr: 'HQ',
456
+ children: [
457
+ {
458
+ code: 'exec',
459
+ text: 'Executive',
460
+ abbr: 'Exec',
461
+ children: [
462
+ { code: 'ceo', text: 'Chief Executive Officer', abbr: 'CEO' },
463
+ { code: 'cto', text: 'Chief Technology Officer', abbr: 'CTO' }
464
+ ]
465
+ },
466
+ {
467
+ code: 'engineering',
468
+ text: 'Engineering',
469
+ abbr: 'Eng',
470
+ children: [
471
+ { code: 'frontend', text: 'Frontend Development', abbr: 'Frontend' },
472
+ { code: 'backend', text: 'Backend Development', abbr: 'Backend' },
473
+ { code: 'devops', text: 'DevOps', abbr: 'DevOps' }
474
+ ]
475
+ }
476
+ ]
477
+ }
478
+ ];
479
+
480
+ let assignedDepartment = null;
481
+
482
+ const handleDepartmentChange = (value) => {
483
+ console.log('Assigned to department:', value);
484
+ // Update user assignment
485
+ };
486
+ </script>
487
+
488
+ <div class="department-assignment">
489
+ <label>Assign to Department:</label>
490
+ <CascadeOptionSelect
491
+ nodes={organizationData}
492
+ bind:value={assignedDepartment}
493
+ onchange={handleDepartmentChange}
494
+ placeholder="Select department..."
495
+ mandatory={true}
496
+ compact={true}
497
+ />
498
+ </div>
499
+ ```
500
+
501
+ ### Menu System with Dynamic Loading
502
+
503
+ ```svelte
504
+ <script>
505
+ let menuItems = [
506
+ { code: 'file', text: 'File', abbr: 'File', hasChildren: true },
507
+ { code: 'edit', text: 'Edit', abbr: 'Edit', hasChildren: true },
508
+ { code: 'view', text: 'View', abbr: 'View', hasChildren: true }
509
+ ];
510
+
511
+ const loadMenuChildren = async (menuItem) => {
512
+ // Simulate loading menu items from server
513
+ await new Promise(resolve => setTimeout(resolve, 500));
514
+
515
+ const menuMap = {
516
+ 'file': [
517
+ { code: 'new', text: 'New', abbr: 'New', action: 'file.new' },
518
+ { code: 'open', text: 'Open', abbr: 'Open', action: 'file.open' },
519
+ { code: 'save', text: 'Save', abbr: 'Save', action: 'file.save' }
520
+ ],
521
+ 'edit': [
522
+ { code: 'cut', text: 'Cut', abbr: 'Cut', action: 'edit.cut' },
523
+ { code: 'copy', text: 'Copy', abbr: 'Copy', action: 'edit.copy' },
524
+ { code: 'paste', text: 'Paste', abbr: 'Paste', action: 'edit.paste' }
525
+ ],
526
+ 'view': [
527
+ { code: 'zoom-in', text: 'Zoom In', abbr: 'Zoom+', action: 'view.zoomIn' },
528
+ { code: 'zoom-out', text: 'Zoom Out', abbr: 'Zoom-', action: 'view.zoomOut' }
529
+ ]
530
+ };
531
+
532
+ return menuMap[menuItem.code] || [];
533
+ };
534
+
535
+ const isMenuItem = (item) => {
536
+ return item.action != null;
537
+ };
538
+
539
+ let selectedAction = null;
540
+
541
+ $: if (selectedAction) {
542
+ console.log('Execute action:', selectedAction);
543
+ }
544
+ </script>
545
+
546
+ <CascadeOptionSelect
547
+ nodes={menuItems}
548
+ bind:value={selectedAction}
549
+ onSelect={loadMenuChildren}
550
+ checkLeaf={isMenuItem}
551
+ placeholder="Select action..."
552
+ variant="outlined"
553
+ />
554
+ ```
555
+
556
+ ## Styling
557
+
558
+ The component uses the following CSS classes and can be styled through:
559
+
560
+ - Custom `style` prop for the main container
561
+ - `box$style` prop for individual option boxes
562
+ - `menu$height` prop for dropdown height
563
+ - CSS custom properties for deeper customization
564
+
565
+ ### Example Styling
566
+
567
+ ```svelte
568
+ <CascadeOptionSelect
569
+ nodes={data}
570
+ style="border-radius: 8px; border: 2px solid #007acc;"
571
+ box$style="background: #f5f5f5; border-radius: 4px;"
572
+ menu$height={250}
573
+ />
574
+ ```
575
+
576
+ ## Accessibility
577
+
578
+ The component includes:
579
+
580
+ - Proper focus management
581
+ - Keyboard navigation support
582
+ - ARIA attributes for screen readers
583
+ - Focus and blur event handling
584
+ - Clear visual indicators for selected items
585
+
586
+ ## Best Practices
587
+
588
+ 1. **Data Structure**: Use consistent field naming across all levels
589
+ 2. **Loading States**: Provide feedback during async operations
590
+ 3. **Error Handling**: Handle API failures gracefully in onSelect callbacks
591
+ 4. **Performance**: Consider virtualization for very large datasets
592
+ 5. **Validation**: Validate leaf selection when mandatory is true
593
+ 6. **Responsive Design**: Test dropdown behavior on mobile devices
594
+ 7. **User Experience**: Provide clear visual hierarchy in option display
595
+
596
+ ## Common Patterns
597
+
598
+ ### Form Integration
599
+
600
+ ```svelte
601
+ <script>
602
+ let formData = {
603
+ location: null,
604
+ category: null
605
+ };
606
+
607
+ const validateForm = () => {
608
+ return formData.location && formData.category;
609
+ };
610
+ </script>
611
+
612
+ <form>
613
+ <div class="form-field">
614
+ <label>Location:</label>
615
+ <CascadeOptionSelect
616
+ nodes={locationData}
617
+ bind:value={formData.location}
618
+ mandatory={true}
619
+ placeholder="Select location..."
620
+ />
621
+ </div>
622
+
623
+ <button type="submit" disabled={!validateForm()}>
624
+ Submit
625
+ </button>
626
+ </form>
627
+ ```
628
+
629
+ ### State Management
630
+
631
+ ```svelte
632
+ <script>
633
+ import { writable } from 'svelte/store';
634
+
635
+ const selectedValues = writable({
636
+ location: null,
637
+ category: null,
638
+ department: null
639
+ });
640
+
641
+ $: console.log('Current selections:', $selectedValues);
642
+ </script>
643
+
644
+ <CascadeOptionSelect
645
+ nodes={locationData}
646
+ value={$selectedValues.location}
647
+ onchange={(value) => selectedValues.update(s => ({...s, location: value}))}
648
+ />
649
+ ```
650
+
651
+ ## Browser Support
652
+
653
+ Works in all modern browsers that support:
654
+ - ES6+ JavaScript
655
+ - CSS Flexbox
656
+ - Modern DOM APIs
657
+ - Promises/async-await
658
+
659
+ ## Performance Considerations
660
+
661
+ - Efficient handling of large datasets through virtual scrolling in option boxes
662
+ - Debounced async loading to prevent excessive API calls
663
+ - Proper cleanup of event listeners and timeouts
664
+ - Optimized re-rendering with Svelte's reactivity system