export type FileIntakeErrorCode = 'FILE_INVALID_TYPE' | 'FILE_TOO_LARGE' | 'FILE_TOO_SMALL' | 'TOO_MANY_FILES' | 'FILE_EXISTS' | 'CUSTOM'; export interface FileIntakeError { /** Machine-readable error code. */ code: FileIntakeErrorCode; /** Human-readable error message. */ message: string; } export type FileIntakeStatus = 'pending' | 'uploading' | 'complete' | 'error'; export interface FileIntakeEntry { /** Unique identifier for this file entry. */ id: string; /** The native File object. */ file: File; /** Object URL for image previews (auto-generated, auto-revoked). */ preview?: string; /** Upload progress 0–100. Undefined when not tracking. */ progress?: number; /** Current lifecycle status. */ status: FileIntakeStatus; /** Validation or upload errors. */ errors: FileIntakeError[]; } export interface FileIntakeRejection { /** The rejected file. */ file: File; /** Why it was rejected. */ errors: FileIntakeError[]; } /** Validation limits shared by every intake surface. */ export interface FileIntakeConstraints { /** Accepted MIME types or file extensions (e.g. 'image/*', '.pdf'). */ accept?: string | string[]; /** Maximum number of files across the whole list. */ maxFiles?: number; /** Maximum file size in bytes. */ maxFileSize?: number; /** Minimum file size in bytes. */ minFileSize?: number; /** Custom validation function. Return errors array or null. */ validate?: (file: File) => FileIntakeError[] | null; } /** Error-text factories — components inject their i18n/label source here. */ export interface FileIntakeMessages { invalidType: (type: string) => string; tooLarge: (formattedSize: string) => string; tooSmall: (formattedSize: string) => string; exists: () => string; tooMany: (count: number) => string; } /** Does a picked/dropped file match the accept spec (`.ext`, `type/*`, exact MIME)? */ export declare function matchesAccept(file: File, accept: string | string[] | undefined): boolean; /** * Dragged-over feedback: do ALL items look acceptable? Extension patterns * (`.pdf`) match permissively — file names are unavailable during dragenter, * so a definitive verdict only exists for MIME patterns. */ export declare function dragItemsMatchAccept(items: Iterable, accept: string | string[] | undefined): boolean; /** Validate one file against the constraints and the existing list (duplicates). */ export declare function validateIntakeFile(file: File, existing: readonly FileIntakeEntry[], constraints: FileIntakeConstraints, messages: FileIntakeMessages): FileIntakeError[]; /** * Split incoming files into accepted entries (id + pending status + image * preview object-URL) and rejections. Files beyond the remaining `maxFiles` * budget are rejected with `TOO_MANY_FILES` before any validation runs. * The caller owns the returned entries — including revoking their previews * (`revokeIntakePreviews`) when they leave the list. */ export declare function partitionIntake(incoming: readonly File[], existing: readonly FileIntakeEntry[], constraints: FileIntakeConstraints, messages: FileIntakeMessages, idPrefix?: string): { accepted: FileIntakeEntry[]; rejected: FileIntakeRejection[]; }; /** Wrap a (pre-validated) file as a pending entry with id and image preview. */ export declare function createIntakeEntry(file: File, idPrefix?: string): FileIntakeEntry; /** Revoke the preview object-URLs of the given entries (removal/teardown). */ export declare function revokeIntakePreviews(entries: Iterable): void; /** Human-readable file size (`1.5 MB`). Empty string for non-finite values. */ export declare function formatFileSize(bytes: number): string; /** Is this file an image (drives preview object-URL creation)? */ export declare function isImageFile(file: File): boolean;