react-smart-file-picker
v1.0.1
Published
`React Smart File Picker` is a file selection component for React that simplifies file handling with built-in image compression. It leverages the powerful [browser-image-compression](https://www.npmjs.com/package/browser-image-compression) library to auto
Maintainers
Readme
React Smart File Picker
React Smart File Picker is a file selection component for React that simplifies file handling with built-in image compression. It leverages the powerful browser-image-compression library to automatically compress images before upload, optimizing bandwidth usage and improving performance.
Demo
Coming soon...
Features
- Built-in Image Compression: Automatically compresses image files to a specified size using browser-image-compression.
- Multiple File Selection: Easily handle single or multiple file uploads.
- TypeScript Support: Fully typed for developer experience.
- Progress Tracking: Real-time feedback on file processing status.
- Customizable UI: Completely customize the trigger button with render props.
- File Validation: Flexible validation for file types and sizes.
- Preview URLs: Auto-generates preview URLs for selected images.
- Error Handling: Comprehensive error reporting for validation and compression issues.
Installation
You can install react-smart-file-picker via npm or yarn:
npm install react-smart-file-picker
# or
yarn add react-smart-file-pickerUsage
import { useState } from "react";
import { FilePicker } from "react-smart-file-picker";
const App = () => {
const [files, setFiles] = useState([]);
const [processingProgress, setProcessingProgress] = useState(0);
const [errors, setErrors] = useState([]);
const handleOnChange = (pickedFiles) => {
const newFiles = Array.isArray(pickedFiles) ? pickedFiles : [pickedFiles];
setFiles((prevFiles) => {
const existingIds = new Set(prevFiles.map((file) => file.id));
const uniqueFiles = newFiles.filter((file) => !existingIds.has(file.id));
return [...prevFiles, ...uniqueFiles];
});
};
return (
<div className="max-w-4xl mx-auto p-6">
<h1 className="text-3xl font-semibold mb-6 text-center">File Uploader</h1>
<FilePicker
renderTrigger={() => (
<button className="w-full py-3 bg-blue-600 text-white font-medium rounded hover:bg-blue-700 transition">
Select Files
{processingProgress > 0 && processingProgress < 100 && (
<span className="ml-2 text-sm text-white/80">
({processingProgress}% Processing)
</span>
)}
</button>
)}
allowedFileTypes={["image/jpeg", "image/png", "application/pdf"]}
maxFileSizePerFile={10 * 1024 * 1024}
multiple
compressImageMaxSize={1}
onChange={handleOnChange}
onError={(fileErrors) => setErrors(fileErrors)}
onProcessing={setProcessingProgress}
/>
{errors.length > 0 && (
<div className="mt-4 p-3 bg-red-50 border border-red-200 rounded-md">
<h3 className="text-red-700 font-medium">Errors:</h3>
<ul className="mt-1 list-disc pl-5">
{errors.map((error, index) => (
<li key={index} className="text-sm text-red-600">
{error.message}
</li>
))}
</ul>
</div>
)}
{files.length > 0 && (
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4 mt-6">
{files.map((file) => (
<div key={file.id} className="border rounded-lg p-3 shadow-sm">
{file.src ? (
<img
src={file.src}
alt={file.name}
className="w-full h-32 object-cover rounded mb-2"
/>
) : (
<div className="w-full h-32 bg-gray-200 flex items-center justify-center rounded mb-2 text-lg font-bold text-gray-600">
{file.name.split(".").pop()?.toUpperCase()}
</div>
)}
<p className="text-sm font-medium truncate">{file.name}</p>
<p className="text-xs text-gray-500">{file.fileSize}</p>
{file.originalName !== file.name && (
<p className="text-xs text-gray-400">
Original: {file.originalName}
</p>
)}
</div>
))}
</div>
)}
</div>
);
};
export default App;Props
| Prop | Type | Default Value | Description |
| ------------------- | --------------------------------------------- | ------------- | ------------------------------------------------------------------------------ |
| renderTrigger | () => ReactElement | required | Render prop for customizing the button that triggers the file selection. |
| allowedFileTypes | string[] | [] | Array of MIME types that are allowed. Empty array means all types allowed. |
| maxFileSizePerFile| number | 5242880 | Maximum allowed size per file in bytes (default: 5MB). |
| multiple | boolean | false | Enable multiple file selection. |
| compressImageMaxSize | number \| undefined | undefined | Target size in MB for image compression. Set to undefined to skip compression. |
| onChange | (files: PickedFile \| PickedFile[]) => void | required | Callback function that receives the selected file(s) after processing. |
| onError | (errors: FilePickerError[]) => void | optional | Callback for handling validation or processing errors. |
| onProcessing | (progressPercent: number) => void | optional | Callback that reports processing progress percentage (0-100, or -1 for error). |
Types
PickedFile
interface PickedFile {
id: string; // Unique identifier for the file
name: string; // File name
originalName: string; // Original file name before processing
fileSize: string; // Human-readable file size (e.g., "2.5 MB")
source: File; // The actual File object
src?: string; // URL for previewing images (only for image files)
}FilePickerError
interface FilePickerError {
type: string; // Error type (e.g., "type", "size", "compression", "processing")
message: string; // Human-readable error message
}Image Compression
React Smart File Picker uses browser-image-compression under the hood to provide efficient client-side image compression. When you set the compressImageMaxSize prop, images are automatically compressed to approximately that size in MB while maintaining reasonable quality.
The compression process:
- Only applies to files with image MIME types
- Preserves the original aspect ratio
- Runs asynchronously to avoid blocking the UI
- Provides progress feedback through the
onProcessingcallback
You can disable compression by setting compressImageMaxSize to undefined.
Error Handling
The component handles various error scenarios:
- Type validation: Checks if file types match the allowed MIME types
- Size validation: Ensures files don't exceed the maximum size limit
- Compression errors: Reports issues encountered during image compression
- Processing errors: Captures general file processing problems
All errors are reported through the onError callback as an array of FilePickerError objects.
Progress Tracking
The onProcessing callback provides real-time feedback on file processing:
- 0: Processing started
- 1-99: Progress percentage during processing
- 100: Processing completed successfully
- -1: Processing encountered an error
License
React Smart File Picker is released under the MIT license.
