@uploadista/react 0.0.20-beta.2 → 0.0.20-beta.4

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 (37) hide show
  1. package/dist/components/index.d.mts +3 -3
  2. package/dist/components/index.mjs +1 -1
  3. package/dist/flow-upload-list-D6j8JSP8.mjs +2 -0
  4. package/dist/flow-upload-list-D6j8JSP8.mjs.map +1 -0
  5. package/dist/hooks/index.d.mts +3 -3
  6. package/dist/hooks/index.mjs +1 -1
  7. package/dist/index.d.mts +6 -6
  8. package/dist/index.mjs +1 -1
  9. package/dist/{uploadista-provider-D-N-eL2l.d.mts → uploadista-provider-Cb13AK7Z.d.mts} +515 -318
  10. package/dist/uploadista-provider-Cb13AK7Z.d.mts.map +1 -0
  11. package/dist/use-upload-BvvGROMR.mjs +2 -0
  12. package/dist/use-upload-BvvGROMR.mjs.map +1 -0
  13. package/dist/{use-uploadista-client-m9nF-irM.d.mts → use-uploadista-client-CkzVVmFT.d.mts} +121 -286
  14. package/dist/use-uploadista-client-CkzVVmFT.d.mts.map +1 -0
  15. package/dist/use-uploadista-events-BwUD-2Ck.mjs +2 -0
  16. package/dist/use-uploadista-events-BwUD-2Ck.mjs.map +1 -0
  17. package/dist/{use-upload-metrics-DhzS4lhG.d.mts → use-uploadista-events-CtDXJYrR.d.mts} +169 -371
  18. package/dist/use-uploadista-events-CtDXJYrR.d.mts.map +1 -0
  19. package/package.json +6 -6
  20. package/src/components/flow-primitives.tsx +843 -0
  21. package/src/components/index.tsx +31 -13
  22. package/src/hooks/index.ts +25 -37
  23. package/src/hooks/use-drag-drop.ts +1 -0
  24. package/src/index.ts +90 -81
  25. package/dist/upload-zone-BjWHuP7p.mjs +0 -6
  26. package/dist/upload-zone-BjWHuP7p.mjs.map +0 -1
  27. package/dist/uploadista-provider-D-N-eL2l.d.mts.map +0 -1
  28. package/dist/use-upload-BDHVhQsI.mjs +0 -2
  29. package/dist/use-upload-BDHVhQsI.mjs.map +0 -1
  30. package/dist/use-upload-metrics-Df90wIos.mjs +0 -2
  31. package/dist/use-upload-metrics-Df90wIos.mjs.map +0 -1
  32. package/dist/use-upload-metrics-DhzS4lhG.d.mts.map +0 -1
  33. package/dist/use-uploadista-client-m9nF-irM.d.mts.map +0 -1
  34. package/src/components/flow-input.tsx +0 -299
  35. package/src/components/flow-upload-zone.tsx +0 -441
  36. package/src/hooks/use-flow-execution.ts +0 -502
  37. package/src/hooks/use-flow-upload.ts +0 -299
