import type { Block } from './block.js'; import { type Inline } from './inline.js'; /** * Canonical table grid. Invariant: every logical grid position appears * exactly once — content and spans exist only on the origin slot, and each * position covered by a span holds a Covered marker pointing back at its * origin. */ export interface Table { grid: CellSlot[][]; /** Number of leading rows that are header rows (0 = no header). */ headerRows: number; kind: TableKind; } export type TableKind = 'data' | 'layout'; export type CellSlot = { type: 'origin'; cell: Cell; } | { type: 'covered'; originRow: number; originCol: number; }; export interface Cell { blocks: Block[]; colSpan: number; rowSpan: number; } export declare function newCell(blocks: Block[]): Cell; export declare function cellFromInlines(inlines: Inline[]): Cell; export declare function cellSpanning(blocks: Block[], colSpan: number, rowSpan: number): Cell; export declare function emptyCell(): Cell; /** * True when the cell holds nothing that would render: only paragraphs count * toward emptiness, so a cell with a table or list in it is not empty even * if that content is blank. */ export declare function cellIsEmpty(cell: Cell): boolean; /** Build a plain span-less table from rows of cells (spreadsheets, CSV). */ export declare function tableFromRows(rows: Cell[][], headerRows: number, kind: TableKind): Table; /** True when the table is a single origin cell (any covered padding aside). */ export declare function tableIsSingleCell(table: Table): boolean; /** * Sole constructor for Table grids. Enforces the exactly-once invariant: * spans register their covered positions, later placements skip over them, * and overlapping spans are clamped rather than double-counted. */ export declare class GridBuilder { private grid; /** Positions in future rows covered by an earlier row-spanning origin. */ private pending; nextRow(): void; nextRows(n: number): void; /** * Materialize `n` empty 1x1 origins on the current row. Used for ODF * interior empty-cell repeats so later content keeps source columns * without going through per-cell span accounting. */ placeEmptyRun(n: number): void; private rowIndex; /** Materialize pending covered positions at the cursor. */ private skipPending; place(cell: Cell): void; /** * Consume one explicitly-written covered position (ODF covered-table-cell). * Returns false when no span accounts for the position — the stray marker * then becomes an empty cell. */ covered(): boolean; finish(kind: TableKind): Table; }