nicklabs-ui 1.0.80 → 1.0.82
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 +58 -24
- package/dist/index.mjs +715 -503
- package/dist/nicklabs-ui.css +1 -1
- package/dist/src/components/NAudioSelect.vue.d.ts +1 -0
- package/dist/src/components/NImageSelect.vue.d.ts +1 -0
- package/dist/src/components/NVideoSelect.vue.d.ts +1 -0
- package/dist/src/types/components/audioselect.d.ts +4 -4
- package/dist/src/types/components/imageselect.d.ts +5 -5
- package/dist/src/types/components/videoselect.d.ts +6 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A Vue 3 component library with glassmorphism design, built for modern web applications.
|
|
4
4
|
|
|
5
|
-
**Version**: 1.0.
|
|
5
|
+
**Version**: 1.0.81 | **Framework**: Vue 3.5+
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -544,7 +544,7 @@ function handleFiles(files: File[]) {
|
|
|
544
544
|
|
|
545
545
|
#### NImageSelect
|
|
546
546
|
|
|
547
|
-
A card-grid image uploader with drag-and-drop, multi-file support, automatic resolution probing, a built-in dark preview lightbox, and a confirm dialog before removal. Files are tracked as `NImageSelectItem[]` via `v-model`.
|
|
547
|
+
A card-grid image uploader with drag-and-drop, multi-file support, automatic resolution probing, a built-in dark preview lightbox, and a confirm dialog before removal. Files are tracked as `NImageSelectItem[]` via `v-model`. Supports backfilling existing data by URL and a read-only view mode (see notes below).
|
|
548
548
|
|
|
549
549
|
> Removal uses `useAlert` internally, so mount `<NAlert />` once at the app root (see [NAlert](#nalert)).
|
|
550
550
|
|
|
@@ -556,7 +556,8 @@ A card-grid image uploader with drag-and-drop, multi-file support, automatic res
|
|
|
556
556
|
| `accept` | `string` | `"image/*"` | Accepted types — used for both the file dialog and drop validation. Supports `image/*`, exact MIME (`image/png`), extensions (`.png`), and comma-separated combinations |
|
|
557
557
|
| `multiple` | `boolean` | `false` | Allow multiple images; when `false`, extra files are rejected with a `count` error |
|
|
558
558
|
| `maxSize` | `number` | `0` | Per-file size limit in **MB** (`0` = unlimited) |
|
|
559
|
-
| `disabled` | `boolean` | `false` | Disable adding and removing |
|
|
559
|
+
| `disabled` | `boolean` | `false` | Disable adding and removing (also dims the component) |
|
|
560
|
+
| `readonly` | `boolean` | `false` | View-only mode: browse and preview only. Hides the add/delete affordances and disables drag/drop, but keeps a normal (non-dimmed) appearance |
|
|
560
561
|
| `title` | `string` | `""` | Label above the grid |
|
|
561
562
|
| `showCount` | `boolean` | `false` | Show a count chip next to the title |
|
|
562
563
|
| `emptyTitle` | `string` | `"將圖片拖放到這裡"` | Empty-state heading |
|
|
@@ -612,13 +613,24 @@ async function upload() {
|
|
|
612
613
|
</script>
|
|
613
614
|
```
|
|
614
615
|
|
|
615
|
-
> `width` / `height` are probed asynchronously after a file is added and written back into the item. The component creates object URLs for previews and revokes them on removal automatically, and on unmount too unless `autoRevoke` is `false` — in which case the parent owns the URLs and must revoke them.
|
|
616
|
+
> `width` / `height` are probed asynchronously after a file is added and written back into the item. The component creates object URLs for previews and revokes them on removal automatically, and on unmount too unless `autoRevoke` is `false` — in which case the parent owns the URLs and must revoke them. Only `blob:` URLs the component created are revoked; remote URLs are never touched.
|
|
617
|
+
|
|
618
|
+
**Backfilling existing data (edit mode)**
|
|
619
|
+
|
|
620
|
+
After upload, the server usually returns only a URL. To show that data, push items with just `id` and `url` (leave `file` empty) — the component probes `width`/`height` and derives the display name from the URL:
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
const images = ref<NImageSelectItem[]>([
|
|
624
|
+
{ id: 'remote-1', url: 'https://cdn.example.com/images/cover.jpg' },
|
|
625
|
+
])
|
|
626
|
+
// <NImageSelect v-model="images" readonly title="Image content" />
|
|
627
|
+
```
|
|
616
628
|
|
|
617
629
|
---
|
|
618
630
|
|
|
619
631
|
#### NVideoSelect
|
|
620
632
|
|
|
621
|
-
A card-grid video uploader. Same interaction model as [NImageSelect](#nimageselect) — drag-and-drop, multi-file, confirm-before-remove, and a built-in preview modal — but items also carry `duration`, `width`, and `height`.
|
|
633
|
+
A card-grid video uploader. Same interaction model as [NImageSelect](#nimageselect) — drag-and-drop, multi-file, confirm-before-remove, and a built-in preview modal — but items also carry `duration`, `width`, and `height`. Supports backfilling existing data by URL and a read-only view mode (same as [NImageSelect](#nimageselect)).
|
|
622
634
|
|
|
623
635
|
> Removal uses `useAlert` internally, so mount `<NAlert />` once at the app root (see [NAlert](#nalert)).
|
|
624
636
|
|
|
@@ -630,7 +642,8 @@ A card-grid video uploader. Same interaction model as [NImageSelect](#nimagesele
|
|
|
630
642
|
| `accept` | `string` | `"video/*"` | Accepted types — supports `video/*`, exact MIME (`video/mp4`), extensions (`.mp4`), and comma-separated combinations |
|
|
631
643
|
| `multiple` | `boolean` | `false` | Allow multiple videos |
|
|
632
644
|
| `maxSize` | `number` | `0` | Per-file size limit in **MB** (`0` = unlimited) |
|
|
633
|
-
| `disabled` | `boolean` | `false` | Disable adding and removing |
|
|
645
|
+
| `disabled` | `boolean` | `false` | Disable adding and removing (also dims the component) |
|
|
646
|
+
| `readonly` | `boolean` | `false` | View-only mode: browse and preview only. Hides the add/delete affordances and disables drag/drop, but keeps a normal (non-dimmed) appearance |
|
|
634
647
|
| `title` | `string` | `""` | Label above the grid |
|
|
635
648
|
| `showCount` | `boolean` | `false` | Show a count chip next to the title |
|
|
636
649
|
| `emptyTitle` | `string` | `"將影片拖放到這裡"` | Empty-state heading |
|
|
@@ -667,11 +680,13 @@ function onError(err: NVideoSelectError) {
|
|
|
667
680
|
</script>
|
|
668
681
|
```
|
|
669
682
|
|
|
683
|
+
> **Backfilling existing data:** push items with just `id` and `url` (leave `file` empty); `duration` / `width` / `height` are probed and the name is derived from the URL. Only component-created `blob:` URLs are revoked on remove/unmount — remote URLs are never touched.
|
|
684
|
+
|
|
670
685
|
---
|
|
671
686
|
|
|
672
687
|
#### NAudioSelect
|
|
673
688
|
|
|
674
|
-
An audio uploader that decodes each file with the Web Audio API to render a waveform, showing a skeleton row while decoding. Same drag-and-drop / multi-file / confirm-before-remove model as the other media selectors; items carry `duration`.
|
|
689
|
+
An audio uploader that decodes each file with the Web Audio API to render a waveform, showing a skeleton row while decoding. Each row has an inline player (play/pause + click-and-drag seek on the waveform); only one track plays at a time. Same drag-and-drop / multi-file / confirm-before-remove model as the other media selectors; items carry `duration`. Supports backfilling existing data by URL and a read-only view mode.
|
|
675
690
|
|
|
676
691
|
> Removal uses `useAlert` internally, so mount `<NAlert />` once at the app root (see [NAlert](#nalert)).
|
|
677
692
|
|
|
@@ -683,7 +698,8 @@ An audio uploader that decodes each file with the Web Audio API to render a wave
|
|
|
683
698
|
| `accept` | `string` | `".mp3,.wav,.ogg,.m4a,.aac,.flac,audio/mpeg,audio/wav,audio/ogg,audio/aac,audio/flac"` | Accepted types. Defaults to an explicit extension + MIME list (rather than `audio/*`) so the dialog doesn't offer `.mp4`-style containers |
|
|
684
699
|
| `multiple` | `boolean` | `false` | Allow multiple files |
|
|
685
700
|
| `maxSize` | `number` | `0` | Per-file size limit in **MB** (`0` = unlimited) |
|
|
686
|
-
| `disabled` | `boolean` | `false` | Disable adding and removing |
|
|
701
|
+
| `disabled` | `boolean` | `false` | Disable adding and removing (also dims the component) |
|
|
702
|
+
| `readonly` | `boolean` | `false` | View-only mode: browse and play only. Hides the add/delete affordances and disables drag/drop, but keeps a normal (non-dimmed) appearance. **Playback and seek stay enabled** |
|
|
687
703
|
| `title` | `string` | `""` | Label above the list |
|
|
688
704
|
| `showCount` | `boolean` | `false` | Show a count chip next to the title |
|
|
689
705
|
| `emptyTitle` | `string` | `"將音訊拖放到這裡"` | Empty-state heading |
|
|
@@ -720,6 +736,21 @@ function onError(err: NAudioSelectError) {
|
|
|
720
736
|
</script>
|
|
721
737
|
```
|
|
722
738
|
|
|
739
|
+
**Backfilling existing data (edit mode)**
|
|
740
|
+
|
|
741
|
+
Push items with just `id` and `url` (leave `file` empty); the display name is derived from the URL:
|
|
742
|
+
|
|
743
|
+
```ts
|
|
744
|
+
const tracks = ref<NAudioSelectItem[]>([
|
|
745
|
+
{ id: 'remote-1', url: 'https://cdn.example.com/audios/track.mp3' },
|
|
746
|
+
])
|
|
747
|
+
// <NAudioSelect v-model="tracks" readonly title="Audio content" />
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
> **Waveform vs. duration for remote URLs.** The waveform needs the raw bytes (`fetch` + decode), which is subject to **CORS** — if the host doesn't allow it, the row falls back to a plain progress bar (track + played fill) instead of a waveform. Either way, **click/drag seek and the progress visual stay functional** — seeking only depends on the audio element's `duration`, not the waveform. Duration itself always resolves: it falls back to the `<audio>` element's metadata (no CORS needed), and playback works regardless.
|
|
751
|
+
|
|
752
|
+
> **Waveform cache (survives `v-if` remount).** Decoded waveforms are kept in a module-level cache keyed by `url`, so toggling the component with `v-if` (unmount → remount) restores the waveform instantly with no re-decode and no flash. A `v-if` unmount does **not** clear the cache; only an explicit remove (the delete button) evicts the entry. Note this is independent of `autoRevoke`: the cache preserves the *waveform*, but `autoRevoke: true` still revokes the *blob* on unmount, which breaks **playback** of locally-added files after remount — set `autoRevoke: false` (and take over `URL.revokeObjectURL` in the parent) if you need playback to survive a remount.
|
|
753
|
+
|
|
723
754
|
---
|
|
724
755
|
|
|
725
756
|
#### NSwitch
|
|
@@ -2179,35 +2210,38 @@ type RadiusSize = 'none' | 'sm' | 'md' | 'lg' | 'xl'
|
|
|
2179
2210
|
// Media selectors (NImageSelect / NVideoSelect / NAudioSelect)
|
|
2180
2211
|
type MediaSelectErrorType = 'size' | 'type' | 'count'
|
|
2181
2212
|
|
|
2213
|
+
// Only `id` and `url` are required. The rest are optional so you can backfill
|
|
2214
|
+
// existing data from the server with just a URL — the component probes the
|
|
2215
|
+
// missing metadata (and, for audio, the waveform) itself.
|
|
2182
2216
|
interface NImageSelectItem {
|
|
2183
2217
|
id: string
|
|
2184
|
-
file
|
|
2185
|
-
name
|
|
2186
|
-
size
|
|
2187
|
-
width
|
|
2188
|
-
height
|
|
2189
|
-
url: string
|
|
2218
|
+
file?: File | null // native File for upload; null/absent for remote-URL items
|
|
2219
|
+
name?: string // derived from the URL when absent
|
|
2220
|
+
size?: number | null // bytes; null when unknown (remote)
|
|
2221
|
+
width?: number | null
|
|
2222
|
+
height?: number | null
|
|
2223
|
+
url: string // object URL or a remote URL — for thumbnail & preview
|
|
2190
2224
|
}
|
|
2191
2225
|
interface NImageSelectError { type: MediaSelectErrorType; file: File }
|
|
2192
2226
|
|
|
2193
2227
|
interface NVideoSelectItem {
|
|
2194
2228
|
id: string
|
|
2195
|
-
file
|
|
2196
|
-
name
|
|
2197
|
-
size
|
|
2198
|
-
duration
|
|
2199
|
-
width
|
|
2200
|
-
height
|
|
2229
|
+
file?: File | null
|
|
2230
|
+
name?: string
|
|
2231
|
+
size?: number | null
|
|
2232
|
+
duration?: number | null // seconds
|
|
2233
|
+
width?: number | null
|
|
2234
|
+
height?: number | null
|
|
2201
2235
|
url: string
|
|
2202
2236
|
}
|
|
2203
2237
|
interface NVideoSelectError { type: MediaSelectErrorType; file: File }
|
|
2204
2238
|
|
|
2205
2239
|
interface NAudioSelectItem {
|
|
2206
2240
|
id: string
|
|
2207
|
-
file
|
|
2208
|
-
name
|
|
2209
|
-
size
|
|
2210
|
-
duration
|
|
2241
|
+
file?: File | null
|
|
2242
|
+
name?: string
|
|
2243
|
+
size?: number | null
|
|
2244
|
+
duration?: number | null // seconds
|
|
2211
2245
|
url: string
|
|
2212
2246
|
}
|
|
2213
2247
|
interface NAudioSelectError { type: MediaSelectErrorType; file: File }
|