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.
- package/bin/snice.js +8 -0
- package/bin/templates/CLAUDE.md +11 -0
- package/dist/components/file-gallery/snice-file-gallery.d.ts +87 -0
- package/dist/components/file-gallery/snice-file-gallery.js +892 -0
- package/dist/components/file-gallery/snice-file-gallery.js.map +1 -0
- package/dist/components/file-gallery/snice-file-gallery.types.d.ts +72 -0
- package/dist/components/qr-reader/qr-decoder.d.ts +20 -0
- package/dist/components/qr-reader/qr-decoder.js +49 -0
- package/dist/components/qr-reader/qr-decoder.js.map +1 -0
- package/dist/components/qr-reader/qr-worker.d.ts +6 -0
- package/dist/components/qr-reader/qr-worker.js +64 -0
- package/dist/components/qr-reader/qr-worker.js.map +1 -0
- package/dist/components/qr-reader/snice-qr-reader.d.ts +41 -0
- package/dist/components/qr-reader/snice-qr-reader.js +463 -0
- package/dist/components/qr-reader/snice-qr-reader.js.map +1 -0
- package/dist/components/qr-reader/snice-qr-reader.types.d.ts +17 -0
- package/dist/components/qr-reader/zxing-reader.mjs +1582 -0
- package/dist/components/qr-reader/zxing-share.mjs +305 -0
- package/dist/components/qr-reader/zxing_reader.wasm +0 -0
- package/dist/components/zxing-reader-B3Rfebg9.js +1771 -0
- package/dist/components/zxing-reader-B3Rfebg9.js.map +1 -0
- package/dist/index.cjs +21 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +21 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.iife.js +21 -4
- package/dist/index.iife.js.map +1 -1
- package/dist/symbols.cjs +1 -1
- package/dist/symbols.esm.js +1 -1
- package/dist/transitions.cjs +1 -1
- package/dist/transitions.esm.js +1 -1
- package/docs/ai/README.md +1 -1
- package/docs/ai/api.md +5 -0
- package/docs/ai/components/file-gallery.md +206 -0
- package/docs/ai/components/qr-reader.md +80 -0
- package/docs/components/file-gallery.md +692 -0
- package/docs/components/qr-reader.md +327 -0
- package/package.json +1 -1
package/dist/symbols.cjs
CHANGED
package/dist/symbols.esm.js
CHANGED
package/dist/transitions.cjs
CHANGED
package/dist/transitions.esm.js
CHANGED
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
|