@ticatec/uniface-element 0.2.0 → 0.2.2
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 +320 -1
- package/README_CN.md +392 -0
- package/dist/accordion/Accordion.svelte +1 -1
- package/dist/action-bar/ActionBar.svelte +7 -1
- package/dist/attachment-files/FileRender.svelte +1 -1
- package/dist/attachment-files/FileUploadBar.svelte +7 -6
- package/dist/attachment-files/FileUploadPanel.svelte +2 -2
- package/dist/base-calendar/DateContext.js +5 -4
- package/dist/base-calendar/YearPickupPanel.svelte +4 -4
- package/dist/card/Card.svelte +1 -1
- package/dist/card/Card.svelte.d.ts +1 -1
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +2 -3
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +46 -1
- package/dist/cascade-options-select/CascadePanel.svelte +1 -1
- package/dist/checkbox/CheckBox.svelte +1 -1
- package/dist/color-picker/ColorPicker.svelte +9 -9
- package/dist/color-picker/ColorPicker.svelte.d.ts +0 -2
- package/dist/color-picker/ColorPickerPanel.svelte +11 -15
- package/dist/color-picker/ColorPickerPanel.svelte.d.ts +1 -1
- package/dist/common/CommonPicker.svelte +2 -2
- package/dist/common/CommonPicker.svelte.d.ts +1 -1
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/common/Popover.svelte +28 -6
- package/dist/common/Popover.svelte.d.ts +9 -3
- package/dist/common/uniface-utils.js +6 -4
- package/dist/common-editor/CommonEditor.svelte +1 -1
- package/dist/common-editor/CommonEditor.svelte.d.ts +1 -1
- package/dist/common-editor/NumberInput.svelte +1 -1
- package/dist/common-editor/NumberInput.svelte.d.ts +1 -1
- package/dist/concise-data-table/ConciseListTable.svelte +7 -2
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +1 -0
- package/dist/concise-data-table/DataRow.svelte +1 -1
- package/dist/concise-data-table/TableOptions.d.ts +1 -1
- package/dist/data-table/DataTable.svelte +1 -1
- package/dist/data-table/parts/ActionsPanel.svelte +4 -3
- package/dist/data-table/parts/ActionsRow.svelte +3 -3
- package/dist/data-table/parts/ContentPanel.svelte +3 -2
- package/dist/data-table/parts/FixedColumnsPanel.svelte +0 -1
- package/dist/data-table/parts/FixedColumnsPanel.svelte.d.ts +1 -2
- package/dist/data-table/parts/FixedHeaderPanel.svelte +2 -2
- package/dist/data-table/parts/FixedRow.svelte +2 -1
- package/dist/data-table/parts/FixedRow.svelte.d.ts +1 -1
- package/dist/data-table/parts/HrefCell.svelte +23 -2
- package/dist/data-table/parts/PopupMenu.svelte +25 -2
- package/dist/data-table/parts/PopupMenu.svelte.d.ts +8 -1
- package/dist/date-picker/DatePicker.svelte +0 -1
- package/dist/date-picker/DateTimePicker.svelte +3 -3
- package/dist/date-picker/ScrollBar.svelte +4 -7
- package/dist/date-range/DateRangeEditor.svelte +1 -1
- package/dist/dialog/CommonDialog.svelte +8 -5
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +37 -12
- 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/{common-editor/DateInput.svelte.d.ts → dialog/DialogWrapper.svelte.d.ts} +6 -13
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/dist/drawer/Drawer.svelte +1 -1
- package/dist/form-field/FormField.svelte +2 -1
- package/dist/form-field/FormField.svelte.d.ts +1 -0
- package/dist/form-panel/flex-row-form/FormContainer.svelte +1 -1
- package/dist/form-panel/grid-form/EmptyCell.svelte +8 -7
- package/dist/form-panel/grid-form/EmptyCell.svelte.d.ts +2 -2
- package/dist/form-panel/grid-form/GridField.svelte +1 -1
- package/dist/i18nRes/i18nRes.d.ts +2 -0
- package/dist/i18nRes/i18nRes.js +44 -0
- package/dist/i18nRes/index.d.ts +2 -0
- package/dist/i18nRes/index.js +2 -0
- package/dist/image-files/ImageFilesField.svelte +1 -1
- package/dist/indicator/IndicatorBoard.svelte +1 -1
- package/dist/inline-cell-editor/InvalidEditor.svelte +1 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +6 -6
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +1 -1
- package/dist/layout/flex/FlexBlock.svelte +1 -1
- package/dist/lookup-editor/LookupEditor.svelte +1 -1
- package/dist/memo-editor/MemoEditor.svelte +2 -2
- package/dist/message-box/IMessageBox.d.ts +2 -4
- package/dist/message-box/IMessageBox.js +4 -6
- package/dist/message-box/MessageBoxBoard.svelte +1 -3
- package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +2 -2
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +1 -1
- package/dist/property-editor/PropertyEditor.svelte +3 -3
- package/dist/text-editor/PasswordEditor.svelte +1 -1
- package/dist/transfer/Transfer.svelte +17 -12
- package/dist/transfer/Transfer.svelte.d.ts +0 -1
- package/dist/unit-number-editor/UnitNumberEditor.svelte +2 -2
- 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 +53 -13
- package/dist/common-editor/DateInput.svelte +0 -27
- package/dist/i18n_resources/index.d.ts +0 -3
- package/dist/i18n_resources/index.js +0 -3
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.js +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.js +0 -0
|
@@ -0,0 +1,786 @@
|
|
|
1
|
+
# ListBox Component
|
|
2
|
+
|
|
3
|
+
A versatile list display component that provides item selection, filtering, lazy loading, and multiple selection modes for displaying collections of data.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The ListBox component offers a comprehensive solution for displaying lists of items with rich interaction capabilities. It supports single and multiple selection modes, real-time filtering, lazy loading for large datasets, and custom item rendering. Perfect for user selection interfaces, data browsers, and content management systems.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
13
|
+
import type { LazyLoader, FunFilter, LoadResult } from '@ticatec/uniface-element/ListBox';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Basic Usage
|
|
17
|
+
|
|
18
|
+
```svelte
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
21
|
+
|
|
22
|
+
// Simple item renderer component
|
|
23
|
+
const ItemRenderer = ({ item }) => `
|
|
24
|
+
<div class="list-item">
|
|
25
|
+
<h4>${item.title}</h4>
|
|
26
|
+
<p>${item.description}</p>
|
|
27
|
+
</div>
|
|
28
|
+
`;
|
|
29
|
+
|
|
30
|
+
let items = [
|
|
31
|
+
{ id: 1, title: 'Item 1', description: 'First item description' },
|
|
32
|
+
{ id: 2, title: 'Item 2', description: 'Second item description' },
|
|
33
|
+
{ id: 3, title: 'Item 3', description: 'Third item description' }
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
let selectedItem = null;
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<ListBox
|
|
40
|
+
list={items}
|
|
41
|
+
itemRender={ItemRenderer}
|
|
42
|
+
selectMode="single"
|
|
43
|
+
bind:selectedItem
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Properties
|
|
48
|
+
|
|
49
|
+
| Property | Type | Default | Description |
|
|
50
|
+
|----------|------|---------|-------------|
|
|
51
|
+
| `readonly` | `boolean` | `false` | Make the list read-only |
|
|
52
|
+
| `style` | `string \| null` | `null` | Custom CSS styles for container |
|
|
53
|
+
| `header$style` | `string \| null` | `null` | Custom styles for header area |
|
|
54
|
+
| `footer$style` | `string \| null` | `null` | Custom styles for footer area |
|
|
55
|
+
| `list` | `Array<any>` | - | Array of items to display |
|
|
56
|
+
| `itemRender` | `any` | - | Component for rendering each item |
|
|
57
|
+
| `selectMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | Selection behavior mode |
|
|
58
|
+
| `filter` | `FunFilter \| null` | `null` | Filter function for items |
|
|
59
|
+
| `lazyLoader` | `LazyLoader \| null` | `null` | Lazy loading configuration |
|
|
60
|
+
| `selectedItem` | `any` | `null` | Currently selected item (single mode) |
|
|
61
|
+
| `selectedList` | `Array<any>` | `[]` | Selected items (multiple mode) |
|
|
62
|
+
| `class` | `string` | `''` | Additional CSS class names |
|
|
63
|
+
| `item$props` | `any` | `null` | Additional props for item renderer |
|
|
64
|
+
| `onSelectChange` | `OnSelectChange` | `null` | Selection change callback |
|
|
65
|
+
| `onItemDblClick` | `OnItemDblClick` | `null` | Item double-click callback |
|
|
66
|
+
| `onItemClick` | `OnItemClick` | `null` | Item click callback |
|
|
67
|
+
| `title` | `string` | `null` | Header title |
|
|
68
|
+
| `round` | `boolean` | `false` | Apply rounded corners |
|
|
69
|
+
|
|
70
|
+
## Slots
|
|
71
|
+
|
|
72
|
+
| Slot | Description |
|
|
73
|
+
|------|-------------|
|
|
74
|
+
| `header` | Custom header content |
|
|
75
|
+
| `footer` | Custom footer content |
|
|
76
|
+
| `loadMoreIndicator` | Custom loading indicator for lazy loading |
|
|
77
|
+
|
|
78
|
+
## Type Definitions
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
/**
|
|
82
|
+
* Filter function for items
|
|
83
|
+
*/
|
|
84
|
+
export type FunFilter = (item: any, text: string) => boolean;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Lazy loading result structure
|
|
88
|
+
*/
|
|
89
|
+
export interface LoadResult {
|
|
90
|
+
hasMore: boolean;
|
|
91
|
+
list: Array<any>;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Lazy loader function
|
|
96
|
+
*/
|
|
97
|
+
export type LazyLoader = (text: string, pageNo: number) => Promise<LoadResult>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Event handler types
|
|
101
|
+
*/
|
|
102
|
+
type OnSelectChange = (item: any) => void;
|
|
103
|
+
type OnItemDblClick = (item: any) => void;
|
|
104
|
+
type OnItemClick = (item: any) => void;
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Usage Examples
|
|
108
|
+
|
|
109
|
+
### Single Selection List
|
|
110
|
+
|
|
111
|
+
```svelte
|
|
112
|
+
<script lang="ts">
|
|
113
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
114
|
+
|
|
115
|
+
// Custom item renderer
|
|
116
|
+
const UserRenderer = ({ item, selected }) => `
|
|
117
|
+
<div class="user-item ${selected ? 'selected' : ''}">
|
|
118
|
+
<div class="user-avatar">
|
|
119
|
+
<img src="${item.avatar}" alt="${item.name}" width="32" height="32" />
|
|
120
|
+
</div>
|
|
121
|
+
<div class="user-info">
|
|
122
|
+
<div class="user-name">${item.name}</div>
|
|
123
|
+
<div class="user-role">${item.role}</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
let users = [
|
|
129
|
+
{ id: 1, name: 'Alice Johnson', role: 'Developer', avatar: '/avatars/alice.jpg' },
|
|
130
|
+
{ id: 2, name: 'Bob Smith', role: 'Designer', avatar: '/avatars/bob.jpg' },
|
|
131
|
+
{ id: 3, name: 'Carol Davis', role: 'Manager', avatar: '/avatars/carol.jpg' }
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
let selectedUser = null;
|
|
135
|
+
|
|
136
|
+
function handleUserSelect(user: any) {
|
|
137
|
+
console.log('Selected user:', user);
|
|
138
|
+
}
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<ListBox
|
|
142
|
+
title="Select User"
|
|
143
|
+
list={users}
|
|
144
|
+
itemRender={UserRenderer}
|
|
145
|
+
selectMode="single"
|
|
146
|
+
bind:selectedItem={selectedUser}
|
|
147
|
+
onSelectChange={handleUserSelect}
|
|
148
|
+
style="width: 300px; height: 400px; border: 1px solid #ddd;"
|
|
149
|
+
/>
|
|
150
|
+
|
|
151
|
+
<style>
|
|
152
|
+
:global(.user-item) {
|
|
153
|
+
display: flex;
|
|
154
|
+
align-items: center;
|
|
155
|
+
gap: 12px;
|
|
156
|
+
padding: 12px;
|
|
157
|
+
border-bottom: 1px solid #f0f0f0;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
transition: background-color 0.2s;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
:global(.user-item:hover) {
|
|
163
|
+
background-color: #f8f9fa;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
:global(.user-item.selected) {
|
|
167
|
+
background-color: #e3f2fd;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
:global(.user-avatar img) {
|
|
171
|
+
border-radius: 50%;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
:global(.user-name) {
|
|
175
|
+
font-weight: 500;
|
|
176
|
+
margin-bottom: 2px;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
:global(.user-role) {
|
|
180
|
+
font-size: 0.875rem;
|
|
181
|
+
color: #666;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Multiple Selection List
|
|
187
|
+
|
|
188
|
+
```svelte
|
|
189
|
+
<script lang="ts">
|
|
190
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
191
|
+
|
|
192
|
+
const TaskRenderer = ({ item }) => `
|
|
193
|
+
<div class="task-item">
|
|
194
|
+
<div class="task-title">${item.title}</div>
|
|
195
|
+
<div class="task-meta">
|
|
196
|
+
<span class="task-priority priority-${item.priority.toLowerCase()}">${item.priority}</span>
|
|
197
|
+
<span class="task-due">Due: ${new Date(item.dueDate).toLocaleDateString()}</span>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
let tasks = [
|
|
203
|
+
{ id: 1, title: 'Review pull request', priority: 'High', dueDate: '2024-03-20' },
|
|
204
|
+
{ id: 2, title: 'Update documentation', priority: 'Medium', dueDate: '2024-03-22' },
|
|
205
|
+
{ id: 3, title: 'Fix minor bugs', priority: 'Low', dueDate: '2024-03-25' },
|
|
206
|
+
{ id: 4, title: 'Plan next sprint', priority: 'High', dueDate: '2024-03-18' }
|
|
207
|
+
];
|
|
208
|
+
|
|
209
|
+
let selectedTasks = [];
|
|
210
|
+
|
|
211
|
+
$: console.log('Selected tasks:', selectedTasks);
|
|
212
|
+
</script>
|
|
213
|
+
|
|
214
|
+
<ListBox
|
|
215
|
+
title="Select Tasks"
|
|
216
|
+
list={tasks}
|
|
217
|
+
itemRender={TaskRenderer}
|
|
218
|
+
selectMode="multiple"
|
|
219
|
+
bind:selectedList={selectedTasks}
|
|
220
|
+
style="width: 400px; height: 500px;"
|
|
221
|
+
round={true}
|
|
222
|
+
/>
|
|
223
|
+
|
|
224
|
+
<div class="selection-summary">
|
|
225
|
+
<p>Selected: {selectedTasks.length} task(s)</p>
|
|
226
|
+
{#if selectedTasks.length > 0}
|
|
227
|
+
<ul>
|
|
228
|
+
{#each selectedTasks as task}
|
|
229
|
+
<li>{task.title}</li>
|
|
230
|
+
{/each}
|
|
231
|
+
</ul>
|
|
232
|
+
{/if}
|
|
233
|
+
</div>
|
|
234
|
+
|
|
235
|
+
<style>
|
|
236
|
+
:global(.task-item) {
|
|
237
|
+
padding: 12px;
|
|
238
|
+
border-bottom: 1px solid #eee;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
:global(.task-title) {
|
|
242
|
+
font-weight: 500;
|
|
243
|
+
margin-bottom: 6px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
:global(.task-meta) {
|
|
247
|
+
display: flex;
|
|
248
|
+
justify-content: space-between;
|
|
249
|
+
align-items: center;
|
|
250
|
+
font-size: 0.875rem;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
:global(.task-priority) {
|
|
254
|
+
padding: 2px 8px;
|
|
255
|
+
border-radius: 12px;
|
|
256
|
+
font-size: 0.75rem;
|
|
257
|
+
font-weight: 500;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
:global(.priority-high) {
|
|
261
|
+
background: #ffebee;
|
|
262
|
+
color: #c62828;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
:global(.priority-medium) {
|
|
266
|
+
background: #fff3e0;
|
|
267
|
+
color: #ef6c00;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
:global(.priority-low) {
|
|
271
|
+
background: #e8f5e8;
|
|
272
|
+
color: #2e7d32;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
:global(.task-due) {
|
|
276
|
+
color: #666;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.selection-summary {
|
|
280
|
+
margin-top: 16px;
|
|
281
|
+
padding: 12px;
|
|
282
|
+
background: #f8f9fa;
|
|
283
|
+
border-radius: 4px;
|
|
284
|
+
}
|
|
285
|
+
</style>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Filtered List
|
|
289
|
+
|
|
290
|
+
```svelte
|
|
291
|
+
<script lang="ts">
|
|
292
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
293
|
+
import type { FunFilter } from '@ticatec/uniface-element/ListBox';
|
|
294
|
+
|
|
295
|
+
const ProductRenderer = ({ item }) => `
|
|
296
|
+
<div class="product-item">
|
|
297
|
+
<img src="${item.image}" alt="${item.name}" class="product-image" />
|
|
298
|
+
<div class="product-info">
|
|
299
|
+
<div class="product-name">${item.name}</div>
|
|
300
|
+
<div class="product-category">${item.category}</div>
|
|
301
|
+
<div class="product-price">$${item.price.toFixed(2)}</div>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
`;
|
|
305
|
+
|
|
306
|
+
let products = [
|
|
307
|
+
{ id: 1, name: 'Laptop Pro', category: 'Electronics', price: 1299.99, image: '/images/laptop.jpg' },
|
|
308
|
+
{ id: 2, name: 'Coffee Maker', category: 'Appliances', price: 89.99, image: '/images/coffee.jpg' },
|
|
309
|
+
{ id: 3, name: 'Smartphone', category: 'Electronics', price: 699.99, image: '/images/phone.jpg' },
|
|
310
|
+
{ id: 4, name: 'Desk Chair', category: 'Furniture', price: 249.99, image: '/images/chair.jpg' },
|
|
311
|
+
{ id: 5, name: 'Tablet', category: 'Electronics', price: 329.99, image: '/images/tablet.jpg' }
|
|
312
|
+
];
|
|
313
|
+
|
|
314
|
+
const productFilter: FunFilter = (item, text) => {
|
|
315
|
+
if (!text) return true;
|
|
316
|
+
const searchText = text.toLowerCase();
|
|
317
|
+
return (
|
|
318
|
+
item.name.toLowerCase().includes(searchText) ||
|
|
319
|
+
item.category.toLowerCase().includes(searchText)
|
|
320
|
+
);
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
let selectedProduct = null;
|
|
324
|
+
</script>
|
|
325
|
+
|
|
326
|
+
<ListBox
|
|
327
|
+
title="Product Catalog"
|
|
328
|
+
list={products}
|
|
329
|
+
itemRender={ProductRenderer}
|
|
330
|
+
selectMode="single"
|
|
331
|
+
filter={productFilter}
|
|
332
|
+
bind:selectedItem={selectedProduct}
|
|
333
|
+
style="width: 350px; height: 600px;"
|
|
334
|
+
header$style="padding: 16px;"
|
|
335
|
+
/>
|
|
336
|
+
|
|
337
|
+
{#if selectedProduct}
|
|
338
|
+
<div class="product-details">
|
|
339
|
+
<h3>Selected Product</h3>
|
|
340
|
+
<p><strong>Name:</strong> {selectedProduct.name}</p>
|
|
341
|
+
<p><strong>Category:</strong> {selectedProduct.category}</p>
|
|
342
|
+
<p><strong>Price:</strong> ${selectedProduct.price.toFixed(2)}</p>
|
|
343
|
+
</div>
|
|
344
|
+
{/if}
|
|
345
|
+
|
|
346
|
+
<style>
|
|
347
|
+
:global(.product-item) {
|
|
348
|
+
display: flex;
|
|
349
|
+
align-items: center;
|
|
350
|
+
gap: 12px;
|
|
351
|
+
padding: 12px;
|
|
352
|
+
border-bottom: 1px solid #f0f0f0;
|
|
353
|
+
cursor: pointer;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
:global(.product-item:hover) {
|
|
357
|
+
background-color: #f8f9fa;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
:global(.product-image) {
|
|
361
|
+
width: 48px;
|
|
362
|
+
height: 48px;
|
|
363
|
+
object-fit: cover;
|
|
364
|
+
border-radius: 4px;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
:global(.product-name) {
|
|
368
|
+
font-weight: 500;
|
|
369
|
+
margin-bottom: 2px;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
:global(.product-category) {
|
|
373
|
+
font-size: 0.875rem;
|
|
374
|
+
color: #666;
|
|
375
|
+
margin-bottom: 2px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
:global(.product-price) {
|
|
379
|
+
font-weight: 600;
|
|
380
|
+
color: #007bff;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.product-details {
|
|
384
|
+
margin-top: 20px;
|
|
385
|
+
padding: 16px;
|
|
386
|
+
background: #f8f9fa;
|
|
387
|
+
border-radius: 4px;
|
|
388
|
+
width: 350px;
|
|
389
|
+
}
|
|
390
|
+
</style>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Lazy Loading List
|
|
394
|
+
|
|
395
|
+
```svelte
|
|
396
|
+
<script lang="ts">
|
|
397
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
398
|
+
import type { LazyLoader, LoadResult } from '@ticatec/uniface-element/ListBox';
|
|
399
|
+
|
|
400
|
+
const MessageRenderer = ({ item }) => `
|
|
401
|
+
<div class="message-item">
|
|
402
|
+
<div class="message-header">
|
|
403
|
+
<span class="sender">${item.sender}</span>
|
|
404
|
+
<span class="timestamp">${new Date(item.timestamp).toLocaleTimeString()}</span>
|
|
405
|
+
</div>
|
|
406
|
+
<div class="message-subject">${item.subject}</div>
|
|
407
|
+
<div class="message-preview">${item.preview}</div>
|
|
408
|
+
</div>
|
|
409
|
+
`;
|
|
410
|
+
|
|
411
|
+
// Simulate API call for lazy loading
|
|
412
|
+
const messageLoader: LazyLoader = async (searchText, pageNo) => {
|
|
413
|
+
console.log(`Loading page ${pageNo} with search: "${searchText}"`);
|
|
414
|
+
|
|
415
|
+
// Simulate network delay
|
|
416
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
417
|
+
|
|
418
|
+
const pageSize = 10;
|
|
419
|
+
const totalMessages = 100;
|
|
420
|
+
|
|
421
|
+
// Generate mock messages
|
|
422
|
+
const messages = Array.from({ length: pageSize }, (_, i) => {
|
|
423
|
+
const messageId = (pageNo - 1) * pageSize + i + 1;
|
|
424
|
+
return {
|
|
425
|
+
id: messageId,
|
|
426
|
+
sender: `User ${messageId}`,
|
|
427
|
+
subject: searchText
|
|
428
|
+
? `Message about ${searchText} #${messageId}`
|
|
429
|
+
: `Message Subject ${messageId}`,
|
|
430
|
+
preview: `This is a preview of message ${messageId}. It contains some sample content...`,
|
|
431
|
+
timestamp: new Date(Date.now() - Math.random() * 86400000).toISOString()
|
|
432
|
+
};
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Filter messages if search text provided
|
|
436
|
+
const filteredMessages = searchText
|
|
437
|
+
? messages.filter(msg =>
|
|
438
|
+
msg.subject.toLowerCase().includes(searchText.toLowerCase()) ||
|
|
439
|
+
msg.sender.toLowerCase().includes(searchText.toLowerCase())
|
|
440
|
+
)
|
|
441
|
+
: messages;
|
|
442
|
+
|
|
443
|
+
return {
|
|
444
|
+
list: filteredMessages,
|
|
445
|
+
hasMore: pageNo * pageSize < totalMessages
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
let selectedMessage = null;
|
|
450
|
+
</script>
|
|
451
|
+
|
|
452
|
+
<ListBox
|
|
453
|
+
title="Messages (Lazy Loading)"
|
|
454
|
+
itemRender={MessageRenderer}
|
|
455
|
+
selectMode="single"
|
|
456
|
+
lazyLoader={messageLoader}
|
|
457
|
+
bind:selectedItem={selectedMessage}
|
|
458
|
+
style="width: 400px; height: 500px;"
|
|
459
|
+
/>
|
|
460
|
+
|
|
461
|
+
<div slot="loadMoreIndicator" class="load-more">
|
|
462
|
+
<div class="loading-spinner">Loading more messages...</div>
|
|
463
|
+
</div>
|
|
464
|
+
|
|
465
|
+
{#if selectedMessage}
|
|
466
|
+
<div class="message-details">
|
|
467
|
+
<h3>Selected Message</h3>
|
|
468
|
+
<p><strong>From:</strong> {selectedMessage.sender}</p>
|
|
469
|
+
<p><strong>Subject:</strong> {selectedMessage.subject}</p>
|
|
470
|
+
<p><strong>Time:</strong> {new Date(selectedMessage.timestamp).toLocaleString()}</p>
|
|
471
|
+
<div class="message-content">
|
|
472
|
+
<p>{selectedMessage.preview}</p>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
{/if}
|
|
476
|
+
|
|
477
|
+
<style>
|
|
478
|
+
:global(.message-item) {
|
|
479
|
+
padding: 12px;
|
|
480
|
+
border-bottom: 1px solid #eee;
|
|
481
|
+
cursor: pointer;
|
|
482
|
+
transition: background-color 0.2s;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
:global(.message-item:hover) {
|
|
486
|
+
background-color: #f8f9fa;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
:global(.message-header) {
|
|
490
|
+
display: flex;
|
|
491
|
+
justify-content: space-between;
|
|
492
|
+
align-items: center;
|
|
493
|
+
margin-bottom: 4px;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
:global(.sender) {
|
|
497
|
+
font-weight: 500;
|
|
498
|
+
color: #333;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
:global(.timestamp) {
|
|
502
|
+
font-size: 0.75rem;
|
|
503
|
+
color: #666;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
:global(.message-subject) {
|
|
507
|
+
font-weight: 500;
|
|
508
|
+
margin-bottom: 4px;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
:global(.message-preview) {
|
|
512
|
+
font-size: 0.875rem;
|
|
513
|
+
color: #666;
|
|
514
|
+
display: -webkit-box;
|
|
515
|
+
-webkit-line-clamp: 2;
|
|
516
|
+
-webkit-box-orient: vertical;
|
|
517
|
+
overflow: hidden;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.load-more {
|
|
521
|
+
padding: 16px;
|
|
522
|
+
text-align: center;
|
|
523
|
+
color: #666;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.loading-spinner {
|
|
527
|
+
display: flex;
|
|
528
|
+
align-items: center;
|
|
529
|
+
justify-content: center;
|
|
530
|
+
gap: 8px;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.message-details {
|
|
534
|
+
margin-top: 20px;
|
|
535
|
+
padding: 16px;
|
|
536
|
+
background: #f8f9fa;
|
|
537
|
+
border-radius: 4px;
|
|
538
|
+
width: 400px;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.message-content {
|
|
542
|
+
margin-top: 12px;
|
|
543
|
+
padding-top: 12px;
|
|
544
|
+
border-top: 1px solid #dee2e6;
|
|
545
|
+
}
|
|
546
|
+
</style>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### Custom Item Renderer
|
|
550
|
+
|
|
551
|
+
```svelte
|
|
552
|
+
<script lang="ts">
|
|
553
|
+
import ListBox from '@ticatec/uniface-element/ListBox';
|
|
554
|
+
|
|
555
|
+
// Custom Svelte component for item rendering
|
|
556
|
+
import FileItemRenderer from './FileItemRenderer.svelte';
|
|
557
|
+
|
|
558
|
+
let files = [
|
|
559
|
+
{ id: 1, name: 'document.pdf', size: 2048000, type: 'pdf', modified: '2024-03-15T10:30:00Z' },
|
|
560
|
+
{ id: 2, name: 'image.jpg', size: 1536000, type: 'image', modified: '2024-03-14T15:45:00Z' },
|
|
561
|
+
{ id: 3, name: 'script.js', size: 8192, type: 'code', modified: '2024-03-13T09:20:00Z' },
|
|
562
|
+
{ id: 4, name: 'data.csv', size: 512000, type: 'data', modified: '2024-03-12T14:10:00Z' }
|
|
563
|
+
];
|
|
564
|
+
|
|
565
|
+
let selectedFiles = [];
|
|
566
|
+
|
|
567
|
+
function handleFileDoubleClick(file: any) {
|
|
568
|
+
console.log('Opening file:', file.name);
|
|
569
|
+
// Implement file opening logic
|
|
570
|
+
}
|
|
571
|
+
</script>
|
|
572
|
+
|
|
573
|
+
<ListBox
|
|
574
|
+
title="File Browser"
|
|
575
|
+
list={files}
|
|
576
|
+
itemRender={FileItemRenderer}
|
|
577
|
+
selectMode="multiple"
|
|
578
|
+
bind:selectedList={selectedFiles}
|
|
579
|
+
onItemDblClick={handleFileDoubleClick}
|
|
580
|
+
style="width: 500px; height: 400px;"
|
|
581
|
+
item$props={{ showDetails: true, allowPreview: true }}
|
|
582
|
+
>
|
|
583
|
+
<div slot="footer" class="file-footer">
|
|
584
|
+
<span>{files.length} item(s), {selectedFiles.length} selected</span>
|
|
585
|
+
</div>
|
|
586
|
+
</ListBox>
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
FileItemRenderer.svelte:
|
|
590
|
+
```svelte
|
|
591
|
+
<script lang="ts">
|
|
592
|
+
export let item: any;
|
|
593
|
+
export let selected: boolean = false;
|
|
594
|
+
export let readonly: boolean = false;
|
|
595
|
+
export let showDetails: boolean = false;
|
|
596
|
+
export let allowPreview: boolean = false;
|
|
597
|
+
|
|
598
|
+
function formatFileSize(bytes: number) {
|
|
599
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
600
|
+
if (bytes === 0) return '0 B';
|
|
601
|
+
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
602
|
+
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
function getFileIcon(type: string) {
|
|
606
|
+
const icons = {
|
|
607
|
+
pdf: '📄',
|
|
608
|
+
image: '🖼️',
|
|
609
|
+
code: '💻',
|
|
610
|
+
data: '📊',
|
|
611
|
+
default: '📁'
|
|
612
|
+
};
|
|
613
|
+
return icons[type] || icons.default;
|
|
614
|
+
}
|
|
615
|
+
</script>
|
|
616
|
+
|
|
617
|
+
<div class="file-item" class:selected class:readonly>
|
|
618
|
+
<div class="file-icon">
|
|
619
|
+
{getFileIcon(item.type)}
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
<div class="file-info">
|
|
623
|
+
<div class="file-name">{item.name}</div>
|
|
624
|
+
{#if showDetails}
|
|
625
|
+
<div class="file-details">
|
|
626
|
+
<span class="file-size">{formatFileSize(item.size)}</span>
|
|
627
|
+
<span class="file-modified">Modified: {new Date(item.modified).toLocaleDateString()}</span>
|
|
628
|
+
</div>
|
|
629
|
+
{/if}
|
|
630
|
+
</div>
|
|
631
|
+
|
|
632
|
+
{#if allowPreview && item.type === 'image'}
|
|
633
|
+
<button class="preview-btn" on:click|stopPropagation={() => console.log('Preview', item.name)}>
|
|
634
|
+
👁️
|
|
635
|
+
</button>
|
|
636
|
+
{/if}
|
|
637
|
+
</div>
|
|
638
|
+
|
|
639
|
+
<style>
|
|
640
|
+
.file-item {
|
|
641
|
+
display: flex;
|
|
642
|
+
align-items: center;
|
|
643
|
+
gap: 12px;
|
|
644
|
+
padding: 8px 12px;
|
|
645
|
+
border-bottom: 1px solid #f0f0f0;
|
|
646
|
+
cursor: pointer;
|
|
647
|
+
transition: background-color 0.2s;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.file-item:hover:not(.readonly) {
|
|
651
|
+
background-color: #f8f9fa;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.file-item.selected {
|
|
655
|
+
background-color: #e3f2fd;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
.file-item.readonly {
|
|
659
|
+
cursor: default;
|
|
660
|
+
opacity: 0.7;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
.file-icon {
|
|
664
|
+
font-size: 24px;
|
|
665
|
+
flex-shrink: 0;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
.file-info {
|
|
669
|
+
flex: 1;
|
|
670
|
+
min-width: 0;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
.file-name {
|
|
674
|
+
font-weight: 500;
|
|
675
|
+
white-space: nowrap;
|
|
676
|
+
overflow: hidden;
|
|
677
|
+
text-overflow: ellipsis;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.file-details {
|
|
681
|
+
display: flex;
|
|
682
|
+
gap: 16px;
|
|
683
|
+
font-size: 0.875rem;
|
|
684
|
+
color: #666;
|
|
685
|
+
margin-top: 2px;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.preview-btn {
|
|
689
|
+
background: none;
|
|
690
|
+
border: 1px solid #ddd;
|
|
691
|
+
border-radius: 4px;
|
|
692
|
+
padding: 4px 8px;
|
|
693
|
+
cursor: pointer;
|
|
694
|
+
opacity: 0.7;
|
|
695
|
+
transition: opacity 0.2s;
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.preview-btn:hover {
|
|
699
|
+
opacity: 1;
|
|
700
|
+
}
|
|
701
|
+
</style>
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
## Styling
|
|
705
|
+
|
|
706
|
+
The ListBox component uses the following CSS classes:
|
|
707
|
+
|
|
708
|
+
```css
|
|
709
|
+
.uniface-listbox {
|
|
710
|
+
/* Main list container */
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.uniface-listbox.round {
|
|
714
|
+
/* Rounded corners variant */
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.box-header {
|
|
718
|
+
/* Header container */
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.header-search {
|
|
722
|
+
/* Search box container */
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.listbox-content {
|
|
726
|
+
/* Main content area */
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
.listbox-content.selectable {
|
|
730
|
+
/* Selectable list styling */
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.listview-item {
|
|
734
|
+
/* Individual list item */
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
.listview-item.selected {
|
|
738
|
+
/* Selected item styling */
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.box-footer {
|
|
742
|
+
/* Footer container */
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
.list-view-mask {
|
|
746
|
+
/* Loading overlay */
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
## API Reference
|
|
751
|
+
|
|
752
|
+
### ListBox Component Props
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
interface ListBoxProps {
|
|
756
|
+
readonly?: boolean; // Read-only mode
|
|
757
|
+
style?: string | null; // Container styles
|
|
758
|
+
header$style?: string | null; // Header styles
|
|
759
|
+
footer$style?: string | null; // Footer styles
|
|
760
|
+
list: Array<any>; // Items to display
|
|
761
|
+
itemRender: any; // Item renderer component
|
|
762
|
+
selectMode: 'none' | 'single' | 'multiple'; // Selection mode
|
|
763
|
+
filter?: FunFilter | null; // Filter function
|
|
764
|
+
lazyLoader?: LazyLoader | null; // Lazy loading config
|
|
765
|
+
selectedItem?: any; // Selected item (single mode)
|
|
766
|
+
selectedList?: Array<any>; // Selected items (multiple mode)
|
|
767
|
+
class?: string; // CSS classes
|
|
768
|
+
item$props?: any; // Props for item renderer
|
|
769
|
+
onSelectChange?: OnSelectChange; // Selection callback
|
|
770
|
+
onItemDblClick?: OnItemDblClick; // Double-click callback
|
|
771
|
+
onItemClick?: OnItemClick; // Click callback
|
|
772
|
+
title?: string; // Header title
|
|
773
|
+
round?: boolean; // Rounded corners
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
## Best Practices
|
|
778
|
+
|
|
779
|
+
1. **Performance** - Use lazy loading for large datasets (>100 items)
|
|
780
|
+
2. **Item Renderers** - Keep item rendering components lightweight and focused
|
|
781
|
+
3. **Filtering** - Implement efficient filter functions for responsive search
|
|
782
|
+
4. **Selection Management** - Always bind to selectedItem/selectedList for state tracking
|
|
783
|
+
5. **Accessibility** - Ensure item renderers support keyboard navigation
|
|
784
|
+
6. **Error Handling** - Handle loading errors gracefully in lazy loader
|
|
785
|
+
7. **Visual Feedback** - Provide clear visual indicators for selection and loading states
|
|
786
|
+
8. **Mobile Support** - Consider touch-friendly item sizes and interactions
|