Commands: Tables
Commands for creating and editing tables: rows, columns, cells, layout, sorting and borders.
import { insertTable, insertRowBefore, setBorders } from "@stesura/core/commands";Creating Tables
insertTable
Insert a table sized to the section’s content width, with the cursor in the first cell. Refused inside code blocks, inside another table, and wherever the schema cannot host a table (footnote/endnote bodies).
insertTable({
rows: number,
cols: number,
borders?: Borders | null // omit for default visible borders; null for borderless
}): CommandcreateTableNode
Build a table Node (not a command) for programmatic builders. Returns null when the schema lacks the table nodes.
createTableNode(state: EditorState, options: CreateTableOptions): Node | null
type CreateTableOptions = {
rows: number;
cols: number;
borders?: Borders | null;
maxWidth?: number; // px to size the columns against; default: the section's content width
// per-cell paragraph attrs and/or inline content
cellParagraph?: (row: number, col: number) =>
{ attrs?: Record<string, unknown>; content?: Node | Fragment | null } | undefined;
};Column Operations
insertColumnBefore / insertColumnAfter
Insert a column left / right of the selection, rescaling the existing columns so the table keeps its overall width. Refused when no column has a width to rescale.
insertColumnBefore: Command
insertColumnAfter: CommanddeleteColumn
Delete the selected columns and redistribute their width across the remaining ones. Refused when every column is selected. While track changes is enabled, the widths are not redistributed.
deleteColumn: CommanddistributeColWidths
Set every selected column to width px. Omit width to give them their average width (needs 2+ columns). Floored at 25px.
distributeColWidths(width?: number): CommandRow Operations
insertRowBefore / insertRowAfter
Insert as many rows as the selection spans, above / below it. New cells copy the adjacent selected row’s cell attrs, including colspans, with empty content; above the first row they are plain cells. Rowspans crossing the insert point grow to cover the new rows.
insertRowBefore(updateSelection?: boolean): Command
insertRowAfter(updateSelection?: boolean): CommandinsertRow
The TransactionFn factory behind both commands, for custom insertions. It inserts rect.bottom - rect.top rows at row index row. copyRow picks the row whose cell attrs are copied: "bottom" the row at row, "top" the row above it, null for plain cells.
insertRow(
rect: TableRect,
row: number,
copyRow: "bottom" | "top" | null,
updateSelection?: boolean
): TransactionFndeleteRow
Delete the selected rows. When the selection spans every row, delete the whole table instead. Deleting rows with vertically merged cells is not tracked (skipTrackChanges). deleteRowTr (in @stesura/core/commands/internal) is the transaction-level variant, without the whole-table case.
deleteRow: CommandsetRowHeight
Set the height attr on every row covered by the selection, capped at the section’s page height. Pass null, or a value below the 30px minimum, to clear it. Refused when every row already has that height.
setRowHeight(height: number | null): CommandCells
mergeCells
Merge the selected cells into one. Only available when the selection’s outline forms a rectangle. The merge is not tracked (skipTrackChanges). mergeCellsTr in @stesura/core/commands/internal is the transaction-level variant and does not set skipTrackChanges.
mergeCells: CommandsplitCell
Split a merged cell (rowspan or colspan > 1) back into single cells of its own type. The split is not tracked (skipTrackChanges). splitCellWithTypeTr(getCellType) in @stesura/core/commands/internal takes a custom cell-type resolver and does not set skipTrackChanges.
splitCell: CommandsetCellAlignment
Align the selected cells’ content. The vertical half sets the cells’ verticalAlign; the horizontal half sets the text alignment of the blocks inside them.
setCellAlignment(alignment: `${"top" | "middle" | "bottom"}-${"start" | "center" | "end"}`): Command
// setCellAlignment("top-start")setCellAttr
Set attribute name on the selected cells. A dry run returns false when the cell already has value, unless returnTrueOnSameValue is set.
setCellAttr(name: string, value: unknown, returnTrueOnSameValue?: boolean): CommandTable Layout
setTableAlignment
Align the table within the section’s content width. Refused when the table already has that alignment.
setTableAlignment(alignment: "start" | "center" | "end"): CommandsetTableSpacing
Merge spacing into the table’s space before/after; sides you leave out keep their value. Requires the whole table to be selected, as do the two commands below.
setTableSpacing(spacing: { before?: number; after?: number }): CommandsetTableSpacingBeforeAfter
Set the spacing on one side.
setTableSpacingBeforeAfter({
position: "before" | "after",
value: number
}): CommandincrementTableSpacing
Add value to the spacing on one side, floored at 0.
incrementTableSpacing({
position: "before" | "after",
value: number
}): CommandSelection & Deletion
selectEntireTable
Select every cell of the table containing the selection, as a CellSelection. selectEntireTableAtPos(tablePos) targets the table at a known position.
selectEntireTable: Command
selectEntireTableAtPos(tablePos: number): CommanddeleteTable
Delete the table and put an empty paragraph in its place. deleteTableIfSelected runs only when the whole table is selected, so Delete inside a cell edits the cell instead.
deleteTable: Command
deleteTableIfSelected: CommandSorting
sortTableRows
Reorder all rows by one column’s text, compared as text, number or date according to orderBy. Empty or unparsable values sort last. Without options, it uses the table’s stored sort options, then { colIndex: 0, descending: false, orderBy: "text" }. It is refused, with a toast, when the table has any vertically merged cell or colIndex is out of range. It returns false when the rows are already sorted.
sortTableRows(options?: {
colIndex: number;
descending: boolean;
orderBy: "text" | "number" | "date";
}): CommandsetTableSortOptions
Store the sort options on the table (its sortable attr), so sortTableRows() can re-run later with the same settings.
setTableSortOptions(options: SortOptions): CommandAdvanced
splitTable
Split the table in two at the cursor’s row, which becomes the first row of the second table. Refused on the first row and when a rowspan crosses that row.
splitTable: CommandBorders
setBorders applies borders to whatever the selection targets. It tries a selected horizontal rule, then a whole selected table, then cells, then styled blocks, and the first that applies wins.
import { setBorders } from "@stesura/core/commands";
setBorders(borders?: Borders): CommandsetBordersTr(borders) in @stesura/core/commands/internal is the transaction-level variant.
Each side takes a BorderOptions:
type BorderOptions = {
style: BorderStyle; // "single" | "dashed" | "dotted" | "double" | "groove"
// | "ridge" | "inset" | "outset" | "none"
color?: string;
size?: number;
space?: number;
};
type Borders = {
top?: BorderOptions;
bottom?: BorderOptions;
left?: BorderOptions;
right?: BorderOptions;
between?: BorderOptions; // blocks only
insideHorizontal?: BorderOptions; // tables only
insideVertical?: BorderOptions; // tables only
};// Horizontal rules on the selected cells, no verticals
setBorders({
top: { style: "single", size: 1, color: "#000" },
bottom: { style: "single", size: 1, color: "#000" },
left: { style: "none" },
right: { style: "none" },
});There is no "solid" style; the single-line style is "single". Use { style: "none" } to remove a side. A per-side null is only accepted on cell borders (CellBorders).
toggleOutline
Toggle the editor-wide outline overlay: dashed guides drawn where a block has no real border. Meta-only, so the doc is untouched.
toggleOutline: CommandinsertHorizontalRule
Insert a horizontal_rule node at the selection.
insertHorizontalRule: CommandNext Steps
- Commands: Sections & Track Changes — Page layout and revision tracking
- Commands: Specialized — Numbering, images, code blocks, and more