@uploadista/react 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.
@@ -0,0 +1,89 @@
1
+
2
+ > @uploadista/react@ check /Users/denislaboureyras/Documents/uploadista/dev/uploadista/packages/uploadista/clients/react
3
+ > biome check --write ./src
4
+
5
+ src/hooks/use-upload-metrics.ts:5:21 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
6
+
7
+ ! Unexpected any. Specify a different type.
8
+
9
+ 4 │ // Types
10
+ > 5 │ type ChunkMetrics = any;
11
+ │ ^^^
12
+ 6 │ type PerformanceInsights = any;
13
+ 7 │ type UploadSessionMetrics = any;
14
+
15
+ i any disables many type checking rules. Its use should be avoided.
16
+
17
+
18
+ src/hooks/use-upload-metrics.ts:6:28 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
19
+
20
+ ! Unexpected any. Specify a different type.
21
+
22
+ 4 │ // Types
23
+ 5 │ type ChunkMetrics = any;
24
+ > 6 │ type PerformanceInsights = any;
25
+ │ ^^^
26
+ 7 │ type UploadSessionMetrics = any;
27
+ 8 │ type Timeout = ReturnType<typeof setTimeout>;
28
+
29
+ i any disables many type checking rules. Its use should be avoided.
30
+
31
+
32
+ src/hooks/use-upload-metrics.ts:7:29 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
33
+
34
+ ! Unexpected any. Specify a different type.
35
+
36
+ 5 │ type ChunkMetrics = any;
37
+ 6 │ type PerformanceInsights = any;
38
+ > 7 │ type UploadSessionMetrics = any;
39
+ │ ^^^
40
+ 8 │ type Timeout = ReturnType<typeof setTimeout>;
41
+ 9 │
42
+
43
+ i any disables many type checking rules. Its use should be avoided.
44
+
45
+
46
+ src/hooks/use-upload.ts:9:28 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
+
48
+ ! Unexpected any. Specify a different type.
49
+
50
+ 7 │ // Re-export types for convenience
51
+ 8 │ export type UploadInput = File | Blob;
52
+ > 9 │ export type ChunkMetrics = any;
53
+ │ ^^^
54
+ 10 │ export type PerformanceInsights = any;
55
+ 11 │ export type UploadSessionMetrics = any;
56
+
57
+ i any disables many type checking rules. Its use should be avoided.
58
+
59
+
60
+ src/hooks/use-upload.ts:10:35 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
61
+
62
+ ! Unexpected any. Specify a different type.
63
+
64
+ 8 │ export type UploadInput = File | Blob;
65
+ 9 │ export type ChunkMetrics = any;
66
+ > 10 │ export type PerformanceInsights = any;
67
+ │ ^^^
68
+ 11 │ export type UploadSessionMetrics = any;
69
+ 12 │
70
+
71
+ i any disables many type checking rules. Its use should be avoided.
72
+
73
+
74
+ src/hooks/use-upload.ts:11:36 lint/suspicious/noExplicitAny ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
75
+
76
+ ! Unexpected any. Specify a different type.
77
+
78
+ 9 │ export type ChunkMetrics = any;
79
+ 10 │ export type PerformanceInsights = any;
80
+ > 11 │ export type UploadSessionMetrics = any;
81
+ │ ^^^
82
+ 12 │
83
+ 13 │ export type UploadStatus =
84
+
85
+ i any disables many type checking rules. Its use should be avoided.
86
+ Checked 15 files in 38ms. Fixed 2 files.
87
+ Found 6 warnings.
88
+
89
+
package/FLOW_UPLOAD.md ADDED
@@ -0,0 +1,307 @@
1
+ # Flow Upload - React Hooks & Components
2
+
3
+ The Flow Upload feature allows you to upload files through Uploadista flows, enabling post-processing like image optimization, video transcoding, and automatic storage.
4
+
5
+ ## Overview
6
+
7
+ Flow uploads combine the robustness of direct upload with the flexibility of flow-based processing:
8
+
9
+ 1. **Init**: Client starts flow → streaming-input-node creates upload → flow pauses
10
+ 2. **Upload**: Client uploads chunks **directly** to upload API (efficient, full-featured)
11
+ 3. **Finalize**: Client notifies flow → flow resumes → processes file through remaining nodes
12
+
13
+ ## Hooks
14
+
15
+ ### `useFlowUpload`
16
+
17
+ Basic hook for uploading a single file through a flow.
18
+
19
+ ```tsx
20
+ import { useUploadClient, useFlowUpload } from "@uploadista/react";
21
+
22
+ function MyUploadComponent() {
23
+ const client = useUploadClient({
24
+ baseUrl: "http://localhost:4200",
25
+ storageId: "my-storage",
26
+ chunkSize: 5 * 1024 * 1024,
27
+ });
28
+
29
+ const flowUpload = useFlowUpload(client, {
30
+ flowConfig: {
31
+ flowId: "image-optimization-flow",
32
+ storageId: "my-storage",
33
+ },
34
+ onSuccess: (result) => {
35
+ console.log("Upload complete:", result);
36
+ },
37
+ });
38
+
39
+ return (
40
+ <div>
41
+ <input
42
+ type="file"
43
+ onChange={(e) => {
44
+ const file = e.target.files?.[0];
45
+ if (file) flowUpload.upload(file);
46
+ }}
47
+ />
48
+ {flowUpload.isUploading && (
49
+ <progress value={flowUpload.state.progress} max={100} />
50
+ )}
51
+ </div>
52
+ );
53
+ }
54
+ ```
55
+
56
+ ### `useMultiFlowUpload`
57
+
58
+ Hook for uploading multiple files through a flow with concurrent upload control.
59
+
60
+ ```tsx
61
+ import { useUploadClient, useMultiFlowUpload } from "@uploadista/react";
62
+
63
+ function BatchUploadComponent() {
64
+ const client = useUploadClient({
65
+ baseUrl: "http://localhost:4200",
66
+ storageId: "my-storage",
67
+ chunkSize: 5 * 1024 * 1024,
68
+ });
69
+
70
+ const multiUpload = useMultiFlowUpload(client, {
71
+ flowConfig: {
72
+ flowId: "batch-image-optimization",
73
+ storageId: "my-storage",
74
+ },
75
+ maxConcurrent: 3,
76
+ onComplete: (items) => {
77
+ console.log("All uploads complete:", items);
78
+ },
79
+ });
80
+
81
+ return (
82
+ <div>
83
+ <input
84
+ type="file"
85
+ multiple
86
+ onChange={(e) => {
87
+ if (e.target.files) {
88
+ multiUpload.addFiles(e.target.files);
89
+ multiUpload.startUpload();
90
+ }
91
+ }}
92
+ />
93
+ {multiUpload.state.items.map((item) => (
94
+ <div key={item.id}>
95
+ {item.file.name} - {item.progress}%
96
+ </div>
97
+ ))}
98
+ </div>
99
+ );
100
+ }
101
+ ```
102
+
103
+ ## Components
104
+
105
+ ### `FlowUploadZone`
106
+
107
+ Render-props component for creating custom drag-and-drop upload zones.
108
+
109
+ ```tsx
110
+ import { FlowUploadZone } from "@uploadista/react";
111
+
112
+ function CustomUploadZone() {
113
+ return (
114
+ <FlowUploadZone
115
+ client={client}
116
+ flowConfig={{
117
+ flowId: "my-flow",
118
+ storageId: "my-storage",
119
+ }}
120
+ accept="image/*"
121
+ >
122
+ {({ isDragging, isUploading, state, getRootProps, getInputProps }) => (
123
+ <div {...getRootProps()}>
124
+ <input {...getInputProps()} />
125
+ {isDragging && <p>Drop files here...</p>}
126
+ {isUploading && <progress value={state.progress} max={100} />}
127
+ </div>
128
+ )}
129
+ </FlowUploadZone>
130
+ );
131
+ }
132
+ ```
133
+
134
+ ### `SimpleFlowUploadZone`
135
+
136
+ Pre-styled upload zone component for quick implementation.
137
+
138
+ ```tsx
139
+ import { SimpleFlowUploadZone } from "@uploadista/react";
140
+
141
+ function QuickUploadZone() {
142
+ return (
143
+ <SimpleFlowUploadZone
144
+ client={client}
145
+ flowConfig={{
146
+ flowId: "my-flow",
147
+ storageId: "my-storage",
148
+ }}
149
+ accept="image/*"
150
+ dragText="Drop your images here"
151
+ idleText="Drag & drop images or click to browse"
152
+ options={{
153
+ onSuccess: (result) => console.log("Uploaded:", result),
154
+ }}
155
+ />
156
+ );
157
+ }
158
+ ```
159
+
160
+ ### `FlowUploadList`
161
+
162
+ Render-props component for managing multiple file uploads.
163
+
164
+ ```tsx
165
+ import { FlowUploadList } from "@uploadista/react";
166
+
167
+ function CustomUploadList() {
168
+ return (
169
+ <FlowUploadList
170
+ client={client}
171
+ flowConfig={{
172
+ flowId: "batch-flow",
173
+ storageId: "my-storage",
174
+ }}
175
+ options={{ maxConcurrent: 3 }}
176
+ >
177
+ {({ items, addFiles, startUpload, abortUpload, retryUpload }) => (
178
+ <div>
179
+ <input
180
+ type="file"
181
+ multiple
182
+ onChange={(e) => {
183
+ if (e.target.files) {
184
+ addFiles(e.target.files);
185
+ startUpload();
186
+ }
187
+ }}
188
+ />
189
+ {items.map((item) => (
190
+ <div key={item.id}>
191
+ {item.file.name}
192
+ <progress value={item.progress} max={100} />
193
+ {item.status === "error" && (
194
+ <button onClick={() => retryUpload(item.id)}>Retry</button>
195
+ )}
196
+ </div>
197
+ ))}
198
+ </div>
199
+ )}
200
+ </FlowUploadList>
201
+ );
202
+ }
203
+ ```
204
+
205
+ ### `SimpleFlowUploadList`
206
+
207
+ Pre-styled upload list component with built-in file input.
208
+
209
+ ```tsx
210
+ import { SimpleFlowUploadList } from "@uploadista/react";
211
+
212
+ function QuickUploadList() {
213
+ return (
214
+ <SimpleFlowUploadList
215
+ client={client}
216
+ flowConfig={{
217
+ flowId: "batch-flow",
218
+ storageId: "my-storage",
219
+ }}
220
+ options={{
221
+ maxConcurrent: 3,
222
+ onComplete: (items) => alert(`${items.length} files uploaded!`),
223
+ }}
224
+ accept="image/*"
225
+ />
226
+ );
227
+ }
228
+ ```
229
+
230
+ ## Server-Side Flow Setup
231
+
232
+ Your server needs to define flows with a streaming-input-node:
233
+
234
+ ```typescript
235
+ // Server-side flow definition
236
+ import { createFlow } from "@uploadista/core/flow";
237
+ import { createInputNode } from "@uploadista/core/flow/nodes/input-node";
238
+ import { createImageOptimizeNode } from "@uploadista/core/flow/image-nodes/image-optimize-node";
239
+ import { createOutputNode } from "@uploadista/core/flow/output-nodes/output-node";
240
+
241
+ const imageOptimizationFlow = createFlow({
242
+ flowId: "image-optimization-flow",
243
+ name: "Image Upload & Optimization",
244
+ nodes: [
245
+ createInputNode("upload-node"),
246
+ createImageOptimizeNode("optimize-node", {
247
+ quality: 80,
248
+ format: "webp",
249
+ }),
250
+ createOutputNode("save-node", {
251
+ storageId: "my-storage",
252
+ }),
253
+ ],
254
+ edges: [
255
+ { source: "upload-node", target: "optimize-node" },
256
+ { source: "optimize-node", target: "save-node" },
257
+ ],
258
+ });
259
+ ```
260
+
261
+ ## Benefits
262
+
263
+ ✅ **Efficient**: Chunks upload directly via upload API (not wrapped in flow messages)
264
+ ✅ **Full-featured**: Supports all upload features (smart chunking, retry, metrics, parallel)
265
+ ✅ **Flow-integrated**: Flow orchestrates and can post-process files
266
+ ✅ **Clean separation**: Upload logic in upload layer, flow handles orchestration
267
+ ✅ **React-friendly**: Hooks and components follow React best practices
268
+
269
+ ## Migration from Regular Upload
270
+
271
+ If you're currently using `useUpload` and want to add flow-based processing:
272
+
273
+ **Before (direct upload):**
274
+ ```tsx
275
+ const upload = useUpload(client, {
276
+ onSuccess: (result) => {
277
+ // Manual post-processing needed
278
+ fetch('/api/optimize', { body: result.id });
279
+ },
280
+ });
281
+ ```
282
+
283
+ **After (flow upload):**
284
+ ```tsx
285
+ const flowUpload = useFlowUpload(client, {
286
+ flowConfig: {
287
+ flowId: "auto-optimize-flow", // Flow handles optimization automatically
288
+ storageId: "my-storage",
289
+ },
290
+ onSuccess: (result) => {
291
+ // File is already optimized by the flow!
292
+ },
293
+ });
294
+ ```
295
+
296
+ ## TypeScript Support
297
+
298
+ All hooks and components are fully typed:
299
+
300
+ ```typescript
301
+ import type {
302
+ FlowUploadState,
303
+ FlowUploadItem,
304
+ UseFlowUploadOptions,
305
+ FlowUploadZoneRenderProps,
306
+ } from "@uploadista/react";
307
+ ```
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 uploadista
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.