react-file-upload-ui 0.1.0 → 0.1.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/README.md +31 -1
- package/dist/index.d.mts +42 -4
- package/dist/index.d.ts +42 -4
- package/dist/index.js +833 -10
- package/dist/index.mjs +833 -6
- package/dist/styles.css +2 -0
- package/package.json +59 -53
package/dist/index.js
CHANGED
|
@@ -20,22 +20,845 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.tsx
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
ReactFileUploaderUI: () => ReactFileUploaderUI,
|
|
24
23
|
default: () => index_default
|
|
25
24
|
});
|
|
26
25
|
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
var import_react5 = require("react");
|
|
27
|
+
|
|
28
|
+
// src/components/ErrorComponent.tsx
|
|
29
|
+
var import_react = require("react");
|
|
27
30
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
28
|
-
|
|
31
|
+
function ErrorComponent({ error, setError }) {
|
|
32
|
+
const [isVisible, setIsVisible] = (0, import_react.useState)(true);
|
|
33
|
+
(0, import_react.useEffect)(() => {
|
|
34
|
+
setIsVisible(true);
|
|
35
|
+
const fadeTimer = setTimeout(() => {
|
|
36
|
+
setIsVisible(false);
|
|
37
|
+
}, 1e3);
|
|
38
|
+
const clearTimer = setTimeout(() => {
|
|
39
|
+
setError("");
|
|
40
|
+
}, 1e3);
|
|
41
|
+
return () => {
|
|
42
|
+
clearTimeout(fadeTimer);
|
|
43
|
+
clearTimeout(clearTimer);
|
|
44
|
+
};
|
|
45
|
+
}, [error, setError]);
|
|
46
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
className: `mt-3 absolute bottom-0 left-0 w-full bg-red-50 border border-red-200 rounded-lg p-3 flex items-start gap-2 transition-opacity duration-500 ${isVisible ? "opacity-100" : "opacity-0"}`,
|
|
50
|
+
children: [
|
|
51
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
52
|
+
"svg",
|
|
53
|
+
{
|
|
54
|
+
className: "w-4 h-4 text-red-500 mt-0.5 flex-shrink-0",
|
|
55
|
+
fill: "none",
|
|
56
|
+
stroke: "currentColor",
|
|
57
|
+
viewBox: "0 0 24 24",
|
|
58
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
59
|
+
"path",
|
|
60
|
+
{
|
|
61
|
+
strokeLinecap: "round",
|
|
62
|
+
strokeLinejoin: "round",
|
|
63
|
+
strokeWidth: 2,
|
|
64
|
+
d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-red-700 flex-1", children: error }),
|
|
70
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
onClick: () => setError(""),
|
|
74
|
+
className: "text-red-500 hover:text-red-700",
|
|
75
|
+
type: "button",
|
|
76
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
77
|
+
"svg",
|
|
78
|
+
{
|
|
79
|
+
className: "w-4 h-4",
|
|
80
|
+
fill: "none",
|
|
81
|
+
stroke: "currentColor",
|
|
82
|
+
viewBox: "0 0 24 24",
|
|
83
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
84
|
+
"path",
|
|
85
|
+
{
|
|
86
|
+
strokeLinecap: "round",
|
|
87
|
+
strokeLinejoin: "round",
|
|
88
|
+
strokeWidth: 2,
|
|
89
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
var ErrorComponent_default = ErrorComponent;
|
|
101
|
+
|
|
102
|
+
// src/components/ProgressBarComponent.tsx
|
|
103
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
104
|
+
function ProgressBarComponent({ uploadProgress }) {
|
|
105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
106
|
+
"div",
|
|
107
|
+
{
|
|
108
|
+
className: "bg-blue-600 h-1 -mt-1 rounded-full transition-all duration-300",
|
|
109
|
+
style: { width: `${uploadProgress}%` }
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
var ProgressBarComponent_default = ProgressBarComponent;
|
|
114
|
+
|
|
115
|
+
// src/components/FileList/index.tsx
|
|
116
|
+
var import_react2 = require("react");
|
|
117
|
+
|
|
118
|
+
// src/components/FileList/MainPreview.tsx
|
|
119
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
120
|
+
function MainPreview({ selectedFile }) {
|
|
121
|
+
if (!selectedFile) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "w-[180px] h-[180px] p-1.5 border border-gray-100 rounded-xl", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
125
|
+
"img",
|
|
126
|
+
{
|
|
127
|
+
src: selectedFile.preview,
|
|
128
|
+
alt: selectedFile.name,
|
|
129
|
+
className: "w-full h-full object-cover rounded-lg"
|
|
130
|
+
}
|
|
131
|
+
) });
|
|
132
|
+
}
|
|
133
|
+
var MainPreview_default = MainPreview;
|
|
134
|
+
|
|
135
|
+
// src/components/svg/CrossIcon.tsx
|
|
136
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
137
|
+
function CrossIcon({ ...props }) {
|
|
138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
139
|
+
"svg",
|
|
140
|
+
{
|
|
141
|
+
className: "w-3 h-3",
|
|
142
|
+
fill: "none",
|
|
143
|
+
stroke: "currentColor",
|
|
144
|
+
viewBox: "0 0 24 24",
|
|
145
|
+
...props,
|
|
146
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
147
|
+
"path",
|
|
148
|
+
{
|
|
149
|
+
strokeLinecap: "round",
|
|
150
|
+
strokeLinejoin: "round",
|
|
151
|
+
strokeWidth: 2,
|
|
152
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
var CrossIcon_default = CrossIcon;
|
|
159
|
+
|
|
160
|
+
// src/components/svg/PlusIcon.tsx
|
|
161
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
162
|
+
function PlusIcon({ ...props }) {
|
|
163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
164
|
+
"svg",
|
|
165
|
+
{
|
|
166
|
+
className: "w-8 h-8",
|
|
167
|
+
fill: "none",
|
|
168
|
+
stroke: "currentColor",
|
|
169
|
+
viewBox: "0 0 24 24",
|
|
170
|
+
...props,
|
|
171
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
172
|
+
"path",
|
|
173
|
+
{
|
|
174
|
+
strokeLinecap: "round",
|
|
175
|
+
strokeLinejoin: "round",
|
|
176
|
+
strokeWidth: 2,
|
|
177
|
+
d: "M12 4v16m8-8H4"
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
var PlusIcon_default = PlusIcon;
|
|
184
|
+
|
|
185
|
+
// src/components/FileList/AddFileButton.tsx
|
|
186
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
187
|
+
function AddFileButton({ onAddFile }) {
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
189
|
+
"button",
|
|
190
|
+
{
|
|
191
|
+
onClick: onAddFile,
|
|
192
|
+
className: "shrink-0 cursor-pointer w-16 h-16 rounded-lg border-2 border-dashed border-gray-300 flex items-center justify-center text-gray-400 hover:text-blue-500 hover:border-blue-500 hover:bg-blue-50 transition-all",
|
|
193
|
+
type: "button",
|
|
194
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PlusIcon_default, {})
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
var AddFileButton_default = AddFileButton;
|
|
199
|
+
|
|
200
|
+
// src/components/svg/CheckIcon.tsx
|
|
201
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
202
|
+
function CheckIcon({ ...props }) {
|
|
203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
204
|
+
"svg",
|
|
205
|
+
{
|
|
206
|
+
className: "w-6 h-6",
|
|
207
|
+
fill: "none",
|
|
208
|
+
stroke: "currentColor",
|
|
209
|
+
viewBox: "0 0 24 24",
|
|
210
|
+
...props,
|
|
211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
212
|
+
"path",
|
|
213
|
+
{
|
|
214
|
+
strokeLinecap: "round",
|
|
215
|
+
strokeLinejoin: "round",
|
|
216
|
+
strokeWidth: 2,
|
|
217
|
+
d: "M5 13l4 4L19 7"
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
var CheckIcon_default = CheckIcon;
|
|
224
|
+
|
|
225
|
+
// src/components/svg/StarIcon.tsx
|
|
226
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
227
|
+
function StarIcon({ ...props }) {
|
|
228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { className: "w-6 h-6", fill: "currentColor", viewBox: "0 0 20 20", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" }) });
|
|
229
|
+
}
|
|
230
|
+
var StarIcon_default = StarIcon;
|
|
231
|
+
|
|
232
|
+
// src/components/FileList/SetDefaultButton.tsx
|
|
233
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
234
|
+
function SetDefaultButton({
|
|
235
|
+
selectedFile,
|
|
236
|
+
onSetDefault
|
|
237
|
+
}) {
|
|
238
|
+
const isDefault = selectedFile.isDefault;
|
|
239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
240
|
+
"button",
|
|
241
|
+
{
|
|
242
|
+
onClick: () => onSetDefault(selectedFile.id),
|
|
243
|
+
className: `w-40 flex items-center justify-center cursor-pointer gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-all duration-200 ${isDefault ? "bg-green-100 text-green-700 border border-green-200 hover:bg-green-200" : "bg-white border border-gray-200 text-gray-600 hover:border-blue-500 hover:text-blue-600 hover:bg-blue-50"}`,
|
|
244
|
+
type: "button",
|
|
245
|
+
children: [
|
|
246
|
+
isDefault ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckIcon_default, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StarIcon_default, { className: "w-4 h-4 opacity-60" }),
|
|
247
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: isDefault ? "Default Image" : "Set as Default" })
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
var SetDefaultButton_default = SetDefaultButton;
|
|
253
|
+
|
|
254
|
+
// src/components/svg/TrashIcon.tsx
|
|
255
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
256
|
+
function TrashIcon({ ...props }) {
|
|
257
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
258
|
+
"svg",
|
|
259
|
+
{
|
|
260
|
+
className: "w-6 h-6",
|
|
261
|
+
fill: "none",
|
|
262
|
+
stroke: "currentColor",
|
|
263
|
+
viewBox: "0 0 24 24",
|
|
264
|
+
...props,
|
|
265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
266
|
+
"path",
|
|
267
|
+
{
|
|
268
|
+
strokeLinecap: "round",
|
|
269
|
+
strokeLinejoin: "round",
|
|
270
|
+
strokeWidth: 2,
|
|
271
|
+
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
var TrashIcon_default = TrashIcon;
|
|
278
|
+
|
|
279
|
+
// src/components/FileList/ClearAllFile.tsx
|
|
280
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
281
|
+
function ClearAllFile({ onClearAll }) {
|
|
282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
283
|
+
"button",
|
|
284
|
+
{
|
|
285
|
+
onClick: onClearAll,
|
|
286
|
+
className: "flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium bg-white border border-gray-200 text-gray-600 hover:border-red-500 hover:text-red-600 hover:bg-red-50 transition-all duration-200 w-full justify-center",
|
|
287
|
+
title: "Clear all files",
|
|
288
|
+
children: [
|
|
289
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TrashIcon_default, { className: "w-4 h-4" }),
|
|
290
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Clear All" })
|
|
291
|
+
]
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
var ClearAllFile_default = ClearAllFile;
|
|
296
|
+
|
|
297
|
+
// src/components/FileList/index.tsx
|
|
298
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
299
|
+
var FileList = ({
|
|
300
|
+
files,
|
|
301
|
+
removeFile,
|
|
302
|
+
clearAll,
|
|
303
|
+
setAsDefault,
|
|
304
|
+
onAddFile
|
|
305
|
+
}) => {
|
|
306
|
+
const [selectedFileId, setSelectedFileId] = (0, import_react2.useState)(null);
|
|
307
|
+
(0, import_react2.useEffect)(() => {
|
|
308
|
+
if (files.length > 0) {
|
|
309
|
+
if (!selectedFileId || !files.find((f) => f.id === selectedFileId)) {
|
|
310
|
+
setSelectedFileId(files[0].id);
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
setSelectedFileId(null);
|
|
314
|
+
}
|
|
315
|
+
}, [files, selectedFileId]);
|
|
316
|
+
if (files.length === 0) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
const selectedFile = files.find((f) => f.id === selectedFileId) || files[0];
|
|
320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-4 p-3", children: [
|
|
321
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-center gap-6", children: [
|
|
322
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MainPreview_default, { selectedFile }),
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
324
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
325
|
+
SetDefaultButton_default,
|
|
326
|
+
{
|
|
327
|
+
selectedFile,
|
|
328
|
+
onSetDefault: setAsDefault
|
|
329
|
+
}
|
|
330
|
+
),
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ClearAllFile_default, { onClearAll: clearAll })
|
|
332
|
+
] })
|
|
333
|
+
] }),
|
|
334
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "w-full flex flex-wrap items-center gap-1", children: [
|
|
335
|
+
files.map((file) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative group/thumb", children: [
|
|
336
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
337
|
+
"button",
|
|
338
|
+
{
|
|
339
|
+
onClick: () => setSelectedFileId(file.id),
|
|
340
|
+
className: `relative cursor-pointer w-16 h-16 p-0.5 rounded-lg overflow-hidden border transition-all ${selectedFileId === file.id ? "border-gray-300" : "border-transparent hover:border-gray-100"}`,
|
|
341
|
+
children: [
|
|
342
|
+
file.preview ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
343
|
+
"img",
|
|
344
|
+
{
|
|
345
|
+
src: file.preview,
|
|
346
|
+
alt: file.name,
|
|
347
|
+
className: "w-full h-full object-cover"
|
|
348
|
+
}
|
|
349
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full h-full bg-gray-100 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
350
|
+
"svg",
|
|
351
|
+
{
|
|
352
|
+
className: "w-6 h-6 text-gray-400",
|
|
353
|
+
fill: "none",
|
|
354
|
+
stroke: "currentColor",
|
|
355
|
+
viewBox: "0 0 24 24",
|
|
356
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
357
|
+
"path",
|
|
358
|
+
{
|
|
359
|
+
strokeLinecap: "round",
|
|
360
|
+
strokeLinejoin: "round",
|
|
361
|
+
strokeWidth: 2,
|
|
362
|
+
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
) }),
|
|
367
|
+
file.isDefault && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "absolute top-1 left-1 p-0.5 bg-yellow-400 rounded-full", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
368
|
+
"svg",
|
|
369
|
+
{
|
|
370
|
+
className: "w-3 h-3 text-white",
|
|
371
|
+
fill: "currentColor",
|
|
372
|
+
viewBox: "0 0 20 20",
|
|
373
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" })
|
|
374
|
+
}
|
|
375
|
+
) })
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
),
|
|
379
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
380
|
+
"button",
|
|
381
|
+
{
|
|
382
|
+
onClick: (e) => {
|
|
383
|
+
e.stopPropagation();
|
|
384
|
+
removeFile(file.id);
|
|
385
|
+
},
|
|
386
|
+
className: "absolute cursor-pointer -top-2 -right-2 w-5 h-5 bg-red-500 text-white rounded-full flex items-center justify-center opacity-0 group-hover/thumb:opacity-100 transition-opacity shadow-sm hover:bg-red-600 z-10",
|
|
387
|
+
title: "Remove file",
|
|
388
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CrossIcon_default, {})
|
|
389
|
+
}
|
|
390
|
+
)
|
|
391
|
+
] }, file.id)),
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AddFileButton_default, { onAddFile })
|
|
393
|
+
] })
|
|
394
|
+
] });
|
|
395
|
+
};
|
|
396
|
+
var FileList_default = FileList;
|
|
397
|
+
|
|
398
|
+
// src/hooks/useDragging.ts
|
|
399
|
+
var import_react3 = require("react");
|
|
400
|
+
function useDragging({ disabled }) {
|
|
401
|
+
const [isDragging, setIsDragging] = (0, import_react3.useState)(false);
|
|
402
|
+
const handleDragEnter = (e) => {
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
e.stopPropagation();
|
|
405
|
+
if (!disabled) {
|
|
406
|
+
setIsDragging(true);
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
const handleDragLeave = (e) => {
|
|
410
|
+
e.preventDefault();
|
|
411
|
+
e.stopPropagation();
|
|
412
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
413
|
+
const x = e.clientX;
|
|
414
|
+
const y = e.clientY;
|
|
415
|
+
if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) {
|
|
416
|
+
setIsDragging(false);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
const handleDragOver = (e) => {
|
|
420
|
+
e.preventDefault();
|
|
421
|
+
e.stopPropagation();
|
|
422
|
+
};
|
|
423
|
+
return {
|
|
424
|
+
isDragging,
|
|
425
|
+
setIsDragging,
|
|
426
|
+
handleDragEnter,
|
|
427
|
+
handleDragLeave,
|
|
428
|
+
handleDragOver
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
var useDragging_default = useDragging;
|
|
432
|
+
|
|
433
|
+
// src/hooks/useFileHandler.ts
|
|
434
|
+
var import_react4 = require("react");
|
|
435
|
+
|
|
436
|
+
// src/utils/format.ts
|
|
437
|
+
function formatFileSize(bytes) {
|
|
438
|
+
if (bytes === 0) {
|
|
439
|
+
return "0 Bytes";
|
|
440
|
+
}
|
|
441
|
+
const k = 1024;
|
|
442
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
443
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
444
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/utils/validation.ts
|
|
448
|
+
var validateFiles = (newFiles, currentFiles, maxFiles, maxSize, accept) => {
|
|
449
|
+
let validFiles = newFiles;
|
|
450
|
+
const errors = [];
|
|
451
|
+
if (currentFiles.length + validFiles.length > maxFiles) {
|
|
452
|
+
errors.push(`Maximum ${maxFiles} files allowed`);
|
|
453
|
+
validFiles = validFiles.slice(0, maxFiles - currentFiles.length);
|
|
454
|
+
}
|
|
455
|
+
const oversizedFiles = validFiles.filter((file) => file.size > maxSize);
|
|
456
|
+
if (oversizedFiles.length > 0) {
|
|
457
|
+
errors.push(
|
|
458
|
+
`${oversizedFiles.length} file(s) exceed ${formatFileSize(maxSize)}`
|
|
459
|
+
);
|
|
460
|
+
validFiles = validFiles.filter((file) => file.size <= maxSize);
|
|
461
|
+
}
|
|
462
|
+
if (accept) {
|
|
463
|
+
const acceptedTypes = accept.split(",").map((type) => type.trim());
|
|
464
|
+
const invalidFiles = validFiles.filter((file) => {
|
|
465
|
+
return !acceptedTypes.some((type) => {
|
|
466
|
+
if (type.startsWith(".")) {
|
|
467
|
+
return file.name.toLowerCase().endsWith(type.toLowerCase());
|
|
468
|
+
}
|
|
469
|
+
if (type.endsWith("/*")) {
|
|
470
|
+
const mainType = type.split("/")[0];
|
|
471
|
+
return file.type.startsWith(mainType);
|
|
472
|
+
}
|
|
473
|
+
return file.type === type;
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
if (invalidFiles.length > 0) {
|
|
477
|
+
errors.push(`${invalidFiles.length} file(s) have invalid type`);
|
|
478
|
+
}
|
|
479
|
+
validFiles = validFiles.filter((file) => {
|
|
480
|
+
return acceptedTypes.some((type) => {
|
|
481
|
+
if (type.startsWith(".")) {
|
|
482
|
+
return file.name.toLowerCase().endsWith(type.toLowerCase());
|
|
483
|
+
}
|
|
484
|
+
if (type.endsWith("/*")) {
|
|
485
|
+
const mainType = type.split("/")[0];
|
|
486
|
+
return file.type.startsWith(mainType);
|
|
487
|
+
}
|
|
488
|
+
return file.type === type;
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
return { validFiles, errors };
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
// src/hooks/useFileHandler.ts
|
|
496
|
+
var useFileHandler = ({
|
|
497
|
+
maxFiles,
|
|
498
|
+
maxSize,
|
|
29
499
|
accept,
|
|
30
|
-
multiple
|
|
500
|
+
multiple,
|
|
501
|
+
onFilesSelected,
|
|
502
|
+
onError,
|
|
503
|
+
initialFiles
|
|
31
504
|
}) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
505
|
+
const transformToFileData = (files2) => {
|
|
506
|
+
return files2.map((file) => ({
|
|
507
|
+
id: file.id,
|
|
508
|
+
isDefault: file.isDefault || false,
|
|
509
|
+
file: file.rawFile,
|
|
510
|
+
url: file.preview,
|
|
511
|
+
name: file.name
|
|
512
|
+
}));
|
|
513
|
+
};
|
|
514
|
+
const extractNameFromUrl = (url) => {
|
|
515
|
+
try {
|
|
516
|
+
const pathname = new URL(url).pathname;
|
|
517
|
+
const parts = pathname.split("/").filter(Boolean);
|
|
518
|
+
return parts[parts.length - 1] || url;
|
|
519
|
+
} catch (e) {
|
|
520
|
+
return url;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
const [files, setFiles] = (0, import_react4.useState)(() => {
|
|
524
|
+
if (!initialFiles || initialFiles.length === 0) return [];
|
|
525
|
+
return initialFiles.map((f) => {
|
|
526
|
+
var _a, _b, _c;
|
|
527
|
+
return {
|
|
528
|
+
id: (_a = f.id) != null ? _a : `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
529
|
+
name: (_b = f.name) != null ? _b : extractNameFromUrl(f.url),
|
|
530
|
+
size: 0,
|
|
531
|
+
type: (_c = f.type) != null ? _c : "",
|
|
532
|
+
preview: f.url,
|
|
533
|
+
isDefault: !!f.isDefault,
|
|
534
|
+
rawFile: void 0
|
|
535
|
+
};
|
|
536
|
+
});
|
|
537
|
+
});
|
|
538
|
+
const [uploadProgress, setUploadProgress] = (0, import_react4.useState)(0);
|
|
539
|
+
const [error, setError] = (0, import_react4.useState)("");
|
|
540
|
+
(0, import_react4.useEffect)(() => {
|
|
541
|
+
if (files.length > 0 && onFilesSelected) {
|
|
542
|
+
onFilesSelected(transformToFileData(files));
|
|
543
|
+
}
|
|
544
|
+
}, []);
|
|
545
|
+
const simulateUpload = (0, import_react4.useCallback)(() => {
|
|
546
|
+
setUploadProgress(0);
|
|
547
|
+
const interval = setInterval(() => {
|
|
548
|
+
setUploadProgress((prev) => {
|
|
549
|
+
if (prev >= 100) {
|
|
550
|
+
clearInterval(interval);
|
|
551
|
+
return 100;
|
|
552
|
+
}
|
|
553
|
+
return prev + 10;
|
|
554
|
+
});
|
|
555
|
+
}, 150);
|
|
556
|
+
}, []);
|
|
557
|
+
const handleFiles = (0, import_react4.useCallback)(
|
|
558
|
+
(newFiles) => {
|
|
559
|
+
setError("");
|
|
560
|
+
const { validFiles, errors } = validateFiles(
|
|
561
|
+
newFiles,
|
|
562
|
+
files,
|
|
563
|
+
maxFiles,
|
|
564
|
+
maxSize,
|
|
565
|
+
accept
|
|
566
|
+
);
|
|
567
|
+
if (errors.length > 0) {
|
|
568
|
+
const errorMessage = errors.join(". ");
|
|
569
|
+
setError(errorMessage);
|
|
570
|
+
onError == null ? void 0 : onError(errorMessage);
|
|
571
|
+
}
|
|
572
|
+
if (validFiles.length === 0) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const filesWithMeta = validFiles.map((file) => {
|
|
576
|
+
var _a;
|
|
577
|
+
const id = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
578
|
+
const isImage = (_a = file.type) == null ? void 0 : _a.startsWith("image/");
|
|
579
|
+
const preview = isImage ? URL.createObjectURL(file) : void 0;
|
|
580
|
+
const fileWithMeta = {
|
|
581
|
+
id,
|
|
582
|
+
name: file.name,
|
|
583
|
+
size: file.size,
|
|
584
|
+
type: file.type,
|
|
585
|
+
preview,
|
|
586
|
+
isDefault: false,
|
|
587
|
+
rawFile: file
|
|
588
|
+
};
|
|
589
|
+
return fileWithMeta;
|
|
590
|
+
});
|
|
591
|
+
const updatedFiles = multiple ? [...files, ...filesWithMeta] : filesWithMeta;
|
|
592
|
+
setFiles(updatedFiles);
|
|
593
|
+
onFilesSelected == null ? void 0 : onFilesSelected(transformToFileData(updatedFiles));
|
|
594
|
+
if (filesWithMeta.length > 0) {
|
|
595
|
+
simulateUpload();
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
[
|
|
599
|
+
files,
|
|
600
|
+
maxFiles,
|
|
601
|
+
maxSize,
|
|
602
|
+
accept,
|
|
603
|
+
multiple,
|
|
604
|
+
onFilesSelected,
|
|
605
|
+
onError,
|
|
606
|
+
simulateUpload
|
|
607
|
+
]
|
|
608
|
+
);
|
|
609
|
+
const handleFileInput = (0, import_react4.useCallback)(
|
|
610
|
+
(e) => {
|
|
611
|
+
if (e.target.files) {
|
|
612
|
+
const selectedFiles = Array.from(e.target.files);
|
|
613
|
+
handleFiles(selectedFiles);
|
|
614
|
+
}
|
|
615
|
+
},
|
|
616
|
+
[handleFiles]
|
|
617
|
+
);
|
|
618
|
+
const removeFile = (0, import_react4.useCallback)(
|
|
619
|
+
(id) => {
|
|
620
|
+
const fileToRemove = files.find((f) => f.id === id);
|
|
621
|
+
if ((fileToRemove == null ? void 0 : fileToRemove.preview) && fileToRemove.rawFile) {
|
|
622
|
+
URL.revokeObjectURL(fileToRemove.preview);
|
|
623
|
+
}
|
|
624
|
+
const updatedFiles = files.filter((f) => f.id !== id);
|
|
625
|
+
setFiles(updatedFiles);
|
|
626
|
+
onFilesSelected == null ? void 0 : onFilesSelected(transformToFileData(updatedFiles));
|
|
627
|
+
setError("");
|
|
628
|
+
},
|
|
629
|
+
[files, onFilesSelected]
|
|
630
|
+
);
|
|
631
|
+
const clearAll = (0, import_react4.useCallback)(() => {
|
|
632
|
+
files.forEach((file) => {
|
|
633
|
+
if (file.preview && file.rawFile) {
|
|
634
|
+
URL.revokeObjectURL(file.preview);
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
setFiles([]);
|
|
638
|
+
onFilesSelected == null ? void 0 : onFilesSelected(transformToFileData([]));
|
|
639
|
+
setError("");
|
|
640
|
+
setUploadProgress(0);
|
|
641
|
+
}, [files, onFilesSelected]);
|
|
642
|
+
const setAsDefault = (0, import_react4.useCallback)(
|
|
643
|
+
(id) => {
|
|
644
|
+
const updatedFiles = files.map((file) => {
|
|
645
|
+
if (file.id === id && file.isDefault) {
|
|
646
|
+
file.isDefault = false;
|
|
647
|
+
} else {
|
|
648
|
+
file.isDefault = file.id === id;
|
|
649
|
+
}
|
|
650
|
+
return file;
|
|
651
|
+
});
|
|
652
|
+
setFiles([...updatedFiles]);
|
|
653
|
+
onFilesSelected == null ? void 0 : onFilesSelected(transformToFileData(updatedFiles));
|
|
654
|
+
},
|
|
655
|
+
[files, onFilesSelected]
|
|
656
|
+
);
|
|
657
|
+
return {
|
|
658
|
+
files,
|
|
659
|
+
uploadProgress,
|
|
660
|
+
error,
|
|
661
|
+
setError,
|
|
662
|
+
handleFiles,
|
|
663
|
+
handleFileInput,
|
|
664
|
+
removeFile,
|
|
665
|
+
clearAll,
|
|
666
|
+
setAsDefault
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
var useFileHandler_default = useFileHandler;
|
|
670
|
+
|
|
671
|
+
// src/utils/input-handler.ts
|
|
672
|
+
var handleDrop = (e, setIsDragging, handleFiles, disabled) => {
|
|
673
|
+
e.preventDefault();
|
|
674
|
+
e.stopPropagation();
|
|
675
|
+
setIsDragging(false);
|
|
676
|
+
if (disabled) {
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
const droppedFiles = Array.from(e.dataTransfer.files);
|
|
680
|
+
handleFiles(droppedFiles);
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/components/svg/UploadIcon.tsx
|
|
684
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
685
|
+
function UploadIcon({ ...props }) {
|
|
686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
687
|
+
"svg",
|
|
688
|
+
{
|
|
689
|
+
fill: "none",
|
|
690
|
+
stroke: "currentColor",
|
|
691
|
+
viewBox: "0 0 24 24",
|
|
692
|
+
...props,
|
|
693
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
694
|
+
"path",
|
|
695
|
+
{
|
|
696
|
+
strokeLinecap: "round",
|
|
697
|
+
strokeLinejoin: "round",
|
|
698
|
+
strokeWidth: 2,
|
|
699
|
+
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"
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
}
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
var UploadIcon_default = UploadIcon;
|
|
706
|
+
|
|
707
|
+
// src/components/LabelUI.tsx
|
|
708
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
709
|
+
function LabelUI({
|
|
710
|
+
accept,
|
|
711
|
+
isDragging,
|
|
712
|
+
maxSize = 10 * 1024 * 1024,
|
|
713
|
+
maxFiles = 10,
|
|
714
|
+
disabled = false
|
|
715
|
+
}) {
|
|
716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "p-6", children: [
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mb-3 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
718
|
+
UploadIcon_default,
|
|
719
|
+
{
|
|
720
|
+
className: `w-8 h-8 transition-colors duration-200 ${isDragging && !disabled ? "text-blue-500" : "text-gray-400"}`
|
|
721
|
+
}
|
|
722
|
+
) }) }),
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-lg font-semibold text-gray-700 mb-1", children: isDragging && !disabled ? "Drop files here" : "Drag & drop files" }),
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-gray-500 mb-3", children: "or click to browse" }),
|
|
725
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "text-xs text-gray-400 space-y-1", children: [
|
|
726
|
+
accept && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
|
|
727
|
+
"Accepted: ",
|
|
728
|
+
accept
|
|
729
|
+
] }),
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
|
|
731
|
+
"Max size: ",
|
|
732
|
+
formatFileSize(maxSize),
|
|
733
|
+
" \u2022 Max files: ",
|
|
734
|
+
maxFiles
|
|
735
|
+
] })
|
|
736
|
+
] })
|
|
35
737
|
] });
|
|
738
|
+
}
|
|
739
|
+
var LabelUI_default = LabelUI;
|
|
740
|
+
|
|
741
|
+
// src/index.tsx
|
|
742
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
743
|
+
var ReactFileUploaderUI = ({
|
|
744
|
+
accept,
|
|
745
|
+
multiple = true,
|
|
746
|
+
maxSize = 10 * 1024 * 1024,
|
|
747
|
+
maxFiles = 10,
|
|
748
|
+
onFilesSelected,
|
|
749
|
+
onError,
|
|
750
|
+
disabled = false,
|
|
751
|
+
className = "",
|
|
752
|
+
defaultFiles
|
|
753
|
+
}) => {
|
|
754
|
+
const fileInputRef = (0, import_react5.useRef)(null);
|
|
755
|
+
const {
|
|
756
|
+
files,
|
|
757
|
+
uploadProgress,
|
|
758
|
+
error,
|
|
759
|
+
setError,
|
|
760
|
+
handleFiles,
|
|
761
|
+
handleFileInput,
|
|
762
|
+
removeFile,
|
|
763
|
+
clearAll,
|
|
764
|
+
setAsDefault
|
|
765
|
+
} = useFileHandler_default({
|
|
766
|
+
maxFiles,
|
|
767
|
+
maxSize,
|
|
768
|
+
accept,
|
|
769
|
+
multiple,
|
|
770
|
+
onFilesSelected,
|
|
771
|
+
onError,
|
|
772
|
+
initialFiles: defaultFiles
|
|
773
|
+
});
|
|
774
|
+
const {
|
|
775
|
+
isDragging,
|
|
776
|
+
setIsDragging,
|
|
777
|
+
handleDragEnter,
|
|
778
|
+
handleDragLeave,
|
|
779
|
+
handleDragOver
|
|
780
|
+
} = useDragging_default({ disabled });
|
|
781
|
+
const onDrop = (e) => {
|
|
782
|
+
handleDrop(e, setIsDragging, handleFiles, disabled);
|
|
783
|
+
};
|
|
784
|
+
const hasFiles = files.length > 0;
|
|
785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
786
|
+
"div",
|
|
787
|
+
{
|
|
788
|
+
className: `w-full border-gray-200 border border-dashed rounded-xl relative ${className}`,
|
|
789
|
+
children: [
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
791
|
+
"div",
|
|
792
|
+
{
|
|
793
|
+
className: `
|
|
794
|
+
relative text-center
|
|
795
|
+
transition-all duration-200 ease-in-out
|
|
796
|
+
${disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"}
|
|
797
|
+
${isDragging && !disabled ? "border-blue-500 bg-blue-50 scale-[1.01]" : "border-gray-300 bg-white hover:border-blue-400 hover:bg-gray-50"}
|
|
798
|
+
`,
|
|
799
|
+
onDragEnter: handleDragEnter,
|
|
800
|
+
onDragOver: handleDragOver,
|
|
801
|
+
onDragLeave: handleDragLeave,
|
|
802
|
+
onDrop,
|
|
803
|
+
onClick: () => {
|
|
804
|
+
var _a;
|
|
805
|
+
return !disabled && ((_a = fileInputRef.current) == null ? void 0 : _a.click());
|
|
806
|
+
},
|
|
807
|
+
role: "button",
|
|
808
|
+
"aria-label": "File upload area",
|
|
809
|
+
tabIndex: disabled ? -1 : 0,
|
|
810
|
+
onKeyDown: (e) => {
|
|
811
|
+
var _a;
|
|
812
|
+
if ((e.key === "Enter" || e.key === " ") && !disabled) {
|
|
813
|
+
(_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
814
|
+
}
|
|
815
|
+
},
|
|
816
|
+
children: [
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
818
|
+
"input",
|
|
819
|
+
{
|
|
820
|
+
ref: fileInputRef,
|
|
821
|
+
type: "file",
|
|
822
|
+
accept,
|
|
823
|
+
multiple,
|
|
824
|
+
onChange: handleFileInput,
|
|
825
|
+
className: "hidden",
|
|
826
|
+
disabled,
|
|
827
|
+
"aria-label": "File input"
|
|
828
|
+
}
|
|
829
|
+
),
|
|
830
|
+
!hasFiles && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
831
|
+
LabelUI_default,
|
|
832
|
+
{
|
|
833
|
+
accept,
|
|
834
|
+
multiple,
|
|
835
|
+
maxSize,
|
|
836
|
+
maxFiles,
|
|
837
|
+
disabled,
|
|
838
|
+
isDragging
|
|
839
|
+
}
|
|
840
|
+
)
|
|
841
|
+
]
|
|
842
|
+
}
|
|
843
|
+
),
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
845
|
+
FileList_default,
|
|
846
|
+
{
|
|
847
|
+
files,
|
|
848
|
+
uploadProgress,
|
|
849
|
+
removeFile,
|
|
850
|
+
clearAll,
|
|
851
|
+
setAsDefault,
|
|
852
|
+
onAddFile: () => {
|
|
853
|
+
var _a;
|
|
854
|
+
return !disabled && ((_a = fileInputRef.current) == null ? void 0 : _a.click());
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
),
|
|
858
|
+
files.length > 0 && uploadProgress < 100 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ProgressBarComponent_default, { uploadProgress }),
|
|
859
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ErrorComponent_default, { error, setError })
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
);
|
|
36
863
|
};
|
|
37
864
|
var index_default = ReactFileUploaderUI;
|
|
38
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
39
|
-
0 && (module.exports = {
|
|
40
|
-
ReactFileUploaderUI
|
|
41
|
-
});
|