export type FileRejectReason = 'type' | 'size' | 'count';
export type FileRejection = {
file: File;
reason: FileRejectReason;
};
/** Reactive inputs are passed as getters so the core tracks live prop changes. */
export type FileUploadConfig = {
files: () => File[];
onChange?: (files: File[]) => void;
/** Rejected files (wrong type / too big / over the count cap). */
onReject?: (rejections: FileRejection[]) => void;
/** Comma list like "image/*,.pdf" (matches MIME or extension). */
accept?: () => string | undefined;
multiple?: () => boolean;
/** Max size per file in bytes. */
maxSize?: () => number | undefined;
/** Max number of files (multiple mode). */
maxFiles?: () => number | undefined;
disabled?: () => boolean;
readonly?: () => boolean;
id?: () => string | undefined;
invalid?: () => boolean;
required?: () => boolean;
error?: () => string | undefined;
hint?: () => string | undefined;
ariaLabel?: () => string | undefined;
};
/** Whether `file` satisfies an `accept` list (MIME globs or extensions). Pure. */
export declare function fileMatchesAccept(file: File, accept?: string): boolean;
export declare function createFileUpload(config: FileUploadConfig): {
/** Whether files are being dragged over the dropzone. */
readonly dragging: boolean;
/** Whether interaction is allowed. */
readonly isInteractive: boolean;
/** Selected files (controlled value). */
readonly files: File[];
addFiles: (incoming: File[]) => void;
removeAt: (index: number) => void;
clear: () => void;
setDragging: (v: boolean) => void;
/** Spread onto the dropzone element (click opens the picker; Enter/Space too).
* Wire drag events yourself (they carry a DataTransfer): call
* `setDragging(true/false)` and `addFiles([...e.dataTransfer.files])`. */
dropzoneProps: () => {
'aria-invalid': "true" | undefined;
'aria-required': "true" | undefined;
'aria-describedby': string | undefined;
'aria-label': string | undefined;
role: "button";
tabindex: number;
'data-dragging': string | undefined;
'aria-disabled': true | undefined;
};
/** Spread onto the visually-hidden . */
inputProps: () => {
type: "file";
accept: string | undefined;
multiple: boolean;
disabled: boolean;
tabindex: number;
};
/** Spread onto a selected file's remove