@uploadista/react 0.0.20-beta.1 → 0.0.20-beta.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.
Files changed (36) 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-SbpCaxRq.mjs +2 -0
  4. package/dist/flow-upload-list-SbpCaxRq.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-CM48PPSp.d.mts → uploadista-provider-C1l0iBc9.d.mts} +503 -309
  10. package/dist/uploadista-provider-C1l0iBc9.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-DHbLSpIb.d.mts} +120 -286
  14. package/dist/use-uploadista-client-DHbLSpIb.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 +839 -0
  21. package/src/components/index.tsx +31 -13
  22. package/src/hooks/index.ts +25 -37
  23. package/src/index.ts +90 -81
  24. package/dist/upload-zone-BjWHuP7p.mjs +0 -6
  25. package/dist/upload-zone-BjWHuP7p.mjs.map +0 -1
  26. package/dist/uploadista-provider-CM48PPSp.d.mts.map +0 -1
  27. package/dist/use-upload-BDHVhQsI.mjs +0 -2
  28. package/dist/use-upload-BDHVhQsI.mjs.map +0 -1
  29. package/dist/use-upload-metrics-Df90wIos.mjs +0 -2
  30. package/dist/use-upload-metrics-Df90wIos.mjs.map +0 -1
  31. package/dist/use-upload-metrics-DhzS4lhG.d.mts.map +0 -1
  32. package/dist/use-uploadista-client-m9nF-irM.d.mts.map +0 -1
  33. package/src/components/flow-input.tsx +0 -299
  34. package/src/components/flow-upload-zone.tsx +0 -441
  35. package/src/hooks/use-flow-execution.ts +0 -502
  36. package/src/hooks/use-flow-upload.ts +0 -299
