Row selection
View as MarkdownRow selection identifies rows for operations such as delete, export, bulk edit, or a pinned side panel. It is separate from active-row context and rectangular cell selection.
Configuration and value
Section titled “Configuration and value”type SelectedRowsConfig = | { readonly kind: "none" } | { readonly kind: "enabled"; readonly mode: "single" | "range" | "multi"; readonly sync: | { readonly kind: "follows-active-row" } | { readonly kind: "independent" }; readonly keyboard: { readonly space: "toggle-active-row" | "ignore"; }; };follows-active-row derives the effective selection from the active row. It is
a read-only projection. independent stores a path-local row selection that can
differ from the active row.
type RowSelection = | { readonly kind: "single"; readonly rowId: RowId } | { readonly kind: "range"; readonly anchor: RowId; readonly head: RowId; } | { readonly kind: "set"; readonly rowIds: ReadonlySet<RowId> } | null;Read and change row state through a GridLevelRuntime:
const level = runtime.root;const rowId = makeRowId(level.path, "task-1");
level.activeRow();level.selectedRows();level.selectedRowIds();level.rowInteractionSnapshot();
level.selectRow(rowId);level.toggleRowSelection(rowId);level.extendRowSelectionTo(rowId);level.clearRowSelection();Selection commands normalize row ids against the current displayed rows and the configured selection mode. Non-selectable and stale rows are removed.
Pointer gestures
Section titled “Pointer gestures”In a row list (mode: "row-list"), every mouse press on a selectable row moves
the row cursor to that row. The modifier keys decide what else happens to an
independent selection:
| Gesture | Effect on the selection |
|---|---|
| Click | None. The click only moves the row cursor. |
| Shift-click | Selects the range from the previous row cursor to the clicked row, when activeRow.keyboard.shiftArrows is "extend-selected-rows". |
| Cmd-click or Ctrl-click | Toggles the clicked row, the same way Shift+Space toggles the active row. A "multi" selection adds or removes the row and keeps the other selected rows. A "single" selection selects the row, or clears it when it is already selected. Adding Shift is still a toggle. |
When the configuration does not allow a gesture, the press only moves the row
cursor. For example, a selection that follows the active row has no stored
selection to toggle, and Shift-click does not extend when shiftArrows is
"move-active-row". Because a toggle moves the row cursor, a following
Shift-click selects the range that starts at the toggled row.
ROW_MULTISELECT_LIST enables all three gestures.
In a cell grid, the same gestures apply to row headers and row-selection controls. There, a plain click replaces the selection with the clicked row.
Subscriptions
Section titled “Subscriptions”Level subscriptions correspond to distinct read models:
level.subscribeActiveRow(() => { renderInspector(level.activeRow());});
level.subscribeSelectedRows(() => { persistSelection(level.selectedRows());});
level.subscribeSelectedRowIds(() => { updateCount(level.selectedRowIds().length);});
level.subscribeRowInteractionSnapshot(() => { updateRowChrome(level.rowInteractionSnapshot());});subscribeSelectedRows() observes the configured selection value.
subscribeSelectedRowIds() also observes displayed-order changes that alter the
projected ids. subscribeRowInteractionSnapshot() is designed for row
decoration.
React components use the corresponding hooks:
useActiveRow(path);useSelectedRows(path);useSelectedRowIds(path);useRowInteractionSnapshot(path);Row selection chrome
Section titled “Row selection chrome”rowSelectionColumn() creates a normal ColumnSchema that reads path-local row
status and invokes the level selection commands.
import { rowSelectionColumn, text } from "@sapporta/grid/column-preset";
const columns = [ rowSelectionColumn(), text({ id: "title", name: "Title", edit: "default" }),];Set the level’s rowHeaderColumn to { column: selectorColumnId } when
row-header behavior should be attached to that column. Use
"empty-selectable-cell" for a separate row header or "none" when the level
has no row header.
Cross-path operations
Section titled “Cross-path operations”Stored selection remains path-local. Use
runtime.rowOperations
when one command intentionally spans the expanded hierarchy.