@khoipn2112/shadsheet
v0.3.0
Published
Headless React spreadsheet component library built with TanStack Table, HyperFormula, and shadcn conventions
Maintainers
Readme
ShadSheet
Headless React spreadsheet component library built with React 19, TanStack Table, TanStack Virtual, Zustand, and HyperFormula.
Install
npm install @khoipn2112/shadsheet react react-domImport the bundled stylesheet once in your app entry:
import "@khoipn2112/shadsheet/style.css";Requirements
- React 19+
- Browser or client-rendered React environment
- A parent container with an explicit height because
Spreadsheetdefaults toheight="100%"
Quick Start
import { Spreadsheet, type ColumnConfig } from "@khoipn2112/shadsheet";
type Row = {
A: string;
B: number;
C: boolean;
};
const columns: ColumnConfig<Row>[] = [
{ id: "A", header: "Name", editable: true, sortable: true, width: 180 },
{ id: "B", header: "Amount", type: "number", editable: true, width: 140 },
{ id: "C", header: "Active", type: "checkbox", editable: true, width: 120 },
];
const data: Row[] = [
{ A: "Alpha", B: 120, C: true },
{ A: "Beta", B: 80, C: false },
];
export function Example() {
return (
<div style={{ height: 480 }}>
<Spreadsheet
data={data}
columns={columns}
exportFileName="orders"
onCellChange={({ rowIndex, columnId, newValue }) => {
console.log("Edited", rowIndex, columnId, newValue);
}}
/>
</div>
);
}What It Includes
- Virtualized row rendering and virtualized center columns for large datasets
- Left and right pinned column panes
- Column sorting, hiding, pinning, resize handles, and auto-fit
- Global search plus per-column filter panels with expression filters
- Inline cell editors for text, number, date, select, and checkbox columns
- Formula bar backed by HyperFormula
- Range selection, keyboard navigation, clipboard copy/cut/paste, and status bar aggregates
- Toolbar formatting controls and CSV/XLSX export
- Tree rows, grouping, row selection, and light or dark theme support
Headless API
ShadSheet exports a layered API for different levels of control:
Components
import {
Spreadsheet, // Batteries-included
SpreadsheetGrid, // Virtualized grid only
Toolbar, // Formatting toolbar
FormulaBar, // Formula input
StatusBar, // Row count + aggregates
ColumnHeaders, // Header row with sorting/filtering
} from "@shadsheet/ui";Hooks
import {
useSpreadsheetStore, // Access Zustand store
useCellSelection, // Selection logic
useClipboard, // Copy/cut/paste
useKeyboardNavigation, // Arrow keys, Tab, Enter
useHyperFormula, // Formula engine access
useMergeCells, // Cell merging
useColumnResize, // Column width resizing
useGridOperations, // Insert/delete rows/columns
useAutoFill, // Fill handle
} from "@shadsheet/ui";Providers & Contexts
import {
SpreadsheetProvider, // Context wrapper
SpreadsheetContext, // Zustand store context
TableContext, // TanStack Table context
HyperFormulaContext, // Formula engine context
} from "@shadsheet/ui";Utilities
import {
exportToCSV, // CSV export
exportToXLSX, // XLSX export
spreadsheetColumnFilterFn, // Filter expression parser
evaluateColumnFilter, // Filter expression evaluator
validateCellValue, // Zod-based validation
colIndexToLetter, // Column index to letter (0→A)
letterToColIndex, // Letter to column index (A→0)
toA1, // Row/col to A1 notation
fromA1, // A1 notation to row/col
createSpreadsheetStore, // Standalone store factory
} from "@shadsheet/ui";Public Component Surface
Spreadsheet is the package entry point.
Key props:
data,columnsgetRowId,getSubRowssortable,filterable,editable,resizableColumns,formulasEnabledshowToolbar,showFormulaBar,globalSearchablerowSelectionpinnedColumns,groupingheight,defaultColumnWidth,exportFileName,theme,className
Column config supports:
id,header,width,minWidth,maxWidthsortable,filterable,pinnedtypeoftext | number | date | select | checkboxeditableasbooleanor row predicatevalidationvia Zod schemaoptionsfor select columns
Callbacks
onSelectionChange(selection)onCellChange(change)onBeforeCellEdit(cell, row)onSort(sorting)onFilter(filters)onExport(format)
Behavior notes:
onCellChangecan veto an edit by returningfalse.onBeforeCellEditcan block entry into edit mode for a specific cell.onFilterreturns both global search and per-column filter state.
Ref API
SpreadsheetRef exposes:
focus()scrollToCell(rowIndex, columnIndexOrId)getSelectedData()getData()setData(data)exportToCSV()exportToXLSX()undo()redo()
exportToXLSX() is async.
Filter Expressions
Each column menu supports plain search and an expression mode. Examples:
>100 && <500contains(alpha)blank()in(open,closed)regex(^A)between(2026-01-01, 2026-12-31)
Supported operators and helpers include =, !=, >, >=, <, <=, &&, ||, not, contains, startsWith, endsWith, between, in, blank, and regex.
Storybook
Storybook stories cover:
- default grid
- read-only mode
- large dataset virtualization
- formulas
- pinned columns
- tree rows
- dark theme
Run locally with:
npm run storybookScripts
npm run dev
npm run build
npm run lint
npm run preview
npm run storybook
npm run build-storybookCurrent Notes
- This package is browser-oriented. Clipboard, download, and DOM APIs are used directly.
- Build and Storybook are configured. A dedicated automated test runner is not configured in
package.jsonyet. - The docs only guarantee the features described here. Partially wired behavior in the codebase, such as structural row or column commands and auto-fill, is intentionally not advertised as stable package contract yet.
Migration from v0.2.x
The package name changed from spreadsheet to @shadsheet/ui. Update your imports:
// Before
import { Spreadsheet } from "spreadsheet";
import "spreadsheet/style.css";
// After
import { Spreadsheet } from "@shadsheet/ui";
import "@khoipn2112/shadsheet/style.css";The CSS import is now required explicitly (no longer auto-imported).
