{ "name": "file-upload", "type": "registry:component", "dependencies": [ "lucide-react", "motion" ], "files": [ { "type": "registry:component", "content": "\"use client\";\n\n/**\n * @author: @dorianbaffier\n * @description: File Upload\n * @version: 1.0.0\n * @date: 2025-06-26\n * @license: MIT\n * @website: https://kokonutui.com\n * @github: https://github.com/kokonut-labs/kokonutui\n */\n\nimport { UploadCloud } from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport {\n type DragEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ntype FileStatus = \"idle\" | \"dragging\" | \"uploading\" | \"error\";\n\ninterface FileError {\n message: string;\n code: string;\n}\n\ninterface FileUploadProps {\n onUploadSuccess?: (file: File) => void;\n onUploadError?: (error: FileError) => void;\n acceptedFileTypes?: string[];\n maxFileSize?: number;\n currentFile?: File | null;\n onFileRemove?: () => void;\n /** Duration in milliseconds for the upload simulation. Defaults to 2000ms (2s), 0 for no simulation */\n uploadDelay?: number;\n validateFile?: (file: File) => FileError | null;\n className?: string;\n}\n\nconst DEFAULT_MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB\nconst UPLOAD_STEP_SIZE = 5;\nconst FILE_SIZES = [\n \"Bytes\",\n \"KB\",\n \"MB\",\n \"GB\",\n \"TB\",\n \"PB\",\n \"EB\",\n \"ZB\",\n \"YB\",\n] as const;\n\nconst formatBytes = (bytes: number, decimals = 2): string => {\n if (!+bytes) return \"0 Bytes\";\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const unit = FILE_SIZES[i] || FILE_SIZES[FILE_SIZES.length - 1];\n return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${unit}`;\n};\n\nconst UploadIllustration = () => (\n
\n {acceptedFileTypes?.length\n ? `${acceptedFileTypes\n .map((t) => t.split(\"/\")[1])\n .join(\", \")\n .toUpperCase()}`\n : \"SVG, PNG, JPG or GIF\"}{\" \"}\n {maxFileSize && `up to ${formatBytes(maxFileSize)}`}\n
\n\n or drag and drop your file here\n
\n\n \n\n {error.message}\n
\n