@karstenda/react-csv-editor
v1.0.5
Published
A powerful, feature-rich CSV viewer and editor React component with a beautiful dark UI
Maintainers
Readme
@karstenda/react-csv-editor
A powerful, feature-rich CSV viewer and editor for React — with inline cell editing, sorting, filtering, undo/redo, and instant CSV export.
✨ Features
| Feature | Details |
|---|---|
| 📂 Upload | Drag-and-drop or browse to open any .csv file |
| ✏️ Inline editing | Double-click any cell to edit; Enter / Esc / Tab to confirm or cancel |
| ↩ Undo | 20-level undo history |
| ➕ Add rows / columns | Modal forms with auto-detected data types |
| 🗑 Delete | Multi-select rows with checkboxes, bulk delete |
| 🔍 Search | Real-time full-table fuzzy search |
| 🔽 Column filter | Filter by any column value, stack multiple filters |
| ↕️ Sort | Click any header to sort asc/desc; type-aware (numbers, dates, strings) |
| 📊 Sidebar stats | Live row/column/modified/selected counts |
| 🏷 Type inference | Automatic detection of number, date, boolean, string columns |
| 📄 Pagination | 50 rows per page |
| ⬇️ Export | Download as .csv or use your own onExport handler |
| 🎨 Beautiful UI | Dark theme with JetBrains Mono + Syne typography |
📦 Installation
npm install @karstenda/react-csv-editor
# or
yarn add @karstenda/react-csv-editor
# or
pnpm add @karstenda/react-csv-editorPeer dependencies:
react >= 17andreact-dom >= 17must be installed in your project.
🚀 Quick Start
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
export default function App() {
return (
<div style={{ height: '100vh' }}>
<CSVEditor />
</div>
);
}⚠️ The component fills its container. Wrap it in an element with a defined height (e.g.
100vh).
🛠 Props
interface CSVEditorProps {
/** Pre-load data without a file upload */
initialData?: { headers: string[]; rows: Record<string, string>[] };
/** Filename shown in the top bar */
filename?: string;
/** Called on every data mutation */
onDataChange?: (data: { headers: string[]; rows: Record<string, string>[] }) => void;
/** Override the default download behaviour */
onExport?: (csvString: string, filename: string) => void;
/** Show the "Load demo data" button in the empty state (default: true) */
showDemo?: boolean;
/** Extra CSS class for the root element */
className?: string;
/** Inline styles for the root element */
style?: React.CSSProperties;
/** Visual theme. Defaults to 'light'. */
theme?: 'light' | 'dark';
/** UI language. Defaults to 'en'. */
language?: 'en' | 'fr' | 'de' | 'es' | 'it' | 'nl';
/** Optional replacement component for the top toolbar. */
TopToolbarComponent?: React.ComponentType<CSVEditorTopToolbarProps>;
}
interface CSVEditorTopToolbarProps {
t: (key: string, options?: Record<string, unknown>) => string;
language: 'en' | 'fr' | 'de' | 'es' | 'it' | 'nl';
hasData: boolean;
filename: string | null;
rowCount: number;
rowCountFormatted: string;
selectedCount: number;
canUndo: boolean;
onUndo: () => void;
onAddRow: () => void;
onAddColumn: () => void;
onDeleteSelected: () => void;
onExportCSV: () => void;
onUploadCSV: () => void;
}Change UI language
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
export default function App() {
return (
<div style={{ height: '100vh' }}>
<CSVEditor language="fr" />
</div>
);
}Customize top toolbar
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
function CustomTopToolbar({
t,
hasData,
filename,
rowCount,
rowCountFormatted,
selectedCount,
canUndo,
onUndo,
onAddRow,
onAddColumn,
onDeleteSelected,
onExportCSV,
onUploadCSV,
}) {
return (
<div style={{ display: 'flex', gap: 8, alignItems: 'center', padding: 12 }}>
<strong>{filename || t('appName')}</strong>
{hasData && <span>{t('labels.rowsCount', { count: rowCount, formattedCount: rowCountFormatted })}</span>}
<button onClick={onUndo} disabled={!canUndo}>{t('buttons.undo')}</button>
<button onClick={onAddRow}>{t('buttons.addRow')}</button>
<button onClick={onAddColumn}>{t('buttons.addColumn')}</button>
{selectedCount > 0 && <button onClick={onDeleteSelected}>{t('buttons.delete')} {selectedCount}</button>}
<button onClick={onExportCSV}>{t('buttons.exportCsv')}</button>
<button onClick={onUploadCSV}>{t('buttons.uploadCsv')}</button>
</div>
);
}
export default function App() {
return (
<div style={{ height: '100vh' }}>
<CSVEditor TopToolbarComponent={CustomTopToolbar} />
</div>
);
}📖 Examples
Load data programmatically
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
const data = {
headers: ['id', 'name', 'email'],
rows: [
{ id: '1', name: 'Alice', email: '[email protected]' },
{ id: '2', name: 'Bob', email: '[email protected]' },
],
};
export default function App() {
return (
<div style={{ height: '100vh' }}>
<CSVEditor initialData={data} filename="contacts.csv" />
</div>
);
}Controlled data with onDataChange
import { useState } from 'react';
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
export default function App() {
const [csvData, setCsvData] = useState(null);
return (
<div style={{ height: '100vh' }}>
<CSVEditor
onDataChange={(data) => {
setCsvData(data);
console.log('rows:', data.rows.length);
}}
/>
</div>
);
}Custom export handler (e.g. upload to server)
import { CSVEditor } from '@karstenda/react-csv-editor';
import '@karstenda/react-csv-editor/styles';
export default function App() {
const handleExport = async (csvString, filename) => {
const blob = new Blob([csvString], { type: 'text/csv' });
const formData = new FormData();
formData.append('file', blob, filename);
await fetch('/api/upload-csv', { method: 'POST', body: formData });
alert('Uploaded successfully!');
};
return (
<div style={{ height: '100vh' }}>
<CSVEditor onExport={handleExport} />
</div>
);
}Inside a Next.js app (App Router)
// app/csv/page.tsx
'use client';
import dynamic from 'next/dynamic';
const CSVEditor = dynamic(
() => import('@karstenda/react-csv-editor').then((m) => m.CSVEditor),
{ ssr: false }
);
import '@karstenda/react-csv-editor/styles';
export default function Page() {
return (
<main style={{ height: '100vh' }}>
<CSVEditor showDemo />
</main>
);
}⌨️ Keyboard Shortcuts
| Key | Action |
|-----|--------|
| Double-click cell | Enter edit mode |
| Enter | Confirm edit |
| Escape | Cancel edit |
| Tab | Confirm edit and move focus |
🏗 Development
git clone https://github.com/codebiba/react-csv-editor
cd react-csv-editor
npm install
npm run build # production build → dist/
npm run dev # watch mode📦 Publishing
This package is published to npm under the @karstenda scope.
npm whoami # confirm you are logged in
npm run build # produce dist/
npm pack --dry-run # verify the publish payload
npm version patch # or: minor / major (creates a git tag)
npm publish # access:public is set via publishConfigprepublishOnly runs npm run build, so dist/ is always rebuilt on publish.
📄 License
MIT © Aditya Yaduvanshi
