@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,688 @@
|
|
|
1
|
+
# NumberRange Component
|
|
2
|
+
|
|
3
|
+
A numeric range input component that allows users to specify a range between two numbers, commonly used for filtering data by numeric criteria such as price ranges, age ranges, or quantity filters.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The NumberRange component provides an intuitive interface for selecting numeric ranges with built-in validation, automatic range constraints, and clear functionality. It features two connected number inputs that intelligently validate against each other, ensuring the "from" value is always less than or equal to the "to" value. Perfect for search filters, data queries, and any application requiring numeric range selection.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import NumberRange from '@ticatec/uniface-element/NumberRange';
|
|
13
|
+
import type { OnChangeHandler } from '@ticatec/uniface-element/NumberRange';
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Basic Usage
|
|
17
|
+
|
|
18
|
+
```svelte
|
|
19
|
+
<script lang="ts">
|
|
20
|
+
import NumberRange from '@ticatec/uniface-element/NumberRange';
|
|
21
|
+
|
|
22
|
+
let fromValue: number = 0;
|
|
23
|
+
let toValue: number = 100;
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<NumberRange
|
|
27
|
+
bind:fromValue
|
|
28
|
+
bind:toValue
|
|
29
|
+
variant="outlined"
|
|
30
|
+
/>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Properties
|
|
34
|
+
|
|
35
|
+
| Property | Type | Default | Description |
|
|
36
|
+
|----------|------|---------|-------------|
|
|
37
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual styling variant |
|
|
38
|
+
| `compact` | `boolean` | `false` | Enable compact layout for dense forms |
|
|
39
|
+
| `class` | `string` | `''` | Additional CSS class names |
|
|
40
|
+
| `style` | `string` | `''` | Custom inline styles |
|
|
41
|
+
| `min` | `number \| null` | `null` | Global minimum allowed value |
|
|
42
|
+
| `max` | `number \| null` | `null` | Global maximum allowed value |
|
|
43
|
+
| `fromValue` | `number` | - | Starting value of the range (bindable) |
|
|
44
|
+
| `toValue` | `number` | - | Ending value of the range (bindable) |
|
|
45
|
+
| `allowNegative` | `boolean` | `false` | Allow negative numbers in inputs |
|
|
46
|
+
|
|
47
|
+
## Features
|
|
48
|
+
|
|
49
|
+
- **Smart Validation**: Automatically validates range constraints (from ≤ to)
|
|
50
|
+
- **Cross-Field Limits**: The "from" value sets the maximum for "to", and "to" value sets minimum for "from"
|
|
51
|
+
- **Clear Functionality**: Built-in clear button that appears when values exist
|
|
52
|
+
- **Auto Focus**: Focuses the first input after clearing values
|
|
53
|
+
- **Negative Numbers**: Optional support for negative number ranges
|
|
54
|
+
- **Consistent Styling**: Matches other form components with variant support
|
|
55
|
+
|
|
56
|
+
## Type Definitions
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
/**
|
|
60
|
+
* Change event handler type
|
|
61
|
+
*/
|
|
62
|
+
type OnChangeHandler<T> = (value: T) => void;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage Examples
|
|
66
|
+
|
|
67
|
+
### Price Range Filter
|
|
68
|
+
|
|
69
|
+
```svelte
|
|
70
|
+
<script lang="ts">
|
|
71
|
+
import NumberRange from '@ticatec/uniface-element/NumberRange';
|
|
72
|
+
|
|
73
|
+
let minPrice: number = 0;
|
|
74
|
+
let maxPrice: number = 1000;
|
|
75
|
+
|
|
76
|
+
// Reactive statement to handle price range changes
|
|
77
|
+
$: if (minPrice !== undefined && maxPrice !== undefined) {
|
|
78
|
+
filterProductsByPrice(minPrice, maxPrice);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function filterProductsByPrice(min: number, max: number) {
|
|
82
|
+
console.log(`Filtering products between $${min} and $${max}`);
|
|
83
|
+
// Implement filtering logic here
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function resetPriceFilter() {
|
|
87
|
+
minPrice = 0;
|
|
88
|
+
maxPrice = 1000;
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<div class="price-filter">
|
|
93
|
+
<h3>Price Range</h3>
|
|
94
|
+
|
|
95
|
+
<NumberRange
|
|
96
|
+
bind:fromValue={minPrice}
|
|
97
|
+
bind:toValue={maxPrice}
|
|
98
|
+
variant="outlined"
|
|
99
|
+
min={0}
|
|
100
|
+
max={10000}
|
|
101
|
+
style="width: 300px;"
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
<div class="price-display">
|
|
105
|
+
<span class="price-label">
|
|
106
|
+
${minPrice?.toLocaleString() || 0} - ${maxPrice?.toLocaleString() || 0}
|
|
107
|
+
</span>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<button class="reset-btn" on:click={resetPriceFilter}>
|
|
111
|
+
Reset Filter
|
|
112
|
+
</button>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<style>
|
|
116
|
+
.price-filter {
|
|
117
|
+
padding: 16px;
|
|
118
|
+
background: #f8f9fa;
|
|
119
|
+
border-radius: 8px;
|
|
120
|
+
max-width: 400px;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.price-filter h3 {
|
|
124
|
+
margin: 0 0 12px 0;
|
|
125
|
+
color: #333;
|
|
126
|
+
font-size: 1.1rem;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.price-display {
|
|
130
|
+
margin: 12px 0;
|
|
131
|
+
text-align: center;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.price-label {
|
|
135
|
+
font-weight: 500;
|
|
136
|
+
color: #007bff;
|
|
137
|
+
font-size: 1.1rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.reset-btn {
|
|
141
|
+
width: 100%;
|
|
142
|
+
padding: 8px 16px;
|
|
143
|
+
background: #6c757d;
|
|
144
|
+
color: white;
|
|
145
|
+
border: none;
|
|
146
|
+
border-radius: 4px;
|
|
147
|
+
cursor: pointer;
|
|
148
|
+
margin-top: 8px;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.reset-btn:hover {
|
|
152
|
+
background: #5a6268;
|
|
153
|
+
}
|
|
154
|
+
</style>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Age Range Selector
|
|
158
|
+
|
|
159
|
+
```svelte
|
|
160
|
+
<script lang="ts">
|
|
161
|
+
import NumberRange from '@ticatec/uniface-element/NumberRange';
|
|
162
|
+
|
|
163
|
+
let minAge: number = 18;
|
|
164
|
+
let maxAge: number = 65;
|
|
165
|
+
let selectedProfiles = [];
|
|
166
|
+
|
|
167
|
+
// Function to filter user profiles by age
|
|
168
|
+
function filterProfilesByAge(min: number, max: number) {
|
|
169
|
+
// Mock profiles data
|
|
170
|
+
const allProfiles = [
|
|
171
|
+
{ id: 1, name: 'Alice Johnson', age: 25 },
|
|
172
|
+
{ id: 2, name: 'Bob Smith', age: 35 },
|
|
173
|
+
{ id: 3, name: 'Carol Davis', age: 45 },
|
|
174
|
+
{ id: 4, name: 'David Wilson', age: 28 },
|
|
175
|
+
{ id: 5, name: 'Emma Brown', age: 52 }
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
selectedProfiles = allProfiles.filter(profile =>
|
|
179
|
+
profile.age >= min && profile.age <= max
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Filter on initial load and when values change
|
|
184
|
+
$: filterProfilesByAge(minAge || 0, maxAge || 100);
|
|
185
|
+
</script>
|
|
186
|
+
|
|
187
|
+
<div class="age-filter-demo">
|
|
188
|
+
<div class="filter-section">
|
|
189
|
+
<h3>Filter by Age Range</h3>
|
|
190
|
+
|
|
191
|
+
<NumberRange
|
|
192
|
+
bind:fromValue={minAge}
|
|
193
|
+
bind:toValue={maxAge}
|
|
194
|
+
variant="filled"
|
|
195
|
+
min={16}
|
|
196
|
+
max={100}
|
|
197
|
+
style="width: 250px;"
|
|
198
|
+
compact={true}
|
|
199
|
+
/>
|
|
200
|
+
|
|
201
|
+
<div class="age-summary">
|
|
202
|
+
<p>Showing profiles aged {minAge} to {maxAge} years</p>
|
|
203
|
+
<p class="result-count">{selectedProfiles.length} profiles found</p>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<div class="results-section">
|
|
208
|
+
<h4>Matching Profiles</h4>
|
|
209
|
+
{#if selectedProfiles.length > 0}
|
|
210
|
+
<div class="profiles-grid">
|
|
211
|
+
{#each selectedProfiles as profile}
|
|
212
|
+
<div class="profile-card">
|
|
213
|
+
<div class="profile-name">{profile.name}</div>
|
|
214
|
+
<div class="profile-age">Age: {profile.age}</div>
|
|
215
|
+
</div>
|
|
216
|
+
{/each}
|
|
217
|
+
</div>
|
|
218
|
+
{:else}
|
|
219
|
+
<p class="no-results">No profiles match the selected age range</p>
|
|
220
|
+
{/if}
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<style>
|
|
225
|
+
.age-filter-demo {
|
|
226
|
+
max-width: 600px;
|
|
227
|
+
margin: 0 auto;
|
|
228
|
+
padding: 20px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.filter-section {
|
|
232
|
+
background: #ffffff;
|
|
233
|
+
padding: 20px;
|
|
234
|
+
border-radius: 8px;
|
|
235
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
236
|
+
margin-bottom: 20px;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.filter-section h3 {
|
|
240
|
+
margin: 0 0 16px 0;
|
|
241
|
+
color: #333;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.age-summary {
|
|
245
|
+
margin-top: 12px;
|
|
246
|
+
padding: 12px;
|
|
247
|
+
background: #e3f2fd;
|
|
248
|
+
border-radius: 4px;
|
|
249
|
+
text-align: center;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.result-count {
|
|
253
|
+
font-weight: 600;
|
|
254
|
+
color: #1976d2;
|
|
255
|
+
margin: 4px 0 0 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.results-section h4 {
|
|
259
|
+
margin: 0 0 16px 0;
|
|
260
|
+
color: #333;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.profiles-grid {
|
|
264
|
+
display: grid;
|
|
265
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
266
|
+
gap: 12px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.profile-card {
|
|
270
|
+
padding: 16px;
|
|
271
|
+
background: #f8f9fa;
|
|
272
|
+
border-radius: 6px;
|
|
273
|
+
border-left: 4px solid #007bff;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.profile-name {
|
|
277
|
+
font-weight: 500;
|
|
278
|
+
color: #333;
|
|
279
|
+
margin-bottom: 4px;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.profile-age {
|
|
283
|
+
color: #666;
|
|
284
|
+
font-size: 0.9rem;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.no-results {
|
|
288
|
+
text-align: center;
|
|
289
|
+
color: #666;
|
|
290
|
+
font-style: italic;
|
|
291
|
+
padding: 40px 20px;
|
|
292
|
+
}
|
|
293
|
+
</style>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Inventory Range Query
|
|
297
|
+
|
|
298
|
+
```svelte
|
|
299
|
+
<script lang="ts">
|
|
300
|
+
import NumberRange from '@ticatec/uniface-element/NumberRange';
|
|
301
|
+
|
|
302
|
+
let minQuantity: number = 0;
|
|
303
|
+
let maxQuantity: number = 500;
|
|
304
|
+
|
|
305
|
+
// Mock inventory data
|
|
306
|
+
let inventoryItems = [
|
|
307
|
+
{ id: 'A001', name: 'Widget Alpha', quantity: 45, category: 'Electronics' },
|
|
308
|
+
{ id: 'B002', name: 'Gadget Beta', quantity: 120, category: 'Tools' },
|
|
309
|
+
{ id: 'C003', name: 'Device Gamma', quantity: 8, category: 'Electronics' },
|
|
310
|
+
{ id: 'D004', name: 'Tool Delta', quantity: 300, category: 'Tools' },
|
|
311
|
+
{ id: 'E005', name: 'Part Epsilon', quantity: 750, category: 'Parts' }
|
|
312
|
+
];
|
|
313
|
+
|
|
314
|
+
let filteredItems = [];
|
|
315
|
+
|
|
316
|
+
function applyQuantityFilter() {
|
|
317
|
+
filteredItems = inventoryItems.filter(item =>
|
|
318
|
+
item.quantity >= (minQuantity || 0) &&
|
|
319
|
+
item.quantity <= (maxQuantity || Infinity)
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Apply filter when range changes
|
|
324
|
+
$: {
|
|
325
|
+
minQuantity, maxQuantity;
|
|
326
|
+
applyQuantityFilter();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function exportResults() {
|
|
330
|
+
const csvContent = [
|
|
331
|
+
'ID,Name,Quantity,Category',
|
|
332
|
+
...filteredItems.map(item =>
|
|
333
|
+
`${item.id},${item.name},${item.quantity},${item.category}`
|
|
334
|
+
)
|
|
335
|
+
].join('\n');
|
|
336
|
+
|
|
337
|
+
console.log('Export data:', csvContent);
|
|
338
|
+
alert('Data exported to console');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Predefined range presets
|
|
342
|
+
const presets = [
|
|
343
|
+
{ label: 'Low Stock (0-50)', min: 0, max: 50 },
|
|
344
|
+
{ label: 'Medium Stock (51-200)', min: 51, max: 200 },
|
|
345
|
+
{ label: 'High Stock (201-500)', min: 201, max: 500 },
|
|
346
|
+
{ label: 'Overstocked (500+)', min: 500, max: 1000 }
|
|
347
|
+
];
|
|
348
|
+
|
|
349
|
+
function applyPreset(preset) {
|
|
350
|
+
minQuantity = preset.min;
|
|
351
|
+
maxQuantity = preset.max;
|
|
352
|
+
}
|
|
353
|
+
</script>
|
|
354
|
+
|
|
355
|
+
<div class="inventory-query">
|
|
356
|
+
<header class="query-header">
|
|
357
|
+
<h2>Inventory Quantity Filter</h2>
|
|
358
|
+
<p>Filter inventory items by quantity range</p>
|
|
359
|
+
</header>
|
|
360
|
+
|
|
361
|
+
<div class="filter-controls">
|
|
362
|
+
<div class="range-input-section">
|
|
363
|
+
<label>Quantity Range:</label>
|
|
364
|
+
<NumberRange
|
|
365
|
+
bind:fromValue={minQuantity}
|
|
366
|
+
bind:toValue={maxQuantity}
|
|
367
|
+
variant="outlined"
|
|
368
|
+
min={0}
|
|
369
|
+
max={1000}
|
|
370
|
+
style="width: 280px;"
|
|
371
|
+
/>
|
|
372
|
+
</div>
|
|
373
|
+
|
|
374
|
+
<div class="presets-section">
|
|
375
|
+
<label>Quick Presets:</label>
|
|
376
|
+
<div class="preset-buttons">
|
|
377
|
+
{#each presets as preset}
|
|
378
|
+
<button
|
|
379
|
+
class="preset-btn"
|
|
380
|
+
on:click={() => applyPreset(preset)}
|
|
381
|
+
>
|
|
382
|
+
{preset.label}
|
|
383
|
+
</button>
|
|
384
|
+
{/each}
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
|
|
389
|
+
<div class="results-section">
|
|
390
|
+
<div class="results-header">
|
|
391
|
+
<h3>Results ({filteredItems.length} items)</h3>
|
|
392
|
+
{#if filteredItems.length > 0}
|
|
393
|
+
<button class="export-btn" on:click={exportResults}>
|
|
394
|
+
Export CSV
|
|
395
|
+
</button>
|
|
396
|
+
{/if}
|
|
397
|
+
</div>
|
|
398
|
+
|
|
399
|
+
<div class="results-table">
|
|
400
|
+
{#if filteredItems.length > 0}
|
|
401
|
+
<table>
|
|
402
|
+
<thead>
|
|
403
|
+
<tr>
|
|
404
|
+
<th>Item ID</th>
|
|
405
|
+
<th>Name</th>
|
|
406
|
+
<th>Quantity</th>
|
|
407
|
+
<th>Category</th>
|
|
408
|
+
<th>Status</th>
|
|
409
|
+
</tr>
|
|
410
|
+
</thead>
|
|
411
|
+
<tbody>
|
|
412
|
+
{#each filteredItems as item}
|
|
413
|
+
<tr>
|
|
414
|
+
<td class="item-id">{item.id}</td>
|
|
415
|
+
<td class="item-name">{item.name}</td>
|
|
416
|
+
<td class="item-quantity">{item.quantity}</td>
|
|
417
|
+
<td class="item-category">{item.category}</td>
|
|
418
|
+
<td class="item-status">
|
|
419
|
+
<span class="status-badge status-{item.quantity < 50 ? 'low' : item.quantity < 200 ? 'medium' : 'high'}">
|
|
420
|
+
{item.quantity < 50 ? 'Low' : item.quantity < 200 ? 'Medium' : 'High'}
|
|
421
|
+
</span>
|
|
422
|
+
</td>
|
|
423
|
+
</tr>
|
|
424
|
+
{/each}
|
|
425
|
+
</tbody>
|
|
426
|
+
</table>
|
|
427
|
+
{:else}
|
|
428
|
+
<div class="no-results">
|
|
429
|
+
<p>No inventory items found in the specified quantity range.</p>
|
|
430
|
+
<p class="suggestion">Try adjusting the range or using a preset filter.</p>
|
|
431
|
+
</div>
|
|
432
|
+
{/if}
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<style>
|
|
438
|
+
.inventory-query {
|
|
439
|
+
max-width: 900px;
|
|
440
|
+
margin: 0 auto;
|
|
441
|
+
padding: 20px;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.query-header {
|
|
445
|
+
text-align: center;
|
|
446
|
+
margin-bottom: 30px;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.query-header h2 {
|
|
450
|
+
color: #333;
|
|
451
|
+
margin: 0 0 8px 0;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.query-header p {
|
|
455
|
+
color: #666;
|
|
456
|
+
margin: 0;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.filter-controls {
|
|
460
|
+
display: flex;
|
|
461
|
+
flex-wrap: wrap;
|
|
462
|
+
gap: 30px;
|
|
463
|
+
align-items: flex-end;
|
|
464
|
+
margin-bottom: 30px;
|
|
465
|
+
padding: 20px;
|
|
466
|
+
background: #f8f9fa;
|
|
467
|
+
border-radius: 8px;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.range-input-section,
|
|
471
|
+
.presets-section {
|
|
472
|
+
flex: 1;
|
|
473
|
+
min-width: 250px;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.range-input-section label,
|
|
477
|
+
.presets-section label {
|
|
478
|
+
display: block;
|
|
479
|
+
font-weight: 500;
|
|
480
|
+
margin-bottom: 8px;
|
|
481
|
+
color: #333;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.preset-buttons {
|
|
485
|
+
display: flex;
|
|
486
|
+
flex-wrap: wrap;
|
|
487
|
+
gap: 8px;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.preset-btn {
|
|
491
|
+
padding: 6px 12px;
|
|
492
|
+
background: #e9ecef;
|
|
493
|
+
border: 1px solid #ced4da;
|
|
494
|
+
border-radius: 4px;
|
|
495
|
+
cursor: pointer;
|
|
496
|
+
font-size: 0.875rem;
|
|
497
|
+
transition: all 0.2s;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.preset-btn:hover {
|
|
501
|
+
background: #dee2e6;
|
|
502
|
+
border-color: #adb5bd;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.results-section {
|
|
506
|
+
background: white;
|
|
507
|
+
border-radius: 8px;
|
|
508
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
509
|
+
overflow: hidden;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.results-header {
|
|
513
|
+
display: flex;
|
|
514
|
+
justify-content: space-between;
|
|
515
|
+
align-items: center;
|
|
516
|
+
padding: 20px;
|
|
517
|
+
background: #f8f9fa;
|
|
518
|
+
border-bottom: 1px solid #dee2e6;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.results-header h3 {
|
|
522
|
+
margin: 0;
|
|
523
|
+
color: #333;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.export-btn {
|
|
527
|
+
padding: 8px 16px;
|
|
528
|
+
background: #007bff;
|
|
529
|
+
color: white;
|
|
530
|
+
border: none;
|
|
531
|
+
border-radius: 4px;
|
|
532
|
+
cursor: pointer;
|
|
533
|
+
font-size: 0.875rem;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.export-btn:hover {
|
|
537
|
+
background: #0056b3;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.results-table {
|
|
541
|
+
padding: 20px;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
table {
|
|
545
|
+
width: 100%;
|
|
546
|
+
border-collapse: collapse;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
th, td {
|
|
550
|
+
text-align: left;
|
|
551
|
+
padding: 12px;
|
|
552
|
+
border-bottom: 1px solid #dee2e6;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
th {
|
|
556
|
+
font-weight: 600;
|
|
557
|
+
color: #333;
|
|
558
|
+
background: #f8f9fa;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.item-id {
|
|
562
|
+
font-family: monospace;
|
|
563
|
+
font-weight: 500;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.item-quantity {
|
|
567
|
+
text-align: right;
|
|
568
|
+
font-weight: 500;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.status-badge {
|
|
572
|
+
padding: 4px 8px;
|
|
573
|
+
border-radius: 12px;
|
|
574
|
+
font-size: 0.75rem;
|
|
575
|
+
font-weight: 500;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.status-low {
|
|
579
|
+
background: #ffebee;
|
|
580
|
+
color: #c62828;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.status-medium {
|
|
584
|
+
background: #fff3e0;
|
|
585
|
+
color: #ef6c00;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.status-high {
|
|
589
|
+
background: #e8f5e8;
|
|
590
|
+
color: #2e7d32;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.no-results {
|
|
594
|
+
text-align: center;
|
|
595
|
+
padding: 60px 20px;
|
|
596
|
+
color: #666;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.suggestion {
|
|
600
|
+
font-size: 0.9rem;
|
|
601
|
+
color: #888;
|
|
602
|
+
margin-top: 8px;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
@media (max-width: 768px) {
|
|
606
|
+
.filter-controls {
|
|
607
|
+
flex-direction: column;
|
|
608
|
+
align-items: stretch;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
.preset-buttons {
|
|
612
|
+
justify-content: center;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.results-header {
|
|
616
|
+
flex-direction: column;
|
|
617
|
+
gap: 12px;
|
|
618
|
+
align-items: stretch;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
table {
|
|
622
|
+
font-size: 0.875rem;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
th, td {
|
|
626
|
+
padding: 8px;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
</style>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## Styling
|
|
633
|
+
|
|
634
|
+
The NumberRange component uses the following CSS classes:
|
|
635
|
+
|
|
636
|
+
```css
|
|
637
|
+
.uniface-range-editor {
|
|
638
|
+
/* Main range container */
|
|
639
|
+
display: flex;
|
|
640
|
+
align-items: center;
|
|
641
|
+
gap: 8px;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
.uniface-range-editor .range-divider {
|
|
645
|
+
/* Divider between from/to inputs */
|
|
646
|
+
color: var(--uniface-editor-border-color, #dee2e6);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.uniface-range-editor .action-icon {
|
|
650
|
+
/* Clear button styling */
|
|
651
|
+
cursor: pointer;
|
|
652
|
+
opacity: 0.6;
|
|
653
|
+
transition: opacity 0.2s;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.uniface-range-editor .action-icon:hover {
|
|
657
|
+
opacity: 1;
|
|
658
|
+
}
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
## API Reference
|
|
662
|
+
|
|
663
|
+
### NumberRange Component Props
|
|
664
|
+
|
|
665
|
+
```typescript
|
|
666
|
+
interface NumberRangeProps {
|
|
667
|
+
variant?: '' | 'plain' | 'outlined' | 'filled'; // Visual styling variant
|
|
668
|
+
compact?: boolean; // Compact layout mode
|
|
669
|
+
class?: string; // CSS class names
|
|
670
|
+
style?: string; // Custom inline styles
|
|
671
|
+
min?: number | null; // Global minimum value
|
|
672
|
+
max?: number | null; // Global maximum value
|
|
673
|
+
fromValue: number; // Range start value
|
|
674
|
+
toValue: number; // Range end value
|
|
675
|
+
allowNegative?: boolean; // Allow negative numbers
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
## Best Practices
|
|
680
|
+
|
|
681
|
+
1. **Validation** - Always bind both `fromValue` and `toValue` for proper range validation
|
|
682
|
+
2. **Limits** - Set appropriate `min` and `max` values to guide user input
|
|
683
|
+
3. **User Feedback** - Provide clear indication of selected range values
|
|
684
|
+
4. **Accessibility** - Ensure sufficient color contrast and keyboard navigation
|
|
685
|
+
5. **Mobile Support** - Test input behavior on touch devices
|
|
686
|
+
6. **Data Types** - Handle undefined/null values gracefully in reactive statements
|
|
687
|
+
7. **Performance** - Debounce filtering operations for large datasets
|
|
688
|
+
8. **Clear Functionality** - Rely on built-in clear button for consistent UX
|