Packages
Tablin packages are private workspace packages. They are not published to npm, and no public installation command is available.
@tablin/grid exposes the DOM grid and convenience
APIs. @tablin/core provides the headless controller.
@tablin/themes contains the default CSS theme.
Example
This example creates a local customer grid with one editable, sortable text column. It runs inside the private workspace.
import {
createGrid, createLocalProvider, defineColumn, defineColumns,
field, textCodec, rowKey, columnId, datasetId,
} from '@tablin/grid';
import '@tablin/themes/tablin.css';
interface Customer { id: string; name: string }
const columns = defineColumns<Customer>()([
defineColumn<Customer>()({
id: columnId('name'), label: 'Customer', kind: 'text',
field: field<Customer>()('name'), codec: textCodec,
sortable: true, editable: true,
width: { kind: 'flex', weight: 1 },
}),
]);
const dataset = datasetId('customers');
const provider = createLocalProvider({
datasetId: dataset, columns,
rows: [{ id: 'customer-1', name: 'Ada' }],
getRowKey: customer => rowKey(customer.id),
});
const host = document.querySelector<HTMLElement>('#customers');
if (!host) throw new Error('Customer grid host is missing.');
// The host needs a bounded height, e.g. 480px, and display:flex.
const grid = createGrid(host, {
id: 'Customers', datasetId: dataset, columns, provider,
});
await grid.ready();
Call await grid.dispose() when the host application
removes the grid. For headless use, import
createController from @tablin/core.
Host
The DOM renderer needs a browser with ResizeObserver. Give the host a bounded height and a flex layout so the grid can size its scroll viewport.
<div id="customers" style="height: 480px; display: flex;"></div>
Import the theme once. Its --tl-* custom properties
control surfaces, text, boundaries, selection, and focus. The
implemented defaults are light, with a forced-colors mapping. A
dark theme is not implemented.
Keyboard
Cell commands apply within the grid. Native editors keep their own text-entry behavior. The search shortcut belongs to the Orders playground.
| Key | Action |
|---|---|
| Arrow keys | Move between cells. |
| Shift + arrow or click | Select a cell rectangle within the loaded window. |
| Ctrl/Cmd + C or V | Copy cells or paste values. A paste is one undo step. |
| Enter or F2 | Edit the active editable cell. |
| Left/Right on a resize boundary | Resize by 8 pixels. Hold Shift for 1 pixel. |
| Enter on a resize boundary | Restore its column definition. Ctrl/Cmd + Enter fits a sample of mounted rows. |
| Enter in an editor | Validate and commit the draft. |
| Tab in an editor | Commit, then move to the next cell. Shift reverses direction. |
| Escape | Cancel an active resize, then a draft or cell range. |
| Space on a cell | Toggle selection for its row. |
| Ctrl/Cmd + Z | Undo an edit. Add Shift to redo. |
| Enter or Space on a header | Cycle that column’s sort order. |
| / | Focus the playground search field when outside a text field. |
Double-clicking an editable cell also starts editing. In the playground, Shift-click a sortable header to build a multi-column sort.
Drag a header boundary to preview a width, then release to commit. Escape cancels. Double-click fits that column using a sample of up to 32 mounted rows. The Columns panel offers Fit visible columns and Reset widths. Fit is labelled as sampled and never scans the complete result. Hidden columns retain their width overrides.
Paste accepts quoted TSV and CSV, including multiline fields. A single value fills the selected rectangle; larger sources must fit exactly. Invalid values, read-only cells, and unloaded destinations reject the entire paste. Ranges currently cover loaded rows and visible columns.
Data
The host owns its source records and backend authority. The local provider clones plain structured records, publishes immutable row envelopes, and commits validated patches with row-version checks.
The Orders playground keeps edits in memory for the current session. Reloading the page or replacing the dataset discards those changes. Amounts use ordinary numbers; the example is not an exact-decimal accounting implementation.
See Status for the implemented boundaries and Benchmarks for measurement scope.