intelliwaketssveltekitv25 1.0.82 → 1.0.83
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 +2 -2
- package/dist/app.css +1 -1
- package/docs/DateRangePicker.md +272 -0
- package/docs/DisplayHTML.md +249 -0
- package/docs/DropDown.md +269 -0
- package/docs/Functions.md +796 -0
- package/docs/Home.md +109 -0
- package/docs/Icon.md +203 -0
- package/docs/Importer.md +328 -0
- package/docs/ImporterAnalysis.md +249 -0
- package/docs/ImporterLoad.md +288 -0
- package/docs/InputNumber.md +159 -0
- package/docs/Integration.md +215 -0
- package/docs/Modal.md +207 -0
- package/docs/MultiSelect.md +304 -0
- package/docs/Paginator.md +332 -0
- package/docs/Search.md +364 -0
- package/docs/SlideDown.md +358 -0
- package/docs/Svelte-5-Patterns.md +364 -0
- package/docs/Switch.md +107 -0
- package/docs/TabHeader.md +333 -0
- package/docs/TabHref.md +370 -0
- package/docs/TextArea.md +118 -0
- package/docs/_Sidebar.md +38 -0
- package/llms.txt +113 -0
- package/package.json +3 -2
- package/llm.txt +0 -1635
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# ImporterAnalysis Component
|
|
2
|
+
|
|
3
|
+
**Purpose:** CSV validation, column mapping, and error reporting phase of import workflow
|
|
4
|
+
|
|
5
|
+
**When to Use:**
|
|
6
|
+
- Rarely used directly (use **Importer** instead)
|
|
7
|
+
- Advanced use cases requiring custom import flow
|
|
8
|
+
- When you need granular control over validation display
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
ImporterAnalysis is the second phase of the **Importer** component. It displays CSV data in a table format with:
|
|
13
|
+
- Column header mapping (manual remapping if alternateNames provided)
|
|
14
|
+
- Row-by-row validation with error/warning highlighting
|
|
15
|
+
- Filter by errors or warnings
|
|
16
|
+
- Import/Clear actions
|
|
17
|
+
|
|
18
|
+
**Note:** Most applications should use the parent **Importer** component instead of ImporterAnalysis directly.
|
|
19
|
+
|
|
20
|
+
## Key Props
|
|
21
|
+
|
|
22
|
+
- `definition: TDataImportProcessorDefinition<T>` (required) - Import column definitions
|
|
23
|
+
- `alternateNames?: Record<string, string[]>` ($bindable) - Column name mappings
|
|
24
|
+
- `csvData?: string | null` ($bindable) - CSV content
|
|
25
|
+
- `arrayData?: string[][] | null` ($bindable) - Array of arrays format
|
|
26
|
+
- `onprocess?: (results: TDataImportProcessorResult<T>[]) => Promise<boolean>` - Process validated rows
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
### Error/Warning Filtering
|
|
31
|
+
- Red "Errors" button - Shows rows with validation errors
|
|
32
|
+
- Yellow "Warnings" button - Shows rows with warnings
|
|
33
|
+
- Click to toggle filter, shows count
|
|
34
|
+
|
|
35
|
+
### Column Remapping
|
|
36
|
+
When `alternateNames` is bound, users can:
|
|
37
|
+
- Click column header dropdown
|
|
38
|
+
- Select target column from definition
|
|
39
|
+
- Reset mapping
|
|
40
|
+
- System remembers alternate names for future imports
|
|
41
|
+
|
|
42
|
+
### Data Preview
|
|
43
|
+
- Table view with all columns
|
|
44
|
+
- Missing required columns highlighted in red
|
|
45
|
+
- Error/warning messages shown in cells
|
|
46
|
+
- Text alignment based on data type
|
|
47
|
+
|
|
48
|
+
## Usage Examples
|
|
49
|
+
|
|
50
|
+
### Direct Usage (Advanced)
|
|
51
|
+
```svelte
|
|
52
|
+
<script>
|
|
53
|
+
import { ImporterAnalysis } from 'intelliwaketssveltekitv25';
|
|
54
|
+
|
|
55
|
+
const definition = {
|
|
56
|
+
columns: {
|
|
57
|
+
'Name': { required: true },
|
|
58
|
+
'Email': { required: true }
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
let csvData = $state('Name,Email\nJohn,john@example.com');
|
|
63
|
+
let alternateNames = $state<Record<string, string[]> | null>({});
|
|
64
|
+
|
|
65
|
+
async function processData(validRows) {
|
|
66
|
+
console.log('Processing', validRows);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<ImporterAnalysis
|
|
72
|
+
{definition}
|
|
73
|
+
bind:alternateNames
|
|
74
|
+
bind:csvData
|
|
75
|
+
onprocess={processData}
|
|
76
|
+
/>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### With Array Data
|
|
80
|
+
```svelte
|
|
81
|
+
<script>
|
|
82
|
+
let arrayData = $state([
|
|
83
|
+
['Name', 'Email'],
|
|
84
|
+
['John', 'john@example.com'],
|
|
85
|
+
['Jane', 'jane@example.com']
|
|
86
|
+
]);
|
|
87
|
+
</script>
|
|
88
|
+
|
|
89
|
+
<ImporterAnalysis
|
|
90
|
+
{definition}
|
|
91
|
+
bind:arrayData
|
|
92
|
+
onprocess={processData}
|
|
93
|
+
/>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Validation Display
|
|
97
|
+
|
|
98
|
+
### Error Cells (Red Background)
|
|
99
|
+
- Invalid data
|
|
100
|
+
- Missing required column
|
|
101
|
+
- Failed custom validation
|
|
102
|
+
|
|
103
|
+
### Warning Cells (Yellow Background)
|
|
104
|
+
- Non-critical issues
|
|
105
|
+
- Data transformations applied
|
|
106
|
+
|
|
107
|
+
### Gray Cells
|
|
108
|
+
- Unmapped columns (not in definition)
|
|
109
|
+
|
|
110
|
+
### Normal Cells
|
|
111
|
+
- Valid data
|
|
112
|
+
|
|
113
|
+
## Column Header Mapping
|
|
114
|
+
|
|
115
|
+
Headers show:
|
|
116
|
+
1. **Mapped column name** (from definition) - Bold
|
|
117
|
+
2. **Original CSV header** (if different) - Normal weight
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
```
|
|
121
|
+
Email Address ← Definition column (bold)
|
|
122
|
+
email_addr ← CSV header (normal)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Manual Remapping
|
|
126
|
+
If alternateNames is bound:
|
|
127
|
+
1. Click column header dropdown
|
|
128
|
+
2. Select correct target column
|
|
129
|
+
3. Mapping is saved in alternateNames
|
|
130
|
+
4. Future imports remember the mapping
|
|
131
|
+
|
|
132
|
+
## Actions
|
|
133
|
+
|
|
134
|
+
### Import Button
|
|
135
|
+
- Disabled if validation errors exist
|
|
136
|
+
- Calls `onprocess` with valid rows only
|
|
137
|
+
- Clears data if `onprocess` returns true
|
|
138
|
+
|
|
139
|
+
### Clear Button
|
|
140
|
+
- Resets csvData/arrayData to null
|
|
141
|
+
- Returns to ImporterLoad phase (if using Importer)
|
|
142
|
+
|
|
143
|
+
## DataImportProcessor
|
|
144
|
+
|
|
145
|
+
The component uses `DataImportProcessor` from `@solidbasisventures/intelliwaketsfoundation`:
|
|
146
|
+
```typescript
|
|
147
|
+
const processor = new DataImportProcessor(definition.columns, {
|
|
148
|
+
alternateNames: alternateNames ?? {}
|
|
149
|
+
});
|
|
150
|
+
processor.populateFromCSV(csvData);
|
|
151
|
+
// or
|
|
152
|
+
processor.populateFromArray(arrayData);
|
|
153
|
+
|
|
154
|
+
// Access results:
|
|
155
|
+
processor.allErrors // All error messages
|
|
156
|
+
processor.allWarnings // All warning messages
|
|
157
|
+
processor.validRows // Rows passing validation
|
|
158
|
+
processor.analysisRows // All rows with metadata
|
|
159
|
+
processor.isValid // True if no errors
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Common Patterns
|
|
163
|
+
|
|
164
|
+
### Custom Import Flow
|
|
165
|
+
```svelte
|
|
166
|
+
<script>
|
|
167
|
+
let step = $state<'upload' | 'analyze' | 'complete'>('upload');
|
|
168
|
+
let csvData = $state(null);
|
|
169
|
+
</script>
|
|
170
|
+
|
|
171
|
+
{#if step === 'upload'}
|
|
172
|
+
<ImporterLoad bind:csvData {definition} />
|
|
173
|
+
<button onclick={() => step = 'analyze'}>
|
|
174
|
+
Analyze
|
|
175
|
+
</button>
|
|
176
|
+
{:else if step === 'analyze'}
|
|
177
|
+
<ImporterAnalysis
|
|
178
|
+
bind:csvData
|
|
179
|
+
{definition}
|
|
180
|
+
onprocess={async (rows) => {
|
|
181
|
+
await import(rows);
|
|
182
|
+
step = 'complete';
|
|
183
|
+
return true;
|
|
184
|
+
}}
|
|
185
|
+
/>
|
|
186
|
+
{:else}
|
|
187
|
+
<div>Import complete!</div>
|
|
188
|
+
{/if}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Programmatic Validation
|
|
192
|
+
```svelte
|
|
193
|
+
<script>
|
|
194
|
+
import { DataImportProcessor } from '@solidbasisventures/intelliwaketsfoundation';
|
|
195
|
+
|
|
196
|
+
function validateCSV(csv: string) {
|
|
197
|
+
const processor = new DataImportProcessor(definition.columns);
|
|
198
|
+
processor.populateFromCSV(csv);
|
|
199
|
+
|
|
200
|
+
if (!processor.isValid) {
|
|
201
|
+
console.error('Validation failed:', processor.allErrors);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return processor.validRows;
|
|
206
|
+
}
|
|
207
|
+
</script>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Common Mistakes
|
|
211
|
+
|
|
212
|
+
- ❌ Using ImporterAnalysis without providing csvData or arrayData
|
|
213
|
+
✅ Correct: Ensure data is bound and populated
|
|
214
|
+
|
|
215
|
+
- ❌ Not providing `onprocess` callback
|
|
216
|
+
✅ Correct: Always provide onprocess to handle validated rows
|
|
217
|
+
|
|
218
|
+
- ❌ Forgetting that `onprocess` should return boolean
|
|
219
|
+
✅ Correct: Return true to clear, false to keep data
|
|
220
|
+
|
|
221
|
+
- ❌ Using this component when Importer would suffice
|
|
222
|
+
✅ Correct: Use Importer for standard workflows
|
|
223
|
+
|
|
224
|
+
## Related Components
|
|
225
|
+
|
|
226
|
+
- **Importer** - Complete import workflow (recommended)
|
|
227
|
+
- **ImporterLoad** - File upload and template download phase
|
|
228
|
+
- **DropDown** - Used for column mapping dropdown
|
|
229
|
+
- **DataImportProcessor** - Core validation logic
|
|
230
|
+
|
|
231
|
+
## Props Reference
|
|
232
|
+
|
|
233
|
+
| Prop | Type | Default | Description |
|
|
234
|
+
|------|------|---------|-------------|
|
|
235
|
+
| `definition` | `TDataImportProcessorDefinition<T>` | (required) | Column definitions |
|
|
236
|
+
| `alternateNames` | `Record<string, string[]>` | `null` | Column mappings ($bindable) |
|
|
237
|
+
| `csvData` | `string \| null` | `null` | CSV content ($bindable) |
|
|
238
|
+
| `arrayData` | `string[][] \| null` | `null` | Array format ($bindable) |
|
|
239
|
+
| `onprocess` | `(rows) => Promise<boolean>` | - | Process valid rows |
|
|
240
|
+
|
|
241
|
+
## Styling
|
|
242
|
+
|
|
243
|
+
Uses standard table classes:
|
|
244
|
+
- `table` - Base table styles
|
|
245
|
+
- `tableBordered` - Cell borders
|
|
246
|
+
- `tableSticky` - Sticky header
|
|
247
|
+
- `data-color-light="danger"` - Error highlighting
|
|
248
|
+
- `data-color-light="warning"` - Warning highlighting
|
|
249
|
+
- `data-color-light="gray"` - Unmapped columns
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# ImporterLoad Component
|
|
2
|
+
|
|
3
|
+
**Purpose:** File upload and CSV template download phase of import workflow
|
|
4
|
+
|
|
5
|
+
**When to Use:**
|
|
6
|
+
- Rarely used directly (use **Importer** instead)
|
|
7
|
+
- Advanced use cases requiring custom import UI
|
|
8
|
+
- When building multi-step import wizards
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
ImporterLoad is the first phase of the **Importer** component. It provides:
|
|
13
|
+
- CSV file upload via button or drag-and-drop
|
|
14
|
+
- Download empty template
|
|
15
|
+
- Download template with sample data
|
|
16
|
+
- Download current data as template
|
|
17
|
+
|
|
18
|
+
**Note:** Most applications should use the parent **Importer** component instead of ImporterLoad directly.
|
|
19
|
+
|
|
20
|
+
## Key Props
|
|
21
|
+
|
|
22
|
+
- `definition: TDataImportProcessorDefinition<T>` (required) - Import column definitions
|
|
23
|
+
- `csvData?: string | null` ($bindable) - CSV content (set when file uploaded)
|
|
24
|
+
- `description?: Snippet` - Custom description/instructions
|
|
25
|
+
- `currentData?: object[]` - Existing data for "Download Current Data" option
|
|
26
|
+
- `templateName?: string` (default: 'Template') - Filename prefix for downloads
|
|
27
|
+
- `fileAccept?: string` (default: '.csv') - Accepted file types
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
### File Upload
|
|
32
|
+
- **Button upload** - Click "Import CSV" button to select file
|
|
33
|
+
- **Drag-and-drop** - Drag CSV file onto component area
|
|
34
|
+
- Visual feedback on drag (blue background)
|
|
35
|
+
- File content stored in `csvData` binding
|
|
36
|
+
|
|
37
|
+
### Template Downloads
|
|
38
|
+
Three template download options:
|
|
39
|
+
|
|
40
|
+
1. **Download Empty Template**
|
|
41
|
+
- CSV with just column headers
|
|
42
|
+
- Filename: `{templateName}_YYYY-MM-DD_HH-mm-ss.csv`
|
|
43
|
+
|
|
44
|
+
2. **Download with Sample Data**
|
|
45
|
+
- Headers + description row + sample data row
|
|
46
|
+
- Only shown if columns have `description` or `sampleData`
|
|
47
|
+
|
|
48
|
+
3. **Download Current Data**
|
|
49
|
+
- Current data exported as CSV template
|
|
50
|
+
- Only shown if `currentData` prop provided
|
|
51
|
+
- Helps users see expected format
|
|
52
|
+
|
|
53
|
+
## Usage Examples
|
|
54
|
+
|
|
55
|
+
### Direct Usage (Advanced)
|
|
56
|
+
```svelte
|
|
57
|
+
<script>
|
|
58
|
+
import { ImporterLoad } from 'intelliwaketssveltekitv25';
|
|
59
|
+
|
|
60
|
+
const definition = {
|
|
61
|
+
descriptionHTML: '<p>Upload CSV with user data</p>',
|
|
62
|
+
columns: {
|
|
63
|
+
'Name': {
|
|
64
|
+
required: true,
|
|
65
|
+
description: 'Full name',
|
|
66
|
+
sampleData: 'John Doe'
|
|
67
|
+
},
|
|
68
|
+
'Email': {
|
|
69
|
+
required: true,
|
|
70
|
+
description: 'Email address',
|
|
71
|
+
sampleData: 'john@example.com'
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
let csvData = $state<string | null>(null);
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<!-- Upload phase -->
|
|
80
|
+
{#if csvData === null}
|
|
81
|
+
<ImporterLoad
|
|
82
|
+
{definition}
|
|
83
|
+
bind:csvData
|
|
84
|
+
/>
|
|
85
|
+
{:else}
|
|
86
|
+
<!-- Process csvData or show ImporterAnalysis -->
|
|
87
|
+
{/if}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With Custom Description
|
|
91
|
+
```svelte
|
|
92
|
+
<ImporterLoad
|
|
93
|
+
{definition}
|
|
94
|
+
bind:csvData
|
|
95
|
+
>
|
|
96
|
+
{#snippet description()}
|
|
97
|
+
<div class="alert alert-info">
|
|
98
|
+
<h4>Before uploading:</h4>
|
|
99
|
+
<ul>
|
|
100
|
+
<li>Ensure email addresses are valid</li>
|
|
101
|
+
<li>Names should be in "First Last" format</li>
|
|
102
|
+
<li>Maximum 500 rows per import</li>
|
|
103
|
+
</ul>
|
|
104
|
+
</div>
|
|
105
|
+
{/snippet}
|
|
106
|
+
</ImporterLoad>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### With Current Data Download
|
|
110
|
+
```svelte
|
|
111
|
+
<script>
|
|
112
|
+
let existingUsers = [
|
|
113
|
+
{ Name: 'John Doe', Email: 'john@example.com', Age: 30 },
|
|
114
|
+
{ Name: 'Jane Smith', Email: 'jane@example.com', Age: 28 }
|
|
115
|
+
];
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<ImporterLoad
|
|
119
|
+
{definition}
|
|
120
|
+
bind:csvData
|
|
121
|
+
currentData={existingUsers}
|
|
122
|
+
templateName="Users"
|
|
123
|
+
/>
|
|
124
|
+
<!-- Users can download existing data as reference -->
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Custom File Types
|
|
128
|
+
```svelte
|
|
129
|
+
<ImporterLoad
|
|
130
|
+
{definition}
|
|
131
|
+
bind:csvData
|
|
132
|
+
fileAccept=".csv,.txt"
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Template Generation
|
|
137
|
+
|
|
138
|
+
### Empty Template
|
|
139
|
+
```csv
|
|
140
|
+
Name,Email,Age
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### With Sample Data
|
|
144
|
+
```csv
|
|
145
|
+
Name,Email,Age
|
|
146
|
+
Full name,Email address,User age
|
|
147
|
+
John Doe,john@example.com,25
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Current Data
|
|
151
|
+
```csv
|
|
152
|
+
Name,Email,Age
|
|
153
|
+
John Doe,john@example.com,30
|
|
154
|
+
Jane Smith,jane@example.com,28
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Drag-and-Drop
|
|
158
|
+
|
|
159
|
+
Visual feedback during drag:
|
|
160
|
+
- Component background turns blue (`bg-blue-50`)
|
|
161
|
+
- Drop zone covers entire component
|
|
162
|
+
- Accepts single file only
|
|
163
|
+
- File content immediately loaded into `csvData`
|
|
164
|
+
|
|
165
|
+
## Column Definition Display
|
|
166
|
+
|
|
167
|
+
The component shows a table with:
|
|
168
|
+
- **Header row:** Column names from definition
|
|
169
|
+
- **Description row:** If any column has `description` (optional)
|
|
170
|
+
- **Sample row:** If any column has `sampleData` (optional)
|
|
171
|
+
|
|
172
|
+
## Common Patterns
|
|
173
|
+
|
|
174
|
+
### Multi-Step Import
|
|
175
|
+
```svelte
|
|
176
|
+
<script>
|
|
177
|
+
let csvData = $state(null);
|
|
178
|
+
let step = $state<'upload' | 'validate'>('upload');
|
|
179
|
+
</script>
|
|
180
|
+
|
|
181
|
+
{#if step === 'upload'}
|
|
182
|
+
<ImporterLoad
|
|
183
|
+
{definition}
|
|
184
|
+
bind:csvData
|
|
185
|
+
/>
|
|
186
|
+
<button
|
|
187
|
+
disabled={!csvData}
|
|
188
|
+
onclick={() => step = 'validate'}
|
|
189
|
+
>
|
|
190
|
+
Next
|
|
191
|
+
</button>
|
|
192
|
+
{:else}
|
|
193
|
+
<ImporterAnalysis
|
|
194
|
+
{definition}
|
|
195
|
+
bind:csvData
|
|
196
|
+
onprocess={handleImport}
|
|
197
|
+
/>
|
|
198
|
+
{/if}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### With Progress Indicator
|
|
202
|
+
```svelte
|
|
203
|
+
<script>
|
|
204
|
+
let uploading = $state(false);
|
|
205
|
+
|
|
206
|
+
$effect(() => {
|
|
207
|
+
if (csvData !== null) {
|
|
208
|
+
uploading = false;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
{#if uploading}
|
|
214
|
+
<div>Processing file...</div>
|
|
215
|
+
{/if}
|
|
216
|
+
|
|
217
|
+
<ImporterLoad
|
|
218
|
+
{definition}
|
|
219
|
+
bind:csvData
|
|
220
|
+
/>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Reset Upload
|
|
224
|
+
```svelte
|
|
225
|
+
<script>
|
|
226
|
+
let csvData = $state(null);
|
|
227
|
+
</script>
|
|
228
|
+
|
|
229
|
+
<ImporterLoad {definition} bind:csvData />
|
|
230
|
+
|
|
231
|
+
{#if csvData}
|
|
232
|
+
<button onclick={() => csvData = null}>
|
|
233
|
+
Reset
|
|
234
|
+
</button>
|
|
235
|
+
{/if}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Common Mistakes
|
|
239
|
+
|
|
240
|
+
- ❌ Not binding `csvData` prop
|
|
241
|
+
✅ Correct: Use `bind:csvData` for two-way binding
|
|
242
|
+
|
|
243
|
+
- ❌ Not checking if csvData exists before processing
|
|
244
|
+
✅ Correct: Check `if (csvData !== null)` before analysis
|
|
245
|
+
|
|
246
|
+
- ❌ Using complex objects in `currentData` that don't match definition
|
|
247
|
+
✅ Correct: Ensure currentData keys match column definitions
|
|
248
|
+
|
|
249
|
+
- ❌ Not providing sample data for complex formats
|
|
250
|
+
✅ Correct: Add `sampleData` to help users understand format
|
|
251
|
+
|
|
252
|
+
## Related Components
|
|
253
|
+
|
|
254
|
+
- **Importer** - Complete import workflow (recommended)
|
|
255
|
+
- **ImporterAnalysis** - Validation and processing phase
|
|
256
|
+
- **DropDown** - Used for template download options
|
|
257
|
+
- **DisplayHTML** - Renders definition.descriptionHTML
|
|
258
|
+
|
|
259
|
+
## Props Reference
|
|
260
|
+
|
|
261
|
+
| Prop | Type | Default | Description |
|
|
262
|
+
|------|------|---------|-------------|
|
|
263
|
+
| `definition` | `TDataImportProcessorDefinition<T>` | (required) | Column definitions |
|
|
264
|
+
| `csvData` | `string \| null` | `null` | CSV content ($bindable) |
|
|
265
|
+
| `description` | `Snippet` | - | Custom instructions |
|
|
266
|
+
| `currentData` | `object[]` | - | Data for template download |
|
|
267
|
+
| `templateName` | `string` | `'Template'` | Download filename prefix |
|
|
268
|
+
| `fileAccept` | `string` | `'.csv'` | Accepted file extensions |
|
|
269
|
+
|
|
270
|
+
## Utility Functions
|
|
271
|
+
|
|
272
|
+
Uses these functions from the library:
|
|
273
|
+
- **DataToCSVExport(filename, data)** - Generate and download CSV
|
|
274
|
+
- **YYYY_MM_DD_HH_mm_ss(date)** - Format timestamp for filename
|
|
275
|
+
|
|
276
|
+
## Styling
|
|
277
|
+
|
|
278
|
+
- Drag-and-drop zone: `bg-blue-50` on dragover
|
|
279
|
+
- Upload button: Standard button styles with upload icon (SVG)
|
|
280
|
+
- Table: Uses `table`, `tableBordered`, `tableSticky` classes
|
|
281
|
+
- Icons: Inline SVG for upload/download icons
|
|
282
|
+
|
|
283
|
+
## Accessibility
|
|
284
|
+
|
|
285
|
+
- File input hidden, triggered by button click
|
|
286
|
+
- Drag-and-drop zone marked with `role="region"` and `aria-label`
|
|
287
|
+
- Upload button has descriptive SVG icon
|
|
288
|
+
- All interactive elements keyboard accessible
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# InputNumber Component
|
|
2
|
+
|
|
3
|
+
**Replaces:** `<input type="number">` for ALL numeric inputs
|
|
4
|
+
|
|
5
|
+
**Purpose:** Formatted numeric input with automatic currency, percentage, and decimal handling
|
|
6
|
+
|
|
7
|
+
**When to Use:**
|
|
8
|
+
- Currency amounts (prices, costs, payments)
|
|
9
|
+
- Percentages (tax rates, discounts, progress)
|
|
10
|
+
- Decimal numbers (measurements, weights, quantities)
|
|
11
|
+
- Integer counts with min/max constraints
|
|
12
|
+
- Any numeric data entry where formatting matters
|
|
13
|
+
|
|
14
|
+
## Key Props
|
|
15
|
+
|
|
16
|
+
- `value?: number | null` ($bindable) - Current numeric value, use `bind:value`
|
|
17
|
+
- `currency?: boolean` - Format as currency (adds $ prefix, 2 decimal places)
|
|
18
|
+
- `percent?: boolean` - Format as percentage (adds % suffix, stores as decimal 0-1, displays as 0-100)
|
|
19
|
+
- `fixedDecimals?: number` - Force exact number of decimal places
|
|
20
|
+
- `minDecimals?: number` - Minimum decimal places to show
|
|
21
|
+
- `maxDecimals?: number` - Maximum decimal places allowed
|
|
22
|
+
- `min?: number` - Minimum allowed value (enforced on input)
|
|
23
|
+
- `max?: number` - Maximum allowed value (enforced on input)
|
|
24
|
+
- `allowNegative?: boolean` - Allow negative numbers (default: false)
|
|
25
|
+
- `zeroBlank?: boolean` - Display empty string instead of 0
|
|
26
|
+
- `zeroDash?: boolean` - Display "-" instead of 0
|
|
27
|
+
- `nullBlank?: boolean` - Display empty string for null values
|
|
28
|
+
- `nullDash?: boolean` - Display "-" for null values
|
|
29
|
+
- `prefix?: string` - Custom prefix (overrides currency $)
|
|
30
|
+
- `suffix?: string` - Custom suffix (overrides percent %)
|
|
31
|
+
- `delayChange?: boolean | number | 'blur'` - Delay before updating bound value
|
|
32
|
+
- `true`: 1500ms delay
|
|
33
|
+
- `number`: Custom milliseconds delay
|
|
34
|
+
- `'blur'`: Update only on blur event
|
|
35
|
+
- `widthNumbers?: number` - Set input width based on number of digits
|
|
36
|
+
- `class?: string` - Additional CSS classes for wrapper div
|
|
37
|
+
- `inputClass?: string` - CSS classes for the input element itself
|
|
38
|
+
- `onchange?: (value: number | null) => void` - Callback when value changes
|
|
39
|
+
- Standard HTML input props: `disabled`, `readonly`, `required`, `name`, `placeholder`, `id`, etc.
|
|
40
|
+
|
|
41
|
+
**TypeScript Type:** `TInputNumberAttributes` (extends standard input attributes)
|
|
42
|
+
|
|
43
|
+
## Usage Examples
|
|
44
|
+
|
|
45
|
+
```svelte
|
|
46
|
+
<script>
|
|
47
|
+
import { InputNumber } from 'intelliwaketssveltekitv25';
|
|
48
|
+
let price = $state(29.99);
|
|
49
|
+
let taxRate = $state(0.08); // 8% stored as 0.08, displays as 8
|
|
50
|
+
let quantity = $state(1);
|
|
51
|
+
let weight = $state(null);
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<!-- Currency input -->
|
|
55
|
+
<label>
|
|
56
|
+
Price:
|
|
57
|
+
<InputNumber bind:value={price} currency required />
|
|
58
|
+
</label>
|
|
59
|
+
<!-- Displays: $29.99 -->
|
|
60
|
+
|
|
61
|
+
<!-- Percentage input -->
|
|
62
|
+
<label>
|
|
63
|
+
Tax Rate:
|
|
64
|
+
<InputNumber bind:value={taxRate} percent />
|
|
65
|
+
</label>
|
|
66
|
+
<!-- Displays: 8% (user enters 8, stored as 0.08) -->
|
|
67
|
+
|
|
68
|
+
<!-- Integer quantity with constraints -->
|
|
69
|
+
<label>
|
|
70
|
+
Quantity:
|
|
71
|
+
<InputNumber bind:value={quantity} fixedDecimals={0} min={1} max={999} />
|
|
72
|
+
</label>
|
|
73
|
+
|
|
74
|
+
<!-- Decimal with custom suffix -->
|
|
75
|
+
<label>
|
|
76
|
+
Weight:
|
|
77
|
+
<InputNumber bind:value={weight} suffix="kg" maxDecimals={2} zeroBlank />
|
|
78
|
+
</label>
|
|
79
|
+
|
|
80
|
+
<!-- With delayed change (for expensive calculations) -->
|
|
81
|
+
<InputNumber
|
|
82
|
+
bind:value={searchAmount}
|
|
83
|
+
currency
|
|
84
|
+
delayChange={true}
|
|
85
|
+
placeholder="Filter by amount..."
|
|
86
|
+
/>
|
|
87
|
+
<!-- Value updates 1.5 seconds after user stops typing -->
|
|
88
|
+
|
|
89
|
+
<!-- Update only on blur -->
|
|
90
|
+
<InputNumber
|
|
91
|
+
bind:value={finalTotal}
|
|
92
|
+
currency
|
|
93
|
+
delayChange="blur"
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
<!-- Readonly display -->
|
|
97
|
+
<InputNumber value={calculatedTotal} currency readonly />
|
|
98
|
+
|
|
99
|
+
<!-- Allow negative numbers -->
|
|
100
|
+
<InputNumber
|
|
101
|
+
bind:value={profitLoss}
|
|
102
|
+
currency
|
|
103
|
+
allowNegative
|
|
104
|
+
zeroDash
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
<!-- Width based on digit count -->
|
|
108
|
+
<InputNumber
|
|
109
|
+
bind:value={zipCode}
|
|
110
|
+
fixedDecimals={0}
|
|
111
|
+
widthNumbers={5}
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
<!-- With change handler -->
|
|
115
|
+
<InputNumber
|
|
116
|
+
bind:value={discount}
|
|
117
|
+
percent
|
|
118
|
+
onchange={(val) => {
|
|
119
|
+
console.log('Discount changed to:', val);
|
|
120
|
+
recalculateTotal();
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Common Mistakes
|
|
126
|
+
|
|
127
|
+
- ❌ Using `<input type="number">` for currency: `<input type="number" step="0.01">`
|
|
128
|
+
✅ Correct: `<InputNumber currency bind:value={amount} />`
|
|
129
|
+
|
|
130
|
+
- ❌ Storing percentages as whole numbers (8) instead of decimals (0.08)
|
|
131
|
+
✅ Correct: Store as decimal (0.08), use `percent` prop to display as 8%
|
|
132
|
+
|
|
133
|
+
- ❌ Not using `bind:value`: `<InputNumber value={x} />`
|
|
134
|
+
✅ Correct: `<InputNumber bind:value={x} />` (for two-way binding)
|
|
135
|
+
|
|
136
|
+
- ❌ Expecting immediate updates without considering `delayChange`
|
|
137
|
+
✅ Correct: Use `delayChange="blur"` or `delayChange={false}` for immediate updates
|
|
138
|
+
|
|
139
|
+
- ❌ Using both `currency` and `percent` props together
|
|
140
|
+
✅ Correct: Use only one formatting option at a time
|
|
141
|
+
|
|
142
|
+
## Props Combinations
|
|
143
|
+
|
|
144
|
+
- **Currency:** `currency` (auto-adds $ prefix, 2 decimals)
|
|
145
|
+
- **Percentage:** `percent` (auto-adds % suffix, multiplies display by 100)
|
|
146
|
+
- **Integer:** `fixedDecimals={0}`
|
|
147
|
+
- **Range validation:** `min={x} max={y}`
|
|
148
|
+
- **Performance optimization:** `delayChange={true}` or `delayChange={500}` (ms) or `delayChange="blur"`
|
|
149
|
+
- **Zero handling:** `zeroBlank` or `zeroDash`
|
|
150
|
+
- **Null handling:** `nullBlank` or `nullDash`
|
|
151
|
+
|
|
152
|
+
## Related Components
|
|
153
|
+
|
|
154
|
+
- `InputNumberScroll` - Numeric input with scroll wheel adjustment support
|
|
155
|
+
- `NumberFormat` - Display-only formatted number component
|
|
156
|
+
|
|
157
|
+
## Storybook
|
|
158
|
+
|
|
159
|
+
See `Components/InputNumber` stories
|