UNPKG

react-muntaha-uploader

Version:

A flexible, feature-rich React hook for robust file uploads with drag-and-drop, folder support, validation, progress tracking, abort, and more.

134 lines (133 loc) 9.09 kB
import React from 'react'; /** * Union type representing all supported MIME types for file uploads. * Includes categories for images, videos, audio, documents, archives, fonts, and more. */ type MimeType = 'image/*' | 'image/apng' | 'image/avif' | 'image/bmp' | 'image/cgm' | 'image/dicom-rle' | 'image/emf' | 'image/fits' | 'image/g3fax' | 'image/gif' | 'image/heic' | 'image/heif' | 'image/ief' | 'image/jls' | 'image/jp2' | 'image/jpeg' | 'image/jpg' | 'image/jph' | 'image/jpm' | 'image/jpx' | 'image/ktx' | 'image/png' | 'image/prs.btif' | 'image/prs.pti' | 'image/svg+xml' | 'image/t38' | 'image/tiff' | 'image/vnd.adobe.photoshop' | 'image/vnd.airzip.accelerator.azv' | 'image/vnd.cns.inf2' | 'image/vnd.djvu' | 'image/vnd.dwg' | 'image/vnd.dxf' | 'image/vnd.fastbidsheet' | 'image/vnd.fpx' | 'image/vnd.fst' | 'image/vnd.fujixerox.edmics-mmr' | 'image/vnd.fujixerox.edmics-rlc' | 'image/vnd.ms-modi' | 'image/vnd.net-fpx' | 'image/vnd.pco.b16' | 'image/vnd.tencent.tap' | 'image/vnd.valve.source.texture' | 'image/vnd.wap.wbmp' | 'image/vnd.xiff' | 'image/webp' | 'image/wmf' | 'image/x-cmu-raster' | 'image/x-cmx' | 'image/x-freehand' | 'image/x-icon' | 'image/x-jng' | 'image/x-mrsid-image' | 'image/x-pcx' | 'image/x-pict' | 'image/x-portable-anymap' | 'image/x-portable-bitmap' | 'image/x-portable-graymap' | 'image/x-portable-pixmap' | 'image/x-rgb' | 'image/x-xbitmap' | 'image/x-xpixmap' | 'image/x-xwindowdump' | 'video/*' | 'video/3gpp' | 'video/3gpp2' | 'video/h261' | 'video/h263' | 'video/h264' | 'video/jpeg' | 'video/jpm' | 'video/mj2' | 'video/mp4' | 'video/mpeg' | 'video/ogg' | 'video/quicktime' | 'video/vnd.dece.hd' | 'video/vnd.dece.mobile' | 'video/vnd.dece.pd' | 'video/vnd.dece.sd' | 'video/vnd.dece.video' | 'video/vnd.dvb.file' | 'video/vnd.fvt' | 'video/vnd.mpegurl' | 'video/vnd.ms-playready.media.pyv' | 'video/vnd.uvvu.mp4' | 'video/vnd.vivo' | 'video/webm' | 'video/x-f4v' | 'video/x-flv' | 'video/x-m4v' | 'video/x-ms-asf' | 'video/x-ms-wm' | 'video/x-ms-wmv' | 'video/x-ms-wmx' | 'video/x-ms-wvx' | 'video/x-msvideo' | 'video/x-sgi-movie' | 'audio/*' | 'audio/aac' | 'audio/ac3' | 'audio/adpcm' | 'audio/basic' | 'audio/midi' | 'audio/mp3' | 'audio/mp4' | 'audio/mpeg' | 'audio/ogg' | 'audio/opus' | 'audio/vorbis' | 'audio/wav' | 'audio/webm' | 'audio/x-aiff' | 'audio/x-mpegurl' | 'audio/x-ms-wax' | 'audio/x-ms-wma' | 'audio/x-pn-realaudio' | 'audio/x-wav' | 'application/*' | 'application/pdf' | 'application/msword' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/vnd.ms-powerpoint' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'application/rtf' | 'text/plain' | 'text/csv' | 'text/html' | 'text/css' | 'text/javascript' | 'application/json' | 'application/xml' | 'application/zip' | 'application/x-7z-compressed' | 'application/x-rar-compressed' | 'application/x-tar' | 'application/x-bzip' | 'application/x-bzip2' | 'application/gzip' | 'font/*' | 'font/otf' | 'font/ttf' | 'font/woff' | 'font/woff2' | 'application/x-httpd-php' | 'application/x-java-archive' | 'application/x-python-code' | 'application/x-ruby' | 'application/x-perl' | 'application/x-sh' | 'application/typescript' | 'application/javascript' | 'application/vnd.oasis.opendocument.text' | 'application/vnd.oasis.opendocument.spreadsheet' | 'application/vnd.oasis.opendocument.presentation' | 'application/vnd.oasis.opendocument.graphics' | 'application/vnd.oasis.opendocument.chart' | 'application/vnd.oasis.opendocument.formula' | 'application/vnd.oasis.opendocument.database' | '*'; /** * Represents the state of files based on whether multiple files are allowed. * @template T - Boolean indicating if multiple files are allowed */ type FileState<T extends boolean> = T extends true ? File[] : File | null; /** * Represents the state of ArrayBuffer data based on whether multiple files are allowed. * @template T - Boolean indicating if multiple files are allowed */ type ArrayBufferState<T extends boolean> = T extends true ? ArrayBuffer[] : ArrayBuffer | null; /** * Configuration options for the drop zone hook * @template T - Boolean indicating if multiple files are allowed */ interface DropZoneOptions<T extends boolean> { /** Accepted MIME types for the files */ accept?: MimeType[]; /** Minimum file size in bytes */ minSize?: number; /** Maximum file size in bytes */ maxSize?: number; /** Maximum number of files allowed (only applicable when multiple is true) */ maxFiles?: number; /** Whether multiple files are allowed */ multiple?: T; /** Whether the drop zone is disabled */ disabled?: boolean; /** Whether to read files as ArrayBuffer */ isArrayBuffer?: boolean; /** Callback when files are dropped/selected */ onDrop?: (files: FileState<T>) => void; /** Callback when an error occurs */ onError?: (err: string | null) => void; /** Enable folder upload (requires browser support) */ enableFolderUpload?: boolean; /** Enable keyboard navigation */ enableKeyboard?: boolean; } /** * The enhanced state and methods returned by the useDrop hook with abort support * @template T - Boolean indicating if multiple files are allowed */ interface EnhancedDropZoneState<T extends boolean> { /** Current error message, if any */ error: string | null; /** Upload progress (single number or record of indices to progress) */ progress: number | Record<number, number>; /** The current files */ files: FileState<T>; /** ArrayBuffer representations of files (if isArrayBuffer is true) */ arrayBuffer: ArrayBufferState<T>; /** Whether files are currently being dragged over the drop zone */ isDragActive: boolean; /** Function to remove files (optionally by index) */ onDelete: (index?: number) => void; /** Aborts all current upload operations */ abortUpload: () => void; /** Current upload status */ status: 'idle' | 'reading' | 'aborted' | 'error'; /** Utility functions */ utils: { /** Get file(s) by index or all files */ getFile: (index?: number) => FileState<T>; /** Get ArrayBuffer(s) by index or all ArrayBuffers */ getData: (index?: number) => ArrayBufferState<T>; /** Get progress by index or all progress */ getProgress: (index?: number) => number | Record<number, number>; reset: () => void; }; /** Props to spread on the root drop zone element */ getRootProps: () => { /** Ref for the root element */ ref: React.RefObject<HTMLDivElement>; /** Click handler */ onClick: () => void; /** Drag enter handler */ onDragEnter: (e: React.DragEvent<HTMLDivElement>) => void; /** Drag over handler */ onDragOver: (e: React.DragEvent<HTMLDivElement>) => void; /** Drag leave handler */ onDragLeave: (e: React.DragEvent<HTMLDivElement>) => void; /** Drop handler */ onDrop: (e: React.DragEvent<HTMLDivElement>) => void; /** Data attribute indicating drag active state */ /** Data attribute indicating drag state */ 'data-dragging': boolean; /** Data attribute indicating disabled state */ 'data-disabled': boolean; /** Data attribute indicating error state */ 'data-has-error': boolean; /** Accessible label for screen readers */ 'aria-label': string; /** Indicates whether the element is disabled for assistive technologies */ 'aria-disabled': boolean; }; /** Props to spread on the hidden file input element */ getInputProps: () => { /** Ref for the input element */ ref: React.RefObject<HTMLInputElement>; /** Input type */ type: 'file'; /** Input style */ style: { display: 'none'; }; /** Accepted MIME types */ accept?: string; /** Whether multiple files are allowed */ multiple?: boolean; /** Whether input is disabled */ disabled?: boolean; /** Change handler */ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; /** Allows users to select an entire directory (WebKit-specific) */ webkitdirectory?: string; /** Allows users to select an entire directory (non-standard, used in some browsers) */ directory?: string; }; } /** * A custom React hook for handling file drops and uploads with validation, progress tracking, and abort support. * @template T - A boolean type indicating whether multiple files are allowed (defaults to true) * @param {DropZoneOptions<T>} options - Configuration options for the drop zone * @returns {EnhancedDropZoneState<T>} An object containing state and utility functions for the drop zone */ declare const useMuntahaDrop: <T extends boolean = true>(options?: DropZoneOptions<T>) => EnhancedDropZoneState<T>; export { useMuntahaDrop };