superdoc 2.23.1-next.9 → 2.24.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5938,6 +5938,7 @@ function buildTableCommandInput(action, context) {
5938
5938
  };
5939
5939
  case "delete-table": return { nodeId };
5940
5940
  case "merge-cells": {
5941
+ if (!context.canMerge) return null;
5941
5942
  const range = mergeRange ?? {
5942
5943
  start: {
5943
5944
  rowIndex,
@@ -6244,7 +6245,7 @@ function createSuperDocUI(options) {
6244
6245
  };
6245
6246
  const resolveTableContext = () => {
6246
6247
  const snapshot = readHostTableContext();
6247
- if (!snapshot || snapshot.inTable !== true) return null;
6248
+ if (!snapshot || snapshot.inTable !== true || snapshot.status && snapshot.status !== "ready") return null;
6248
6249
  const table = snapshot.table;
6249
6250
  const tableNodeId = typeof table?.nodeId === "string" && table.nodeId.length > 0 ? table.nodeId : null;
6250
6251
  if (!tableNodeId) return null;
@@ -6256,12 +6257,15 @@ function createSuperDocUI(options) {
6256
6257
  if (rowIndex == null || columnIndex == null) return null;
6257
6258
  const cellNodeId = typeof cell?.nodeId === "string" && cell.nodeId.length > 0 ? cell.nodeId : null;
6258
6259
  const range = snapshot.cellRange;
6260
+ const mergeRange = readMergeRange(range);
6261
+ const metadata = snapshot.tableSelection;
6259
6262
  return {
6260
6263
  tableNodeId,
6261
6264
  rowIndex,
6262
6265
  columnIndex,
6263
6266
  cellNodeId,
6264
- mergeRange: readMergeRange(range)
6267
+ mergeRange,
6268
+ canMerge: metadata == null || metadata.selectionMode === "cells" && metadata.isRectangular === true
6265
6269
  };
6266
6270
  };
6267
6271
  const customCommands = /* @__PURE__ */ new Map();
@@ -9155,7 +9159,7 @@ function createSuperDocUI(options) {
9155
9159
  reason: SUPERDOC_UI_REASONS.documentReadonly
9156
9160
  }, "builtin");
9157
9161
  const context = resolveTableContext();
9158
- if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null))) return normalizeCommandState({
9162
+ if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null) && (descriptor.table.action !== "merge-cells" || context.canMerge))) return normalizeCommandState({
9159
9163
  enabled: false,
9160
9164
  active: false,
9161
9165
  supported: true,
@@ -13060,7 +13064,13 @@ function createSuperDocUI(options) {
13060
13064
  return {
13061
13065
  point,
13062
13066
  entities: validInput ? entityAt(point) : [],
13063
- selection: state.selection,
13067
+ selection: (() => {
13068
+ const current = computeSelection();
13069
+ return current.status === "ready" ? current : {
13070
+ ...current,
13071
+ tableSelection: null
13072
+ };
13073
+ })(),
13064
13074
  position: null,
13065
13075
  insideSelection: false
13066
13076
  };
@@ -13277,21 +13287,67 @@ function createSuperDocUI(options) {
13277
13287
  columnIndex: null,
13278
13288
  cellNodeId: null,
13279
13289
  rows: null,
13280
- columns: null
13290
+ columns: null,
13291
+ status: "ready",
13292
+ cellRange: null,
13293
+ tableSelection: null
13294
+ };
13295
+ const publicTableContext = (snapshot) => {
13296
+ const status = snapshot?.status === "pending" || snapshot?.status === "stale" ? snapshot.status : "ready";
13297
+ if (!snapshot || snapshot.inTable !== true || status !== "ready") return {
13298
+ ...EMPTY_TABLE_CONTEXT,
13299
+ status
13300
+ };
13301
+ const table = snapshot.table;
13302
+ const row = snapshot.row;
13303
+ const column = snapshot.column;
13304
+ const cell = snapshot.cell;
13305
+ if (typeof table?.nodeId !== "string") return {
13306
+ ...EMPTY_TABLE_CONTEXT,
13307
+ status
13308
+ };
13309
+ return {
13310
+ inTable: true,
13311
+ status,
13312
+ tableNodeId: table.nodeId,
13313
+ rowIndex: typeof row?.index === "number" ? row.index : null,
13314
+ columnIndex: typeof column?.index === "number" ? column.index : null,
13315
+ cellNodeId: typeof cell?.nodeId === "string" ? cell.nodeId : null,
13316
+ rows: typeof table.rows === "number" ? table.rows : null,
13317
+ columns: typeof table.columns === "number" ? table.columns : null,
13318
+ cellRange: readMergeRange(snapshot.cellRange),
13319
+ tableSelection: snapshot.tableSelection ?? null
13320
+ };
13281
13321
  };
13282
13322
  const tables = {
13283
- getContext: () => {
13284
- const context = resolveTableContext();
13285
- if (!context) return { ...EMPTY_TABLE_CONTEXT };
13286
- const table = readHostTableContext()?.table;
13323
+ getContext: () => publicTableContext(readHostTableContext()),
13324
+ getContextAsync: async () => {
13325
+ for (let attempt = 0; attempt < 2; attempt += 1) {
13326
+ const token = selectionReadToken();
13327
+ const host = getHost();
13328
+ const read = host?.getTableContextAsync;
13329
+ if (typeof read !== "function") return publicTableContext(readHostTableContext());
13330
+ let snapshot = null;
13331
+ try {
13332
+ snapshot = await read.call(host);
13333
+ } catch {
13334
+ return {
13335
+ ...EMPTY_TABLE_CONTEXT,
13336
+ status: "pending"
13337
+ };
13338
+ }
13339
+ if (disposed) return {
13340
+ ...EMPTY_TABLE_CONTEXT,
13341
+ status: "pending"
13342
+ };
13343
+ if (token !== selectionReadToken() || host !== getHost()) continue;
13344
+ const context = publicTableContext(snapshot);
13345
+ if (context.status === "stale") continue;
13346
+ return context;
13347
+ }
13287
13348
  return {
13288
- inTable: true,
13289
- tableNodeId: context.tableNodeId,
13290
- rowIndex: context.rowIndex,
13291
- columnIndex: context.columnIndex,
13292
- cellNodeId: context.cellNodeId,
13293
- rows: typeof table?.rows === "number" ? table.rows : null,
13294
- columns: typeof table?.columns === "number" ? table.columns : null
13349
+ ...EMPTY_TABLE_CONTEXT,
13350
+ status: "stale"
13295
13351
  };
13296
13352
  },
13297
13353
  isInTable: () => resolveTableContext() != null
@@ -5939,6 +5939,7 @@ function buildTableCommandInput(action, context) {
5939
5939
  };
5940
5940
  case "delete-table": return { nodeId };
5941
5941
  case "merge-cells": {
5942
+ if (!context.canMerge) return null;
5942
5943
  const range = mergeRange ?? {
5943
5944
  start: {
5944
5945
  rowIndex,
@@ -6245,7 +6246,7 @@ function createSuperDocUI(options) {
6245
6246
  };
6246
6247
  const resolveTableContext = () => {
6247
6248
  const snapshot = readHostTableContext();
6248
- if (!snapshot || snapshot.inTable !== true) return null;
6249
+ if (!snapshot || snapshot.inTable !== true || snapshot.status && snapshot.status !== "ready") return null;
6249
6250
  const table = snapshot.table;
6250
6251
  const tableNodeId = typeof table?.nodeId === "string" && table.nodeId.length > 0 ? table.nodeId : null;
6251
6252
  if (!tableNodeId) return null;
@@ -6257,12 +6258,15 @@ function createSuperDocUI(options) {
6257
6258
  if (rowIndex == null || columnIndex == null) return null;
6258
6259
  const cellNodeId = typeof cell?.nodeId === "string" && cell.nodeId.length > 0 ? cell.nodeId : null;
6259
6260
  const range = snapshot.cellRange;
6261
+ const mergeRange = readMergeRange(range);
6262
+ const metadata = snapshot.tableSelection;
6260
6263
  return {
6261
6264
  tableNodeId,
6262
6265
  rowIndex,
6263
6266
  columnIndex,
6264
6267
  cellNodeId,
6265
- mergeRange: readMergeRange(range)
6268
+ mergeRange,
6269
+ canMerge: metadata == null || metadata.selectionMode === "cells" && metadata.isRectangular === true
6266
6270
  };
6267
6271
  };
6268
6272
  const customCommands = /* @__PURE__ */ new Map();
@@ -9156,7 +9160,7 @@ function createSuperDocUI(options) {
9156
9160
  reason: SUPERDOC_UI_REASONS.documentReadonly
9157
9161
  }, "builtin");
9158
9162
  const context = resolveTableContext();
9159
- if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null))) return normalizeCommandState({
9163
+ if (!(context != null && (!descriptor.table.requiresCell || context.cellNodeId != null) && (descriptor.table.action !== "merge-cells" || context.canMerge))) return normalizeCommandState({
9160
9164
  enabled: false,
9161
9165
  active: false,
9162
9166
  supported: true,
@@ -13061,7 +13065,13 @@ function createSuperDocUI(options) {
13061
13065
  return {
13062
13066
  point,
13063
13067
  entities: validInput ? entityAt(point) : [],
13064
- selection: state.selection,
13068
+ selection: (() => {
13069
+ const current = computeSelection();
13070
+ return current.status === "ready" ? current : {
13071
+ ...current,
13072
+ tableSelection: null
13073
+ };
13074
+ })(),
13065
13075
  position: null,
13066
13076
  insideSelection: false
13067
13077
  };
@@ -13278,21 +13288,67 @@ function createSuperDocUI(options) {
13278
13288
  columnIndex: null,
13279
13289
  cellNodeId: null,
13280
13290
  rows: null,
13281
- columns: null
13291
+ columns: null,
13292
+ status: "ready",
13293
+ cellRange: null,
13294
+ tableSelection: null
13295
+ };
13296
+ const publicTableContext = (snapshot) => {
13297
+ const status = snapshot?.status === "pending" || snapshot?.status === "stale" ? snapshot.status : "ready";
13298
+ if (!snapshot || snapshot.inTable !== true || status !== "ready") return {
13299
+ ...EMPTY_TABLE_CONTEXT,
13300
+ status
13301
+ };
13302
+ const table = snapshot.table;
13303
+ const row = snapshot.row;
13304
+ const column = snapshot.column;
13305
+ const cell = snapshot.cell;
13306
+ if (typeof table?.nodeId !== "string") return {
13307
+ ...EMPTY_TABLE_CONTEXT,
13308
+ status
13309
+ };
13310
+ return {
13311
+ inTable: true,
13312
+ status,
13313
+ tableNodeId: table.nodeId,
13314
+ rowIndex: typeof row?.index === "number" ? row.index : null,
13315
+ columnIndex: typeof column?.index === "number" ? column.index : null,
13316
+ cellNodeId: typeof cell?.nodeId === "string" ? cell.nodeId : null,
13317
+ rows: typeof table.rows === "number" ? table.rows : null,
13318
+ columns: typeof table.columns === "number" ? table.columns : null,
13319
+ cellRange: readMergeRange(snapshot.cellRange),
13320
+ tableSelection: snapshot.tableSelection ?? null
13321
+ };
13282
13322
  };
13283
13323
  const tables = {
13284
- getContext: () => {
13285
- const context = resolveTableContext();
13286
- if (!context) return { ...EMPTY_TABLE_CONTEXT };
13287
- const table = readHostTableContext()?.table;
13324
+ getContext: () => publicTableContext(readHostTableContext()),
13325
+ getContextAsync: async () => {
13326
+ for (let attempt = 0; attempt < 2; attempt += 1) {
13327
+ const token = selectionReadToken();
13328
+ const host = getHost();
13329
+ const read = host?.getTableContextAsync;
13330
+ if (typeof read !== "function") return publicTableContext(readHostTableContext());
13331
+ let snapshot = null;
13332
+ try {
13333
+ snapshot = await read.call(host);
13334
+ } catch {
13335
+ return {
13336
+ ...EMPTY_TABLE_CONTEXT,
13337
+ status: "pending"
13338
+ };
13339
+ }
13340
+ if (disposed) return {
13341
+ ...EMPTY_TABLE_CONTEXT,
13342
+ status: "pending"
13343
+ };
13344
+ if (token !== selectionReadToken() || host !== getHost()) continue;
13345
+ const context = publicTableContext(snapshot);
13346
+ if (context.status === "stale") continue;
13347
+ return context;
13348
+ }
13288
13349
  return {
13289
- inTable: true,
13290
- tableNodeId: context.tableNodeId,
13291
- rowIndex: context.rowIndex,
13292
- columnIndex: context.columnIndex,
13293
- cellNodeId: context.cellNodeId,
13294
- rows: typeof table?.rows === "number" ? table.rows : null,
13295
- columns: typeof table?.columns === "number" ? table.columns : null
13350
+ ...EMPTY_TABLE_CONTEXT,
13351
+ status: "stale"
13296
13352
  };
13297
13353
  },
13298
13354
  isInTable: () => resolveTableContext() != null
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
19
19
  var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
20
20
  var ENGINE_INFO = Object.freeze({
21
21
  ...PRIVATE_ENGINE_INFO,
22
- superdocVersion: "2.23.1-next.9",
22
+ superdocVersion: "2.24.0-next.2",
23
23
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
24
24
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
25
25
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
18
18
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
19
19
  var ENGINE_INFO = Object.freeze({
20
20
  ...PRIVATE_ENGINE_INFO,
21
- superdocVersion: "2.23.1-next.9",
21
+ superdocVersion: "2.24.0-next.2",
22
22
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
23
23
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
24
24
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -1,6 +1,8 @@
1
1
  import { SelectionTarget, TextTarget } from '../types/address.js';
2
2
  export interface SelectionTableCellsTarget {
3
3
  kind: 'tableCells';
4
+ selectionMode?: 'cells';
5
+ isRectangular?: true;
4
6
  tableId: string;
5
7
  start: {
6
8
  rowIndex: number;
@@ -12,15 +14,33 @@ export interface SelectionTableCellsTarget {
12
14
  };
13
15
  story?: SelectionTarget['story'];
14
16
  }
15
- /** Table identity for a caret, rectangular cell selection, or whole-grid selection. */
16
- export interface TableSelectionInfo extends SelectionTableCellsTarget {
17
- /** `cell` includes a caret or text range contained in one cell. */
17
+ /** Table/cell context for the selection; bounds alone are not an editing target. */
18
+ export interface TableSelectionInfo {
19
+ kind: 'tableCells';
20
+ tableId: string;
21
+ story?: SelectionTarget['story'];
22
+ /** Inclusive logical bounds, including each selected owner's span. */
23
+ start: {
24
+ rowIndex: number;
25
+ columnIndex: number;
26
+ };
27
+ end: {
28
+ rowIndex: number;
29
+ columnIndex: number;
30
+ };
31
+ /** Whole-table identity requires whole-cell selection intent. */
18
32
  type: 'table' | 'cell' | 'cells';
19
- /** Selected cells in row-major order, using opaque Document API node IDs. */
33
+ /** Text context preserves exact character targets; cells denotes whole-cell intent. */
34
+ selectionMode: 'text' | 'cells';
35
+ /** Whether the exact cells fill the bounding rectangle without holes. */
36
+ isRectangular: boolean;
37
+ /** Exact logical owners in row-major order; vertical continuations are deduplicated. */
20
38
  cells: {
21
39
  nodeId: string;
22
40
  rowIndex: number;
23
41
  columnIndex: number;
42
+ rowspan: number;
43
+ colspan: number;
24
44
  }[];
25
45
  }
26
46
  export type SelectionExtractOoxmlInput = {
@@ -132,10 +152,11 @@ export interface SelectionInfo {
132
152
  */
133
153
  selectionTarget?: SelectionTarget | null;
134
154
  /**
135
- * V2 browser table selection with inclusive, zero-based grid coordinates.
136
- * Rectangles in unmerged tables clear `target` and `selectionTarget`.
137
- * Rectangles in tables containing merged cells return null and empty text.
138
- * A single-cell caret/text range preserves its text targets and `empty` value.
155
+ * V2 browser cell context with inclusive, zero-based logical bounds.
156
+ * Whole-cell selections clear text targets. Character selections preserve
157
+ * their targets and include the containing cells, including endpoint cells.
158
+ * Exact cell IDs and spans describe merged or nonrectangular selections;
159
+ * only rectangular whole-cell metadata can become a table-cells target.
139
160
  */
140
161
  tableSelection?: TableSelectionInfo | null;
141
162
  /**
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-D_FbXpOQ.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-tJenv7pA.cjs");
3
3
  const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
4
4
  let react = require("react");
5
5
  //#region src/public/ui/react.ts
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-DFNXiKvQ.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BOrgnNVV.es.js";
2
2
  import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
3
3
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
4
4
  //#region src/public/ui/react.ts
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-D_FbXpOQ.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-tJenv7pA.cjs");
3
3
  const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
4
4
  let superdoc_entry_vue = require("vue");
5
5
  //#region src/public/ui/vue.ts
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-DFNXiKvQ.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BOrgnNVV.es.js";
2
2
  import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
3
3
  import { computed, inject, onScopeDispose, provide, shallowRef, toRaw, toValue, watch } from "vue";
4
4
  //#region src/public/ui/vue.ts
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-D_FbXpOQ.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-tJenv7pA.cjs");
3
3
  exports.BUILT_IN_COMMAND_IDS = require_create_super_doc_ui.BUILT_IN_COMMAND_IDS;
4
4
  exports.createSuperDocUI = require_create_super_doc_ui.createSuperDocUI;
5
5
  exports.shallowEqual = require_create_super_doc_ui.shallowEqual;
@@ -1,2 +1,2 @@
1
- import { a as BUILT_IN_COMMAND_IDS, t as createSuperDocUI, u as shallowEqual } from "../chunks/create-super-doc-ui-DFNXiKvQ.es.js";
1
+ import { a as BUILT_IN_COMMAND_IDS, t as createSuperDocUI, u as shallowEqual } from "../chunks/create-super-doc-ui-BOrgnNVV.es.js";
2
2
  export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };