import * as React from 'react'; import { Upload, X, FileIcon, AlertCircle } from 'lucide-react'; import { cn } from '../../shared/utils'; import { Button } from '../button'; import { useFileUpload } from './use-file-upload'; interface FileUploadProps extends Omit< React.InputHTMLAttributes, 'onChange' | 'onError' > { onFilesChange?: (files: File[]) => void; maxFiles?: number; maxSize?: number; // in bytes showPreview?: boolean; /** Called when files are rejected due to size or count limits. */ onError?: (rejectedFiles: File[], reason: 'size' | 'count') => void; } /** * Drag-and-drop file input with preview list. * * @description * Manages selected file state and provides a standardized, accessible interface * for file uploads. Supports click-to-browse and drag-and-drop. Shows a preview * list of selected files with per-file remove buttons. * * Headless logic is available via `useFileUpload` for custom drop-zone UIs. * * @ai-rules * 1. Use `onFilesChange` to capture the selected files array in your form state. * 2. `maxFiles` defaults to 1 (single file). Set to a higher number for multi-upload. * 3. `maxSize` is in bytes (default: 5MB). Files exceeding the limit trigger `onError` and show an inline error. * 4. Set `showPreview={false}` if you manage the file list externally. * 5. Use `onError` to handle rejected files (e.g., show a toast notification). */ const FileUpload = React.forwardRef( ( { className, onFilesChange, maxFiles = 1, maxSize = 5 * 1024 * 1024, // 5MB default showPreview = true, onError, accept, disabled, ...props }, ref ) => { const { files, dragActive, errorMessage, inputRef, handleDrag, handleDrop, handleChange, removeFile, openFileDialog, } = useFileUpload({ maxFiles, maxSize, onFilesChange, onError, disabled }); return (

Click to upload or drag and drop

{maxFiles > 1 ? `Up to ${maxFiles} files` : '1 file'} • Max{' '} {(maxSize / 1024 / 1024).toFixed(0)}MB

1} accept={accept} disabled={disabled} />
{errorMessage && (
{errorMessage}
)} {showPreview && files.length > 0 && (
{files.map((file, index) => (

{file.name}

{(file.size / 1024).toFixed(2)} KB

))}
)}
); } ); FileUpload.displayName = 'FileUpload'; export { FileUpload }; export type { FileUploadProps };