@cristianmpx/react-import-sheet-headless
v2.0.3
Published
Headless React library for importing and validating Excel/CSV sheet data
Downloads
1,161
Maintainers
Readme
@cristianmpx/react-import-sheet-headless
Headless React library for importing and validating Excel/CSV sheet data. No built-in table UI—you bring your own components; the library provides the logic and bulk validation.
Installation
npm install @cristianmpx/react-import-sheet-headlessPeer dependencies: React 18+ (react and react-dom).
⚙️ Framework Setup
Good news: As of version 2.0.0, no special configuration is required! The library runs entirely on the main thread, so it works out-of-the-box with all bundlers (Vite, Webpack, Rollup, etc.) and frameworks (Next.js, Remix, etc.).
Why Headless
Bring your own components; we provide the logic and bulk validation. No prebuilt <Table />—you own the UI and the UX.
Pipeline
Data flows through a single pipeline on the main thread.
flowchart LR
A[Input File] --> B[Parser]
B --> C[Convert]
C --> D[Sanitizer]
D --> E[Validator]
E --> F[Transform]
F --> G[Sheet + Errors]
G -.-> H[Edit optional]Order: Input File → Parser → Convert → Sanitizer → Validator → Transform → Result (sheet) + Errors. Optional: cell-level edit on the result.
Quick Start
~10 lines to see the value: wrap with the provider, pick a file, read result and errors.
import {
ImporterProvider,
useImporter,
useSheetView,
} from '@cristianm/react-import-sheet-headless';
const myLayout = { name: 'my-sheet', version: 1, fields: {} };
function App() {
return (
<ImporterProvider>
<ImporterUI />
</ImporterProvider>
);
}
function ImporterUI() {
const { processFile } = useImporter({ layout: myLayout });
const { sheet, getPaginatedResult } = useSheetView({ defaultPageSize: 10 });
if (!sheet) {
return (
<input
type="file"
accept=".csv,.xlsx"
onChange={(e) => e.target.files?.[0] && processFile(e.target.files[0])}
/>
);
}
const { rows } = getPaginatedResult(1, 10);
return (
<div>
<p>
Rows: {sheet.rows.length} | Errors: {sheet.errors.length}
</p>
{/* Your table component here, e.g. rows.map(...) */}
</div>
);
}For layout, custom validators, and step-by-step usage, see How to / Usage. For a documented example (layout, fields, sanitizers, validators, transforms) with comments, see examples/ImportExample.md.
Virtualization (e.g. react-window)
Use totalRows and getRows(page, limit) (page is 1-based) from useSheetView() to feed a virtual list without loading all rows into the DOM:
import { FixedSizeList as List } from 'react-window';
import { useSheetView } from '@cristianm/react-import-sheet-headless';
function VirtualizedTable() {
const { getRows, totalRows } = useSheetView({ filterMode: 'all' });
const pageSize = 50;
const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => {
const page = Math.floor(index / pageSize) + 1;
const offset = index % pageSize;
const chunk = getRows(page, pageSize);
const row = chunk[offset];
return <div style={style}>{row ? `Row ${row.index}: ${JSON.stringify(row.cells)}` : null}</div>;
};
return (
<List height={400} itemCount={totalRows} itemSize={32} width="100%">
{Row}
</List>
);
}Persistence: When using persist={true}, call clearPersistedState() (from useSheetView) after the user has successfully submitted the import to your server, so data is not left in IndexedDB indefinitely. See View / Persist.
Error Handling
The library exposes errors through useSheetData().errors. Errors include both global errors (parser failures) and validation errors (cell/row/sheet level).
const { errors, sheet } = useSheetData();
const { status } = useImporterStatus();
if (status === 'error' && !sheet) {
// Fatal error: parser failed before creating a sheet
const fatalError = errors[0];
console.error(`${fatalError.code}: ${fatalError.message}`);
// Example: PARSER_FAILED, PARSER_NO_SHEETS
}
if (errors.length > 0) {
// Validation errors or warnings
errors.forEach((error) => {
console.error(`Row ${error.rowIndex}, Cell ${error.cellKey}: ${error.message}`);
});
}Error codes reference: See Error Codes for a complete list of error codes, their meanings, and how to handle them.
How to (usage)
Step-by-step usage and recipes (handling large files, real-time errors, session recovery): How to / Usage.
Topic-specific guides: Parser, Convert, Sanitizer, Validators, Transformers, Edit, View, Result — convert to your object for submit.
Schema Docs
The sheet layout (SheetLayout) defines validators, sanitizers, and transformers by level (cell, row, sheet). Options and parameters are documented in:
| Type | Documentation | | ------------ | ---------------------------------------------- | | Validators | Validators reference | | Sanitizers | Sanitizers reference | | Transformers | Transformers reference |
By level:
- Validators: cell (per field), row, sheet — see docs/validators.md.
- Sanitizers: cell, row, sheet — see docs/sanitizers.md.
- Transformers: cell, row, sheet — see docs/transformers.md.
To add or use controller modules (validators, sanitizers, transforms by context): Controllers.
Contributing
- Conventional Commits: This project uses Conventional Commits (
feat:,fix:,docs:, etc.). PRs that do not follow this convention may be asked to amend their commit messages. - Tests required: All contributions must pass the test suite. Run
npm run testbefore opening a PR. Vitest is used; coverage is maintained. Pre-push hooks may run tests.
