UNPKG

react-filezone

Version:

filezone: A Robust, Flexible React File Upload Library with Advanced Features and Seamless User Experience

335 lines (288 loc) 9.12 kB
# react-filezone A powerful, flexible React file upload library with advanced features and a seamless user experience. ## 🚀 Features - Multiple and single file upload modes - Advanced file type and size validation - Detailed upload progress tracking - Concurrent upload support - Robust error handling - Full TypeScript support - Drag and drop functionality - Customizable file preview generation ## 📦 Installation ```bash npm install react-filezone # or yarn add react-filezone ``` ## 🔧 Configuration Options ### Global Configuration | Option | Type | Default | Description | |--------|------|---------|-------------| | `mode` | 'single' \| 'multiple' | 'multiple' | Upload mode | | `maxFiles` | number | 3 | Maximum number of files | | `maxFileSize` | number | 10GB | Maximum file size in bytes | | `allowedFileTypes` | string[] | ['*/*'] | Allowed MIME types | | `maxConcurrentUploads` | number | 5 | Maximum concurrent uploads | | `disabled` | boolean | false | Disable file upload | ## 📝 Usage Examples ### 1. Basic Image Upload ```tsx import React from 'react'; import { useUpload } from 'react-filezone'; const BasicImageUploader: React.FC = () => { const { acceptedFiles, errors, getRootProps, getInputProps, removeFile } = useUpload({ action: '/api/upload', globalConfig: { allowedFileTypes: ['image/*'], maxFiles: 5, maxFileSize: 5 * 1024 * 1024 // 5MB }, onUploadComplete: (data) => { console.log('Upload complete:', data); } }); return ( <div> <div {...getRootProps()} className="dropzone"> <input {...getInputProps()} /> <p>Drag and drop images here, or click to select</p> </div> {errors.map((error, index) => ( <div key={index} className="error">{error}</div> ))} <div className="preview-container"> {acceptedFiles.map((file) => ( <div key={file.id} className="file-preview"> {file.previewUrl && ( <img src={file.previewUrl} alt={file.file.name} className="thumbnail" /> )} <div className="file-info"> <p>{file.file.name}</p> <p>Progress: {file.state.progress}%</p> <button onClick={() => removeFile(file.id)}>Remove</button> </div> </div> ))} </div> </div> ); }; export default BasicImageUploader; ``` ### 2. Professional Document Upload with Custom Headers ```tsx import React, { useState } from 'react'; import { useUpload } from 'react-filezone'; const DocumentUploader: React.FC = () => { const [userId, setUserId] = useState(''); const { acceptedFiles, errors, getRootProps, getInputProps, removeFile, uploadFile } = useUpload({ action: '/api/upload-documents', headers: { 'X-User-ID': userId, 'Authorization': `Bearer ${localStorage.getItem('token')}` }, globalConfig: { allowedFileTypes: [ 'application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ], maxFiles: 3, maxFileSize: 10 * 1024 * 1024 // 10MB }, onUploadStart: (files) => { console.log('Starting upload for:', files.map(f => f.file.name)); }, onUploadComplete: (data) => { alert('Documents uploaded successfully!'); }, onError: (error, file) => { console.error(`Upload failed for ${file.file.name}:`, error); } }); return ( <div> <input type="text" placeholder="Enter User ID" value={userId} onChange={(e) => setUserId(e.target.value)} /> <div {...getRootProps()} className="document-dropzone"> <input {...getInputProps()} /> <p>Drag and drop documents here, or click to select</p> </div> {errors.map((error, index) => ( <div key={index} className="error">{error}</div> ))} <div className="document-list"> {acceptedFiles.map((file) => ( <div key={file.id} className="document-item"> <p>{file.file.name}</p> <p>Size: {(file.file.size / 1024).toFixed(2)} KB</p> <p>Status: {file.state.status}</p> <p>Progress: {file.state.progress}%</p> <div className="actions"> <button onClick={() => removeFile(file.id)}>Remove</button> {file.state.status === 'error' && ( <button onClick={() => uploadFile(file.id)}>Retry</button> )} </div> </div> ))} </div> </div> ); }; export default DocumentUploader; ``` ### 3. Multi-Type File Upload with Strict Validation ```tsx import React from 'react'; import { useUpload } from 'react-filezone'; const MultiTypeUploader: React.FC = () => { const { acceptedFiles, errors, getRootProps, getInputProps, removeFile } = useUpload({ action: '/api/upload-multi', globalConfig: { mode: 'multiple', allowedFileTypes: [ 'image/*', 'video/mp4', 'application/pdf', 'text/plain' ], maxFiles: 10, maxFileSize: 50 * 1024 * 1024 // 50MB }, onUploadComplete: (data) => { console.log('Multi-type files uploaded:', data); } }); const renderFilePreview = (file: FileState) => { if (file.previewUrl && file.file.type.startsWith('image/')) { return <img src={file.previewUrl} alt={file.file.name} />; } if (file.videoPreviewUrl && file.file.type.startsWith('video/')) { return <video src={file.videoPreviewUrl} controls />; } return <p>{file.file.name}</p>; }; return ( <div> <div {...getRootProps()} className="multi-dropzone"> <input {...getInputProps()} /> <p>Drag and drop multiple file types, or click to select</p> </div> {errors.map((error, index) => ( <div key={index} className="error">{error}</div> ))} <div className="file-grid"> {acceptedFiles.map((file) => ( <div key={file.id} className="file-item"> {renderFilePreview(file)} <div className="file-details"> <p>{file.file.name}</p> <p>Type: {file.file.type}</p> <p>Progress: {file.state.progress}%</p> <button onClick={() => removeFile(file.id)}>Remove</button> </div> </div> ))} </div> </div> ); }; export default MultiTypeUploader; ``` ### 4. Single File Mode with Disabled State ```tsx import React from 'react'; import { useUpload } from 'react-filezone'; const ProfilePictureUploader: React.FC = () => { const { acceptedFiles, errors, getRootProps, getInputProps, removeFile } = useUpload({ action: '/api/upload-profile-pic', globalConfig: { mode: 'single', allowedFileTypes: ['image/*'], maxFileSize: 2 * 1024 * 1024, // 2MB disabled: false // Can be dynamically set based on conditions } }); return ( <div> <div {...getRootProps()} className="profile-dropzone"> <input {...getInputProps()} /> <p>Click or drag a profile picture</p> </div> {errors.map((error, index) => ( <div key={index} className="error">{error}</div> ))} {acceptedFiles[0] && ( <div className="profile-preview"> <img src={acceptedFiles[0].previewUrl} alt="Profile" className="profile-image" /> <button onClick={() => removeFile(acceptedFiles[0].id)}> Change Picture </button> </div> )} </div> ); }; export default ProfilePictureUploader; ``` ## 📚 API Reference ### `useUpload(options)` #### Options - `action`: Upload endpoint URL (required) - `globalConfig`: Configuration object - `headers`: Custom headers for upload request - `metadata`: Additional metadata to attach to files - `onUploadStart`: Callback when files start uploading - `onUploadComplete`: Callback when upload completes - `onError`: Callback for upload errors #### Returns - `acceptedFiles`: List of processed files - `errors`: Validation and upload errors - `getRootProps()`: Props for drag and drop zone - `getInputProps()`: Props for file input - `removeFile(fileId)`: Remove a file from upload queue - `uploadFile(fileId)`: Manually trigger file upload - `restartUpload(fileId)`: Restart a failed upload ## 🛡️ TypeScript Support Full TypeScript definitions are included for type safety and IDE support. ## 📄 License MIT License