Headless engine Headless API reference

Headless API reference

The public indexed row-model and UI-grid contracts in @pretable/core.

Use the generated core.api.md for every declaration. This page summarizes the ownership boundary — createLocalRowModel and createGrid together, put to work with no <PretableSurface> involved:

Headless custom renderer

Drive your own markup from the @pretable/core row model with useSyncExternalStore — no grid renderer involved.

.md

createLocalRowModel

ts
const rowModel = createLocalRowModel({
  rows,
  columns,
  getRowId: (row) => row.id, // optional when row.id is string | number
  query,
  initialExpansion: { kind: "collapsed" },
});

The const column tuple infers the row type, row-ID type, column IDs, values, legal filters, and aggregates.

Row identity

Rows with a conventional string or number id need no extra configuration. For another key, pass getRowId explicitly:

ts
const rowModel = createLocalRowModel({
  rows,
  columns,
  getRowId: (row) => row.rowKey,
});

IDs must be unique and stable across replacements for the same logical row. Selection, focus, edits, group expansion, and transactions all use that identity.

Row-model store and commands

MemberPurpose
getState() / subscribe(listener)Stable observable { snapshot, status }.
setRows(rows)Replace source rows in authoritative source order.
applyTransaction({ add, update, remove })Publish one typed atomic mutation.
setQuery(query)Atomically rebuild filters, sort, and grouping.
setDerivations(derivations)Replace behavior for the fixed typed column schema.
setGroupExpanded, setExpansionDefault, expandAll, collapseAllChange expansion state.
changesSince(revision)Read retained structural changes or a reset instruction.
distinctValues(columnId, options)Start an async, cancellable distinct-value query.
dispose()End the model lifecycle.

Indexed snapshot

ts
interface PretableRowModelSnapshot<TRow, TRowId, TColumns> {
  readonly revision: number;
  readonly sourceRowCount: number;
  readonly visibleRowCount: number;
  readonly visibleDataRowCount: number;
  rowAt(index: number): PretableVisibleRow<TRow, TRowId, TColumns> | undefined;
  range(
    start: number,
    end: number,
  ): readonly PretableVisibleRow<TRow, TRowId, TColumns>[];
  indexOf(ref: PretableVisibleRowRef<TRowId>): number;
  dataRowAt(index: number): PretableDataRow<TRow, TRowId> | undefined;
}

Data and group references are discriminated, so equal string IDs cannot collide.

createGrid

ts
const grid = createGrid({ rowModel, columns });

createGrid adds UI state over an explicit model. It does not accept rows or own filters, sorting, grouping, expansion, or transactions.

AreaMembers
StoregetState, subscribe
FocussetFocus, moveFocus
SelectionsetSelection, toggleRowSelection, selectRowRange, selectAllVisibleRows, clearSelection, isRowSelected, getSelectionSummary
EditingbeginEdit, setEditDraft, setEditStatus, cancelEdit
LayoutsetViewport, setColumns, setColumnWidth, setColumnPinned, setColumnOrder
Lifecycledispose

React ownership modes

tsx
// Declarative happy path
<PretableSurface rows={rows} columns={columns} getRowId={(row) => row.id} />
 
// Explicit ownership for streaming/imperative producers
<PretableSurface model={rowModel} />

The two modes are mutually exclusive at the type level.

See also