paged.sheet — spreadsheets
The spreadsheet plugin — a Rust/WASM calc engine with spill, structured tables, charts, and XLSX round-trip, lowered to native print-grade tables and editable in-frame.
In short paged.sheet is a full spreadsheet engine in Rust/WASM that lives
inside a print layout — a dependency-graph calc engine with dynamic-array spill,
structured tables, a chart engine, and preservation-safe XLSX round-trip. It
lowers to native <Table> content and is editable in-frame.
What it does
- Calc engine (dependency graph, dirty recalc, Excel-compatible numerics) with a large registered function library and dynamic-array spill.
- Structured tables, a chart engine (plotters → a custom drawing backend → frozen chart geometry), and number formatting with locales.
- XLSX import/export with a byte-faithful preservation invariant.
- Page-surface lowering to native tables, multi-frame pagination, and an in-frame grid with a modal edit session; consumes governed datasets from paged.data.
How it's built
A Cargo workspace (sheet-core, sheet-parser, sheet-calc, sheet-fn,
sheet-xlsx, sheet-lower, sheet-grid, sheet-chart, sheet-js) plus a TS
bundle; a coverage gate requires every function to have a test.
Capability state
● shipped & verified · ◍ shipped, untested · ◐ partial · ✗ failing · · planned
Plugin · sheet 31 features · 93% green
| Feature | Shell | API | Sheet |
|---|---|---|---|
paged.sheet serves the HOST Swatches and Character/Paragraph panels (ADR 023 phase D)sheet.binding-providers | ◍ | ◐ | |
Exact-decimal numeric mode (D-6 spike) — seam proven, deferred to v2 opt-insheet.calc.decimal | ◐ | ||
Calculation engine — dependency graph, dirty recalc, f64 numeric core (D-6), coercion, error valuessheet.calc.engine | ● | ||
Iterative (circular) calculation — OFF by default (D-7), converges to a fixed point when enabledsheet.calc.iterative | ● | ||
Row/col insert-delete wasm door — BLOCKED on xlsx-writer structural re-emissionsheet.calc.rewrite.structural-door | · | ||
Dynamic-array spill (anchor + spill range,sheet.calc.spill | ● | ||
Chart authoring — create a chart from the editor (page-side lowering)sheet.chart.authoring | ● | ||
Charts — plotters-backed custom DrawingBackend → frozen ChartGeometry IR → grid view + paged.draw page loweringsheet.chart.engine | ● | ||
Graph types — stacked column/bar + radar, axis titles, transpose rows/columns, c:grouping importsheet.chart.graphs | ● | ||
Data-provider CONSUMER — source a sheet from a governed dataset (host.dataProviders)sheet.data.consumer | ● | ||
Session edit ops — stable range sort (values lane), find over values/formulas, replace with skip reportingsheet.edit.ops | ● | ||
Function library — 224 registered functions across 18 families, registry-driven dispatchsheet.fn.library | ● | ||
Number-format engine + en/de locale (D-8)sheet.format.engine | ● | ||
Western-European Latin locale tier (fr/es/it) — display formatting data rowssheet.format.locale.latin-tier | ● | ||
Frozen panes — parse sheetViews/pane + render frozen rows/columns in-gridsheet.grid.freeze.render | ● | ||
In-frame grid — sceneLayer render + K-1 modal select/edit (sheets-mode lite)sheet.grid.inframe | ◐ | ||
Cell fill / text colours are MINTED swatches — a raw hex in a colorRef paints nothingsheet.lower.cell-colour-swatches | ◐ | ||
Page-surface lowering — native <Table> + IR-v2 style map + measured column widthssheet.lower.page | ● | ||
Live multi-frame pagination across the host frame chainsheet.lower.paginate | ● | ||
Formula dialect parser — literals, A1 refs, operator precedence, functions, union/intersection, array literals, defined names, canonical print fixpointsheet.parser.dialect | ● | ||
paged.sheet bundle (media.paged.sheet) — manifest + activate + 3 panels + 7 commands + importer/exporter + engine bootsheet.plugin.bundle | ● | ||
Function browser + workbook inventory + the styleFromCell command (workbook panel)sheet.plugin.function-browser | ● | ||
Workbook persistence — host.blob (OPFS) + the metadata binding envelopesheet.plugin.persistence | ◐ | ||
Workbook visual styles — xlsx parse -> deduped IR-v2 style table -> both surfaces (one resolver, cross-surface parity)sheet.style.mapping | ◐ | ||
Excel structured tables / ListObjects — model + structured references + tableN.xml partsheet.table.structured | ● | ||
get_range_styled — the workbook's REAL per-cell visual styles, as a door of its ownsheet.wasm.range-styled-door | ◐ | ||
Cell comments — preserve opaquely + display (grid indicator + panel list), preserve-firstsheet.xlsx.comments | ● | ||
Conditional formatting — xlsx part fidelity + lowering to style overridessheet.xlsx.condfmt | ● | ||
XLSX data validation — preserve byte-faithfully + read-only inventory (NEVER enforced)sheet.xlsx.data-validation | ● | ||
Pivot tables — preserve-only, NEVER interpreted (publishing-first non-goal)sheet.xlsx.pivot | ● | ||
XLSX I/O on the fidelity ladder — preservation invariant + import/export through the platformsheet.xlsx.roundtrip | ● |
Recent activity
- 2026-08-19chore: adopt the 100 MB app-wide wasm budgetc1a4f1c
- 2026-08-18sheets: quick-xml 0.36 -> 0.41 clears the RUSTSEC pair; rust lane gates PRs (0.1.0-canary.6)fabafb0
- 2026-08-17ci: the real engine boot runs on CI — vitest lane builds the wasm, fail-not-skip guard, nextest un-softened7b63e93
- 2026-08-08chore(deps): dev-pin the plugin contract at 0.2.30-canary.0e0116b9
- 2026-08-07ADR 024: the sheet context declares its surface; "Paste" stops lying58143a3
- 2026-08-06deps: the contract becomes a PEER — stop nesting a second copy of it5c47b62
- 2026-08-06deps: contract pins -> 0.2.29-canary.0 (the protocol-61 wire)6ee55cb
- 2026-08-05feat(chart): the nine graph types are real — stacked, radar, axes, transposef2fb100
paged.image — raster
The raster-image plugin — a Rust/WASM pipeline of GPU kernels with PSD round-trip, dual processing engines, color management, and in-editor ingest into the engine's image scene layer.
paged.data — database publishing
The database-publishing plugin — a binding DSL, a sync engine, record-flow pagination, and batch automation over DuckDB-WASM, publishing datasets other plugins can consume.