@uploadista/vue 0.0.3
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/.turbo/turbo-check.log +240 -0
- package/LICENSE +21 -0
- package/README.md +554 -0
- package/package.json +36 -0
- package/src/components/FlowUploadList.vue +342 -0
- package/src/components/FlowUploadZone.vue +305 -0
- package/src/components/UploadList.vue +303 -0
- package/src/components/UploadZone.vue +254 -0
- package/src/components/index.ts +11 -0
- package/src/composables/index.ts +44 -0
- package/src/composables/plugin.ts +76 -0
- package/src/composables/useDragDrop.ts +343 -0
- package/src/composables/useFlowUpload.ts +431 -0
- package/src/composables/useMultiFlowUpload.ts +322 -0
- package/src/composables/useMultiUpload.ts +546 -0
- package/src/composables/useUpload.ts +300 -0
- package/src/composables/useUploadMetrics.ts +502 -0
- package/src/composables/useUploadistaClient.ts +73 -0
- package/src/index.ts +28 -0
- package/src/providers/UploadistaProvider.vue +69 -0
- package/src/providers/index.ts +1 -0
- package/src/utils/index.ts +156 -0
- package/src/utils/is-browser-file.ts +2 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
# @uploadista/vue
|
|
2
|
+
|
|
3
|
+
Vue 3 client for Uploadista - file uploads and flow management with Vue Composition API.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Vue 3 Composition API composables for file uploads
|
|
8
|
+
- Flow-based upload processing
|
|
9
|
+
- WebSocket support for real-time progress
|
|
10
|
+
- TypeScript support
|
|
11
|
+
- Reactive state management
|
|
12
|
+
- Drag and drop support
|
|
13
|
+
- Multiple concurrent uploads
|
|
14
|
+
- Upload metrics and monitoring
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm add @uploadista/vue
|
|
20
|
+
# or
|
|
21
|
+
npm install @uploadista/vue
|
|
22
|
+
# or
|
|
23
|
+
yarn add @uploadista/vue
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Vue 3.3 or higher
|
|
29
|
+
- TypeScript 5.0+ (optional but recommended)
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
### 1. Install the Plugin
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// main.ts
|
|
37
|
+
import { createApp } from 'vue'
|
|
38
|
+
import { createUploadistaPlugin } from '@uploadista/vue'
|
|
39
|
+
import App from './App.vue'
|
|
40
|
+
|
|
41
|
+
const app = createApp(App)
|
|
42
|
+
|
|
43
|
+
app.use(createUploadistaPlugin({
|
|
44
|
+
serverUrl: 'http://localhost:4200', // Your Uploadista server URL
|
|
45
|
+
auth: {
|
|
46
|
+
type: 'saas',
|
|
47
|
+
apiKey: 'your-api-key'
|
|
48
|
+
}
|
|
49
|
+
}))
|
|
50
|
+
|
|
51
|
+
app.mount('#app')
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 2. Use Composables in Components
|
|
55
|
+
|
|
56
|
+
```vue
|
|
57
|
+
<script setup lang="ts">
|
|
58
|
+
import { useUpload } from '@uploadista/vue'
|
|
59
|
+
|
|
60
|
+
const { state, upload, abort, reset } = useUpload()
|
|
61
|
+
|
|
62
|
+
const handleFileChange = async (event: Event) => {
|
|
63
|
+
const file = (event.target as HTMLInputElement).files?.[0]
|
|
64
|
+
if (file) {
|
|
65
|
+
await upload(file)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<template>
|
|
71
|
+
<div>
|
|
72
|
+
<input type="file" @change="handleFileChange" :disabled="state.status === 'uploading'" />
|
|
73
|
+
|
|
74
|
+
<div v-if="state.status === 'uploading'">
|
|
75
|
+
<p>Progress: {{ state.progress.toFixed(0) }}%</p>
|
|
76
|
+
<button @click="abort">Cancel</button>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div v-if="state.status === 'success'">
|
|
80
|
+
<p>Upload complete!</p>
|
|
81
|
+
<p>File ID: {{ state.result?.fileId }}</p>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div v-if="state.status === 'error'">
|
|
85
|
+
<p>Error: {{ state.error?.message }}</p>
|
|
86
|
+
<button @click="reset">Try Again</button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### Plugin
|
|
95
|
+
|
|
96
|
+
#### `createUploadistaPlugin(options)`
|
|
97
|
+
|
|
98
|
+
Creates the Uploadista Vue plugin.
|
|
99
|
+
|
|
100
|
+
**Options:**
|
|
101
|
+
- `serverUrl` - Uploadista server URL
|
|
102
|
+
- `auth` - Authentication configuration
|
|
103
|
+
- `type: 'no-auth' | 'saas' | 'direct'`
|
|
104
|
+
- For SaaS: `{ type: 'saas', apiKey: string, projectId?: string }`
|
|
105
|
+
- For direct: `{ type: 'direct', getAuthorizationHeader: () => Promise<string> }`
|
|
106
|
+
|
|
107
|
+
### Composables
|
|
108
|
+
|
|
109
|
+
#### `useUploadistaClient()`
|
|
110
|
+
|
|
111
|
+
Access the Uploadista client instance.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const client = useUploadistaClient()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### `useUpload(options?)`
|
|
118
|
+
|
|
119
|
+
Single file upload with progress tracking.
|
|
120
|
+
|
|
121
|
+
**Returns:**
|
|
122
|
+
- `state` - Reactive upload state (readonly)
|
|
123
|
+
- `status` - Upload status: 'idle' | 'uploading' | 'success' | 'error' | 'aborted'
|
|
124
|
+
- `progress` - Progress percentage (0-100)
|
|
125
|
+
- `bytesUploaded` - Bytes uploaded
|
|
126
|
+
- `totalBytes` - Total file size
|
|
127
|
+
- `result` - Upload result (when successful)
|
|
128
|
+
- `error` - Error object (when failed)
|
|
129
|
+
- `upload(file, options?)` - Start upload
|
|
130
|
+
- `abort()` - Cancel upload
|
|
131
|
+
- `reset()` - Reset to initial state
|
|
132
|
+
- `retry()` - Retry failed upload
|
|
133
|
+
|
|
134
|
+
**Options:**
|
|
135
|
+
- `onProgress` - Progress callback
|
|
136
|
+
- `onComplete` - Completion callback
|
|
137
|
+
- `onError` - Error callback
|
|
138
|
+
|
|
139
|
+
#### `useMultiUpload(options?)`
|
|
140
|
+
|
|
141
|
+
Multiple file uploads with aggregate tracking.
|
|
142
|
+
|
|
143
|
+
**Returns:**
|
|
144
|
+
- `uploads` - Array of upload items (readonly)
|
|
145
|
+
- `stats` - Aggregate statistics (readonly)
|
|
146
|
+
- `totalFiles`, `completedFiles`, `failedFiles`
|
|
147
|
+
- `totalBytes`, `uploadedBytes`
|
|
148
|
+
- `totalProgress`, `allComplete`, `hasErrors`
|
|
149
|
+
- `add(files)` - Add files to upload queue
|
|
150
|
+
- `remove(uploadId)` - Remove upload
|
|
151
|
+
- `clear()` - Clear all uploads
|
|
152
|
+
- `retryFailed()` - Retry all failed uploads
|
|
153
|
+
|
|
154
|
+
#### `useFlowUpload(options?)`
|
|
155
|
+
|
|
156
|
+
Upload file through a flow pipeline.
|
|
157
|
+
|
|
158
|
+
**Returns:**
|
|
159
|
+
- `state` - Reactive flow upload state (readonly)
|
|
160
|
+
- Includes all `useUpload` state
|
|
161
|
+
- `jobId` - Flow job ID
|
|
162
|
+
- `flowStatus` - Flow status
|
|
163
|
+
- `flowResult` - Flow result
|
|
164
|
+
- `uploadFlow(file, flowOptions)` - Start flow upload
|
|
165
|
+
- `abort()` - Cancel flow upload
|
|
166
|
+
- `reset()` - Reset state
|
|
167
|
+
|
|
168
|
+
#### `useMultiFlowUpload(options?)`
|
|
169
|
+
|
|
170
|
+
Multiple flow uploads with aggregate tracking.
|
|
171
|
+
|
|
172
|
+
Similar to `useMultiUpload` but for flow uploads.
|
|
173
|
+
|
|
174
|
+
#### `useDragDrop(options?)`
|
|
175
|
+
|
|
176
|
+
Drag and drop file handling.
|
|
177
|
+
|
|
178
|
+
**Returns:**
|
|
179
|
+
- `isDragging` - Drag in progress (readonly)
|
|
180
|
+
- `isOver` - Dragging over drop zone (readonly)
|
|
181
|
+
- `files` - Dropped files (readonly)
|
|
182
|
+
- `onDragEnter` - Handler for drag enter event
|
|
183
|
+
- `onDragLeave` - Handler for drag leave event
|
|
184
|
+
- `onDragOver` - Handler for drag over event
|
|
185
|
+
- `onDrop` - Handler for drop event
|
|
186
|
+
- `clearFiles` - Clear dropped files
|
|
187
|
+
|
|
188
|
+
**Options:**
|
|
189
|
+
- `accept` - Accepted file types
|
|
190
|
+
- `maxSize` - Maximum file size in bytes
|
|
191
|
+
- `multiple` - Allow multiple files (default: true)
|
|
192
|
+
- `onFilesDropped` - Callback when files are dropped
|
|
193
|
+
|
|
194
|
+
#### `useFlow(flowId, options?)`
|
|
195
|
+
|
|
196
|
+
Execute a flow.
|
|
197
|
+
|
|
198
|
+
**Returns:**
|
|
199
|
+
- `state` - Flow execution state (readonly)
|
|
200
|
+
- `execute(input)` - Execute flow
|
|
201
|
+
- `cancel()` - Cancel flow execution
|
|
202
|
+
|
|
203
|
+
#### `useFlowClient()`
|
|
204
|
+
|
|
205
|
+
Access the flow client.
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
const flowClient = useFlowClient()
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### `useFlowWebSocket(jobId)`
|
|
212
|
+
|
|
213
|
+
Manage flow WebSocket connection.
|
|
214
|
+
|
|
215
|
+
**Returns:**
|
|
216
|
+
- `isConnected` - Connection status (readonly)
|
|
217
|
+
- `events` - Flow events stream (readonly)
|
|
218
|
+
- `connect()` - Connect to WebSocket
|
|
219
|
+
- `disconnect()` - Disconnect WebSocket
|
|
220
|
+
- `sendPing()` - Send ping message
|
|
221
|
+
|
|
222
|
+
#### `useUploadMetrics()`
|
|
223
|
+
|
|
224
|
+
Access upload performance metrics.
|
|
225
|
+
|
|
226
|
+
**Returns:**
|
|
227
|
+
- `metrics` - Upload metrics (readonly)
|
|
228
|
+
- Network speed, chunk timing, etc.
|
|
229
|
+
|
|
230
|
+
### Components
|
|
231
|
+
|
|
232
|
+
#### `<UploadZone>`
|
|
233
|
+
|
|
234
|
+
File input with drag and drop zone.
|
|
235
|
+
|
|
236
|
+
**Props:**
|
|
237
|
+
- `accept` - Accepted file types
|
|
238
|
+
- `multiple` - Allow multiple files
|
|
239
|
+
- `disabled` - Disable input
|
|
240
|
+
|
|
241
|
+
**Events:**
|
|
242
|
+
- `@file-select` - Emitted when files are selected
|
|
243
|
+
|
|
244
|
+
**Slots:**
|
|
245
|
+
- `default` - Custom drop zone content
|
|
246
|
+
|
|
247
|
+
#### `<UploadList>`
|
|
248
|
+
|
|
249
|
+
Display upload progress for multiple files.
|
|
250
|
+
|
|
251
|
+
**Props:**
|
|
252
|
+
- `uploads` - Array of upload items
|
|
253
|
+
|
|
254
|
+
**Slots:**
|
|
255
|
+
- `item` - Custom upload item template
|
|
256
|
+
|
|
257
|
+
#### `<FlowUploadZone>`
|
|
258
|
+
|
|
259
|
+
Upload zone with flow configuration.
|
|
260
|
+
|
|
261
|
+
**Props:**
|
|
262
|
+
- `flowId` - Flow ID
|
|
263
|
+
- `accept` - Accepted file types
|
|
264
|
+
- `multiple` - Allow multiple files
|
|
265
|
+
|
|
266
|
+
**Events:**
|
|
267
|
+
- `@upload-complete` - Emitted when upload completes
|
|
268
|
+
|
|
269
|
+
#### `<FlowUploadList>`
|
|
270
|
+
|
|
271
|
+
Display flow upload progress.
|
|
272
|
+
|
|
273
|
+
**Props:**
|
|
274
|
+
- `uploads` - Array of flow upload items
|
|
275
|
+
|
|
276
|
+
**Slots:**
|
|
277
|
+
- `item` - Custom upload item template
|
|
278
|
+
|
|
279
|
+
### Utilities
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
import {
|
|
283
|
+
formatFileSize,
|
|
284
|
+
formatProgress,
|
|
285
|
+
isImageFile,
|
|
286
|
+
isVideoFile,
|
|
287
|
+
createFileSizeValidator,
|
|
288
|
+
createFileTypeValidator,
|
|
289
|
+
composeValidators
|
|
290
|
+
} from '@uploadista/vue/utils'
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
See [framework-utils documentation](../../client/src/framework-utils.ts) for details.
|
|
294
|
+
|
|
295
|
+
## Examples
|
|
296
|
+
|
|
297
|
+
### Example: Multiple File Upload with Progress
|
|
298
|
+
|
|
299
|
+
```vue
|
|
300
|
+
<script setup lang="ts">
|
|
301
|
+
import { useMultiUpload } from '@uploadista/vue'
|
|
302
|
+
|
|
303
|
+
const { uploads, stats, add, clear, retryFailed } = useMultiUpload()
|
|
304
|
+
|
|
305
|
+
const handleFilesSelected = async (files: File[]) => {
|
|
306
|
+
await add(files)
|
|
307
|
+
}
|
|
308
|
+
</script>
|
|
309
|
+
|
|
310
|
+
<template>
|
|
311
|
+
<div>
|
|
312
|
+
<input
|
|
313
|
+
type="file"
|
|
314
|
+
multiple
|
|
315
|
+
@change="handleFilesSelected(($event.target as HTMLInputElement).files || [])"
|
|
316
|
+
/>
|
|
317
|
+
|
|
318
|
+
<div v-if="stats.totalFiles > 0">
|
|
319
|
+
<p>Progress: {{ stats.totalProgress.toFixed(0) }}%</p>
|
|
320
|
+
<p>
|
|
321
|
+
Uploaded: {{ stats.completedFiles }}/{{ stats.totalFiles }}
|
|
322
|
+
({{ (stats.uploadedBytes / 1024 / 1024).toFixed(2) }}MB / {{ (stats.totalBytes / 1024 / 1024).toFixed(2) }}MB)
|
|
323
|
+
</p>
|
|
324
|
+
|
|
325
|
+
<div v-for="upload of uploads" :key="upload.id" class="upload-item">
|
|
326
|
+
<span>{{ upload.filename }}</span>
|
|
327
|
+
<progress :value="upload.progress" max="100"></progress>
|
|
328
|
+
<span>{{ upload.status }}</span>
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
<button @click="clear" :disabled="!stats.allComplete">Clear All</button>
|
|
332
|
+
<button v-if="stats.hasErrors" @click="retryFailed">Retry Failed</button>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
</template>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Example: Flow-based Upload with Processing
|
|
339
|
+
|
|
340
|
+
```vue
|
|
341
|
+
<script setup lang="ts">
|
|
342
|
+
import { useFlowUpload } from '@uploadista/vue'
|
|
343
|
+
|
|
344
|
+
const { state, uploadFlow, abort, reset } = useFlowUpload()
|
|
345
|
+
|
|
346
|
+
const handleFlowUpload = async (file: File) => {
|
|
347
|
+
// Upload file through a flow pipeline (e.g., image resize, optimization)
|
|
348
|
+
await uploadFlow(file, {
|
|
349
|
+
flowId: 'image-processor',
|
|
350
|
+
onProgress: (event) => console.log('Processing:', event)
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
</script>
|
|
354
|
+
|
|
355
|
+
<template>
|
|
356
|
+
<div>
|
|
357
|
+
<input type="file" @change="(e) => handleFlowUpload((e.target as HTMLInputElement).files?.[0]!)" />
|
|
358
|
+
|
|
359
|
+
<div v-if="state.status === 'uploading'">
|
|
360
|
+
<p>Upload Progress: {{ state.progress.toFixed(0) }}%</p>
|
|
361
|
+
<p>Flow Status: {{ state.flowStatus }}</p>
|
|
362
|
+
<button @click="abort">Cancel</button>
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<div v-if="state.status === 'success'">
|
|
366
|
+
<p>Processing Complete!</p>
|
|
367
|
+
<p v-if="state.flowResult">Result: {{ JSON.stringify(state.flowResult) }}</p>
|
|
368
|
+
<button @click="reset">Upload Another</button>
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
</template>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Example: Drag and Drop Upload
|
|
375
|
+
|
|
376
|
+
```vue
|
|
377
|
+
<script setup lang="ts">
|
|
378
|
+
import { useUpload, useDragDrop } from '@uploadista/vue'
|
|
379
|
+
|
|
380
|
+
const { state, upload } = useUpload()
|
|
381
|
+
const { isDragging, isOver, onDragEnter, onDragLeave, onDragOver, onDrop } = useDragDrop({
|
|
382
|
+
accept: ['image/*', 'application/pdf'],
|
|
383
|
+
maxSize: 10 * 1024 * 1024, // 10MB
|
|
384
|
+
onFilesDropped: async (files) => {
|
|
385
|
+
if (files.length > 0) {
|
|
386
|
+
await upload(files[0])
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
</script>
|
|
391
|
+
|
|
392
|
+
<template>
|
|
393
|
+
<div
|
|
394
|
+
@dragenter="onDragEnter"
|
|
395
|
+
@dragleave="onDragLeave"
|
|
396
|
+
@dragover="onDragOver"
|
|
397
|
+
@drop="onDrop"
|
|
398
|
+
:class="{ dragging: isDragging, over: isOver }"
|
|
399
|
+
class="drop-zone"
|
|
400
|
+
>
|
|
401
|
+
<p v-if="!isDragging">Drag files here or click to select</p>
|
|
402
|
+
<p v-else>Drop files to upload</p>
|
|
403
|
+
|
|
404
|
+
<input type="file" hidden accept="image/*,application/pdf" />
|
|
405
|
+
|
|
406
|
+
<div v-if="state.status === 'uploading'">
|
|
407
|
+
<progress :value="state.progress" max="100"></progress>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
</template>
|
|
411
|
+
|
|
412
|
+
<style scoped>
|
|
413
|
+
.drop-zone {
|
|
414
|
+
border: 2px dashed #ccc;
|
|
415
|
+
padding: 2rem;
|
|
416
|
+
border-radius: 8px;
|
|
417
|
+
text-align: center;
|
|
418
|
+
cursor: pointer;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.drop-zone.dragging {
|
|
422
|
+
background-color: #f0f0f0;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.drop-zone.over {
|
|
426
|
+
border-color: #007bff;
|
|
427
|
+
background-color: #e7f3ff;
|
|
428
|
+
}
|
|
429
|
+
</style>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Example: Using `UploadZone` Component
|
|
433
|
+
|
|
434
|
+
```vue
|
|
435
|
+
<script setup lang="ts">
|
|
436
|
+
import { UploadZone, UploadList } from '@uploadista/vue'
|
|
437
|
+
import { useMultiUpload } from '@uploadista/vue'
|
|
438
|
+
|
|
439
|
+
const { uploads, add } = useMultiUpload()
|
|
440
|
+
|
|
441
|
+
const handleFileSelect = async (files: File[]) => {
|
|
442
|
+
await add(files)
|
|
443
|
+
}
|
|
444
|
+
</script>
|
|
445
|
+
|
|
446
|
+
<template>
|
|
447
|
+
<div>
|
|
448
|
+
<UploadZone
|
|
449
|
+
multiple
|
|
450
|
+
accept="image/*"
|
|
451
|
+
@file-select="handleFileSelect"
|
|
452
|
+
>
|
|
453
|
+
<div class="custom-drop-zone">
|
|
454
|
+
<p>Drop images here or click to browse</p>
|
|
455
|
+
</div>
|
|
456
|
+
</UploadZone>
|
|
457
|
+
|
|
458
|
+
<UploadList :uploads="uploads">
|
|
459
|
+
<template #item="{ upload }">
|
|
460
|
+
<div class="upload-item">
|
|
461
|
+
<span>{{ upload.filename }}</span>
|
|
462
|
+
<progress :value="upload.progress" max="100"></progress>
|
|
463
|
+
<span class="status">{{ upload.status }}</span>
|
|
464
|
+
</div>
|
|
465
|
+
</template>
|
|
466
|
+
</UploadList>
|
|
467
|
+
</div>
|
|
468
|
+
</template>
|
|
469
|
+
|
|
470
|
+
<style scoped>
|
|
471
|
+
.custom-drop-zone {
|
|
472
|
+
padding: 2rem;
|
|
473
|
+
border: 2px dashed #ccc;
|
|
474
|
+
border-radius: 8px;
|
|
475
|
+
text-align: center;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.upload-item {
|
|
479
|
+
display: flex;
|
|
480
|
+
align-items: center;
|
|
481
|
+
gap: 1rem;
|
|
482
|
+
padding: 1rem;
|
|
483
|
+
border-bottom: 1px solid #eee;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.status {
|
|
487
|
+
margin-left: auto;
|
|
488
|
+
font-size: 0.875rem;
|
|
489
|
+
color: #666;
|
|
490
|
+
}
|
|
491
|
+
</style>
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
See the [Vue example application](../../../../examples/vue-client/) for comprehensive usage examples:
|
|
495
|
+
|
|
496
|
+
- Basic single upload
|
|
497
|
+
- Multiple file uploads
|
|
498
|
+
- Flow-based processing
|
|
499
|
+
- Drag and drop
|
|
500
|
+
- Custom styling
|
|
501
|
+
- Error handling
|
|
502
|
+
- Retry logic
|
|
503
|
+
|
|
504
|
+
## TypeScript Support
|
|
505
|
+
|
|
506
|
+
This package includes full TypeScript types. No additional `@types` package is needed.
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
import type {
|
|
510
|
+
UploadState,
|
|
511
|
+
FlowUploadState,
|
|
512
|
+
UseUploadOptions,
|
|
513
|
+
UseFlowUploadOptions
|
|
514
|
+
} from '@uploadista/vue'
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## SSR Considerations
|
|
518
|
+
|
|
519
|
+
The Vue client works with Nuxt.js and other SSR frameworks. The client is initialized on the client side only:
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
// plugins/uploadista.client.ts (Nuxt)
|
|
523
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
524
|
+
const uploadista = createUploadistaPlugin({
|
|
525
|
+
serverUrl: useRuntimeConfig().public.uploadistaUrl,
|
|
526
|
+
auth: { type: 'no-auth' }
|
|
527
|
+
})
|
|
528
|
+
|
|
529
|
+
nuxtApp.vueApp.use(uploadista)
|
|
530
|
+
})
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
## Migration from React
|
|
534
|
+
|
|
535
|
+
If you're familiar with the React client, here's a quick mapping:
|
|
536
|
+
|
|
537
|
+
| React | Vue |
|
|
538
|
+
|-------|-----|
|
|
539
|
+
| `useState` | `ref` / `reactive` |
|
|
540
|
+
| `useEffect` | `watch` / `watchEffect` / `onMounted` / `onUnmounted` |
|
|
541
|
+
| `useCallback` | Not needed (functions are stable in Vue composables) |
|
|
542
|
+
| `useMemo` | `computed` |
|
|
543
|
+
| `useContext` | `provide` / `inject` |
|
|
544
|
+
| `<UploadistaProvider>` | `app.use(createUploadistaPlugin())` |
|
|
545
|
+
|
|
546
|
+
All hooks have equivalent composables with the same names (e.g., `useUpload`, `useMultiUpload`).
|
|
547
|
+
|
|
548
|
+
## Contributing
|
|
549
|
+
|
|
550
|
+
See the main [Uploadista documentation](../../../../README.md) for contribution guidelines.
|
|
551
|
+
|
|
552
|
+
## License
|
|
553
|
+
|
|
554
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@uploadista/vue",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.3",
|
|
5
|
+
"description": "Vue client for Uploadista",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Uploadista",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.ts",
|
|
10
|
+
"./composables/*": "./src/composables/*.ts",
|
|
11
|
+
"./components/*": "./src/components/*.vue",
|
|
12
|
+
"./providers/*": "./src/providers/*.vue",
|
|
13
|
+
"./utils/*": "./src/utils/*.ts"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"vue": "^3.3.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@uploadista/core": "0.0.3",
|
|
20
|
+
"@uploadista/client-browser": "0.0.3"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@vue/test-utils": "^2.4.6",
|
|
24
|
+
"vitest": "3.2.4",
|
|
25
|
+
"vue": "^3.5.0",
|
|
26
|
+
"@uploadista/typescript-config": "0.0.3"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"format": "biome format --write ./src",
|
|
30
|
+
"lint": "biome lint --write ./src",
|
|
31
|
+
"check": "biome check --write ./src",
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"test:run": "vitest run",
|
|
34
|
+
"test:watch": "vitest --watch"
|
|
35
|
+
}
|
|
36
|
+
}
|