$ pretable — vol. 2 · no. 1
60fps under streaming load. Zero row drift. A deterministic engine designed for live data, agent output, and real-time telemetry — not retrofitted from a batch-era grid.
MIT licensed · open source
02 · how it works
Wrapped row heights are computed with character-width tables and font metrics — pure arithmetic. No getBoundingClientRect, no forced reflow, no measure-on-mount. The DOM is touched exactly once per frame, at commit. The five-stage pipeline below is what enforces that discipline.
Streaming patches and static rows treated identically.
Pure reducer. Sort, filter, selection, row-id stability.
Row-height plan + virtualization range. Off-DOM measurement.
The only stage that touches the DOM.
RAF coalesces patches per animation frame.
LLM streams, partial JSON, tool-call traces — bursts of 100 to 25,000 patches/sec all collapse to one snapshot per animation frame. No per-token reflow. Selection survives every patch.
(rows, columns, sort, filter, selection) → Snapshot. No imperative DOM. Streaming patches and batch arrays hit the same reducer — that's why selection survives every update.
100 to 25,000 patches/sec all collapse to one snapshot per animation frame. Long tasks: zero across the operating envelope.
Render counts, viewport range, planned height — all data emitted by the engine, never read from the DOM. Zero measurement-induced thrash.
↳ Read the source: packages/grid-core, layout-core, text-core, renderer-dom — under 3,000 lines combined.
03 · how we compare
Wrapped-text scroll at 3,000 rows on Chromium, against the three most-cited React grids. Pretable matches MUI at the front, ~1.7× ahead of AG Grid Community and TanStack on raw frame p95 — and is the only adapter here that clears every quality threshold (zero blank gaps, zero anchor shift, ≤1 px row-height drift) at full-grid feature weight. Interactive sort and filter run 2–3.5× faster than every measured comparator on the same dataset. See the methodology →
| metric | pretable | AG Grid | TanStack | MUI X | budget |
|---|---|---|---|---|---|
| frame p95 (ms) — wrapped scroll | 9.07 | 16.7 | 16.7 | 9.14 | ≤ 16 |
| row-height fidelity (px error) | 1 | 2 | 0 | 1 | ≤ 1 |
| blank gaps under scroll | 0 | 1 | 1 | 0 | 0 |
| scroll anchor shift (px) | 0 | 0 | 0 | 0 | ≤ 16 |
| sort latency p95 (ms) — interaction | 17.1 | 58.3 | 34.4 | 35.0 | — |
| filter-metadata latency p95 (ms) | 17.5 | 49.9 | 15.7 | 33.4 | — |
| filter-text latency p95 (ms) | 16.8 | 50.0 | 40.2 | 33.3 | — |
| headless engine + React surface | yes | n/a | engine only | n/a | — |
| streaming pipeline (SSE → partial JSON → batcher → applyTransaction) | yes | n/a | n/a | n/a | — |
05 · streaming, by design
Most grids accept streaming through an adapter layered onto a batch-era data model. Pretable's engine treats a 1,000-patch/sec stream and a static 3,000-row array as the same input shape — one reducer, one render path, one selection model. There's no "streaming mode" toggle.
applyTransaction({ add, update, remove }) is the only entry point into the engine. Static rows hit it via add(); SSE tokens hit it via the same method per chunk. The streaming adapter is a thin batcher around that interface — not a separate code path.
Row-id keys are first-class in the engine. Sort, filter, scroll position, focused row — none of it loses state mid-stream. Drag-select 200 rows during a 25k/sec patch storm and they stay selected.
06 · for engineers
Connect any token-streaming source — OpenAI Responses, Anthropic, or your own SSE — to a pretable grid. Selection survives every chunk.
| Role | Content | Tokens | Latency |
|---|
// @ts-nocheck — sample source for docs; not compiled as app code.
import { ChatGrid } from "./ChatGrid";
export default function Page() {
return <ChatGrid prompt="Summarize the last 10 incidents" />;
}Full reference: /docs/streaming
07 · what's in the box
Each feature backed by a bench scenario or demo. No claim without a click-to-prove.
Sub-frame scroll p95 on wrapped text — at parity with the best full-grid comparator (MUI X) and ~1.7× ahead of AG Grid Community and TanStack. Zero blank gaps, zero anchor shift, ≤1 px row-height drift.
Multi-line cells, variable row heights, smooth scrolling. Multilingual content tested.
Token-by-token rendering for OpenAI, Anthropic, and your own SSE. The full pipeline — partial-JSON parser, frame-budget batcher, applyTransaction wiring — ships as one import.
Filter, sort, and reorder without losing your selection. Stable focus across mutations.
Get started