@spark-ui/components 11.5.1 → 11.6.1
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/dist/alert-dialog/index.mjs +1 -1
- package/dist/avatar/index.mjs +2 -2
- package/dist/carousel/index.mjs +2 -2
- package/dist/{chunk-TKAU6SMC.mjs → chunk-7EWSMIZU.mjs} +21 -4
- package/dist/chunk-7EWSMIZU.mjs.map +1 -0
- package/dist/combobox/index.mjs +3 -3
- package/dist/dialog/index.mjs +1 -1
- package/dist/docgen.json +341 -63
- package/dist/drawer/index.mjs +2 -2
- package/dist/dropdown/index.mjs +2 -2
- package/dist/file-upload/index.d.mts +50 -31
- package/dist/file-upload/index.d.ts +50 -31
- package/dist/file-upload/index.js +294 -120
- package/dist/file-upload/index.js.map +1 -1
- package/dist/file-upload/index.mjs +253 -97
- package/dist/file-upload/index.mjs.map +1 -1
- package/dist/pagination/index.mjs +3 -3
- package/dist/popover/index.mjs +1 -1
- package/dist/progress/index.d.mts +6 -2
- package/dist/progress/index.d.ts +6 -2
- package/dist/progress/index.js +20 -3
- package/dist/progress/index.js.map +1 -1
- package/dist/progress/index.mjs +1 -1
- package/dist/scrolling-list/index.mjs +3 -3
- package/dist/snackbar/index.mjs +3 -3
- package/dist/stepper/index.mjs +2 -2
- package/dist/tabs/index.mjs +3 -3
- package/dist/toast/index.mjs +3 -3
- package/package.json +5 -5
- package/dist/chunk-TKAU6SMC.mjs.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Progress
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-7EWSMIZU.mjs";
|
|
4
4
|
import {
|
|
5
5
|
IconButton
|
|
6
6
|
} from "../chunk-DCXWGQVZ.mjs";
|
|
7
|
+
import {
|
|
8
|
+
Icon
|
|
9
|
+
} from "../chunk-UMUMFMFB.mjs";
|
|
7
10
|
import {
|
|
8
11
|
Button,
|
|
9
12
|
buttonStyles
|
|
10
13
|
} from "../chunk-2YM6GKWW.mjs";
|
|
11
14
|
import "../chunk-GAK4SC2F.mjs";
|
|
12
|
-
import {
|
|
13
|
-
Icon
|
|
14
|
-
} from "../chunk-UMUMFMFB.mjs";
|
|
15
15
|
import "../chunk-KEGAAGJW.mjs";
|
|
16
16
|
import {
|
|
17
17
|
Slot
|
|
@@ -19,8 +19,39 @@ import {
|
|
|
19
19
|
|
|
20
20
|
// src/file-upload/FileUpload.tsx
|
|
21
21
|
import { useFormFieldControl } from "@spark-ui/components/form-field";
|
|
22
|
+
import { createContext, useContext, useId, useRef } from "react";
|
|
23
|
+
|
|
24
|
+
// src/file-upload/useFileUploadState.tsx
|
|
22
25
|
import { useCombinedState } from "@spark-ui/hooks/use-combined-state";
|
|
23
|
-
import {
|
|
26
|
+
import { useState } from "react";
|
|
27
|
+
|
|
28
|
+
// src/file-upload/constants.ts
|
|
29
|
+
var FILE_UPLOAD_ERRORS = {
|
|
30
|
+
/**
|
|
31
|
+
* Exceeds the maxFiles limit
|
|
32
|
+
*/
|
|
33
|
+
TOO_MANY_FILES: "TOO_MANY_FILES",
|
|
34
|
+
/**
|
|
35
|
+
* File type not in the accept list
|
|
36
|
+
*/
|
|
37
|
+
FILE_INVALID_TYPE: "FILE_INVALID_TYPE",
|
|
38
|
+
/**
|
|
39
|
+
* File size exceeds maxFileSize
|
|
40
|
+
*/
|
|
41
|
+
FILE_TOO_LARGE: "FILE_TOO_LARGE",
|
|
42
|
+
/**
|
|
43
|
+
* File size below minFileSize
|
|
44
|
+
*/
|
|
45
|
+
FILE_TOO_SMALL: "FILE_TOO_SMALL",
|
|
46
|
+
/**
|
|
47
|
+
* Generic validation failure
|
|
48
|
+
*/
|
|
49
|
+
FILE_INVALID: "FILE_INVALID",
|
|
50
|
+
/**
|
|
51
|
+
* Duplicate file detected
|
|
52
|
+
*/
|
|
53
|
+
FILE_EXISTS: "FILE_EXISTS"
|
|
54
|
+
};
|
|
24
55
|
|
|
25
56
|
// src/file-upload/utils.ts
|
|
26
57
|
import { CvOutline } from "@spark-ui/icons/CvOutline";
|
|
@@ -120,14 +151,32 @@ function getFileIcon(file) {
|
|
|
120
151
|
}
|
|
121
152
|
return createElement(CvOutline);
|
|
122
153
|
}
|
|
154
|
+
function isFocusable(element) {
|
|
155
|
+
if (!element) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const tabIndex = element.tabIndex;
|
|
159
|
+
if (tabIndex >= 0) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
const isContentEditable = String(element.contentEditable) === "true";
|
|
163
|
+
const naturallyFocusable = element instanceof HTMLInputElement || element instanceof HTMLButtonElement || element instanceof HTMLSelectElement || element instanceof HTMLTextAreaElement || element instanceof HTMLAnchorElement && Boolean(element.href) || isContentEditable;
|
|
164
|
+
return naturallyFocusable;
|
|
165
|
+
}
|
|
166
|
+
function findFocusableElement(candidates, inputRef) {
|
|
167
|
+
for (const candidate of candidates) {
|
|
168
|
+
if (isFocusable(candidate)) {
|
|
169
|
+
return candidate;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (inputRef.current) {
|
|
173
|
+
return inputRef.current;
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
123
177
|
|
|
124
|
-
// src/file-upload/
|
|
125
|
-
|
|
126
|
-
var FileUploadContext = createContext(null);
|
|
127
|
-
var ID_PREFIX = ":file-upload";
|
|
128
|
-
var FileUpload = ({
|
|
129
|
-
asChild: _asChild = false,
|
|
130
|
-
children,
|
|
178
|
+
// src/file-upload/useFileUploadState.tsx
|
|
179
|
+
function useFileUploadState({
|
|
131
180
|
defaultValue = [],
|
|
132
181
|
value: controlledValue,
|
|
133
182
|
onFileAccept,
|
|
@@ -138,32 +187,12 @@ var FileUpload = ({
|
|
|
138
187
|
maxFiles,
|
|
139
188
|
maxFileSize,
|
|
140
189
|
minFileSize,
|
|
141
|
-
disabled
|
|
142
|
-
readOnly
|
|
190
|
+
disabled = false,
|
|
191
|
+
readOnly = false,
|
|
143
192
|
locale
|
|
144
|
-
})
|
|
145
|
-
const field = useFormFieldControl();
|
|
146
|
-
const {
|
|
147
|
-
id: fieldId,
|
|
148
|
-
name: fieldName,
|
|
149
|
-
isInvalid,
|
|
150
|
-
isRequired,
|
|
151
|
-
description,
|
|
152
|
-
disabled: fieldDisabled,
|
|
153
|
-
readOnly: fieldReadOnly,
|
|
154
|
-
labelId
|
|
155
|
-
} = field;
|
|
193
|
+
}) {
|
|
156
194
|
const defaultLocale = locale || (typeof navigator !== "undefined" && navigator.language ? navigator.language : "en");
|
|
157
|
-
const
|
|
158
|
-
const inputId = fieldId || `${ID_PREFIX}-${internalId}`;
|
|
159
|
-
const inputName = fieldName;
|
|
160
|
-
const inputRef = useRef(null);
|
|
161
|
-
const triggerRef = useRef(null);
|
|
162
|
-
const dropzoneRef = useRef(null);
|
|
163
|
-
const deleteButtonRefs = useRef([]);
|
|
164
|
-
const disabled = fieldDisabled ?? disabledProp;
|
|
165
|
-
const readOnly = fieldReadOnly ?? readOnlyProp;
|
|
166
|
-
const [filesState, setFilesState, ,] = useCombinedState(controlledValue, defaultValue);
|
|
195
|
+
const [filesState, setFilesState] = useCombinedState(controlledValue, defaultValue);
|
|
167
196
|
const files = filesState ?? [];
|
|
168
197
|
const setFiles = setFilesState;
|
|
169
198
|
const [rejectedFiles, setRejectedFiles] = useState([]);
|
|
@@ -195,20 +224,17 @@ var FileUpload = ({
|
|
|
195
224
|
};
|
|
196
225
|
setFiles((prev) => {
|
|
197
226
|
const currentFiles = prev ?? [];
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
addRejectedFile(file, "TOO_MANY_FILES");
|
|
204
|
-
});
|
|
205
|
-
}
|
|
227
|
+
const remainingSlots = maxFiles !== void 0 ? maxFiles - currentFiles.length : void 0;
|
|
228
|
+
if (remainingSlots !== void 0 && remainingSlots <= 0) {
|
|
229
|
+
newFiles.forEach((file) => {
|
|
230
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.TOO_MANY_FILES);
|
|
231
|
+
});
|
|
206
232
|
}
|
|
207
233
|
let filteredFiles = newFiles;
|
|
208
234
|
if (accept) {
|
|
209
235
|
const rejectedByAccept = newFiles.filter((file) => !validateFileAccept(file, accept));
|
|
210
236
|
rejectedByAccept.forEach((file) => {
|
|
211
|
-
addRejectedFile(file,
|
|
237
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_INVALID_TYPE);
|
|
212
238
|
});
|
|
213
239
|
filteredFiles = newFiles.filter((file) => validateFileAccept(file, accept));
|
|
214
240
|
}
|
|
@@ -218,11 +244,11 @@ var FileUpload = ({
|
|
|
218
244
|
const validation = validateFileSize(file, minFileSize, maxFileSize, defaultLocale);
|
|
219
245
|
if (!validation.valid) {
|
|
220
246
|
if (maxFileSize !== void 0 && file.size > maxFileSize) {
|
|
221
|
-
addRejectedFile(file,
|
|
247
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_TOO_LARGE);
|
|
222
248
|
} else if (minFileSize !== void 0 && file.size < minFileSize) {
|
|
223
|
-
addRejectedFile(file,
|
|
249
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_TOO_SMALL);
|
|
224
250
|
} else {
|
|
225
|
-
addRejectedFile(file,
|
|
251
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_INVALID);
|
|
226
252
|
}
|
|
227
253
|
return false;
|
|
228
254
|
}
|
|
@@ -230,35 +256,27 @@ var FileUpload = ({
|
|
|
230
256
|
});
|
|
231
257
|
}
|
|
232
258
|
const seenFiles = /* @__PURE__ */ new Map();
|
|
233
|
-
const duplicateFiles = [];
|
|
234
259
|
const uniqueFiles = validSizeFiles.filter((file) => {
|
|
235
260
|
const fileKey = `${file.name}-${file.size}`;
|
|
236
261
|
const existsInPrev = fileExists(file, currentFiles);
|
|
237
262
|
if (existsInPrev) {
|
|
238
|
-
|
|
239
|
-
addRejectedFile(file, "FILE_EXISTS");
|
|
263
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_EXISTS);
|
|
240
264
|
return false;
|
|
241
265
|
}
|
|
242
266
|
if (seenFiles.has(fileKey)) {
|
|
243
|
-
|
|
244
|
-
addRejectedFile(file, "FILE_EXISTS");
|
|
267
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.FILE_EXISTS);
|
|
245
268
|
return false;
|
|
246
269
|
}
|
|
247
270
|
seenFiles.set(fileKey, file);
|
|
248
271
|
return true;
|
|
249
272
|
});
|
|
250
273
|
let filesToAdd = multiple ? uniqueFiles : uniqueFiles.slice(0, 1);
|
|
251
|
-
if (
|
|
252
|
-
const currentCount = currentFiles.length;
|
|
253
|
-
const remainingSlots = maxFiles - currentCount;
|
|
274
|
+
if (remainingSlots !== void 0) {
|
|
254
275
|
if (remainingSlots <= 0) {
|
|
255
|
-
filesToAdd.forEach((file) => {
|
|
256
|
-
addRejectedFile(file, "TOO_MANY_FILES");
|
|
257
|
-
});
|
|
258
276
|
filesToAdd = [];
|
|
259
277
|
} else if (filesToAdd.length > remainingSlots) {
|
|
260
278
|
filesToAdd.forEach((file) => {
|
|
261
|
-
addRejectedFile(file,
|
|
279
|
+
addRejectedFile(file, FILE_UPLOAD_ERRORS.TOO_MANY_FILES);
|
|
262
280
|
});
|
|
263
281
|
filesToAdd = [];
|
|
264
282
|
}
|
|
@@ -291,7 +309,7 @@ var FileUpload = ({
|
|
|
291
309
|
let updatedRejectedFiles = rejectedFiles;
|
|
292
310
|
if (maxFiles !== void 0 && updated.length < maxFiles) {
|
|
293
311
|
updatedRejectedFiles = rejectedFiles.filter(
|
|
294
|
-
(rejected) => !rejected.errors.includes(
|
|
312
|
+
(rejected) => !rejected.errors.includes(FILE_UPLOAD_ERRORS.TOO_MANY_FILES)
|
|
295
313
|
);
|
|
296
314
|
setRejectedFiles(updatedRejectedFiles);
|
|
297
315
|
}
|
|
@@ -310,7 +328,6 @@ var FileUpload = ({
|
|
|
310
328
|
}
|
|
311
329
|
setFiles([]);
|
|
312
330
|
setRejectedFiles([]);
|
|
313
|
-
deleteButtonRefs.current = [];
|
|
314
331
|
if (onFileChange) {
|
|
315
332
|
onFileChange({
|
|
316
333
|
acceptedFiles: [],
|
|
@@ -328,6 +345,82 @@ var FileUpload = ({
|
|
|
328
345
|
setRejectedFiles([]);
|
|
329
346
|
};
|
|
330
347
|
const maxFilesReached = maxFiles !== void 0 && files.length >= maxFiles;
|
|
348
|
+
return {
|
|
349
|
+
files,
|
|
350
|
+
rejectedFiles,
|
|
351
|
+
addFiles,
|
|
352
|
+
removeFile,
|
|
353
|
+
removeRejectedFile,
|
|
354
|
+
clearFiles,
|
|
355
|
+
clearRejectedFiles,
|
|
356
|
+
maxFilesReached
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/file-upload/FileUpload.tsx
|
|
361
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
362
|
+
var FileUploadContext = createContext(null);
|
|
363
|
+
var ID_PREFIX = ":file-upload";
|
|
364
|
+
var FileUpload = ({
|
|
365
|
+
asChild: _asChild = false,
|
|
366
|
+
children,
|
|
367
|
+
defaultValue = [],
|
|
368
|
+
value: controlledValue,
|
|
369
|
+
onFileAccept,
|
|
370
|
+
onFileReject,
|
|
371
|
+
onFileChange,
|
|
372
|
+
multiple = true,
|
|
373
|
+
accept,
|
|
374
|
+
maxFiles,
|
|
375
|
+
maxFileSize,
|
|
376
|
+
minFileSize,
|
|
377
|
+
disabled: disabledProp = false,
|
|
378
|
+
readOnly: readOnlyProp = false,
|
|
379
|
+
locale
|
|
380
|
+
}) => {
|
|
381
|
+
const field = useFormFieldControl();
|
|
382
|
+
const internalId = useId();
|
|
383
|
+
const inputId = field.id || `${ID_PREFIX}-${internalId}`;
|
|
384
|
+
const inputName = field.name;
|
|
385
|
+
const inputRef = useRef(null);
|
|
386
|
+
const triggerRef = useRef(null);
|
|
387
|
+
const dropzoneRef = useRef(null);
|
|
388
|
+
const deleteButtonRefs = useRef([]);
|
|
389
|
+
const rejectedFileDeleteButtonRefs = useRef([]);
|
|
390
|
+
const disabled = field.disabled ?? disabledProp;
|
|
391
|
+
const readOnly = field.readOnly ?? readOnlyProp;
|
|
392
|
+
const {
|
|
393
|
+
files,
|
|
394
|
+
rejectedFiles,
|
|
395
|
+
addFiles,
|
|
396
|
+
removeFile,
|
|
397
|
+
removeRejectedFile,
|
|
398
|
+
clearFiles: clearFilesFromHook,
|
|
399
|
+
clearRejectedFiles,
|
|
400
|
+
maxFilesReached
|
|
401
|
+
} = useFileUploadState({
|
|
402
|
+
defaultValue,
|
|
403
|
+
value: controlledValue,
|
|
404
|
+
onFileAccept,
|
|
405
|
+
onFileReject,
|
|
406
|
+
onFileChange,
|
|
407
|
+
multiple,
|
|
408
|
+
accept,
|
|
409
|
+
maxFiles,
|
|
410
|
+
maxFileSize,
|
|
411
|
+
minFileSize,
|
|
412
|
+
disabled,
|
|
413
|
+
readOnly,
|
|
414
|
+
locale
|
|
415
|
+
});
|
|
416
|
+
const clearFiles = () => {
|
|
417
|
+
clearFilesFromHook();
|
|
418
|
+
deleteButtonRefs.current = [];
|
|
419
|
+
};
|
|
420
|
+
const clearRejectedFilesWithRefs = () => {
|
|
421
|
+
clearRejectedFiles();
|
|
422
|
+
rejectedFileDeleteButtonRefs.current = [];
|
|
423
|
+
};
|
|
331
424
|
return /* @__PURE__ */ jsx(
|
|
332
425
|
FileUploadContext.Provider,
|
|
333
426
|
{
|
|
@@ -339,19 +432,20 @@ var FileUpload = ({
|
|
|
339
432
|
removeFile,
|
|
340
433
|
removeRejectedFile,
|
|
341
434
|
clearFiles,
|
|
342
|
-
clearRejectedFiles,
|
|
435
|
+
clearRejectedFiles: clearRejectedFilesWithRefs,
|
|
343
436
|
triggerRef,
|
|
344
437
|
dropzoneRef,
|
|
345
438
|
deleteButtonRefs,
|
|
439
|
+
rejectedFileDeleteButtonRefs,
|
|
346
440
|
multiple,
|
|
347
441
|
maxFiles,
|
|
348
442
|
maxFilesReached,
|
|
349
443
|
disabled,
|
|
350
444
|
readOnly,
|
|
351
|
-
locale:
|
|
352
|
-
description,
|
|
353
|
-
isInvalid,
|
|
354
|
-
isRequired
|
|
445
|
+
locale: locale || (typeof navigator !== "undefined" && navigator.language ? navigator.language : "en"),
|
|
446
|
+
description: field.description,
|
|
447
|
+
isInvalid: field.isInvalid,
|
|
448
|
+
isRequired: field.isRequired
|
|
355
449
|
},
|
|
356
450
|
children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
357
451
|
children,
|
|
@@ -367,10 +461,10 @@ var FileUpload = ({
|
|
|
367
461
|
accept,
|
|
368
462
|
disabled,
|
|
369
463
|
readOnly: readOnly && !disabled,
|
|
370
|
-
required: isRequired,
|
|
371
|
-
"aria-invalid": isInvalid,
|
|
372
|
-
"aria-describedby": description,
|
|
373
|
-
"aria-label": !labelId ? "Upload files
|
|
464
|
+
required: field.isRequired,
|
|
465
|
+
"aria-invalid": field.isInvalid,
|
|
466
|
+
"aria-describedby": field.description,
|
|
467
|
+
"aria-label": !field.labelId ? "Upload files" : void 0,
|
|
374
468
|
className: "sr-only",
|
|
375
469
|
onChange: (e) => {
|
|
376
470
|
if (e.target.files && !disabled && !readOnly) {
|
|
@@ -398,6 +492,7 @@ var useFileUploadContext = () => {
|
|
|
398
492
|
|
|
399
493
|
// src/file-upload/FileUploadAcceptedFile.tsx
|
|
400
494
|
import { cx as cx2 } from "class-variance-authority";
|
|
495
|
+
import { useCallback, useEffect, useState as useState2 } from "react";
|
|
401
496
|
|
|
402
497
|
// src/file-upload/FileUploadItemDeleteTrigger.tsx
|
|
403
498
|
import { Close } from "@spark-ui/icons/Close";
|
|
@@ -410,7 +505,16 @@ var ItemDeleteTrigger = ({
|
|
|
410
505
|
onClick,
|
|
411
506
|
...props
|
|
412
507
|
}) => {
|
|
413
|
-
const {
|
|
508
|
+
const {
|
|
509
|
+
removeFile,
|
|
510
|
+
triggerRef,
|
|
511
|
+
dropzoneRef,
|
|
512
|
+
deleteButtonRefs,
|
|
513
|
+
inputRef,
|
|
514
|
+
disabled,
|
|
515
|
+
readOnly,
|
|
516
|
+
files
|
|
517
|
+
} = useFileUploadContext();
|
|
414
518
|
const buttonRef = useRef2(null);
|
|
415
519
|
const fileIndex = files.findIndex((f) => f.name === file.name && f.size === file.size);
|
|
416
520
|
const handleClick = (e) => {
|
|
@@ -418,7 +522,7 @@ var ItemDeleteTrigger = ({
|
|
|
418
522
|
return;
|
|
419
523
|
}
|
|
420
524
|
removeFile(fileIndex);
|
|
421
|
-
|
|
525
|
+
requestAnimationFrame(() => {
|
|
422
526
|
const remainingButtons = deleteButtonRefs.current.filter(Boolean);
|
|
423
527
|
if (remainingButtons.length > 0) {
|
|
424
528
|
const targetIndex = Math.min(fileIndex, remainingButtons.length - 1);
|
|
@@ -427,12 +531,15 @@ var ItemDeleteTrigger = ({
|
|
|
427
531
|
nextButton.focus();
|
|
428
532
|
}
|
|
429
533
|
} else {
|
|
430
|
-
const focusTarget =
|
|
534
|
+
const focusTarget = findFocusableElement(
|
|
535
|
+
[triggerRef.current, dropzoneRef.current],
|
|
536
|
+
inputRef
|
|
537
|
+
);
|
|
431
538
|
if (focusTarget) {
|
|
432
539
|
focusTarget.focus();
|
|
433
540
|
}
|
|
434
541
|
}
|
|
435
|
-
}
|
|
542
|
+
});
|
|
436
543
|
onClick?.(e);
|
|
437
544
|
};
|
|
438
545
|
const setRef = (node) => {
|
|
@@ -469,7 +576,6 @@ ItemDeleteTrigger.displayName = "FileUpload.ItemDeleteTrigger";
|
|
|
469
576
|
// src/file-upload/FileUploadAcceptedFile.tsx
|
|
470
577
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
471
578
|
var AcceptedFile = ({
|
|
472
|
-
asChild: _asChild = false,
|
|
473
579
|
className,
|
|
474
580
|
file,
|
|
475
581
|
uploadProgress,
|
|
@@ -478,6 +584,17 @@ var AcceptedFile = ({
|
|
|
478
584
|
...props
|
|
479
585
|
}) => {
|
|
480
586
|
const { locale } = useFileUploadContext();
|
|
587
|
+
const [showProgress, setShowProgress] = useState2(uploadProgress !== void 0);
|
|
588
|
+
useEffect(() => {
|
|
589
|
+
if (uploadProgress !== void 0) {
|
|
590
|
+
setShowProgress(true);
|
|
591
|
+
} else {
|
|
592
|
+
setShowProgress(false);
|
|
593
|
+
}
|
|
594
|
+
}, [uploadProgress]);
|
|
595
|
+
const handleProgressComplete = useCallback(() => {
|
|
596
|
+
setShowProgress(false);
|
|
597
|
+
}, []);
|
|
481
598
|
return /* @__PURE__ */ jsxs2(
|
|
482
599
|
"li",
|
|
483
600
|
{
|
|
@@ -490,13 +607,19 @@ var AcceptedFile = ({
|
|
|
490
607
|
),
|
|
491
608
|
...props,
|
|
492
609
|
children: [
|
|
493
|
-
/* @__PURE__ */ jsx3("div", { className: "size-sz-
|
|
494
|
-
/* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
|
|
495
|
-
/* @__PURE__ */
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
610
|
+
/* @__PURE__ */ jsx3("div", { className: "size-sz-36 bg-support-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ jsx3(Icon, { size: "md", children: getFileIcon(file) }) }),
|
|
611
|
+
/* @__PURE__ */ jsxs2("div", { className: "gap-md relative flex min-w-0 flex-1 flex-row items-center justify-between self-stretch", children: [
|
|
612
|
+
/* @__PURE__ */ jsx3("p", { className: "text-body-2 truncate font-medium", children: file.name }),
|
|
613
|
+
/* @__PURE__ */ jsx3("p", { className: "text-caption opacity-dim-1", children: formatFileSize(file.size, locale) }),
|
|
614
|
+
showProgress && uploadProgress !== void 0 && /* @__PURE__ */ jsx3("div", { className: "absolute bottom-0 left-0 w-full", children: /* @__PURE__ */ jsx3(
|
|
615
|
+
Progress,
|
|
616
|
+
{
|
|
617
|
+
value: uploadProgress,
|
|
618
|
+
max: 100,
|
|
619
|
+
"aria-label": progressAriaLabel,
|
|
620
|
+
onComplete: handleProgressComplete
|
|
621
|
+
}
|
|
622
|
+
) })
|
|
500
623
|
] }),
|
|
501
624
|
/* @__PURE__ */ jsx3(ItemDeleteTrigger, { "aria-label": deleteButtonAriaLabel, file })
|
|
502
625
|
]
|
|
@@ -612,20 +735,19 @@ Dropzone.displayName = "FileUploadDropzone";
|
|
|
612
735
|
|
|
613
736
|
// src/file-upload/FileUploadPreviewImage.tsx
|
|
614
737
|
import { cx as cx4 } from "class-variance-authority";
|
|
615
|
-
import { useEffect, useState as
|
|
738
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
616
739
|
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
617
740
|
var PreviewImage = ({
|
|
618
|
-
asChild: _asChild = false,
|
|
619
741
|
className,
|
|
620
742
|
file,
|
|
621
743
|
fallback = "\u{1F4C4}",
|
|
622
744
|
...props
|
|
623
745
|
}) => {
|
|
624
|
-
const [imageError, setImageError] =
|
|
625
|
-
const [imageLoaded, setImageLoaded] =
|
|
746
|
+
const [imageError, setImageError] = useState3(false);
|
|
747
|
+
const [imageLoaded, setImageLoaded] = useState3(false);
|
|
626
748
|
const isImage = file.type.startsWith("image/");
|
|
627
749
|
const imageUrl = isImage ? URL.createObjectURL(file) : null;
|
|
628
|
-
|
|
750
|
+
useEffect2(() => {
|
|
629
751
|
return () => {
|
|
630
752
|
if (imageUrl) {
|
|
631
753
|
URL.revokeObjectURL(imageUrl);
|
|
@@ -685,7 +807,16 @@ var RejectedFileDeleteTrigger = ({
|
|
|
685
807
|
onClick,
|
|
686
808
|
...props
|
|
687
809
|
}) => {
|
|
688
|
-
const {
|
|
810
|
+
const {
|
|
811
|
+
removeRejectedFile,
|
|
812
|
+
triggerRef,
|
|
813
|
+
dropzoneRef,
|
|
814
|
+
rejectedFileDeleteButtonRefs,
|
|
815
|
+
inputRef,
|
|
816
|
+
disabled,
|
|
817
|
+
readOnly,
|
|
818
|
+
rejectedFiles
|
|
819
|
+
} = useFileUploadContext();
|
|
689
820
|
const buttonRef = useRef4(null);
|
|
690
821
|
const rejectedFileIndex = rejectedFiles.findIndex(
|
|
691
822
|
(rf) => rf.file.name === rejectedFile.file.name && rf.file.size === rejectedFile.file.size
|
|
@@ -695,18 +826,43 @@ var RejectedFileDeleteTrigger = ({
|
|
|
695
826
|
return;
|
|
696
827
|
}
|
|
697
828
|
removeRejectedFile(rejectedFileIndex);
|
|
698
|
-
|
|
699
|
-
const
|
|
700
|
-
if (
|
|
701
|
-
|
|
829
|
+
requestAnimationFrame(() => {
|
|
830
|
+
const remainingButtons = rejectedFileDeleteButtonRefs.current.filter(Boolean);
|
|
831
|
+
if (remainingButtons.length > 0) {
|
|
832
|
+
const targetIndex = Math.min(rejectedFileIndex, remainingButtons.length - 1);
|
|
833
|
+
const nextButton = remainingButtons[targetIndex];
|
|
834
|
+
if (nextButton) {
|
|
835
|
+
nextButton.focus();
|
|
836
|
+
}
|
|
837
|
+
} else {
|
|
838
|
+
const focusTarget = findFocusableElement(
|
|
839
|
+
[triggerRef.current, dropzoneRef.current],
|
|
840
|
+
inputRef
|
|
841
|
+
);
|
|
842
|
+
if (focusTarget) {
|
|
843
|
+
focusTarget.focus();
|
|
844
|
+
}
|
|
702
845
|
}
|
|
703
|
-
}
|
|
846
|
+
});
|
|
704
847
|
onClick?.(e);
|
|
705
848
|
};
|
|
849
|
+
const setRef = (node) => {
|
|
850
|
+
buttonRef.current = node;
|
|
851
|
+
if (node) {
|
|
852
|
+
while (rejectedFileDeleteButtonRefs.current.length <= rejectedFileIndex) {
|
|
853
|
+
rejectedFileDeleteButtonRefs.current.push(null);
|
|
854
|
+
}
|
|
855
|
+
rejectedFileDeleteButtonRefs.current[rejectedFileIndex] = node;
|
|
856
|
+
} else {
|
|
857
|
+
if (rejectedFileDeleteButtonRefs.current[rejectedFileIndex]) {
|
|
858
|
+
rejectedFileDeleteButtonRefs.current[rejectedFileIndex] = null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
};
|
|
706
862
|
return /* @__PURE__ */ jsx7(
|
|
707
863
|
IconButton,
|
|
708
864
|
{
|
|
709
|
-
ref:
|
|
865
|
+
ref: setRef,
|
|
710
866
|
"data-spark-component": "file-upload-rejected-file-delete-trigger",
|
|
711
867
|
className: cx5(className),
|
|
712
868
|
onClick: handleClick,
|
|
@@ -724,7 +880,6 @@ RejectedFileDeleteTrigger.displayName = "FileUpload.RejectedFileDeleteTrigger";
|
|
|
724
880
|
// src/file-upload/FileUploadRejectedFile.tsx
|
|
725
881
|
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
726
882
|
var RejectedFile = ({
|
|
727
|
-
asChild: _asChild = false,
|
|
728
883
|
className,
|
|
729
884
|
rejectedFile,
|
|
730
885
|
renderError,
|
|
@@ -745,7 +900,7 @@ var RejectedFile = ({
|
|
|
745
900
|
),
|
|
746
901
|
...props,
|
|
747
902
|
children: [
|
|
748
|
-
/* @__PURE__ */ jsx8("div", { className: "size-sz-
|
|
903
|
+
/* @__PURE__ */ jsx8("div", { className: "size-sz-36 bg-error-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ jsx8(Icon, { size: "md", className: "text-error", children: /* @__PURE__ */ jsx8(WarningOutline, {}) }) }),
|
|
749
904
|
/* @__PURE__ */ jsx8("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxs4("div", { className: "gap-md flex flex-col", children: [
|
|
750
905
|
/* @__PURE__ */ jsxs4("div", { className: "gap-md flex flex-row items-center justify-between", children: [
|
|
751
906
|
/* @__PURE__ */ jsx8("p", { className: "text-body-2 truncate font-medium", children: rejectedFile.file.name }),
|
|
@@ -863,6 +1018,7 @@ AcceptedFile.displayName = "FileUpload.AcceptedFile";
|
|
|
863
1018
|
RejectedFile.displayName = "FileUpload.RejectedFile";
|
|
864
1019
|
RejectedFileDeleteTrigger.displayName = "FileUpload.RejectedFileDeleteTrigger";
|
|
865
1020
|
export {
|
|
1021
|
+
FILE_UPLOAD_ERRORS,
|
|
866
1022
|
FileUpload2 as FileUpload
|
|
867
1023
|
};
|
|
868
1024
|
//# sourceMappingURL=index.mjs.map
|