snice 3.8.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/bin/snice.js +8 -0
  2. package/bin/templates/CLAUDE.md +11 -0
  3. package/dist/components/file-gallery/snice-file-gallery.d.ts +87 -0
  4. package/dist/components/file-gallery/snice-file-gallery.js +892 -0
  5. package/dist/components/file-gallery/snice-file-gallery.js.map +1 -0
  6. package/dist/components/file-gallery/snice-file-gallery.types.d.ts +72 -0
  7. package/dist/components/qr-reader/qr-decoder.d.ts +20 -0
  8. package/dist/components/qr-reader/qr-decoder.js +49 -0
  9. package/dist/components/qr-reader/qr-decoder.js.map +1 -0
  10. package/dist/components/qr-reader/qr-worker.d.ts +6 -0
  11. package/dist/components/qr-reader/qr-worker.js +64 -0
  12. package/dist/components/qr-reader/qr-worker.js.map +1 -0
  13. package/dist/components/qr-reader/snice-qr-reader.d.ts +41 -0
  14. package/dist/components/qr-reader/snice-qr-reader.js +463 -0
  15. package/dist/components/qr-reader/snice-qr-reader.js.map +1 -0
  16. package/dist/components/qr-reader/snice-qr-reader.types.d.ts +17 -0
  17. package/dist/components/qr-reader/zxing-reader.mjs +1582 -0
  18. package/dist/components/qr-reader/zxing-share.mjs +305 -0
  19. package/dist/components/qr-reader/zxing_reader.wasm +0 -0
  20. package/dist/components/zxing-reader-B3Rfebg9.js +1771 -0
  21. package/dist/components/zxing-reader-B3Rfebg9.js.map +1 -0
  22. package/dist/index.cjs +21 -4
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.esm.js +21 -4
  25. package/dist/index.esm.js.map +1 -1
  26. package/dist/index.iife.js +21 -4
  27. package/dist/index.iife.js.map +1 -1
  28. package/dist/symbols.cjs +1 -1
  29. package/dist/symbols.esm.js +1 -1
  30. package/dist/transitions.cjs +1 -1
  31. package/dist/transitions.esm.js +1 -1
  32. package/docs/ai/README.md +1 -1
  33. package/docs/ai/api.md +5 -0
  34. package/docs/ai/components/file-gallery.md +206 -0
  35. package/docs/ai/components/qr-reader.md +80 -0
  36. package/docs/components/file-gallery.md +692 -0
  37. package/docs/components/qr-reader.md +327 -0
  38. package/package.json +1 -1
package/dist/symbols.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v3.7.0
2
+ * snice v3.9.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v3.7.0
2
+ * snice v3.9.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v3.7.0
2
+ * snice v3.9.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v3.7.0
2
+ * snice v3.9.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, differential rendering, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
package/docs/ai/README.md CHANGED
@@ -21,6 +21,6 @@ Read these instead of `/docs/*.md` for faster context loading.
21
21
  **IMPORTANT:** Do NOT read all component docs. Only read a component's doc when you need to use or reference it.
22
22
 
23
23
  **Implemented Components:**
24
- - accordion, accordion-item, alert, avatar, badge, banner, breadcrumbs, button, card, checkbox, chip, color-display, color-picker, date-picker, divider, drawer, empty-state, file-upload, image, input, login, modal, nav, progress, radio, select, skeleton, slider, spinner, switch, table, tabs, tab, textarea, timeline, tooltip
24
+ - accordion, accordion-item, alert, avatar, badge, banner, breadcrumbs, button, card, checkbox, chip, color-display, color-picker, date-picker, divider, drawer, empty-state, file-gallery, file-upload, image, input, login, modal, nav, progress, qr-code, qr-reader, radio, select, skeleton, slider, spinner, switch, table, tabs, tab, textarea, timeline, tooltip
25
25
 
26
26
  **To use a component:** Read `docs/ai/components/{component-name}.md` only when needed.
package/docs/ai/api.md CHANGED
@@ -208,6 +208,11 @@ attr="${val}" // Attribute
208
208
  ?attr="${bool}" // Boolean attribute
209
209
  @event="${handler}" // Event listener
