@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.
- 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/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/list-box/README.md
CHANGED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
# ListBox
|
|
2
|
+
|
|
3
|
+
A versatile list component that supports filtering, lazy loading, single/multiple selection modes, and custom item rendering.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Selection Modes**: None, single, and multiple selection support
|
|
8
|
+
- **Search & Filter**: Built-in search functionality with custom filter functions
|
|
9
|
+
- **Lazy Loading**: Support for paginated data loading with infinite scroll
|
|
10
|
+
- **Custom Rendering**: Flexible item rendering with custom components
|
|
11
|
+
- **Interactive States**: Hover, selection, and click handling
|
|
12
|
+
- **Header/Footer Slots**: Customizable header and footer sections
|
|
13
|
+
- **Loading States**: Built-in loading indicators for async operations
|
|
14
|
+
- **Accessibility**: Keyboard navigation and screen reader support
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @ticatec/uniface-element
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Basic Usage
|
|
25
|
+
|
|
26
|
+
```svelte
|
|
27
|
+
<script>
|
|
28
|
+
import ListBox from '@ticatec/uniface-element/list-box';
|
|
29
|
+
import MyItemComponent from './MyItemComponent.svelte';
|
|
30
|
+
|
|
31
|
+
let items = [
|
|
32
|
+
{ id: 1, name: 'Item 1', description: 'First item' },
|
|
33
|
+
{ id: 2, name: 'Item 2', description: 'Second item' },
|
|
34
|
+
{ id: 3, name: 'Item 3', description: 'Third item' }
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
let selectedItem = null;
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<ListBox
|
|
41
|
+
list={items}
|
|
42
|
+
itemRender={MyItemComponent}
|
|
43
|
+
selectMode="single"
|
|
44
|
+
bind:selectedItem
|
|
45
|
+
style="width: 300px; height: 400px;"
|
|
46
|
+
/>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Read-Only List Display
|
|
50
|
+
|
|
51
|
+
```svelte
|
|
52
|
+
<ListBox
|
|
53
|
+
list={items}
|
|
54
|
+
itemRender={ItemRenderer}
|
|
55
|
+
selectMode="none"
|
|
56
|
+
readonly={true}
|
|
57
|
+
style="width: 100%; height: 300px;"
|
|
58
|
+
/>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Multiple Selection
|
|
62
|
+
|
|
63
|
+
```svelte
|
|
64
|
+
<script>
|
|
65
|
+
let selectedList = [];
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<ListBox
|
|
69
|
+
list={items}
|
|
70
|
+
itemRender={ItemRenderer}
|
|
71
|
+
selectMode="multiple"
|
|
72
|
+
bind:selectedList
|
|
73
|
+
title="Select Multiple Items"
|
|
74
|
+
style="width: 100%; height: 400px;"
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<p>Selected: {selectedList.length} items</p>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### With Search/Filter
|
|
81
|
+
|
|
82
|
+
```svelte
|
|
83
|
+
<script>
|
|
84
|
+
const filterFunction = (item, searchText) => {
|
|
85
|
+
return item.name.toLowerCase().includes(searchText.toLowerCase()) ||
|
|
86
|
+
item.description.toLowerCase().includes(searchText.toLowerCase());
|
|
87
|
+
};
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<ListBox
|
|
91
|
+
list={items}
|
|
92
|
+
itemRender={ItemRenderer}
|
|
93
|
+
selectMode="single"
|
|
94
|
+
filter={filterFunction}
|
|
95
|
+
title="Searchable List"
|
|
96
|
+
bind:selectedItem
|
|
97
|
+
/>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Lazy Loading
|
|
101
|
+
|
|
102
|
+
```svelte
|
|
103
|
+
<script>
|
|
104
|
+
const lazyLoader = async (searchText, pageNo) => {
|
|
105
|
+
const response = await fetch(`/api/items?search=${searchText}&page=${pageNo}`);
|
|
106
|
+
const data = await response.json();
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
list: data.items,
|
|
110
|
+
hasMore: data.hasMore
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<ListBox
|
|
116
|
+
lazyLoader={lazyLoader}
|
|
117
|
+
itemRender={ItemRenderer}
|
|
118
|
+
selectMode="single"
|
|
119
|
+
bind:selectedItem
|
|
120
|
+
style="width: 100%; height: 500px;"
|
|
121
|
+
/>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Custom Header and Footer
|
|
125
|
+
|
|
126
|
+
```svelte
|
|
127
|
+
<ListBox
|
|
128
|
+
list={items}
|
|
129
|
+
itemRender={ItemRenderer}
|
|
130
|
+
selectMode="single"
|
|
131
|
+
bind:selectedItem
|
|
132
|
+
>
|
|
133
|
+
<div slot="header" style="padding: 12px; background: #f8f9fa; font-weight: 600;">
|
|
134
|
+
Custom Header - Total: {items.length}
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<div slot="footer" style="padding: 8px; text-align: right; background: #f8f9fa;">
|
|
138
|
+
Selected: {selectedItem?.name || 'None'}
|
|
139
|
+
</div>
|
|
140
|
+
</ListBox>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## API Reference
|
|
144
|
+
|
|
145
|
+
### Props
|
|
146
|
+
|
|
147
|
+
| Prop | Type | Default | Description |
|
|
148
|
+
|------|------|---------|-------------|
|
|
149
|
+
| `list` | `Array<any>` | `[]` | Array of items to display |
|
|
150
|
+
| `itemRender` | `SvelteComponent` | - | Component to render each item |
|
|
151
|
+
| `selectMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | Selection mode |
|
|
152
|
+
| `selectedItem` | `any` | `null` | Currently selected item (single mode) |
|
|
153
|
+
| `selectedList` | `Array<any>` | `[]` | Array of selected items (multiple mode) |
|
|
154
|
+
| `filter` | `FunFilter \| null` | `null` | Filter function for search |
|
|
155
|
+
| `lazyLoader` | `LazyLoader \| null` | `null` | Lazy loading function |
|
|
156
|
+
| `readonly` | `boolean` | `false` | Whether the list is read-only |
|
|
157
|
+
| `title` | `string` | - | Title text for the header |
|
|
158
|
+
| `style` | `string` | `''` | Custom CSS styles |
|
|
159
|
+
| `header$style` | `string` | `''` | Custom styles for header |
|
|
160
|
+
| `footer$style` | `string` | `''` | Custom styles for footer |
|
|
161
|
+
| `round` | `boolean` | `false` | Whether to use rounded corners |
|
|
162
|
+
| `item$props` | `any` | `null` | Additional props passed to item components |
|
|
163
|
+
| `class` | `string` | `''` | Additional CSS classes |
|
|
164
|
+
|
|
165
|
+
### Events
|
|
166
|
+
|
|
167
|
+
| Event | Type | Description |
|
|
168
|
+
|-------|------|-------------|
|
|
169
|
+
| `onSelectChange` | `(item: any) => void` | Fired when selection changes (single mode) |
|
|
170
|
+
| `onItemClick` | `(item: any) => void` | Fired when an item is clicked |
|
|
171
|
+
| `onItemDblClick` | `(item: any) => void` | Fired when an item is double-clicked |
|
|
172
|
+
|
|
173
|
+
### Slots
|
|
174
|
+
|
|
175
|
+
| Slot | Description |
|
|
176
|
+
|------|-------------|
|
|
177
|
+
| `header` | Custom header content |
|
|
178
|
+
| `footer` | Custom footer content |
|
|
179
|
+
| `loadMoreIndicator` | Custom loading indicator for lazy loading |
|
|
180
|
+
|
|
181
|
+
### Types
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// Filter function type
|
|
185
|
+
type FunFilter = (item: any, searchText: string) => boolean;
|
|
186
|
+
|
|
187
|
+
// Lazy loader function type
|
|
188
|
+
type LazyLoader = (searchText: string, pageNo: number) => Promise<LoadResult>;
|
|
189
|
+
|
|
190
|
+
// Load result interface
|
|
191
|
+
interface LoadResult {
|
|
192
|
+
list: Array<any>;
|
|
193
|
+
hasMore: boolean;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Custom Item Renderer
|
|
198
|
+
|
|
199
|
+
Create a custom component to render list items:
|
|
200
|
+
|
|
201
|
+
```svelte
|
|
202
|
+
<!-- EmployeeRenderer.svelte -->
|
|
203
|
+
<script lang="ts">
|
|
204
|
+
export let item;
|
|
205
|
+
export let selected = false;
|
|
206
|
+
export let readonly = false;
|
|
207
|
+
</script>
|
|
208
|
+
|
|
209
|
+
<div class="employee-item" class:selected>
|
|
210
|
+
<div class="employee-name">{item.name}</div>
|
|
211
|
+
<div class="employee-department">{item.department}</div>
|
|
212
|
+
<div class="employee-phone">{item.phone}</div>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<style>
|
|
216
|
+
.employee-item {
|
|
217
|
+
padding: 12px;
|
|
218
|
+
border-radius: 4px;
|
|
219
|
+
transition: background-color 0.2s;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.employee-item.selected {
|
|
223
|
+
background-color: #e3f2fd;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.employee-name {
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
font-size: 1.1em;
|
|
229
|
+
margin-bottom: 4px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.employee-department {
|
|
233
|
+
color: #666;
|
|
234
|
+
font-size: 0.9em;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.employee-phone {
|
|
238
|
+
color: #888;
|
|
239
|
+
font-size: 0.8em;
|
|
240
|
+
margin-top: 4px;
|
|
241
|
+
}
|
|
242
|
+
</style>
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Examples
|
|
246
|
+
|
|
247
|
+
### Employee Directory
|
|
248
|
+
|
|
249
|
+
```svelte
|
|
250
|
+
<script>
|
|
251
|
+
import ListBox from '@ticatec/uniface-element/list-box';
|
|
252
|
+
import EmployeeRenderer from './EmployeeRenderer.svelte';
|
|
253
|
+
|
|
254
|
+
let employees = [
|
|
255
|
+
{ id: 1, name: 'John Doe', department: 'Engineering', phone: '+1-555-0123' },
|
|
256
|
+
{ id: 2, name: 'Jane Smith', department: 'Marketing', phone: '+1-555-0124' },
|
|
257
|
+
{ id: 3, name: 'Bob Johnson', department: 'Sales', phone: '+1-555-0125' }
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
let selectedEmployee = null;
|
|
261
|
+
|
|
262
|
+
const filterEmployees = (employee, searchText) => {
|
|
263
|
+
const text = searchText.toLowerCase();
|
|
264
|
+
return employee.name.toLowerCase().includes(text) ||
|
|
265
|
+
employee.department.toLowerCase().includes(text);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
function handleEmployeeSelect(employee) {
|
|
269
|
+
console.log('Selected employee:', employee);
|
|
270
|
+
}
|
|
271
|
+
</script>
|
|
272
|
+
|
|
273
|
+
<ListBox
|
|
274
|
+
list={employees}
|
|
275
|
+
itemRender={EmployeeRenderer}
|
|
276
|
+
selectMode="single"
|
|
277
|
+
filter={filterEmployees}
|
|
278
|
+
bind:selectedItem={selectedEmployee}
|
|
279
|
+
onSelectChange={handleEmployeeSelect}
|
|
280
|
+
title="Employee Directory"
|
|
281
|
+
style="width: 400px; height: 500px;"
|
|
282
|
+
>
|
|
283
|
+
<div slot="footer" style="padding: 8px; text-align: center; background: #f5f5f5;">
|
|
284
|
+
Total Employees: {employees.length}
|
|
285
|
+
{#if selectedEmployee}
|
|
286
|
+
| Selected: {selectedEmployee.name}
|
|
287
|
+
{/if}
|
|
288
|
+
</div>
|
|
289
|
+
</ListBox>
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Product Catalog with Lazy Loading
|
|
293
|
+
|
|
294
|
+
```svelte
|
|
295
|
+
<script>
|
|
296
|
+
import ListBox from '@ticatec/uniface-element/list-box';
|
|
297
|
+
import ProductRenderer from './ProductRenderer.svelte';
|
|
298
|
+
|
|
299
|
+
let selectedProducts = [];
|
|
300
|
+
|
|
301
|
+
const loadProducts = async (searchText, pageNo) => {
|
|
302
|
+
const params = new URLSearchParams({
|
|
303
|
+
search: searchText || '',
|
|
304
|
+
page: pageNo.toString(),
|
|
305
|
+
limit: '20'
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
const response = await fetch(`/api/products?${params}`);
|
|
310
|
+
const data = await response.json();
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
list: data.products,
|
|
314
|
+
hasMore: data.totalPages > pageNo
|
|
315
|
+
};
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.error('Failed to load products:', error);
|
|
318
|
+
return { list: [], hasMore: false };
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
</script>
|
|
322
|
+
|
|
323
|
+
<ListBox
|
|
324
|
+
lazyLoader={loadProducts}
|
|
325
|
+
itemRender={ProductRenderer}
|
|
326
|
+
selectMode="multiple"
|
|
327
|
+
bind:selectedList={selectedProducts}
|
|
328
|
+
style="width: 100%; height: 600px;"
|
|
329
|
+
>
|
|
330
|
+
<div slot="header" style="padding: 12px; background: #2196f3; color: white;">
|
|
331
|
+
<h3 style="margin: 0;">Product Catalog</h3>
|
|
332
|
+
</div>
|
|
333
|
+
|
|
334
|
+
<div slot="footer" style="padding: 8px; background: #f0f0f0; text-align: right;">
|
|
335
|
+
Selected: {selectedProducts.length} products
|
|
336
|
+
<button
|
|
337
|
+
on:click={() => selectedProducts = []}
|
|
338
|
+
disabled={selectedProducts.length === 0}
|
|
339
|
+
>
|
|
340
|
+
Clear Selection
|
|
341
|
+
</button>
|
|
342
|
+
</div>
|
|
343
|
+
|
|
344
|
+
<div slot="loadMoreIndicator" style="padding: 16px; text-align: center;">
|
|
345
|
+
<div class="loading-spinner"></div>
|
|
346
|
+
Loading more products...
|
|
347
|
+
</div>
|
|
348
|
+
</ListBox>
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Contact List with Actions
|
|
352
|
+
|
|
353
|
+
```svelte
|
|
354
|
+
<script>
|
|
355
|
+
import ListBox from '@ticatec/uniface-element/list-box';
|
|
356
|
+
import ContactRenderer from './ContactRenderer.svelte';
|
|
357
|
+
|
|
358
|
+
let contacts = [
|
|
359
|
+
{ id: 1, name: 'Alice Brown', email: 'alice@example.com', phone: '+1-555-0001' },
|
|
360
|
+
{ id: 2, name: 'Charlie Davis', email: 'charlie@example.com', phone: '+1-555-0002' }
|
|
361
|
+
];
|
|
362
|
+
|
|
363
|
+
let selectedContact = null;
|
|
364
|
+
|
|
365
|
+
function handleContactDblClick(contact) {
|
|
366
|
+
// Open contact details or edit modal
|
|
367
|
+
console.log('Opening contact:', contact);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function handleContactCall(contact) {
|
|
371
|
+
console.log('Calling:', contact.phone);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function handleContactEmail(contact) {
|
|
375
|
+
window.location.href = `mailto:${contact.email}`;
|
|
376
|
+
}
|
|
377
|
+
</script>
|
|
378
|
+
|
|
379
|
+
<ListBox
|
|
380
|
+
list={contacts}
|
|
381
|
+
itemRender={ContactRenderer}
|
|
382
|
+
selectMode="single"
|
|
383
|
+
bind:selectedItem={selectedContact}
|
|
384
|
+
onItemDblClick={handleContactDblClick}
|
|
385
|
+
item$props={{ onCall: handleContactCall, onEmail: handleContactEmail }}
|
|
386
|
+
title="Contacts"
|
|
387
|
+
style="width: 350px; height: 450px;"
|
|
388
|
+
>
|
|
389
|
+
<div slot="footer" style="padding: 12px; display: flex; gap: 8px;">
|
|
390
|
+
<button
|
|
391
|
+
disabled={!selectedContact}
|
|
392
|
+
on:click={() => handleContactCall(selectedContact)}
|
|
393
|
+
>
|
|
394
|
+
Call
|
|
395
|
+
</button>
|
|
396
|
+
<button
|
|
397
|
+
disabled={!selectedContact}
|
|
398
|
+
on:click={() => handleContactEmail(selectedContact)}
|
|
399
|
+
>
|
|
400
|
+
Email
|
|
401
|
+
</button>
|
|
402
|
+
</div>
|
|
403
|
+
</ListBox>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Styling
|
|
407
|
+
|
|
408
|
+
### CSS Variables
|
|
409
|
+
|
|
410
|
+
The ListBox component uses CSS variables for consistent theming:
|
|
411
|
+
|
|
412
|
+
```css
|
|
413
|
+
:root {
|
|
414
|
+
--uniface-listbox-separator-color: #f0f0f0;
|
|
415
|
+
--uniface-list-box-hover-bg: #ffffe1;
|
|
416
|
+
--uniface-list-box-selected-bg: #b1c8f6;
|
|
417
|
+
--uniface-list-box-header-bottom-border: 1px solid #f0f0f0;
|
|
418
|
+
--uniface-list-box-border-color: #f0f0f0;
|
|
419
|
+
--uniface-list-box-header-bg: #f8fafc;
|
|
420
|
+
--uniface-list-box-footer-bg: #f8fafc;
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Custom Styling
|
|
425
|
+
|
|
426
|
+
```css
|
|
427
|
+
.custom-listbox {
|
|
428
|
+
--uniface-list-box-hover-bg: #e3f2fd;
|
|
429
|
+
--uniface-list-box-selected-bg: #1976d2;
|
|
430
|
+
--uniface-list-box-border-color: #1976d2;
|
|
431
|
+
border-radius: 8px;
|
|
432
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.custom-listbox .listview-item {
|
|
436
|
+
transition: all 0.2s ease;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.custom-listbox .box-header {
|
|
440
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
441
|
+
color: white;
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
## Accessibility Features
|
|
446
|
+
|
|
447
|
+
- **Keyboard Navigation**: Arrow keys for navigation, Enter for selection
|
|
448
|
+
- **Screen Reader Support**: Proper ARIA labels and roles
|
|
449
|
+
- **Focus Management**: Visible focus indicators and logical tab order
|
|
450
|
+
- **Selection Announcements**: Screen reader feedback for selection changes
|
|
451
|
+
- **Search Accessibility**: Proper labeling for search functionality
|
|
452
|
+
|
|
453
|
+
## Performance Considerations
|
|
454
|
+
|
|
455
|
+
### Large Lists
|
|
456
|
+
|
|
457
|
+
For large datasets, use lazy loading:
|
|
458
|
+
|
|
459
|
+
```svelte
|
|
460
|
+
<script>
|
|
461
|
+
const lazyLoader = async (searchText, pageNo) => {
|
|
462
|
+
// Implement efficient server-side pagination
|
|
463
|
+
const response = await fetch(`/api/items?search=${searchText}&page=${pageNo}&limit=50`);
|
|
464
|
+
return await response.json();
|
|
465
|
+
};
|
|
466
|
+
</script>
|
|
467
|
+
|
|
468
|
+
<ListBox
|
|
469
|
+
lazyLoader={lazyLoader}
|
|
470
|
+
itemRender={OptimizedItemRenderer}
|
|
471
|
+
style="height: 400px;"
|
|
472
|
+
/>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Virtual Scrolling
|
|
476
|
+
|
|
477
|
+
For extremely large lists, consider implementing virtual scrolling in your item renderer:
|
|
478
|
+
|
|
479
|
+
```svelte
|
|
480
|
+
<!-- VirtualizedItemRenderer.svelte -->
|
|
481
|
+
<script>
|
|
482
|
+
export let item;
|
|
483
|
+
export let index;
|
|
484
|
+
|
|
485
|
+
// Implement virtual scrolling logic here
|
|
486
|
+
</script>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Best Practices
|
|
490
|
+
|
|
491
|
+
### 1. Optimize Item Renderers
|
|
492
|
+
|
|
493
|
+
Keep item renderers simple and efficient:
|
|
494
|
+
|
|
495
|
+
```svelte
|
|
496
|
+
<!-- Good: Simple and efficient -->
|
|
497
|
+
<script>
|
|
498
|
+
export let item;
|
|
499
|
+
</script>
|
|
500
|
+
|
|
501
|
+
<div class="item">
|
|
502
|
+
<h4>{item.title}</h4>
|
|
503
|
+
<p>{item.description}</p>
|
|
504
|
+
</div>
|
|
505
|
+
|
|
506
|
+
<!-- Avoid: Heavy computations in renderer -->
|
|
507
|
+
<script>
|
|
508
|
+
export let item;
|
|
509
|
+
|
|
510
|
+
// Don't do heavy processing here
|
|
511
|
+
$: processedData = heavyComputation(item);
|
|
512
|
+
</script>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### 2. Implement Proper Loading States
|
|
516
|
+
|
|
517
|
+
```svelte
|
|
518
|
+
<ListBox
|
|
519
|
+
lazyLoader={dataLoader}
|
|
520
|
+
itemRender={ItemRenderer}
|
|
521
|
+
>
|
|
522
|
+
<div slot="loadMoreIndicator" class="loading-indicator">
|
|
523
|
+
<div class="spinner"></div>
|
|
524
|
+
Loading more items...
|
|
525
|
+
</div>
|
|
526
|
+
</ListBox>
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### 3. Handle Empty States
|
|
530
|
+
|
|
531
|
+
```svelte
|
|
532
|
+
<script>
|
|
533
|
+
let items = [];
|
|
534
|
+
let isLoading = false;
|
|
535
|
+
</script>
|
|
536
|
+
|
|
537
|
+
{#if isLoading}
|
|
538
|
+
<div class="loading-state">Loading...</div>
|
|
539
|
+
{:else if items.length === 0}
|
|
540
|
+
<div class="empty-state">No items found</div>
|
|
541
|
+
{:else}
|
|
542
|
+
<ListBox list={items} itemRender={ItemRenderer} />
|
|
543
|
+
{/if}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### 4. Provide Clear Selection Feedback
|
|
547
|
+
|
|
548
|
+
```svelte
|
|
549
|
+
<ListBox
|
|
550
|
+
bind:selectedItem
|
|
551
|
+
selectMode="single"
|
|
552
|
+
style="--uniface-list-box-selected-bg: #2196f3; --uniface-list-box-hover-bg: #e3f2fd;"
|
|
553
|
+
/>
|
|
554
|
+
|
|
555
|
+
<div class="selection-info">
|
|
556
|
+
{#if selectedItem}
|
|
557
|
+
Selected: {selectedItem.name}
|
|
558
|
+
{:else}
|
|
559
|
+
No item selected
|
|
560
|
+
{/if}
|
|
561
|
+
</div>
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
## Browser Support
|
|
565
|
+
|
|
566
|
+
- **Modern Browsers**: Chrome, Firefox, Safari, Edge (latest versions)
|
|
567
|
+
- **Mobile Browsers**: iOS Safari, Chrome Mobile, Firefox Mobile
|
|
568
|
+
- **Flexbox Support**: Required for layout functionality
|
|
569
|
+
- **Intersection Observer**: Required for lazy loading (polyfill available)
|
|
570
|
+
|
|
571
|
+
## Related Components
|
|
572
|
+
|
|
573
|
+
- **SearchBox**: Used internally for filtering functionality
|
|
574
|
+
- **CheckBox**: Used for multiple selection mode
|
|
575
|
+
- **Box**: Base layout component
|
|
576
|
+
|
|
577
|
+
## License
|
|
578
|
+
|
|
579
|
+
MIT License - see LICENSE file for details.
|