bulk-upload-ui
v1.0.4
Published
Production-grade, reusable bulk upload UI library for React and Next.js with configurable validation, duplicate handling, and error management
Downloads
364
Maintainers
Readme
bulk-upload-ui
Production-grade, reusable bulk upload UI library for React and Next.js.
Installation
npm install bulk-upload-ui
# or
yarn add bulk-upload-uiFeatures
- ✅ Framework-agnostic - Works in React (Vite/CRA) and Next.js (Pages + App Router)
- ✅ SSR-safe - No Next.js-specific APIs, fully client-side compatible
- ✅ TypeScript - Full type safety with comprehensive types
- ✅ Config-driven - No hard-coded URLs, supports auth injection
- ✅ Flexible - Use the main component or individual pieces
- ✅ Customizable - CSS variables for easy theming
- ✅ Production-ready - Error handling, validation, progress tracking
Installation
npm install bulk-upload-ui
# or
yarn add bulk-upload-uiQuick Start
React (Vite/CRA)
import { BulkUpload } from 'bulk-upload-ui';
import 'bulk-upload-ui/dist/styles/bulk-upload.css'; // Optional
function App() {
return (
<BulkUpload
entity="lead"
uploadMode="UPSERT"
apiBaseUrl="/api"
onComplete={(result) => console.log(result)}
/>
);
}Next.js App Router
'use client';
import { BulkUpload } from 'bulk-upload-ui';
export default function Page() {
return (
<BulkUpload
entity="lead"
uploadMode="UPSERT"
apiBaseUrl="/api"
getAuthToken={() => localStorage.getItem('token')}
onComplete={(result) => console.log(result)}
/>
);
}Next.js Pages Router
import { BulkUpload } from 'bulk-upload-ui';
export default function Page() {
return (
<BulkUpload
entity="lead"
uploadMode="UPSERT"
apiBaseUrl="/api"
getAuthToken={() => {
// Get token from cookies or context
return document.cookie.match(/token=([^;]+)/)?.[1];
}}
onComplete={(result) => console.log(result)}
/>
);
}API Reference
BulkUpload Component
Main orchestrator component that handles the entire upload flow.
Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| entity | string | ✅ | - | Entity type (e.g., "lead", "user") |
| uploadMode | 'CREATE' \| 'UPDATE' \| 'UPSERT' | ✅ | - | Upload operation mode |
| apiBaseUrl | string | ✅ | - | Base URL for API (e.g., "/api") |
| getAuthToken | () => string \| null \| Promise<string \| null> | ❌ | - | Function to get auth token |
| headers | Record<string, string> | ❌ | {} | Additional HTTP headers |
| requiredFields | string[] | ❌ | [] | Required backend fields |
| availableFields | string[] | ❌ | [] | Available backend fields for mapping |
| showColumnMapper | boolean | ❌ | true | Show column mapping step |
| showPreview | boolean | ❌ | true | Show preview step |
| maxFileSize | number | ❌ | 10485760 | Max file size in bytes (10MB) |
| acceptedFileTypes | string[] | ❌ | ['.csv', '.xlsx', '.xls'] | Accepted file extensions |
| onComplete | (result: BulkUploadResult) => void | ❌ | - | Callback when upload completes |
| onError | (error: string) => void | ❌ | - | Callback when error occurs |
| className | string | ❌ | '' | Additional CSS class |
| disabled | boolean | ❌ | false | Disable the component |
useBulkUpload Hook
Hook for managing bulk upload state and operations.
const {
state,
handleFileSelect,
handleMappingChange,
handleContinueToPreview,
handleUpload,
handleDownloadErrorFile,
reset,
} = useBulkUpload({
entity: 'lead',
uploadMode: 'UPSERT',
config: {
baseUrl: '/api',
getAuthToken: () => localStorage.getItem('token'),
},
availableFields: ['email', 'name', 'phone'],
requiredFields: ['email'],
callbacks: {
onComplete: (result) => console.log(result),
onError: (error) => console.error(error),
},
});API Client
Direct API client for custom implementations.
import { createBulkUploadClient } from 'bulk-upload-ui';
const client = createBulkUploadClient({
baseUrl: '/api',
getAuthToken: () => localStorage.getItem('token'),
});
const result = await client.upload({
entity: 'lead',
uploadMode: 'UPSERT',
file: fileObject,
onProgress: (progress) => console.log(progress.percentage),
});Backend API Contract
The library expects a REST API endpoint:
POST /bulk-upload/:entityRequest
- Content-Type:
multipart/form-data - Body:
file: File (CSV/XLSX)uploadMode:'CREATE' | 'UPDATE' | 'UPSERT'columnMappings: JSON string of column mappings (optional)
Response
{
"success": true,
"status": "SUCCESS" | "PARTIAL_SUCCESS" | "FAILED",
"totalRows": 100,
"successfulRows": 95,
"failedRows": 5,
"errors": [
{
"rowIndex": 0,
"row": { "email": "invalid", "name": "Test" },
"errors": ["Invalid email format"]
}
],
"errorFileUrl": "/api/errors/123.csv",
"message": "Upload completed with some errors"
}Customization
CSS Variables
Override CSS variables to customize the appearance:
:root {
--bulk-upload-primary: #6366f1;
--bulk-upload-primary-hover: #4f46e5;
--bulk-upload-success: #10b981;
--bulk-upload-error: #ef4444;
--bulk-upload-border-radius: 12px;
--bulk-upload-spacing: 20px;
}Individual Components
Use individual components for more control:
import { FilePicker, ColumnMapper, PreviewTable } from 'bulk-upload-ui';
// Use components individually
<FilePicker onFileSelect={handleFile} />
<ColumnMapper fileHeaders={headers} availableFields={fields} />
<PreviewTable data={data} validations={validations} />Examples
See the examples/ directory for:
- React example
- Next.js Pages Router example
- Next.js App Router example
- Advanced usage with hooks
TypeScript
Full TypeScript support with exported types:
import type {
BulkUploadResult,
BulkUploadProps,
UploadMode,
ColumnMapping,
} from 'bulk-upload-ui';Browser Support
- Modern browsers (Chrome, Firefox, Safari, Edge)
- Requires FileReader API support
- Requires FormData and XMLHttpRequest support
License
MIT