@@ -1,299 +0,0 @@
1
- import type { FlowUploadOptions } from "@uploadista/client-browser";
2
- import type {
3
- FlowManager,
4
- FlowUploadState,
5
- FlowUploadStatus,
6
- } from "@uploadista/client-core";
7
- import type { TypedOutput } from "@uploadista/core/flow";
8
- import { useCallback, useEffect, useRef, useState } from "react";
9
- import { useFlowManagerContext } from "../contexts/flow-manager-context";
10
-
11
- // Re-export types from core for convenience
12
- export type { FlowUploadState, FlowUploadStatus };
13
-
14
- /**
15
- * Return value from the useFlowUpload hook with upload control methods and state.
16
- *
17
- * @property state - Complete flow upload state with progress and outputs
18
- * @property upload - Function to initiate file upload through the flow
19
- * @property abort - Cancel the current upload and flow execution
20
- * @property pause - Pause the current upload
21
- * @property reset - Reset state to idle (clears all data)
22
- * @property isUploading - True when upload or processing is active
23
- * @property isUploadingFile - True only during file upload phase
24
- * @property isProcessing - True only during flow processing phase
25
- */
26
- export interface UseFlowUploadReturn {
27
- /**
28
- * Current upload state
29
- */
30
- state: FlowUploadState;
31
-
32
- /**
33
- * Upload a file through the flow
34
- */
35
- upload: (file: File | Blob) => Promise<void>;
36
-
37
- /**
38
- * Abort the current upload
39
- */
40
- abort: () => void;
41
-
42
- /**
43
- * Pause the current upload
44
- */
45
- pause: () => void;
46
-
47
- /**
48
- * Reset the upload state
49
- */
50
- reset: () => void;
51
-
52
- /**
53
- * Whether an upload or flow execution is in progress (uploading OR processing)
54
- */
55
- isUploading: boolean;
56
-
57
- /**
58
- * Whether the file is currently being uploaded (chunks being sent)
59
- */
60
- isUploadingFile: boolean;
61
-
62
- /**
63
- * Whether the flow is currently processing (after upload completes)
64
- */
65
- isProcessing: boolean;
66
- }
67
-
68
- const initialState: FlowUploadState = {
69
- status: "idle",
70
- progress: 0,
71
- bytesUploaded: 0,
72
- totalBytes: null,
73
- error: null,
74
- jobId: null,
75
- flowStarted: false,
76
- currentNodeName: null,
77
- currentNodeType: null,
78
- flowOutputs: null,
79
- };
80
-
81
- /**
82
- * React hook for uploading files through a flow with automatic flow execution.
83
- * Handles both the file upload phase and the flow processing phase, providing
84
- * real-time progress updates and flow node execution tracking.
85
- *
86
- * This is a convenience wrapper around the generic useFlowExecution hook,
87
- * specialized for the common case of file uploads. For more flexible input types
88
- * (URLs, structured data), use useFlowExecution directly with an inputBuilder.
89
- *
90
- * The flow engine processes the uploaded file through a DAG of nodes, which can
91
- * perform operations like image optimization, storage saving, webhooks, etc.
92
- *
93
- * Must be used within FlowManagerProvider (which must be within UploadistaProvider).
94
- * Flow events are automatically routed by the provider to the appropriate manager.
95
- *
96
- * @param options - Flow upload configuration including flow ID and event handlers
97
- * @returns Flow upload state and control methods
98
- *
99
- * @remarks
100
- * **Future refactoring**: This hook could be implemented as a thin wrapper around
101
- * useFlowExecution with a file-specific inputBuilder:
102
- * ```typescript
103
- * return useFlowExecution<File | Blob>({
104
- * ...options,
105
- * inputBuilder: async (file) => {
106
- * const { inputNodes } = await client.findInputNode(options.flowConfig.flowId);
107
- * return {
108
- * [inputNodes[0].id]: {
109
- * operation: "init",
110
- * storageId: options.flowConfig.storageId,
111
- * metadata: { originalName: file.name, mimeType: file.type, size: file.size }
112
- * }
113
- * };
114
- * }
115
- * });
116
- * ```
117
- *
118
- * @example
119
- * ```tsx
120
- * // Basic flow upload with progress tracking
121
- * function ImageUploader() {
122
- * const flowUpload = useFlowUpload({
123
- * flowConfig: {
124
- * flowId: "image-optimization-flow",
125
- * storageId: "s3-images",
126
- * },
127
- * onSuccess: (outputs) => {
128
- * console.log("Flow outputs:", outputs);
129
- * // Access all outputs from the flow
130
- * for (const output of outputs) {
131
- * console.log(`${output.nodeId}:`, output.data);
132
- * }
133
- * },
134
- * onFlowComplete: (outputs) => {
135
- * console.log("All flow outputs:", outputs);
136
- * },
137
- * onError: (error) => {
138
- * console.error("Upload or processing failed:", error);
139
- * },
140
- * });
141
- *
142
- * return (
143
- * <div>
144
- * <input
145
- * type="file"
146
- * accept="image/*"
147
- * onChange={(e) => {
148
- * const file = e.target.files?.[0];
149
- * if (file) flowUpload.upload(file);
150
- * }}
151
- * />
152
- *
153
- * {flowUpload.isUploadingFile && (
154
- * <div>Uploading... {flowUpload.state.progress}%</div>
155
- * )}
156
- *
157
- * {flowUpload.isProcessing && (
158
- * <div>
159
- * Processing...
160
- * {flowUpload.state.currentNodeName && (
161
- * <span>Current step: {flowUpload.state.currentNodeName}</span>
162
- * )}
163
- * </div>
164
- * )}
165
- *
166
- * {flowUpload.state.status === "success" && (
167
- * <div>
168
- * <p>Upload complete!</p>
169
- * {flowUpload.state.flowOutputs && (
170
- * <div>
171
- * {flowUpload.state.flowOutputs.map((output) => (
172
- * <div key={output.nodeId}>{output.nodeId}: {JSON.stringify(output.data)}</div>
173
- * ))}
174
- * </div>
175
- * )}
176
- * </div>
177
- * )}
178
- *
179
- * {flowUpload.state.status === "error" && (
180
- * <div>
181
- * <p>Error: {flowUpload.state.error?.message}</p>
182
- * <button onClick={flowUpload.reset}>Try Again</button>
183
- * </div>
184
- * )}
185
- *
186
- * {flowUpload.isUploading && (
187
- * <button onClick={flowUpload.abort}>Cancel</button>
188
- * )}
189
- * </div>
190
- * );
191
- * }
192
- * ```
193
- *
194
- * @see {@link useMultiFlowUpload} for uploading multiple files through a flow
195
- * @see {@link useUpload} for simple uploads without flow processing
196
- */
197
- export function useFlowUpload(options: FlowUploadOptions): UseFlowUploadReturn {
198
- const { getManager, releaseManager } = useFlowManagerContext();
199
- const [state, setState] = useState<FlowUploadState>(initialState);
200
- const managerRef = useRef<FlowManager<unknown> | null>(null);
201
-
202
- // Store callbacks in refs so they can be updated without recreating the manager
203
- const callbacksRef = useRef(options);
204
-
205
- // Update refs on every render to capture latest callbacks
206
- useEffect(() => {
207
- callbacksRef.current = options;
208
- });
209
-
210
- // Get or create manager from context when component mounts
211
- // Manager lifecycle is now handled by FlowManagerProvider
212
- useEffect(() => {
213
- const flowId = options.flowConfig.flowId;
214
-
215
- // Create stable callback wrappers that call the latest callbacks via refs
216
- const stableCallbacks = {
217
- onStateChange: setState,
218
- onProgress: (
219
- uploadId: string,
220
- bytesUploaded: number,
221
- totalBytes: number | null,
222
- ) => {
223
- callbacksRef.current.onProgress?.(uploadId, bytesUploaded, totalBytes);
224
- },
225
- onChunkComplete: (
226
- chunkSize: number,
227
- bytesAccepted: number,
228
- bytesTotal: number | null,
229
- ) => {
230
- callbacksRef.current.onChunkComplete?.(
231
- chunkSize,
232
- bytesAccepted,
233
- bytesTotal,
234
- );
235
- },
236
- onFlowComplete: (outputs: TypedOutput[]) => {
237
- callbacksRef.current.onFlowComplete?.(outputs);
238
- },
239
- onSuccess: (outputs: TypedOutput[]) => {
240
- callbacksRef.current.onSuccess?.(outputs);
241
- },
242
- onError: (error: Error) => {
243
- callbacksRef.current.onError?.(error);
244
- },
245
- onAbort: () => {
246
- callbacksRef.current.onAbort?.();
247
- },
248
- };
249
-
250
- // Get manager from context (creates if doesn't exist, increments ref count)
251
- managerRef.current = getManager(flowId, stableCallbacks, options);
252
-
253
- // Release manager when component unmounts or flowId changes
254
- return () => {
255
- releaseManager(flowId);
256
- managerRef.current = null;
257
- };
258
- }, [
259
- options.flowConfig.flowId,
260
- options.flowConfig.storageId,
261
- options.flowConfig.outputNodeId,
262
- getManager,
263
- releaseManager,
264
- ]);
265
-
266
- // Wrap manager methods with useCallback
267
- const upload = useCallback(async (file: File | Blob) => {
268
- await managerRef.current?.upload(file);
269
- }, []);
270
-
271
- const abort = useCallback(() => {
272
- managerRef.current?.abort();
273
- }, []);
274
-
275
- const pause = useCallback(() => {
276
- managerRef.current?.pause();
277
- }, []);
278
-
279
- const reset = useCallback(() => {
280
- managerRef.current?.reset();
281
- }, []);
282
-
283
- // Derive computed values from state (reactive to state changes)
284
- const isUploading =
285
- state.status === "uploading" || state.status === "processing";
286
- const isUploadingFile = state.status === "uploading";
287
- const isProcessing = state.status === "processing";
288
-
289
- return {
290
- state,
291
- upload,
292
- abort,
293
- pause,
294
- reset,
295
- isUploading,
296
- isUploadingFile,
297
- isProcessing,
298
- };
299
- }