Spreadsheet canvas
Blank sheet
Begin with an empty workbook and grow rows and columns as you scroll.
EditableUndo / redoCSV / XLSX
Interactive, production component
tsx
"use client";
import { useCallback, useMemo, useState } from "react";
import {
DataTable,
type ColumnSetting,
} from "../../../../../src/Datatable";
import { nextSpreadsheetExtent } from "../../../../../src/Datatable/utils/spreadsheet";
import { useTableTheme } from "../_components/example-preview";
type BlankRow = Record<string, unknown>;
const INITIAL_ROWS = 1_000;
const INITIAL_COLUMNS = 100;
const makeRows = (count: number): BlankRow[] =>
Array.from({ length: count }, () => ({}));
const makeColumns = (count: number): ColumnSetting<BlankRow>[] =>
Array.from({ length: count }, (_, index) => ({
id: `c${index}`,
width: 96,
minWidth: 48,
editor: "text",
enableSorting: false,
enableReordering: false,
}));
export function BlankSheet() {
const { mounted, theme } = useTableTheme();
const [rows, setRows] = useState<BlankRow[]>(() => makeRows(INITIAL_ROWS));
const [columnCount, setColumnCount] = useState(INITIAL_COLUMNS);
const columns = useMemo(() => makeColumns(columnCount), [columnCount]);
const growRows = useCallback((_start: number, visibleEnd: number) => {
setRows((current) => {
const length = nextSpreadsheetExtent(current.length, visibleEnd, 100, 500, 100_000);
return length === current.length
? current
: [...current, ...makeRows(length - current.length)];
});
}, []);
const growColumns = useCallback((_start: number, visibleEnd: number) => {
setColumnCount((current) =>
nextSpreadsheetExtent(current, visibleEnd, 5, 25, 1_000),
);
}, []);
if (!mounted) return <div className="example-mount-placeholder" />;
return (
<DataTable
mode="spreadsheet"
theme={theme}
title="Untitled sheet"
showTitleBar
showFooter={false}
dataSource={rows}
onChange={setRows}
columnSettings={columns}
rowHeight={26}
headerHeight={28}
maxHeight={650}
overscanRowCount={18}
overscanColumnCount={6}
enableEditing
enableRowActions
enableUpload
enableDownload
enableFindReplace
enableGoToCell
enableColumnSettings
undoLimit={20}
redoLimit={20}
enableColumnResizing
enableRowIndex
enableSelection
enableActiveRow={false}
createEmptyRow={() => ({})}
onVisibleRangeChange={growRows}
onVisibleColumnRangeChange={growColumns}
/>
);
}