@arcfusionz/arc-primitive-ui 0.2.15 → 0.2.17
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.
|
@@ -37,20 +37,12 @@ declare function formatFileSize(bytes: number): string;
|
|
|
37
37
|
interface FileUploadHandle {
|
|
38
38
|
/** The currently selected files. */
|
|
39
39
|
files: File[];
|
|
40
|
-
/** Number of selected files. */
|
|
41
|
-
fileCount: number;
|
|
42
40
|
/** A file is being dragged over the dropzone. */
|
|
43
41
|
isDragging: boolean;
|
|
44
42
|
/** The upload is disabled. */
|
|
45
43
|
disabled: boolean;
|
|
46
44
|
/** The upload is marked invalid. */
|
|
47
45
|
invalid: boolean;
|
|
48
|
-
/** Effective file cap (multiple mode only); `undefined` when unlimited or single. */
|
|
49
|
-
maxFiles?: number;
|
|
50
|
-
/** Slots left before `maxFiles`; `undefined` when there is no cap. */
|
|
51
|
-
remainingFiles?: number;
|
|
52
|
-
/** The selection has reached `maxFiles`. */
|
|
53
|
-
isAtMaxFiles: boolean;
|
|
54
46
|
/** Open the native file picker. */
|
|
55
47
|
open: () => void;
|
|
56
48
|
/** Remove one file from the selection. */
|
|
@@ -105,7 +97,7 @@ interface FileUploadProps extends Omit<ComponentPropsWithoutRef<"div">, "classNa
|
|
|
105
97
|
name?: string;
|
|
106
98
|
/** Accessible name for the hidden file input. */
|
|
107
99
|
inputLabel?: string;
|
|
108
|
-
/** Replace the rendered root `div` or inspect `{ dragging, disabled, invalid, empty }`. */
|
|
100
|
+
/** Replace the rendered root `div` or inspect `{ dragging, disabled, invalid, empty, atMax }`. */
|
|
109
101
|
render?: useRender.RenderProp<FileUploadRenderState>;
|
|
110
102
|
/** Compose the pieces: `FileUploadDropzone`, `FileUploadList`, `FileUploadTrigger`. */
|
|
111
103
|
children?: ReactNode;
|
|
@@ -198,7 +190,7 @@ interface FileUploadItemProps extends Omit<ComponentPropsWithoutRef<"li">, "clas
|
|
|
198
190
|
progress?: number;
|
|
199
191
|
/** Detailed message shown while `status="error"`, in place of the size. */
|
|
200
192
|
error?: ReactNode;
|
|
201
|
-
/** Short visible
|
|
193
|
+
/** Short visible, accessible status label. Defaults per `status` ("Uploading", "Uploaded", "Failed"); pass to override the copy. This is not a live-region announcement. */
|
|
202
194
|
statusLabel?: ReactNode;
|
|
203
195
|
/** Show the remove button. Defaults to `true`. */
|
|
204
196
|
removable?: boolean;
|
|
@@ -206,6 +198,12 @@ interface FileUploadItemProps extends Omit<ComponentPropsWithoutRef<"li">, "clas
|
|
|
206
198
|
onRemove?: () => void;
|
|
207
199
|
/** Accessible name for the remove button. Defaults to `Remove {file name}`. */
|
|
208
200
|
removeLabel?: string;
|
|
201
|
+
/**
|
|
202
|
+
* Replace the leading visual completely. This compatibility escape hatch
|
|
203
|
+
* takes precedence over `previewSrc`; the consumer owns its presentation and
|
|
204
|
+
* accessibility. Prefer `previewSrc` when a standard thumbnail is sufficient.
|
|
205
|
+
*/
|
|
206
|
+
preview?: ReactNode;
|
|
209
207
|
/** URL of a preview image (e.g. a server-side thumbnail). The primitive owns the dimensions, radius, `object-fit`, decorative attributes, and drag prevention — you supply only the URL. Falls back to a file icon when omitted, non-image, or the image fails to load. */
|
|
210
208
|
previewSrc?: string;
|
|
211
209
|
/** Replace the entire row body. */
|
|
@@ -58,13 +58,9 @@ function useFileUpload() {
|
|
|
58
58
|
const context = useFileUploadContext("useFileUpload");
|
|
59
59
|
return {
|
|
60
60
|
files: context.files,
|
|
61
|
-
fileCount: context.fileCount,
|
|
62
61
|
isDragging: context.isDragging,
|
|
63
62
|
disabled: context.disabled,
|
|
64
63
|
invalid: context.invalid,
|
|
65
|
-
maxFiles: context.maxFiles,
|
|
66
|
-
remainingFiles: context.remainingFiles,
|
|
67
|
-
isAtMaxFiles: context.isAtMaxFiles,
|
|
68
64
|
open: context.openPicker,
|
|
69
65
|
remove: context.removeFile,
|
|
70
66
|
clear: context.clear
|
|
@@ -430,7 +426,7 @@ const itemStatusColors = {
|
|
|
430
426
|
* consumer-driven so the row reflects real upload state; the component shows
|
|
431
427
|
* failures but does not itself retry.
|
|
432
428
|
*/
|
|
433
|
-
const FileUploadItem = forwardRef(({ file, status = "idle", progress, error, statusLabel, removable = true, onRemove, removeLabel, previewSrc, children, className, ...rest }, ref) => {
|
|
429
|
+
const FileUploadItem = forwardRef(({ file, status = "idle", progress, error, statusLabel, removable = true, onRemove, removeLabel, preview, previewSrc, children, className, ...rest }, ref) => {
|
|
434
430
|
const context = useFileUploadContext("FileUploadItem");
|
|
435
431
|
const handleRemove = onRemove ?? (() => context.removeFile(file));
|
|
436
432
|
const resolvedStatusLabel = statusLabel !== void 0 ? statusLabel : itemStatusLabels[status] || null;
|
|
@@ -443,7 +439,7 @@ const FileUploadItem = forwardRef(({ file, status = "idle", progress, error, sta
|
|
|
443
439
|
children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
444
440
|
/* @__PURE__ */ jsx("span", {
|
|
445
441
|
className: "shrink-0",
|
|
446
|
-
children: /* @__PURE__ */ jsx(FileUploadThumbnail, {
|
|
442
|
+
children: preview ?? /* @__PURE__ */ jsx(FileUploadThumbnail, {
|
|
447
443
|
file,
|
|
448
444
|
src: previewSrc
|
|
449
445
|
})
|
|
@@ -500,9 +496,8 @@ const thumbnailImageClasses = "size-10 rounded-md object-cover";
|
|
|
500
496
|
const thumbnailFallbackClasses = "flex size-10 items-center justify-center rounded-md bg-muted text-muted-foreground";
|
|
501
497
|
function FileUploadThumbnail({ file, src }) {
|
|
502
498
|
const [autoUrl, setAutoUrl] = useState(null);
|
|
503
|
-
const [
|
|
499
|
+
const [failedSrc, setFailedSrc] = useState(null);
|
|
504
500
|
useEffect(() => {
|
|
505
|
-
setFailed(false);
|
|
506
501
|
if (src != null || !file.type.startsWith("image/") || !canUseObjectUrl()) {
|
|
507
502
|
setAutoUrl(null);
|
|
508
503
|
return;
|
|
@@ -512,13 +507,13 @@ function FileUploadThumbnail({ file, src }) {
|
|
|
512
507
|
return () => URL.revokeObjectURL(objectUrl);
|
|
513
508
|
}, [file, src]);
|
|
514
509
|
const resolvedSrc = src ?? autoUrl;
|
|
515
|
-
if (resolvedSrc != null &&
|
|
510
|
+
if (resolvedSrc != null && failedSrc !== resolvedSrc) return /* @__PURE__ */ jsx("img", {
|
|
516
511
|
src: resolvedSrc,
|
|
517
512
|
alt: "",
|
|
518
513
|
"aria-hidden": "true",
|
|
519
514
|
className: thumbnailImageClasses,
|
|
520
515
|
draggable: false,
|
|
521
|
-
onError: () =>
|
|
516
|
+
onError: () => setFailedSrc(resolvedSrc)
|
|
522
517
|
});
|
|
523
518
|
return /* @__PURE__ */ jsx("span", {
|
|
524
519
|
className: thumbnailFallbackClasses,
|