@@ -1,299 +0,0 @@
1
- /** biome-ignore-all lint/a11y/useSemanticElements: button is inside a div*/
2
- "use client";
3
-
4
- import { useDragDrop } from "../hooks/use-drag-drop";
5
- import type { FlowInputMetadata } from "../hooks/use-flow";
6
-
7
- export interface FlowInputProps {
8
- /** Input metadata from flow discovery */
9
- input: FlowInputMetadata;
10
- /** Accepted file types (e.g., "image/*", "video/*") */
11
- accept?: string;
12
- /** Whether the input should support URL input */
13
- allowUrl?: boolean;
14
- /** Current value (File or URL string) */
15
- value?: File | string | null;
16
- /** Callback when value changes */
17
- onChange: (value: File | string) => void;
18
- /** Whether the input is disabled */
19
- disabled?: boolean;
20
- /** Additional CSS classes */
21
- className?: string;
22
- }
23
-
24
- /**
25
- * Input component for flow execution with file drag-and-drop and URL support.
26
- *
27
- * Features:
28
- * - File drag-and-drop with visual feedback
29
- * - URL input for remote files
30
- * - Displays node name and description
31
- * - Shows selected file/URL with size
32
- * - Type validation and error display
33
- *
34
- * @example
35
- * ```tsx
36
- * <FlowInput
37
- * input={inputMetadata}
38
- * accept="image/*"
39
- * allowUrl={true}
40
- * value={selectedValue}
41
- * onChange={(value) => flow.setInput(inputMetadata.nodeId, value)}
42
- * />
43
- * ```
44
- */
45
- export function FlowInput({
46
- input,
47
- accept = "*",
48
- allowUrl = true,
49
- value,
50
- onChange,
51
- disabled = false,
52
- className = "",
53
- }: FlowInputProps) {
54
- const isFileValue = value instanceof File;
55
- const isUrlValue = typeof value === "string" && value.length > 0;
56
-
57
- // Determine input mode based on input type
58
- const supportsFileUpload = input.inputTypeId === "streaming-input-v1";
59
- const supportsUrl =
60
- allowUrl &&
61
- (input.inputTypeId === "url-input-v1" ||
62
- input.inputTypeId === "streaming-input-v1");
63
-
64
- const dragDrop = useDragDrop({
65
- onFilesReceived: (files) => {
66
- if (files[0]) {
67
- onChange(files[0]);
68
- }
69
- },
70
- accept: accept ? accept.split(",").map((type) => type.trim()) : undefined,
71
- multiple: false,
72
- });
73
-
74
- const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
75
- const file = e.target.files?.[0];
76
- if (file) {
77
- onChange(file);
78
- }
79
- };
80
-
81
- const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {
82
- onChange(e.target.value);
83
- };
84
-
85
- const handleClear = () => {
86
- onChange("");
87
- };
88
-
89
- return (
90
- <div className={`space-y-3 ${className}`}>
91
- {/* Header */}
92
- <div>
93
- <div className="flex items-center gap-2 mb-1">
94
- <h4 className="font-semibold text-gray-900">{input.nodeName}</h4>
95
- {input.required && <span className="text-red-500 text-sm">*</span>}
96
- <span className="text-xs px-2 py-1 rounded-full bg-blue-100 text-blue-700 font-medium">
97
- {input.inputTypeId}
98
- </span>
99
- </div>
100
- {input.nodeDescription && (
101
- <p className="text-sm text-gray-600">{input.nodeDescription}</p>
102
- )}
103
- </div>
104
-
105
- {/* File Upload Area */}
106
- {supportsFileUpload && (
107
- <div
108
- role="button"
109
- tabIndex={disabled ? -1 : 0}
110
- {...dragDrop.dragHandlers}
111
- onClick={() => !disabled && dragDrop.openFilePicker()}
112
- onKeyDown={(e) => {
113
- if ((e.key === "Enter" || e.key === " ") && !disabled) {
114
- e.preventDefault();
115
- dragDrop.openFilePicker();
116
- }
117
- }}
118
- className={`
119
- relative border-2 border-dashed rounded-xl p-6 text-center cursor-pointer transition-all
120
- ${
121
- dragDrop.state.isDragging
122
- ? "border-indigo-500 bg-indigo-50"
123
- : "border-gray-300 bg-gray-50 hover:border-indigo-400 hover:bg-indigo-50/50"
124
- }
125
- ${disabled ? "opacity-50 cursor-not-allowed" : ""}
126
- `}
127
- >
128
- {dragDrop.state.isDragging ? (
129
- <div className="flex flex-col items-center gap-2">
130
- <svg
131
- className="w-8 h-8 text-indigo-600"
132
- fill="none"
133
- viewBox="0 0 24 24"
134
- stroke="currentColor"
135
- >
136
- <title>Drop file</title>
137
- <path
138
- strokeLinecap="round"
139
- strokeLinejoin="round"
140
- strokeWidth={2}
141
- d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
142
- />
143
- </svg>
144
- <p className="text-sm font-medium text-indigo-600">
145
- Drop file here
146
- </p>
147
- </div>
148
- ) : isFileValue ? (
149
- <div className="flex items-center justify-between">
150
- <div className="flex items-center gap-3">
151
- <svg
152
- className="w-5 h-5 text-green-500"
153
- fill="currentColor"
154
- viewBox="0 0 20 20"
155
- aria-hidden="true"
156
- >
157
- <path
158
- fillRule="evenodd"
159
- d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
160
- clipRule="evenodd"
161
- />
162
- </svg>
163
- <div className="text-left">
164
- <p className="text-sm font-medium text-gray-900">
165
- {value.name}
166
- </p>
167
- <p className="text-xs text-gray-500">
168
- {(value.size / 1024).toFixed(1)} KB
169
- </p>
170
- </div>
171
- </div>
172
- <button
173
- type="button"
174
- onClick={(e) => {
175
- e.stopPropagation();
176
- handleClear();
177
- }}
178
- className="px-3 py-1 text-sm text-red-600 hover:text-red-700 hover:bg-red-50 rounded-lg transition-colors"
179
- >
180
- Remove
181
- </button>
182
- </div>
183
- ) : (
184
- <div className="flex flex-col items-center gap-2">
185
- <svg
186
- className="w-8 h-8 text-gray-400"
187
- fill="none"
188
- viewBox="0 0 24 24"
189
- stroke="currentColor"
190
- >
191
- <title>Upload file</title>
192
- <path
193
- strokeLinecap="round"
194
- strokeLinejoin="round"
195
- strokeWidth={2}
196
- d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
197
- />
198
- </svg>
199
- <div>
200
- <p className="text-sm font-medium text-gray-700">
201
- Drag and drop a file here, or click to select
202
- </p>
203
- <p className="text-xs text-gray-500 mt-1">Accepted: {accept}</p>
204
- </div>
205
- </div>
206
- )}
207
- <input {...dragDrop.inputProps} />
208
- </div>
209
- )}
210
-
211
- {/* Drag & Drop Errors */}
212
- {dragDrop.state.errors.length > 0 && (
213
- <div className="bg-red-50 border border-red-200 rounded-lg p-3">
214
- {dragDrop.state.errors.map((error, index) => (
215
- <p key={index} className="text-sm text-red-700">
216
- {error}
217
- </p>
218
- ))}
219
- </div>
220
- )}
221
-
222
- {/* URL Input */}
223
- {supportsUrl && supportsFileUpload && (
224
- <div className="flex items-center gap-3">
225
- <div className="flex-1 border-t border-gray-300" />
226
- <span className="text-xs font-medium text-gray-500 uppercase">
227
- Or
228
- </span>
229
- <div className="flex-1 border-t border-gray-300" />
230
- </div>
231
- )}
232
-
233
- {supportsUrl && (
234
- <div className="space-y-2">
235
- {!supportsFileUpload && (
236
- <label
237
- htmlFor={`url-${input.nodeId}`}
238
- className="block text-sm font-medium text-gray-700"
239
- >
240
- URL
241
- </label>
242
- )}
243
- <div className="relative">
244
- <input
245
- id={`url-${input.nodeId}`}
246
- type="url"
247
- value={isUrlValue ? value : ""}
248
- onChange={handleUrlChange}
249
- disabled={disabled}
250
- placeholder="https://example.com/file.jpg"
251
- className="block w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed text-sm"
252
- />
253
- {isUrlValue && (
254
- <button
255
- type="button"
256
- onClick={handleClear}
257
- disabled={disabled}
258
- className="absolute right-2 top-1/2 -translate-y-1/2 p-1 text-gray-400 hover:text-gray-600 rounded-lg hover:bg-gray-100 transition-colors"
259
- aria-label="Clear URL"
260
- >
261
- <svg
262
- className="w-4 h-4"
263
- fill="none"
264
- viewBox="0 0 24 24"
265
- stroke="currentColor"
266
- >
267
- <title>Clear</title>
268
- <path
269
- strokeLinecap="round"
270
- strokeLinejoin="round"
271
- strokeWidth={2}
272
- d="M6 18L18 6M6 6l12 12"
273
- />
274
- </svg>
275
- </button>
276
- )}
277
- </div>
278
- {isUrlValue && (
279
- <div className="flex items-center gap-2 text-xs text-gray-600">
280
- <svg
281
- className="w-4 h-4 text-blue-500"
282
- fill="currentColor"
283
- viewBox="0 0 20 20"
284
- aria-hidden="true"
285
- >
286
- <path
287
- fillRule="evenodd"
288
- d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z"
289
- clipRule="evenodd"
290
- />
291
- </svg>
292
- <span className="truncate">{value}</span>
293
- </div>
294
- )}
295
- </div>
296
- )}
297
- </div>
298
- );
299
- }