SOURCE-PROJECTED REFERENCE

API reference

A concise public surface derived from the implementation source used by the live demos.

Start with the backend port guide, then inspect the authoritativeTypeScript source for optional capabilities.

SpreadsheetBackend

export interface SpreadsheetBackend {
  listSheets?(): Promise<SheetListResult>
  readVisibleProjection(request: VisibleProjectionRequest): Promise<VisibleProjectionResult>
  readRangeProjection(request: RangeProjectionRequest): Promise<RangeProjectionResult>
  exportRangeTsv?(request: RangeTsvExportRequest): Promise<RangeTsvExportResult>
  /**
   * Wave 8.4 — range screenshot. Optional capability; UI core hides the
   * Copy-as-PNG surfaces and `encodeSelectionAsImage` returns `null`
   * when this method is omitted.
   */
  exportRangeAsImage?(request: RangeImageExportRequest): Promise<RangeImageExportResult>
  consumeExportRangeTsvChunks?(
    request: RangeTsvExportRequest,
    onChunk: RangeTsvChunkConsumer,
  ): Promise<RangeTsvChunkExportResult>
  readViewportSizeProjection?(
    request: ViewportSizeProjectionRequest,
  ): Promise<ViewportSizeProjectionResult>
  /**
   * Commit one cell's raw input. Resolving a `BackendMutationResult` means
   * the value really landed — a host that cannot apply the write MUST
   * reject, never resolve a success-shaped ACK, or the user's keystrokes
   * disappear while UI core records history and bumps the revision.
   * `runEditingCommitAtom` turns the rejection into a `rejected` editing
   * lifecycle carrying the Error's `message`, so the reason belongs there
   * (any structured `code` / `detail` is host-private).
   */
  setCellInput(request: SetCellInputRequest): Promise<BackendMutationResult>
  setCellRichValue?(request: SetCellRichValueRequest): Promise<BackendMutationResult>
  importCells?(request: ImportCellsRequest): Promise<BackendMutationResult>
  importCellChunks?(request: ImportCellChunksRequest): Promise<BackendMutationResult>
  clearRange?(request: ClearRangeRequest): Promise<BackendMutationResult>
  insertRows?(request: InsertRowsRequest): Promise<BackendMutationResult>
  deleteRows?(request: DeleteRowsRequest): Promise<BackendMutationResult>
  insertColumns?(request: InsertColumnsRequest): Promise<BackendMutationResult>
  deleteColumns?(request: DeleteColumnsRequest): Promise<BackendMutationResult>
  setFormatRange?(request: SetFormatRangeRequest): Promise<BackendMutationResult>
  setRowHeight?(request: SetRowHeightRequest): Promise<BackendMutationResult>
  setColumnWidth?(request: SetColumnWidthRequest): Promise<BackendMutationResult>
  fillRange?(request: FillRangeRequest): Promise<AutoFillMutationResult>
  resolveDataEdge?(request: ResolveDataEdgeRequest): Promise<ResolveDataEdgeResult>
  addSheet?(request: AddSheetRequest): Promise<SheetMutationResult>
  renameSheet?(request: RenameSheetRequest): Promise<SheetMutationResult>
  deleteSheet?(request: DeleteSheetRequest): Promise<SheetMutationResult>
  reorderSheet?(request: ReorderSheetRequest): Promise<SheetMutationResult>
  undoTransaction?(request: UndoTransactionRequest): Promise<HistoryTransactionResult>
  redoTransaction?(request: RedoTransactionRequest): Promise<HistoryTransactionResult>
  listNamedRanges?(request: ListNamedRangesRequest): Promise<NamedRangeListResult>
  setNamedRange?(request: SetNamedRangeRequest): Promise<NamedRangeMutationResult>
  deleteNamedRange?(request: DeleteNamedRangeRequest): Promise<NamedRangeMutationResult>
  mergeRange?(request: MergeRangeRequest): Promise<BackendMutationResult>
  unmergeRange?(request: UnmergeRangeRequest): Promise<BackendMutationResult>
  readFreezeConfig?(request: ReadFreezeConfigRequest): Promise<ReadFreezeConfigResult>
  setFreezeConfig?(request: SetFreezeConfigRequest): Promise<BackendMutationResult>
  hideRows?(request: HideRowsRequest): Promise<BackendMutationResult>
  unhideRows?(request: UnhideRowsRequest): Promise<BackendMutationResult>
  // Read-back of the engine-owned hidden state (rows + filter), for hydrating
  // UI-core render caches on sheet activation / restore. Optional: a backend
  // whose engine does not OWN this state (the TS worker) omits the port and
  // UI-core keeps its own canonical view fact instead of hydrating from a
  // source that cannot answer authoritatively.
  readSheetHiddenState?(request: SheetHiddenStateRequest): Promise<SheetHiddenStateResult>
  hideColumns?(request: HideColumnsRequest): Promise<BackendMutationResult>
  unhideColumns?(request: UnhideColumnsRequest): Promise<BackendMutationResult>
  // engine hidden-row eval input (parity #23). Optional, fire-and-forget
  // whole-set REPLACE (no exact ACK / undo): mirrors the UI-core canonical
  // hidden-row VIEW fact into the engine so SUBTOTAL 101-111 can exclude
  // manually hidden data rows. A backend whose engine models no such input
  // omits the port; UI core silently skips the push and SUBTOTAL 101-111
  // degrades to "does not exclude" without disturbing any other feature.
  setEvalHiddenRows?(request: SetEvalHiddenRowsRequest): Promise<void> | void
  fillSeries?(request: FillSeriesRequest): Promise<AutoFillMutationResult>
  // comments & notes
  setNote?(request: SetNoteRequest): Promise<BackendMutationResult>
  clearNote?(request: ClearNoteRequest): Promise<BackendMutationResult>
  postComment?(request: PostCommentRequest): Promise<BackendMutationResult>
  resolveCommentThread?(request: ResolveCommentThreadRequest): Promise<BackendMutationResult>
  deleteComment?(request: DeleteCommentRequest): Promise<BackendMutationResult>
  // data validation
  setValidationRule?(request: SetValidationRuleRequest): Promise<BackendMutationResult>
  clearValidationRule?(request: ClearValidationRuleRequest): Promise<BackendMutationResult>
  // conditional formatting
  setConditionalFormatRule?(
    request: SetConditionalFormatRuleRequest,
  ): Promise<BackendMutationResult>
  removeConditionalFormatRule?(
    request: RemoveConditionalFormatRuleRequest,
  ): Promise<BackendMutationResult>
  listConditionalFormatRules?(
    request: ListConditionalFormatRulesRequest,
  ): Promise<ConditionalFormatRulesResult>
  // print config
  readPrintConfig?(request: ReadPrintConfigRequest): Promise<ReadPrintConfigResult>
  setPrintConfig?(request: SetPrintConfigRequest): Promise<SetPrintConfigResult>
  // find-replace
  /**
   * Match offsets are UTF-16 code-unit indexes into the selected target and use half-open
   * `[matchStart, matchEnd)` intervals. Every emitted span satisfies
   * `0 <= matchStart < matchEnd`; zero-width regex results are omitted.
   */
  searchRange?(request: SearchRangeRequest): Promise<SearchRangeResult>
  /**
   * Replacement spans use the same UTF-16 code-unit, half-open, non-empty contract as search
   * results. Zero-width and reversed spans are rejected before any mutation.
   */
  replaceMatches?(request: ReplaceMatchesRequest): Promise<ReplaceMatchesResponse>
  // presence
  subscribePresence?(handler: (update: PresenceUpdate) => void): SubscribePresenceUnsubscribe
  publishLocalPresence?(request: PublishLocalPresenceRequest): Promise<void>
  // filter-sort
  // Resolves the ordinary mutation ACK PLUS the filter-hidden row set the
  // rule scan produced (`SetFilterSortResult.hiddenRowIndices`). Widening the
  // result is backward compatible: a host that returns a bare
  // `BackendMutationResult` still satisfies this signature, and UI core reads
  // the missing field as "cannot compute visibility" and hides nothing.
  setFilterSort?(request: SetFilterSortRequest): Promise<SetFilterSortResult>
  // engine physical sort — design-engine-sort. Optional capability: host
  // adapters whose runtime cannot physically reorder workbook data omit
  // this port (the TS worker declares `sortRange: false`), which hides
  // the physical-sort entry through the standard degradation contract.
  // Unlike `setFilterSort` (a UI-core VIEW fact / display permutation),
  // this reorders engine DATA; undo is host-orchestrated (one bounded
  // range-snapshot transaction). Resolves an applied report OR a
  // structured not-applied result — a gated request does NOT reject the
  // promise.
  sortRange?(request: SortRangeRequest): Promise<SortRangeResult>
  // protection — UI-core canonical (#40). These ports are an optional
  // persistence hook: `setSheetProtection` / `setRangeLock` receive a
  // fire-and-forget mirror of local commits and `readSheetProtection`
  // seeds a one-shot hydration. Backends that omit them keep the full
  // protection feature; enforcement runs in the UI-core mutation gateway.
  setSheetProtection?(request: SetSheetProtectionRequest): Promise<BackendMutationResult>
  setRangeLock?(request: SetRangeLockRequest): Promise<BackendMutationResult>
  readSheetProtection?(request: ReadSheetProtectionRequest): Promise<ReadSheetProtectionResult>
  // paste-special — Wave 7.3. Optional capability: host adapters that
  // omit this method cause the menu entry + dialog to hide via
  // `pasteSpecialSupportedAtom` so the surface degrades cleanly.
  pasteRange?(request: PasteRangeRequest): Promise<PasteRangeResult>
  // Optional fail-closed subdivision of the pasteRange capability (see
  // `PasteSpecialControllerPort.pasteRangeSupportedKinds`): a backend
  // that cannot apply the format leg declares only the value-leg kinds
  // and Core blocks the rest pre-dispatch. Absent → full trust.
  readonly pasteRangeSupportedKinds?: readonly PasteSpecialKind[]
  // remove-duplicates — Wave 7.5. Optional capability; host adapters that
  // omit this method cause the Data > Remove Duplicates menu entry to hide
  // via `removeDuplicatesSupportedAtom` so the surface degrades cleanly.
  removeRows?(request: RemoveRowsRequest): Promise<RemoveRowsResult>
  // custom-formulas — Wave 8. Optional capability; host adapters that
  // omit these methods make the `customFormulaRegistryAtom` inert
  // (writes succeed but no worker side-effect runs). `source` is the
  // body of a function whose argument is bound to `args` (Array) — the
  // adapter is expected to `new Function('args', source)` it inside
  // whichever runtime owns the formula engine. Errors thrown during
  // evaluation surface as `#ERROR!` cells. Wave 8.2: pass
  // `options.isAsync` to compile through the AsyncFunction constructor —
  // the cell holds `#BUSY!` until the returned Promise settles, and the
  // result is memoized per (name, args) until the next registry change.
  registerCustomFormula?(
    name: string,
    source: string,
    options?: { isAsync?: boolean },
  ): Promise<void>
  unregisterCustomFormula?(name: string): Promise<void>
  // tables — Excel Table CRUD (parity #32, design-excel-table.md §10).
  // Optional capability family: host adapters whose engine has no Table
  // model omit these ports (the TS worker declares `structuredTables:
  // false`, the static backend implements none), which hides every Table
  // entry through the standard method-presence degradation contract. The
  // engine registry is canonical (CANONICAL_OWNERSHIP §3 #32) — these are
  // the only path UI core reads a table's geometry; it stores no second
  // copy. `createTable` resolves the engine-assigned canonical name OR a
  // structured `TableMutationRejectedResult` (name conflict / range
  // overlap / cap 256 / …) rather than rejecting the promise; rename and
  // delete follow the same applied-or-structured-reject convention.
  // Table-definition undo is NOT wired in this slice (design §11/§12
  // known gap — persistence and the snapshot primitive do not carry the
  // table registry).
  createTable?(request: CreateTableRequest): Promise<CreateTableResult>
  renameTable?(request: RenameTableRequest): Promise<TableMutationResult>
  renameTableColumn?(request: RenameTableColumnRequest): Promise<TableMutationResult>
  deleteTable?(request: DeleteTableRequest): Promise<TableMutationResult>
  listTables?(request: ListTablesRequest): Promise<ListTablesResult>
  getTable?(request: GetTableRequest): Promise<GetTableResult>
  // Totals row (parity #32 T6, design-excel-table.md §7). Optional
  // subdivision of the Table capability family — the same
  // `structuredTables` witness gates them, so a backend whose engine has no
  // Table model omits them alongside the CRUD ports and UI core hides the
  // totals toggle through the standard method-presence contract. Both
  // resolve the shared applied-or-structured-reject convention: a gated
  // request (row-below occupied → `totals-row-blocked`, function before the
  // row is enabled → `no-totals-row`, unknown aggregate id →
  // `invalid-totals-function`) resolves a `TableMutationRejectedResult`
  // rather than rejecting the promise. Not undoable in this slice (design
  // §11/§12 known gap; the SUBTOTAL cell writes are covered by the existing
  // cell snapshots, the registry geometry change is not).
  setTableTotalsRow?(request: SetTableTotalsRowRequest): Promise<TableMutationResult>
  setTableTotalFunction?(request: SetTableTotalFunctionRequest): Promise<TableMutationResult>
  // spill (dynamic arrays) — ADR 0006 阶段 3。可选能力:引擎里没有动态数组
  // 模型的宿主(静态后端)省掉这个端口,`spillRegionSupportedAtom` 转 false,
  // 溢出边框与投影格标记整体不出现 —— 端口缺席是「功能不存在」,不是错误。
  //
  // 按需查询而不是给 `DisplayCell` 加字段:溢出边框只在选区落进数组时出现,
  // 所以一次选区移动查一次就够。取舍与代价见 `src/spill/README.md`。
  // `region: null` 是明确的「这一格不在任何活动溢出区里」,与端口缺席不同。
  readSpillRegion?(request: SpillRegionRequest): Promise<SpillRegionResult>
  // content-change push — Wave 8.2. Optional capability: backends whose
  // engine can change cell content OUTSIDE a UI-initiated mutation
  // (async custom-formula settles, collaborative edits) invoke the
  // handler after such a change so the host refetches the visible
  // projection. Coarse signal, no payload — hosts must tolerate
  // spurious invocations. Backends whose content only ever changes in
  // response to their own mutation methods may omit it.
  subscribeContentChanges?(handler: () => void): () => void
}

Atom feature guides

Generated API Markdown

Browse the TypeDoc reference generated from the publicspreadsheet-ui-core and solid-excel entry points during this site's build.