210
210
  @event:modifier="${handler}" // With keyboard modifier
211
+
212
+ // IMPORTANT: Event names starting with @
213
+ // Use @@ to escape the @ in event names like @snice/qr-scan
214
+ @@snice/qr-scan="${handler}" // Correct - first @ is syntax, second @ is part of name
215
+ @snice/qr-scan="${handler}" // Wrong - treated as @snice event
211
216
  ```
212
217
 
213
218
  ## Types
@@ -0,0 +1,206 @@
1
+ # snice-file-gallery
2
+
3
+ File upload gallery with drag-and-drop, preview, pausable/resumable uploads.
4
+
5
+ ## Properties
6
+
7
+ ```typescript
8
+ accept: string = '';
9
+ multiple: boolean = true;
10
+ disabled: boolean = false;
11
+ maxSize: number = -1; // bytes, -1 = no limit
12
+ maxFiles: number = -1; // -1 = no limit
13
+ view: 'grid'|'list' = 'grid';
14
+ showProgress: boolean = true;
15
+ allowPause: boolean = true;
16
+ allowDelete: boolean = true;
17
+ autoUpload: boolean = true;
18
+ showAddButton: boolean = false; // show add button tile instead of drop zone
19
+ hideAddButton: boolean = false; // hide default add button (show only custom actions)
20
+ files: GalleryFile[]; // read-only
21
+ ```
22
+
23
+ ## Getters
24
+
25
+ - `files: GalleryFile[]` - Get all files
26
+ - `customActions: CustomAction[]` - Get all custom actions
27
+ - `getFile(fileId): GalleryFile | undefined` - Get specific file
28
+ - `getCustomAction(actionId): CustomAction | undefined` - Get specific action
29
+ - `isPending(fileId): boolean` - Check if pending
30
+ - `isUploading(fileId): boolean` - Check if uploading
31
+ - `isPaused(fileId): boolean` - Check if paused
32
+ - `isCompleted(fileId): boolean` - Check if completed
33
+ - `hasError(fileId): boolean` - Check if has error
34
+ - `canAddFiles(): boolean` - Check if can add more files
35
+
36
+ ## File Management
37
+
38
+ - `addFiles(files: FileList | File[])` - Add files to gallery
39
+ - `addFileWithPreview(file: File, previewDataUrl: string)` - Add file with preview
40
+ - `removeFile(fileId: string)` - Remove file
41
+ - `clear()` - Remove all files
42
+ - `clearCompleted()` - Remove completed files
43
+ - `clearErrors()` - Remove files with errors
44
+
45
+ ## Upload Control
46
+
47
+ - `pauseUpload(fileId: string)` - Pause upload
48
+ - `resumeUpload(fileId: string)` - Resume upload
49
+ - `retryUpload(fileId: string)` - Retry failed upload
50
+ - `cancelUpload(fileId: string)` - Cancel and remove upload
51
+ - `pauseAll()` - Pause all uploading files
52
+ - `resumeAll()` - Resume all paused files
53
+ - `retryAll()` - Retry all errored files
54
+ - `cancelAll()` - Cancel all active uploads
55
+
56
+ ## Custom Actions
57
+
58
+ - `addCustomAction(icon: string, text: string): string` - Add custom action, returns actionId
59
+ - `removeCustomAction(actionId: string)` - Remove action
60
+ - `clearCustomActions()` - Remove all actions
61
+
62
+ ## Utility
63
+
64
+ - `openFilePicker()` - Open file picker dialog
65
+ - `setFileBadge(fileId: string, badge: string, position?: 'top-left'|'top-right'|'bottom-left'|'bottom-right')` - Add badge overlay to file preview (supports HTML)
66
+ - `removeFileBadge(fileId: string)` - Remove badge from file
67
+
68
+ ## Events
69
+
70
+ - `files-change` - {files: GalleryFile[]}
71
+ - `upload-progress` - {file: GalleryFile, progress: number}
72
+ - `upload-complete` - {file: GalleryFile, url?: string}
73
+ - `upload-error` - {file: GalleryFile, error: string}
74
+ - `custom-action-click` - {actionId: string}
75
+ - `error` - {message: string}
76
+
77
+ ## Types
78
+
79
+ ```typescript
80
+ interface GalleryFile {
81
+ id: string;
82
+ file: File;
83
+ preview?: string;
84
+ uploadProgress: number;
85
+ uploadStatus: 'pending'|'uploading'|'paused'|'completed'|'error';
86
+ error?: string;
87
+ badge?: string; // HTML content for badge overlay
88
+ badgePosition?: 'top-left'|'top-right'|'bottom-left'|'bottom-right';
89
+ }
90
+
91
+ interface UploadRequest {
92
+ file: File;
93
+ fileId: string;
94
+ onProgress?: (progress: number) => void;
95
+ signal?: AbortSignal;
96
+ }
97
+
98
+ interface UploadResponse {
99
+ success: boolean;
100
+ fileId: string;
101
+ url?: string;
102
+ error?: string;
103
+ }
104
+ ```
105
+
106
+ ## Upload Handler
107
+
108
+ Uses `@request/@respond` pattern. Handler required:
109
+
110
+ ```typescript
111
+ import { respond } from 'snice';
112
+
113
+ class UploadController {
114
+ @respond('file-gallery-upload')
115
+ async handleUpload(request: UploadRequest): Promise<UploadResponse> {
116
+ const { file, fileId, onProgress, signal } = request;
117
+
118
+ // Implement upload logic
119
+ // Use onProgress(0-1) for progress tracking
120
+ // Check signal.aborted for cancellation
121
+
122
+ return {
123
+ success: true,
124
+ fileId,
125
+ url: 'https://example.com/file.jpg'
126
+ };
127
+ }
128
+ }
129
+
130
+ const controller = new UploadController();
131
+ controller.attach?.(document.body);
132
+ ```
133
+
134
+ ## Usage
135
+
136
+ ```html
137
+ <!-- Basic -->
138
+ <snice-file-gallery></snice-file-gallery>
139
+
140
+ <!-- Images only -->
141
+ <snice-file-gallery accept="image/*"></snice-file-gallery>
142
+
143
+ <!-- Manual upload -->
144
+ <snice-file-gallery auto-upload="false"></snice-file-gallery>
145
+
146
+ <!-- Limits -->
147
+ <snice-file-gallery max-files="3" max-size="2097152"></snice-file-gallery>
148
+
149
+ <!-- List view -->
150
+ <snice-file-gallery view="list"></snice-file-gallery>
151
+
152
+ <!-- Custom options -->
153
+ <snice-file-gallery
154
+ accept=".pdf,.doc,.docx"
155
+ allow-pause="false"
156
+ ></snice-file-gallery>
157
+
158
+ <!-- Add button mode -->
159
+ <snice-file-gallery
160
+ show-add-button="true"
161
+ max-files="6"
162
+ ></snice-file-gallery>
163
+
164
+ <!-- Custom actions -->
165
+ <snice-file-gallery id="gallery"></snice-file-gallery>
166
+ <script>
167
+ const gallery = document.querySelector('#gallery');
168
+
169
+ // Add custom action
170
+ const icon = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">...</svg>';
171
+ const actionId = gallery.addCustomAction(icon, 'Camera');
172
+
173
+ // Handle custom action
174
+ gallery.addEventListener('@snice/custom-action-click', (e) => {
175
+ if (e.detail.actionId === actionId) {
176
+ // Handle camera action
177
+ const file = capturePhoto(); // your implementation
178
+ gallery.addFileWithPreview(file, previewUrl);
179
+ }
180
+ });
181
+
182
+ // Other events
183
+ gallery.addEventListener('@snice/files-change', (e) => {
184
+ console.log('Files:', e.detail.files);
185
+ });
186
+ gallery.addEventListener('@snice/upload-complete', (e) => {
187
+ console.log('Complete:', e.detail.url);
188
+ });
189
+
190
+ // Add custom badge (e.g., user avatar)
191
+ const avatarHTML = `<div style="width:40px;height:40px;border-radius:50%;background:#3b82f6;color:white;display:flex;align-items:center;justify-content:center;font-weight:bold;border:2px solid white;box-shadow:0 2px 4px rgba(0,0,0,0.2)">JD</div>`;
192
+ gallery.setFileBadge(fileId, avatarHTML, 'top-right');
193
+ </script>
194
+ ```
195
+
196
+ ## Features
197
+
198
+ - Drag-and-drop with visual feedback
199
+ - Image preview thumbnails
200
+ - Pausable/resumable uploads via AbortController
201
+ - Real-time progress tracking
202
+ - Grid/list view toggle
203
+ - File validation (size, type)
204
+ - Auto or manual upload modes
205
+ - @request/@respond upload pattern
206
+ - Accessible
@@ -0,0 +1,80 @@
1
+ # snice-qr-reader
2
+
3
+ QR code scanner using device camera and ZXing WASM decoder.
4
+
5
+ ## API
6
+
7
+ ### Properties
8
+ - `auto-start: boolean = false` - Auto-start scanning on mount
9
+ - `camera: 'front'|'back' = 'back'` - Camera selection
10
+ - `pick-first: boolean = false` - Scan at max speed until first hit, then stop and shutdown
11
+ - `manual-snap: boolean = false` - Photo mode: open camera, manually trigger snapshots
12
+ - `scan-speed: number = 3` - Scan speed 1-10 (higher = faster, more CPU). Ignored when pick-first=true
13
+
14
+ ### Methods
15
+ - `start()` - Start camera/scanning
16
+ - `stop()` - Stop camera/scanning
17
+ - `snap()` - Take snapshot (manual-snap mode)
18
+
19
+ ### Events
20
+ - `@snice/qr-scan` - detail: `{data: string, timestamp: number, reader: SniceQRReader}`
21
+ - `@snice/qr-error` - detail: `{error: any, reader: SniceQRReader}`
22
+ - `@snice/camera-ready` - detail: `{reader: SniceQRReader}`
23
+ - `@snice/camera-error` - detail: `{error: any, reader: SniceQRReader}`
24
+
25
+ ## Usage
26
+
27
+ ```html
28
+ <snice-qr-reader auto-start></snice-qr-reader>
29
+ <script>
30
+ reader.addEventListener('@snice/qr-scan', e => console.log(e.detail.data));
31
+ </script>
32
+ ```
33
+
34
+ ## Implementation
35
+
36
+ ### File Structure
37
+ - `snice-qr-reader.ts` - Main component (camera, scanning loop)
38
+ - `qr-worker.ts` - Web Worker for QR detection
39
+ - `qr-decoder.ts` - ZXing WASM wrapper (legacy)
40
+ - `zxing-reader.mjs` - ZXing ES module
41
+ - `zxing_reader.wasm` - WASM binary
42
+ - `ZXING-LICENSE` - Apache 2.0 + MIT
43
+
44
+ ### QR Detection
45
+ Uses ZXing WASM decoder exclusively for universal browser support.
46
+
47
+ ### Camera Loop
48
+ ```ts
49
+ private scanFrame() {
50
+ ctx.drawImage(video, 0, 0, width, height);
51
+ const imageData = ctx.getImageData(0, 0, width, height);
52
+ worker.postMessage({ type: 'decode', imageData });
53
+ // Worker responds with result in background thread
54
+ requestAnimationFrame(() => this.scanFrame());
55
+ }
56
+ ```
57
+
58
+ ### Lifecycle
59
+ - `@ready` - Init worker, auto-start if enabled
60
+ - `@dispose` - Stop scan, release camera, terminate worker
61
+ - Scan loop uses requestAnimationFrame
62
+ - QR detection runs in Web Worker (non-blocking)
63
+ - Only emits event if QR data changed
64
+
65
+ ### CSS Tokens
66
+ ```css
67
+ --qr-reader-border: var(--snice-color-border, #e5e7eb)
68
+ --qr-reader-bg: var(--snice-color-bg, #fff)
69
+ --qr-reader-text: var(--snice-color-text, #1f2937)
70
+ ```
71
+
72
+ ## License
73
+ - ZXing-C++: Apache 2.0
74
+ - zxing-wasm: MIT
75
+ - See ZXING-LICENSE file
76
+
77
+ ## Browser Requirements
78
+ - getUserMedia API
79
+ - WebAssembly support
80
+ - HTTPS for mobile