intelliwaketssveltekitv25 1.0.81 → 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/INTEGRATION.md +574 -0
- package/README.md +199 -45
- package/dist/ArrayTable.stories.js +215 -0
- package/dist/ArrayTable.svelte +46 -0
- package/dist/ArrayTable.svelte.d.ts +44 -0
- package/dist/DropDown.stories.d.ts +96 -0
- package/dist/DropDown.stories.js +192 -0
- package/dist/DropDown.svelte +32 -0
- package/dist/DropDown.svelte.d.ts +30 -0
- package/dist/InputNumber.stories.d.ts +122 -0
- package/dist/InputNumber.stories.js +186 -0
- package/dist/InputNumber.svelte +52 -0
- package/dist/InputNumber.svelte.d.ts +27 -0
- package/dist/Modal.stories.d.ts +114 -0
- package/dist/Modal.stories.js +139 -0
- package/dist/Modal.svelte +34 -3
- package/dist/Modal.svelte.d.ts +35 -3
- package/dist/MultiSelect.stories.js +338 -0
- package/dist/MultiSelect.svelte +81 -0
- package/dist/MultiSelect.svelte.d.ts +38 -0
- package/dist/Switch.stories.d.ts +81 -0
- package/dist/Switch.stories.js +99 -0
- package/dist/Switch.svelte +40 -0
- package/dist/Switch.svelte.d.ts +26 -0
- package/dist/TextArea.stories.d.ts +180 -0
- package/dist/TextArea.stories.js +216 -0
- package/dist/TextArea.svelte +32 -0
- package/dist/TextArea.svelte.d.ts +24 -0
- 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 +7 -2
package/docs/Home.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# IntelliWakeTSSvelteKitV2.5 Component Library
|
|
2
|
+
|
|
3
|
+
**Package:** `intelliwaketssveltekitv25`
|
|
4
|
+
**Technologies:** Svelte 5 | TypeScript | Tailwind CSS v4
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Professional SvelteKit component library providing 41 reusable UI components and 17 utility modules. Built with modern Svelte 5 features (runes, snippets, generics) and optimized for TypeScript developers building data-driven applications.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
### Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install intelliwaketssveltekitv25
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Required Setup
|
|
19
|
+
|
|
20
|
+
1. **Import CSS** (in your root `+layout.svelte` or `app.css`):
|
|
21
|
+
```typescript
|
|
22
|
+
import 'intelliwaketssveltekitv25/dist/app.css';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. **Configure Tailwind** - See [Integration Guide](Integration) for required color configuration
|
|
26
|
+
|
|
27
|
+
3. **Install Peer Dependencies**:
|
|
28
|
+
```bash
|
|
29
|
+
npm install @solidbasisventures/intelliwaketsfoundation @sveltejs/kit svelte
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Component Categories
|
|
33
|
+
|
|
34
|
+
### 🎛️ Form Controls
|
|
35
|
+
Replace native HTML form elements with enhanced features:
|
|
36
|
+
- **[Switch](Switch)** - Toggle switches for boolean values
|
|
37
|
+
- **[InputNumber](InputNumber)** - Numeric inputs with formatting (currency, percent, decimals)
|
|
38
|
+
- **[TextArea](TextArea)** - Auto-resizing text areas
|
|
39
|
+
- **[DropDown](DropDown)** - Rich dropdown menus (replaces `<select>`)
|
|
40
|
+
- **[MultiSelect](MultiSelect)** - Multi-select with search and creation
|
|
41
|
+
|
|
42
|
+
### 📊 Data Display
|
|
43
|
+
Present data with performance and style:
|
|
44
|
+
- **VirtualList** - High-performance lists for large datasets
|
|
45
|
+
- **VirtualTable** - Virtual scrolling tables
|
|
46
|
+
- **Calendar** - Date selection
|
|
47
|
+
- **[DateRangePicker](DateRangePicker)** - Date range selection with presets
|
|
48
|
+
|
|
49
|
+
### 🪟 Layout & Overlays
|
|
50
|
+
Structure your application:
|
|
51
|
+
- **[Modal](Modal)** - Feature-rich dialog overlays
|
|
52
|
+
- **MasterDetailLayout** - Responsive master-detail pattern
|
|
53
|
+
- **[TabHeader](TabHeader)** - Client-side tab navigation
|
|
54
|
+
- **[TabHref](TabHref)** - URL-based tab navigation
|
|
55
|
+
- **[SlideDown](SlideDown)** - Animated dropdown menus
|
|
56
|
+
|
|
57
|
+
### 🎨 Visual & Utilities
|
|
58
|
+
Icons, notifications, and helpers:
|
|
59
|
+
- **[Icon](Icon)** - FontAwesome icon integration
|
|
60
|
+
- **[DisplayHTML](DisplayHTML)** - Safe HTML rendering with link conversion
|
|
61
|
+
- **MessageBoxes** - Toast notifications
|
|
62
|
+
- **[Functions](Functions)** - 20+ utility functions and Svelte use: actions
|
|
63
|
+
|
|
64
|
+
### 🔍 Navigation & Search
|
|
65
|
+
Navigation and filtering tools:
|
|
66
|
+
- **[Search](Search)** - Debounced search input
|
|
67
|
+
- **[Paginator](Paginator)** - Responsive pagination controls
|
|
68
|
+
|
|
69
|
+
### 📥 Data Import
|
|
70
|
+
CSV import workflow components:
|
|
71
|
+
- **[Importer](Importer)** - Complete CSV import with validation
|
|
72
|
+
- **[ImporterLoad](ImporterLoad)** - File upload and template download
|
|
73
|
+
- **[ImporterAnalysis](ImporterAnalysis)** - Column mapping and validation
|
|
74
|
+
|
|
75
|
+
## Native HTML Replacement Guide
|
|
76
|
+
|
|
77
|
+
| Instead of... | Use... |
|
|
78
|
+
|--------------|--------|
|
|
79
|
+
| `<input type="checkbox">` | **[Switch](Switch)** |
|
|
80
|
+
| `<input type="number">` | **[InputNumber](InputNumber)** |
|
|
81
|
+
| `<textarea>` | **[TextArea](TextArea)** |
|
|
82
|
+
| `<select>` | **[DropDown](DropDown)** |
|
|
83
|
+
| `<select multiple>` | **[MultiSelect](MultiSelect)** |
|
|
84
|
+
| `<dialog>` | **[Modal](Modal)** |
|
|
85
|
+
|
|
86
|
+
## Key Features
|
|
87
|
+
|
|
88
|
+
- ✅ **Svelte 5 Runes** - Modern reactive syntax with `$state`, `$derived`, `$effect`, `$bindable`
|
|
89
|
+
- ✅ **TypeScript Generics** - Type-safe data handling
|
|
90
|
+
- ✅ **Tailwind CSS v4** - Custom theme integration
|
|
91
|
+
- ✅ **Two-way Binding** - Comprehensive form controls with `bind:` support
|
|
92
|
+
- ✅ **Performance Optimized** - Virtual scrolling for large datasets
|
|
93
|
+
- ✅ **Responsive Design** - Mobile-first layout patterns
|
|
94
|
+
|
|
95
|
+
## Documentation Structure
|
|
96
|
+
|
|
97
|
+
- **[Component Docs](Home#component-categories)** - Detailed documentation for each component
|
|
98
|
+
- **[Integration Guide](Integration)** - Setup requirements and Tailwind configuration
|
|
99
|
+
- **[Svelte 5 Patterns](Svelte-5-Patterns)** - Runes, snippets, and TypeScript generics usage
|
|
100
|
+
|
|
101
|
+
## Support
|
|
102
|
+
|
|
103
|
+
- **Storybook:** Run `pnpm storybook` for interactive component demos
|
|
104
|
+
- **Project Docs:** See `CLAUDE.md` in package root for development guide
|
|
105
|
+
- **Issues:** Report bugs or request features on GitHub
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
*For AI/LLM usage: See the main `llms.txt` file for progressive disclosure guidance.*
|
package/docs/Icon.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# Icon Component
|
|
2
|
+
|
|
3
|
+
**Purpose:** Render FontAwesome icons with extensive customization options
|
|
4
|
+
|
|
5
|
+
**When to Use:**
|
|
6
|
+
- Display icons throughout your application
|
|
7
|
+
- Add visual indicators to buttons, menus, or text
|
|
8
|
+
- Use duotone icons with custom colors
|
|
9
|
+
- Animate icons with spin or pulse effects
|
|
10
|
+
|
|
11
|
+
## Key Props
|
|
12
|
+
|
|
13
|
+
- `icon: IconDefinition` (required) - FontAwesome icon from `@fortawesome/free-solid-svg-icons`
|
|
14
|
+
- `size?: string` - Icon size: 'xs', 'sm', 'lg', '1x' through '10x' (default: inherits font size)
|
|
15
|
+
- `color?: string` - Icon color (default: 'currentColor')
|
|
16
|
+
- `dataColor?: TDefaultColorPalate` - Theme color palette
|
|
17
|
+
- `fw?: boolean` (default: true) - Fixed width for consistent alignment
|
|
18
|
+
- `pull?: 'left' | 'right'` - Float icon left or right
|
|
19
|
+
|
|
20
|
+
### Transform Props
|
|
21
|
+
- `scale?: number` (default: 1) - Scale the icon
|
|
22
|
+
- `translateX?: number` (default: 0) - Horizontal offset
|
|
23
|
+
- `translateY?: number` (default: 0) - Vertical offset
|
|
24
|
+
- `rotate?: number | string` - Rotation angle in degrees
|
|
25
|
+
- `flip?: 'horizontal' | 'vertical' | 'both' | boolean` - Flip the icon
|
|
26
|
+
|
|
27
|
+
### Animation Props
|
|
28
|
+
- `spin?: boolean` - Continuous rotation animation
|
|
29
|
+
- `pulse?: boolean` - Pulsing animation
|
|
30
|
+
|
|
31
|
+
### Duotone Icon Props
|
|
32
|
+
- `primaryColor?: string` - Color for primary layer
|
|
33
|
+
- `secondaryColor?: string` - Color for secondary layer
|
|
34
|
+
- `primaryOpacity?: number` (default: 1) - Opacity of primary layer
|
|
35
|
+
- `secondaryOpacity?: number` (default: 0.4) - Opacity of secondary layer
|
|
36
|
+
- `swapOpacity?: boolean` - Swap opacity values between layers
|
|
37
|
+
|
|
38
|
+
### Other Props
|
|
39
|
+
- `title?: string` - Accessible title for screen readers
|
|
40
|
+
- `invisible?: boolean` - Hide icon (keeps space)
|
|
41
|
+
- `hidden?: boolean` - Completely remove icon
|
|
42
|
+
- `class?: string` - Additional CSS classes
|
|
43
|
+
- `id?: string` - HTML id attribute
|
|
44
|
+
- `style?: string` - Inline styles
|
|
45
|
+
|
|
46
|
+
## Usage Examples
|
|
47
|
+
|
|
48
|
+
```svelte
|
|
49
|
+
<script>
|
|
50
|
+
import { Icon } from 'intelliwaketssveltekitv25';
|
|
51
|
+
import {
|
|
52
|
+
faUser,
|
|
53
|
+
faSpinner,
|
|
54
|
+
faCheck,
|
|
55
|
+
faExclamation,
|
|
56
|
+
faHeart
|
|
57
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<!-- Basic icon -->
|
|
61
|
+
<Icon icon={faUser} />
|
|
62
|
+
|
|
63
|
+
<!-- Sized icons -->
|
|
64
|
+
<Icon icon={faUser} size="xs" />
|
|
65
|
+
<Icon icon={faUser} size="sm" />
|
|
66
|
+
<Icon icon={faUser} size="lg" />
|
|
67
|
+
<Icon icon={faUser} size="2x" />
|
|
68
|
+
<Icon icon={faUser} size="5x" />
|
|
69
|
+
|
|
70
|
+
<!-- Colored icon -->
|
|
71
|
+
<Icon icon={faHeart} color="red" />
|
|
72
|
+
<Icon icon={faCheck} color="green" />
|
|
73
|
+
|
|
74
|
+
<!-- Spinning icons (loading indicators) -->
|
|
75
|
+
<Icon icon={faSpinner} spin />
|
|
76
|
+
<Icon icon={faSpinner} pulse />
|
|
77
|
+
|
|
78
|
+
<!-- With title for accessibility -->
|
|
79
|
+
<Icon icon={faUser} title="User profile" />
|
|
80
|
+
|
|
81
|
+
<!-- Rotated and scaled -->
|
|
82
|
+
<Icon icon={faExclamation} rotate={45} scale={1.5} />
|
|
83
|
+
|
|
84
|
+
<!-- Flipped icons -->
|
|
85
|
+
<Icon icon={faUser} flip="horizontal" />
|
|
86
|
+
<Icon icon={faUser} flip="vertical" />
|
|
87
|
+
<Icon icon={faUser} flip="both" />
|
|
88
|
+
|
|
89
|
+
<!-- Fixed width for alignment -->
|
|
90
|
+
<div>
|
|
91
|
+
<Icon icon={faUser} fw /> User
|
|
92
|
+
<Icon icon={faCheck} fw /> Verified
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<!-- Pulled left/right -->
|
|
96
|
+
<p>
|
|
97
|
+
<Icon icon={faUser} pull="left" />
|
|
98
|
+
This text wraps around the icon
|
|
99
|
+
</p>
|
|
100
|
+
|
|
101
|
+
<!-- In buttons -->
|
|
102
|
+
<button>
|
|
103
|
+
<Icon icon={faUser} class="mr-1" />
|
|
104
|
+
Profile
|
|
105
|
+
</button>
|
|
106
|
+
|
|
107
|
+
<!-- Duotone icons (if using duotone FontAwesome icons) -->
|
|
108
|
+
<Icon
|
|
109
|
+
icon={myDuotoneIcon}
|
|
110
|
+
primaryColor="#3b82f6"
|
|
111
|
+
secondaryColor="#93c5fd"
|
|
112
|
+
primaryOpacity={1}
|
|
113
|
+
secondaryOpacity={0.4}
|
|
114
|
+
/>
|
|
115
|
+
|
|
116
|
+
<!-- Conditional visibility -->
|
|
117
|
+
<Icon icon={faCheck} hidden={!isComplete} />
|
|
118
|
+
<Icon icon={faSpinner} invisible={!isLoading} />
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Common Patterns
|
|
122
|
+
|
|
123
|
+
### Loading Indicator
|
|
124
|
+
```svelte
|
|
125
|
+
<Icon icon={faSpinner} spin size="2x" />
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Status Icons with Colors
|
|
129
|
+
```svelte
|
|
130
|
+
{#if status === 'success'}
|
|
131
|
+
<Icon icon={faCheck} color="green" />
|
|
132
|
+
{:else if status === 'error'}
|
|
133
|
+
<Icon icon={faExclamation} color="red" />
|
|
134
|
+
{:else if status === 'warning'}
|
|
135
|
+
<Icon icon={faExclamation} color="orange" />
|
|
136
|
+
{/if}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Icon List (Aligned)
|
|
140
|
+
```svelte
|
|
141
|
+
<ul class="list-none">
|
|
142
|
+
<li><Icon icon={faUser} fw /> User Management</li>
|
|
143
|
+
<li><Icon icon={faCog} fw /> Settings</li>
|
|
144
|
+
<li><Icon icon={faChartBar} fw /> Analytics</li>
|
|
145
|
+
</ul>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Button with Icon
|
|
149
|
+
```svelte
|
|
150
|
+
<button>
|
|
151
|
+
<Icon icon={faSave} class="inline-block mr-1" />
|
|
152
|
+
Save Changes
|
|
153
|
+
</button>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Common Mistakes
|
|
157
|
+
|
|
158
|
+
- ❌ Not importing the icon definition from FontAwesome
|
|
159
|
+
✅ Correct: `import { faUser } from '@fortawesome/free-solid-svg-icons'`
|
|
160
|
+
|
|
161
|
+
- ❌ Using string icon names instead of icon objects
|
|
162
|
+
✅ Correct: `<Icon icon={faUser} />` not `<Icon icon="user" />`
|
|
163
|
+
|
|
164
|
+
- ❌ Forgetting `fw` prop when aligning multiple icons
|
|
165
|
+
✅ Correct: Use `fw` for consistent width in lists or navigation
|
|
166
|
+
|
|
167
|
+
- ❌ Not providing `title` for accessibility
|
|
168
|
+
✅ Correct: Add `title` prop for screen reader users when icon conveys meaning
|
|
169
|
+
|
|
170
|
+
## Integration with Other Components
|
|
171
|
+
|
|
172
|
+
Many library components accept `IFAProps` or `faProps` to include icons:
|
|
173
|
+
- **DropDown** - `ddActions[].faProps`
|
|
174
|
+
- **TabHeader** - `tabItems[].faProps`
|
|
175
|
+
- **TabHref** - `tabHrefs[].faProps`
|
|
176
|
+
- **MultiSelect** - `faProps` for selected items
|
|
177
|
+
- **ButtonGroup** - `buttons[].faProps`
|
|
178
|
+
|
|
179
|
+
Example with DropDown:
|
|
180
|
+
```svelte
|
|
181
|
+
<DropDown ddActions={[
|
|
182
|
+
{ title: 'Edit', faProps: { icon: faEdit }, action: () => {} },
|
|
183
|
+
{ title: 'Delete', faProps: { icon: faTrash }, action: () => {} }
|
|
184
|
+
]} />
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Related Components
|
|
188
|
+
|
|
189
|
+
- `IFAProps` interface in `Definitions.ts` defines all icon props
|
|
190
|
+
- Used throughout the library for consistent icon support
|
|
191
|
+
|
|
192
|
+
## FontAwesome Icons
|
|
193
|
+
|
|
194
|
+
This component works with FontAwesome 6 icons:
|
|
195
|
+
- `@fortawesome/free-solid-svg-icons` - Solid style icons
|
|
196
|
+
- `@fortawesome/free-regular-svg-icons` - Regular style icons
|
|
197
|
+
- `@fortawesome/free-brands-svg-icons` - Brand icons
|
|
198
|
+
- Duotone icons (Pro license required)
|
|
199
|
+
|
|
200
|
+
Install FontAwesome:
|
|
201
|
+
```bash
|
|
202
|
+
npm install @fortawesome/free-solid-svg-icons
|
|
203
|
+
```
|
package/docs/Importer.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Importer Component
|
|
2
|
+
|
|
3
|
+
**Purpose:** Complete CSV import workflow with file upload, column mapping, validation, and data processing
|
|
4
|
+
|
|
5
|
+
**When to Use:**
|
|
6
|
+
- Import CSV data with predefined column definitions
|
|
7
|
+
- Validate imported data with custom rules
|
|
8
|
+
- Map CSV columns to database fields
|
|
9
|
+
- Provide user-friendly import interface with error reporting
|
|
10
|
+
|
|
11
|
+
## Key Props
|
|
12
|
+
|
|
13
|
+
- `definition: TDataImportProcessorDefinition<T>` (required) - Import configuration with column definitions
|
|
14
|
+
- `alternateNames?: Record<string, string[]>` ($bindable) - Column name mappings
|
|
15
|
+
- `csvData?: string | null` ($bindable) - CSV file content
|
|
16
|
+
- `arrayData?: string[][] | null` ($bindable) - Alternative: Array of arrays instead of CSV
|
|
17
|
+
- `onprocess?: (results: TDataImportProcessorResult<T>[]) => Promise<boolean>` - Process validated rows
|
|
18
|
+
- `description?: Snippet` - Custom description/instructions
|
|
19
|
+
- `currentData?: object[]` - Existing data for download template
|
|
20
|
+
|
|
21
|
+
## Component Flow
|
|
22
|
+
|
|
23
|
+
The Importer component is a state machine with two phases:
|
|
24
|
+
|
|
25
|
+
1. **ImporterLoad** (csvData/arrayData is null) - File selection and template download
|
|
26
|
+
2. **ImporterAnalysis** (csvData/arrayData exists) - Column mapping, validation, and import
|
|
27
|
+
|
|
28
|
+
## TDataImportProcessorDefinition Structure
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
interface TDataImportProcessorDefinition<T> {
|
|
32
|
+
descriptionHTML?: string // HTML description shown in upload phase
|
|
33
|
+
columns: Record<string, {
|
|
34
|
+
required?: boolean // Column must be present
|
|
35
|
+
description?: string // Column description
|
|
36
|
+
sampleData?: string | string[] // Example data for template
|
|
37
|
+
validate?: (value: any) => string | null // Custom validation function
|
|
38
|
+
transform?: (value: any) => any // Transform imported value
|
|
39
|
+
}>
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage Examples
|
|
44
|
+
|
|
45
|
+
```svelte
|
|
46
|
+
<script>
|
|
47
|
+
import { Importer } from 'intelliwaketssveltekitv25';
|
|
48
|
+
import type { TDataImportProcessorDefinition } from '@solidbasisventures/intelliwaketsfoundation';
|
|
49
|
+
|
|
50
|
+
// Define import structure
|
|
51
|
+
const userImportDefinition: TDataImportProcessorDefinition<any> = {
|
|
52
|
+
descriptionHTML: '<p>Import users from CSV file</p>',
|
|
53
|
+
columns: {
|
|
54
|
+
'Email': {
|
|
55
|
+
required: true,
|
|
56
|
+
description: 'User email address',
|
|
57
|
+
sampleData: 'user@example.com',
|
|
58
|
+
validate: (val) => val?.includes('@') ? null : 'Invalid email'
|
|
59
|
+
},
|
|
60
|
+
'Name': {
|
|
61
|
+
required: true,
|
|
62
|
+
description: 'Full name',
|
|
63
|
+
sampleData: 'John Doe'
|
|
64
|
+
},
|
|
65
|
+
'Age': {
|
|
66
|
+
required: false,
|
|
67
|
+
description: 'User age',
|
|
68
|
+
sampleData: '25',
|
|
69
|
+
validate: (val) => {
|
|
70
|
+
const age = parseInt(val);
|
|
71
|
+
return age > 0 && age < 150 ? null : 'Invalid age';
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
'Role': {
|
|
75
|
+
required: false,
|
|
76
|
+
description: 'User role',
|
|
77
|
+
sampleData: ['Admin', 'User', 'Guest']
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
let alternateNames = $state<Record<string, string[]> | null>(null);
|
|
83
|
+
let csvData = $state<string | null>(null);
|
|
84
|
+
|
|
85
|
+
async function handleImport(validRows) {
|
|
86
|
+
console.log('Importing', validRows.length, 'users');
|
|
87
|
+
|
|
88
|
+
// Process each validated row
|
|
89
|
+
for (const row of validRows) {
|
|
90
|
+
await createUser({
|
|
91
|
+
email: row.Email,
|
|
92
|
+
name: row.Name,
|
|
93
|
+
age: row.Age ? parseInt(row.Age) : null,
|
|
94
|
+
role: row.Role || 'User'
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Return true to clear the importer
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<Importer
|
|
104
|
+
definition={userImportDefinition}
|
|
105
|
+
bind:alternateNames
|
|
106
|
+
bind:csvData
|
|
107
|
+
onprocess={handleImport}
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### With Custom Description
|
|
112
|
+
```svelte
|
|
113
|
+
<Importer
|
|
114
|
+
definition={importDef}
|
|
115
|
+
bind:csvData
|
|
116
|
+
onprocess={handleImport}
|
|
117
|
+
>
|
|
118
|
+
{#snippet description()}
|
|
119
|
+
<div class="bg-blue-50 p-4 mb-4 rounded">
|
|
120
|
+
<h3>Import Instructions</h3>
|
|
121
|
+
<ul>
|
|
122
|
+
<li>Use the template to ensure correct format</li>
|
|
123
|
+
<li>Email column is required</li>
|
|
124
|
+
<li>Maximum 1000 rows per import</li>
|
|
125
|
+
</ul>
|
|
126
|
+
</div>
|
|
127
|
+
{/snippet}
|
|
128
|
+
</Importer>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### With Existing Data Download
|
|
132
|
+
```svelte
|
|
133
|
+
<script>
|
|
134
|
+
// Allows users to download current data as template
|
|
135
|
+
let existingUsers = [
|
|
136
|
+
{ email: 'john@example.com', name: 'John', age: 30 },
|
|
137
|
+
{ email: 'jane@example.com', name: 'Jane', age: 28 }
|
|
138
|
+
];
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<Importer
|
|
142
|
+
definition={userImportDefinition}
|
|
143
|
+
bind:csvData
|
|
144
|
+
currentData={existingUsers}
|
|
145
|
+
onprocess={handleImport}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Product Import Example
|
|
150
|
+
```svelte
|
|
151
|
+
<script>
|
|
152
|
+
const productImportDef = {
|
|
153
|
+
columns: {
|
|
154
|
+
'SKU': {
|
|
155
|
+
required: true,
|
|
156
|
+
description: 'Product SKU',
|
|
157
|
+
sampleData: 'PROD-001'
|
|
158
|
+
},
|
|
159
|
+
'Name': {
|
|
160
|
+
required: true,
|
|
161
|
+
description: 'Product name',
|
|
162
|
+
sampleData: 'Widget Pro'
|
|
163
|
+
},
|
|
164
|
+
'Price': {
|
|
165
|
+
required: true,
|
|
166
|
+
description: 'Price in USD',
|
|
167
|
+
sampleData: '29.99',
|
|
168
|
+
validate: (val) => !isNaN(parseFloat(val)) ? null : 'Must be a number',
|
|
169
|
+
transform: (val) => parseFloat(val)
|
|
170
|
+
},
|
|
171
|
+
'Stock': {
|
|
172
|
+
required: false,
|
|
173
|
+
description: 'Quantity in stock',
|
|
174
|
+
sampleData: '100',
|
|
175
|
+
transform: (val) => parseInt(val) || 0
|
|
176
|
+
},
|
|
177
|
+
'Category': {
|
|
178
|
+
required: false,
|
|
179
|
+
description: 'Product category',
|
|
180
|
+
sampleData: ['Electronics', 'Clothing', 'Food']
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
async function importProducts(products) {
|
|
186
|
+
const result = await fetch('/api/products/import', {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
body: JSON.stringify({ products }),
|
|
189
|
+
headers: { 'Content-Type': 'application/json' }
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return result.ok;
|
|
193
|
+
}
|
|
194
|
+
</script>
|
|
195
|
+
|
|
196
|
+
<Importer
|
|
197
|
+
definition={productImportDef}
|
|
198
|
+
bind:csvData
|
|
199
|
+
onprocess={importProducts}
|
|
200
|
+
/>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Column Mapping
|
|
204
|
+
|
|
205
|
+
The `alternateNames` prop enables flexible column mapping:
|
|
206
|
+
```typescript
|
|
207
|
+
// If CSV has "E-mail" but you expect "Email"
|
|
208
|
+
alternateNames = {
|
|
209
|
+
"Email": ["E-mail", "email", "Email Address"]
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
This is automatically managed by ImporterAnalysis when users manually map columns in the UI.
|
|
214
|
+
|
|
215
|
+
## Process Flow
|
|
216
|
+
|
|
217
|
+
1. **Upload Phase (ImporterLoad)**
|
|
218
|
+
- User clicks "Import CSV" to upload file
|
|
219
|
+
- OR downloads template (empty, with samples, or with current data)
|
|
220
|
+
- File content stored in `csvData` binding
|
|
221
|
+
|
|
222
|
+
2. **Analysis Phase (ImporterAnalysis)**
|
|
223
|
+
- CSV parsed and validated
|
|
224
|
+
- Column headers mapped to definition
|
|
225
|
+
- Errors and warnings displayed
|
|
226
|
+
- User can filter by errors/warnings
|
|
227
|
+
- User can manually remap columns (if `alternateNames` bound)
|
|
228
|
+
|
|
229
|
+
3. **Import Phase**
|
|
230
|
+
- User clicks "Import" button
|
|
231
|
+
- `onprocess` called with valid rows
|
|
232
|
+
- Return `true` to clear and reset
|
|
233
|
+
- Return `false` to keep data visible
|
|
234
|
+
|
|
235
|
+
## Validation Results
|
|
236
|
+
|
|
237
|
+
The component displays:
|
|
238
|
+
- **Errors** (red) - Invalid data, missing required columns
|
|
239
|
+
- **Warnings** (yellow) - Non-critical issues
|
|
240
|
+
|
|
241
|
+
Users can filter the preview to show only rows with errors or warnings.
|
|
242
|
+
|
|
243
|
+
## Common Patterns
|
|
244
|
+
|
|
245
|
+
### With Modal
|
|
246
|
+
```svelte
|
|
247
|
+
<Modal bind:show={showImporter} title="Import Users">
|
|
248
|
+
<Importer
|
|
249
|
+
definition={userImportDef}
|
|
250
|
+
bind:csvData
|
|
251
|
+
onprocess={async (rows) => {
|
|
252
|
+
await handleImport(rows);
|
|
253
|
+
showImporter = false;
|
|
254
|
+
return true;
|
|
255
|
+
}}
|
|
256
|
+
/>
|
|
257
|
+
</Modal>
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### With Progress Indicator
|
|
261
|
+
```svelte
|
|
262
|
+
<script>
|
|
263
|
+
let importing = $state(false);
|
|
264
|
+
|
|
265
|
+
async function handleImport(rows) {
|
|
266
|
+
importing = true;
|
|
267
|
+
try {
|
|
268
|
+
for (const row of rows) {
|
|
269
|
+
await importRow(row);
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
} finally {
|
|
273
|
+
importing = false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
</script>
|
|
277
|
+
|
|
278
|
+
{#if importing}
|
|
279
|
+
<div>Importing... Please wait</div>
|
|
280
|
+
{/if}
|
|
281
|
+
|
|
282
|
+
<Importer
|
|
283
|
+
definition={def}
|
|
284
|
+
bind:csvData
|
|
285
|
+
onprocess={handleImport}
|
|
286
|
+
/>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Common Mistakes
|
|
290
|
+
|
|
291
|
+
- ❌ Not returning boolean from `onprocess`
|
|
292
|
+
✅ Correct: Return `true` to clear, `false` to keep data
|
|
293
|
+
|
|
294
|
+
- ❌ Not using `$bindable` for csvData and alternateNames
|
|
295
|
+
✅ Correct: `bind:csvData` and `bind:alternateNames`
|
|
296
|
+
|
|
297
|
+
- ❌ Complex validation logic that blocks UI
|
|
298
|
+
✅ Correct: Keep validation functions fast and synchronous
|
|
299
|
+
|
|
300
|
+
- ❌ Not providing required column definitions
|
|
301
|
+
✅ Correct: Mark essential columns with `required: true`
|
|
302
|
+
|
|
303
|
+
## Related Components
|
|
304
|
+
|
|
305
|
+
- **ImporterLoad** - File upload and template download phase
|
|
306
|
+
- **ImporterAnalysis** - Column mapping and validation phase
|
|
307
|
+
- **DataImportProcessor** - Core processing logic from `@solidbasisventures/intelliwaketsfoundation`
|
|
308
|
+
- **DropDown** - Used for column mapping
|
|
309
|
+
- **Modal** - Often used as container
|
|
310
|
+
|
|
311
|
+
## Props Reference
|
|
312
|
+
|
|
313
|
+
| Prop | Type | Default | Description |
|
|
314
|
+
|------|------|---------|-------------|
|
|
315
|
+
| `definition` | `TDataImportProcessorDefinition<T>` | (required) | Import configuration |
|
|
316
|
+
| `alternateNames` | `Record<string, string[]>` | `null` | Column name mappings ($bindable) |
|
|
317
|
+
| `csvData` | `string \| null` | `null` | CSV content ($bindable) |
|
|
318
|
+
| `arrayData` | `string[][] \| null` | `null` | Alternative array format ($bindable) |
|
|
319
|
+
| `onprocess` | `(rows) => Promise<boolean>` | - | Process validated rows |
|
|
320
|
+
| `description` | `Snippet` | - | Custom instructions |
|
|
321
|
+
| `currentData` | `object[]` | - | Existing data for template |
|
|
322
|
+
|
|
323
|
+
## Performance Tips
|
|
324
|
+
|
|
325
|
+
- Limit imports to reasonable size (e.g., 1000-5000 rows)
|
|
326
|
+
- Use transform functions to normalize data during import
|
|
327
|
+
- Implement server-side batch processing for large imports
|
|
328
|
+
- Show progress feedback during `onprocess`
|