GridLevelRuntime
View as MarkdownResolve a level once, then use its path-bound reads, subscriptions, and commands.
type GridLevelRuntime = { readonly path: GridPath; readonly schema: LevelSchema; readonly data: RuntimeLevelDataSource;
displayedRows(): DisplayedRows; displayedRowSequence(): DisplayedRowSequence; displayedRow(rowId: RowId): LevelRow | undefined; dataRowTarget(rowId: RowId): RowOperationTarget<"data"> | undefined; subscribeDisplayedRowSequence(listener: () => void): () => void; subscribeDisplayedRow(rowId: RowId, listener: () => void): () => void;
activeRow(): RowCursor | null; selectedRows(): RowSelection; selectedRowIds(): readonly RowId[]; rowInteractionSnapshot(): RowInteractionSnapshot; subscribeActiveRow(listener: () => void): () => void; subscribeSelectedRows(listener: () => void): () => void; subscribeSelectedRowIds(listener: () => void): () => void; subscribeRowInteractionSnapshot(listener: () => void): () => void;
selectRow(rowId: RowId): void; setRowSelection(selection: RowSelection): void; toggleRowSelection(rowId: RowId): void; extendRowSelectionTo(rowId: RowId): void; clearRowSelection(): void;
isExpanded(rowId: RowId): boolean; subscribeExpansion(listener: () => void): () => void; expand(rowId: RowId): void; collapse(rowId: RowId): void; toggleExpand(rowId: RowId): void;
readonly tree: GridLevelTree | null;
writeCell(coord: Coord, value: unknown): void; applyChanges(changes: readonly CellChange[]): void; createRow(node: TreeNode, atIndex?: number): Promise<CreateNodeResult>; removeRow(rowKey: RowKey): Promise<void>;
readonly drafts: { get(): readonly PhantomRow[]; subscribe(listener: () => void): () => void; add(rowKey: RowKey, columns?: Readonly<Record<ColId, unknown>>): void; remove(rowKey: RowKey): void; setCell(rowKey: RowKey, colId: ColId, value: unknown): void; commit(rowKey: RowKey, atIndex?: number): Promise<CreateNodeResult>; };};Dynamic reads, commands, and subscriptions are guarded by the level’s registration lifetime. Static fields remain readable after unregistration.
const level = runtime.root;const rowId = makeRowId(level.path, "project-1");
level.writeCell({ rowId, colId: "status" }, "done");level.applyChanges([ { rowKey: "project-1", colId: "status", value: "done" }, { rowKey: "project-1", colId: "owner", value: "user-7" },]);
await level.createRow({ rowKey: "project-2", levelName: "projects", columns: { name: "New project" },});await level.removeRow("project-2");isExpanded(), expand(), collapse(), and toggleExpand() concern child
levels mounted under a row. Same-level tree rows use level.tree.
Tree rows
Section titled “Tree rows”level.tree is null unless the level declares
tree:
type GridLevelTree = { isExpanded(rowId: RowId): boolean; expand(rowId: RowId): void; collapse(rowId: RowId): void; toggle(rowId: RowId): void; expandAll(): void; collapseAll(): void; reveal(rowId: RowId): void; parentOf(rowId: RowId): RowId | null; childrenOf(rowId: RowId): readonly RowId[]; addChild( parentRowId: RowId, columns?: Readonly<Record<ColId, unknown>>, ): RowId; subscribe(listener: () => void): () => void;};isExpanded()readsfalsefor a row without children, andexpand()leaves such a row unchanged.collapse()hides a row’s descendants and moves a cursor out of them. Hidden rows leave the row selection.expandAll()andcollapseAll()also apply to rows that load later.reveal()expands every ancestor of a row so that the row is displayed.parentOf()returnsnullfor a top-level row.childrenOf()returns children in display order, including hidden ones.addChild()adds a draft row under a data row, reveals it, and returns its row id. The draft’s parent-key field holds the value fromtree.parentKeyValue, or the parent’s row key, unlesscolumnssupplies one. A child draft left blank is removed when the cursor leaves it.subscribe()observes expansion changes on this level. The runtime-widetreeExpansionChangedevent reports the same changes with their path.
const accounts = runtime.root.tree;if (accounts) { accounts.reveal(federalId); const draftId = accounts.addChild(taxesId, { name: "State" });}Data access
Section titled “Data access”level.data is the read and query facade for the level source. Runtime writes
remain on GridLevelRuntime so validation, reconciliation, and host events use
one boundary.
Use Runtime data access for the facade and query APIs. Use Data-source writes and reconciliation for the source-side write contract.