superdoc 2.22.0-next.9 → 2.22.0

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.
Files changed (43) hide show
  1. package/dist/chunks/{create-super-doc-ui-Dos1KQcL.es.js → create-super-doc-ui-DmGX1w-i.es.js} +165 -48
  2. package/dist/chunks/{create-super-doc-ui-DTLJMJIl.cjs → create-super-doc-ui-MSiU8Kg0.cjs} +165 -48
  3. package/dist/collaboration-upgrade-engine.cjs +1 -1
  4. package/dist/collaboration-upgrade-engine.es.js +1 -1
  5. package/dist/document-api/src/content-controls/content-controls.types.d.ts +2 -0
  6. package/dist/document-api/src/contract/operation-definitions.d.ts +2 -2
  7. package/dist/layout-engine/contracts/src/index.d.ts +17 -7
  8. package/dist/layout-engine/contracts/src/justify-utils.d.ts +5 -2
  9. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +30 -4
  10. package/dist/layout-engine/layout-bridge/src/index.d.ts +3 -3
  11. package/dist/layout-engine/layout-bridge/src/layoutHeaderFooter.d.ts +4 -0
  12. package/dist/layout-engine/layout-engine/src/anchors.d.ts +4 -4
  13. package/dist/layout-engine/layout-engine/src/column-balancing.d.ts +2 -2
  14. package/dist/layout-engine/layout-engine/src/execution.d.ts +1 -1
  15. package/dist/layout-engine/layout-engine/src/index.d.ts +28 -1
  16. package/dist/layout-engine/layout-engine/src/inline-drawing-alignment.d.ts +4 -1
  17. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +9 -1
  18. package/dist/layout-engine/layout-engine/src/layout-utils.d.ts +5 -1
  19. package/dist/layout-engine/layout-engine/src/paragraph-continuation.d.ts +6 -0
  20. package/dist/layout-engine/layout-engine/src/section-props.d.ts +1 -1
  21. package/dist/layout-engine/layout-engine/src/source-preparation.d.ts +52 -0
  22. package/dist/layout-engine/painters/dom/src/page-content.d.ts +6 -0
  23. package/dist/layout-engine/painters/dom/src/paragraph/renderParagraphContent.d.ts +3 -1
  24. package/dist/layout-engine/painters/dom/src/paragraph/renderParagraphFragment.d.ts +3 -1
  25. package/dist/layout-engine/painters/dom/src/persistent-page-surface.d.ts +5 -4
  26. package/dist/layout-engine/painters/dom/src/pm-position-validation.d.ts +1 -0
  27. package/dist/layout-engine/painters/dom/src/render-work.d.ts +3 -0
  28. package/dist/layout-engine/painters/dom/src/renderer.d.ts +28 -5
  29. package/dist/layout-engine/painters/dom/src/runs/render-line.d.ts +3 -1
  30. package/dist/layout-engine/painters/dom/src/runs/tab-run.d.ts +1 -1
  31. package/dist/layout-engine/painters/dom/src/table/renderTableCell.d.ts +3 -1
  32. package/dist/layout-engine/painters/dom/src/table/renderTableFragment.d.ts +3 -1
  33. package/dist/layout-engine/painters/dom/src/table/renderTableRow.d.ts +3 -1
  34. package/dist/public/ui-react.cjs +1 -1
  35. package/dist/public/ui-react.es.js +1 -1
  36. package/dist/public/ui-vue.cjs +1 -1
  37. package/dist/public/ui-vue.es.js +1 -1
  38. package/dist/public/ui.cjs +1 -1
  39. package/dist/public/ui.es.js +1 -1
  40. package/dist/superdoc.cjs +3 -3
  41. package/dist/superdoc.es.js +3 -3
  42. package/dist-cdn/superdoc.min.js +40 -40
  43. package/package.json +2 -2
@@ -3992,6 +3992,65 @@ var INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES = Object.freeze([
3992
3992
  ]);
3993
3993
  new Set(INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES);
3994
3994
  //#endregion
3995
+ //#region ../document-api/src/types/story.types.ts
3996
+ /** All recognized story types. */
3997
+ var STORY_TYPES = [
3998
+ "body",
3999
+ "headerFooterSlot",
4000
+ "headerFooterPart",
4001
+ "footnote",
4002
+ "endnote",
4003
+ "textbox"
4004
+ ];
4005
+ /** Valid header/footer story kinds. */
4006
+ var STORY_HEADER_FOOTER_KINDS = ["header", "footer"];
4007
+ /** Valid header/footer slot variants. */
4008
+ var STORY_HEADER_FOOTER_VARIANTS = [
4009
+ "default",
4010
+ "first",
4011
+ "even"
4012
+ ];
4013
+ /** Valid header/footer slot resolution modes. */
4014
+ var STORY_HEADER_FOOTER_RESOLUTIONS = ["effective", "explicit"];
4015
+ /** Valid header/footer slot write modes. */
4016
+ var STORY_HEADER_FOOTER_ON_WRITE_VALUES = [
4017
+ "materializeIfInherited",
4018
+ "editResolvedPart",
4019
+ "error"
4020
+ ];
4021
+ /**
4022
+ * Type guard: returns `true` if `value` is a valid {@link StoryLocator}.
4023
+ *
4024
+ * Checks the full discriminated-union shape so malformed partial locators do
4025
+ * not leak through validation and fail later with raw property-access errors.
4026
+ */
4027
+ function isStoryLocator(value) {
4028
+ if (!isObjectRecord(value) || value.kind !== "story" || !isStringEnumMember(value.storyType, STORY_TYPES)) return false;
4029
+ switch (value.storyType) {
4030
+ case "body": return true;
4031
+ case "headerFooterSlot": return isSectionAddress(value.section) && isStringEnumMember(value.headerFooterKind, STORY_HEADER_FOOTER_KINDS) && isStringEnumMember(value.variant, STORY_HEADER_FOOTER_VARIANTS) && isOptionalStringEnumMember(value.resolution, STORY_HEADER_FOOTER_RESOLUTIONS) && isOptionalStringEnumMember(value.onWrite, STORY_HEADER_FOOTER_ON_WRITE_VALUES);
4032
+ case "headerFooterPart": return isNonEmptyString(value.refId);
4033
+ case "footnote":
4034
+ case "endnote": return isNonEmptyString(value.noteId);
4035
+ case "textbox": return isNonEmptyString(value.textboxId);
4036
+ }
4037
+ }
4038
+ function isObjectRecord(value) {
4039
+ return typeof value === "object" && value !== null;
4040
+ }
4041
+ function isNonEmptyString(value) {
4042
+ return typeof value === "string" && value.length > 0;
4043
+ }
4044
+ function isStringEnumMember(value, allowed) {
4045
+ return typeof value === "string" && allowed.includes(value);
4046
+ }
4047
+ function isOptionalStringEnumMember(value, allowed) {
4048
+ return value === void 0 || isStringEnumMember(value, allowed);
4049
+ }
4050
+ function isSectionAddress(value) {
4051
+ return isObjectRecord(value) && value.kind === "section" && typeof value.sectionId === "string" && value.sectionId.length > 0;
4052
+ }
4053
+ //#endregion
3995
4054
  //#region ../document-api/src/format/inline-run-patch.ts
3996
4055
  var schemaBooleanOrNull = () => ({ oneOf: [{ type: "boolean" }, { type: "null" }] });
3997
4056
  var schemaStringOrNull = () => ({ oneOf: [{
@@ -5702,6 +5761,13 @@ function selectionTargetFromTextTarget(target) {
5702
5761
  ...story ? { story } : {}
5703
5762
  };
5704
5763
  }
5764
+ function capturedTableCellTarget(value) {
5765
+ if (!value || typeof value !== "object") return null;
5766
+ const target = value;
5767
+ if (target.kind !== "selection" || target.coordinateSpace !== void 0 && target.coordinateSpace !== "visible" && target.coordinateSpace !== "tracked" || target.story !== void 0 && !isStoryLocator(target.story)) return null;
5768
+ for (const point of [target.start, target.end]) if (!point || point.kind !== "text" || typeof point.blockId !== "string" || point.blockId.length === 0 || !Number.isInteger(point.offset) || point.offset < 0 || point.story !== void 0 && !isStoryLocator(point.story)) return null;
5769
+ return value;
5770
+ }
5705
5771
  function selectionTargetForRestore(capture) {
5706
5772
  if (capture.selectionTarget) return capture.selectionTarget;
5707
5773
  return selectionTargetFromTextTarget(capture.target);
@@ -7041,11 +7107,11 @@ function createSuperDocUI(options) {
7041
7107
  };
7042
7108
  const selectionScopedAsyncReadKeys = (selection) => {
7043
7109
  const signature = selectionSignature(selection);
7044
- const effectiveUniformitySignature = selectionEffectiveUniformitySignature(selection);
7110
+ const effectiveUniformityKey = effectiveInlineUniformityCacheKey(selection);
7045
7111
  return /* @__PURE__ */ new Set([
7046
7112
  `contentControls:inRange:${signature}`,
7047
7113
  `query:${signature}`,
7048
- ...effectiveUniformitySignature ? [`effInline:${effectiveUniformitySignature}`] : []
7114
+ ...effectiveUniformityKey ? [effectiveUniformityKey] : []
7049
7115
  ]);
7050
7116
  };
7051
7117
  const pruneSelectionScopedAsyncReads = (selection) => {
@@ -7939,7 +8005,7 @@ function createSuperDocUI(options) {
7939
8005
  if (!sawWholeRun) return {};
7940
8006
  return collapseMarkSets(wholeSets);
7941
8007
  };
7942
- const completeProjectedInlineValues = (selection, direct) => {
8008
+ const completeProjectedInlineValues = (selection, direct, effectiveInput = effectiveInlineUniformityInput(selection)) => {
7943
8009
  if (direct.fontFamily !== void 0 && direct.fontSize !== void 0 && direct.color !== void 0 && direct.highlight !== void 0) return {
7944
8010
  values: direct,
7945
8011
  effectiveUniformityStatus: "ready"
@@ -7953,7 +8019,7 @@ function createSuperDocUI(options) {
7953
8019
  ...direct
7954
8020
  };
7955
8021
  if (!selection.empty && (combined.fontFamily === void 0 || combined.fontSize === void 0)) {
7956
- const uniformity = resolveEffectiveInlineUniformityValues(selection);
8022
+ const uniformity = resolveEffectiveInlineUniformityValues(selection, effectiveInput);
7957
8023
  if (uniformity.values) {
7958
8024
  if (combined.fontFamily === void 0 && uniformity.values.fontFamily !== void 0) combined.fontFamily = uniformity.values.fontFamily;
7959
8025
  if (combined.fontSize === void 0 && uniformity.values.fontSize !== void 0) combined.fontSize = uniformity.values.fontSize;
@@ -7983,9 +8049,23 @@ function createSuperDocUI(options) {
7983
8049
  "underline",
7984
8050
  "strikethrough"
7985
8051
  ];
7986
- const readEffectiveInlineUniformityCached = (selection) => {
7987
- const target = selection.selectionTarget;
7988
- if (!target) return {
8052
+ function effectiveInlineUniformityInput(selection) {
8053
+ const cellTarget = currentCellSelectionTarget();
8054
+ const target = cellTarget ?? selection.selectionTarget;
8055
+ if (!target) return null;
8056
+ const tableCellSelection = cellTarget ? tableCellSelectionForTarget(cellTarget) : null;
8057
+ return {
8058
+ target,
8059
+ offsetSpace: "selection",
8060
+ ...tableCellSelection ? { tableCellSelection } : {}
8061
+ };
8062
+ }
8063
+ function effectiveInlineUniformityCacheKey(selection, input = effectiveInlineUniformityInput(selection)) {
8064
+ if (!input) return null;
8065
+ return `effInline:${input.tableCellSelection ? `${selectionKey({ selectionTarget: input.target })}|cells:${JSON.stringify(input.tableCellSelection)}` : selectionEffectiveUniformitySignature(selection) ?? selectionSignature(selection)}`;
8066
+ }
8067
+ const readEffectiveInlineUniformityCached = (selection, input = effectiveInlineUniformityInput(selection)) => {
8068
+ if (!input) return {
7989
8069
  value: null,
7990
8070
  status: "ready"
7991
8071
  };
@@ -7994,15 +8074,13 @@ function createSuperDocUI(options) {
7994
8074
  value: null,
7995
8075
  status: "ready"
7996
8076
  };
7997
- const signature = selectionEffectiveUniformitySignature(selection) ?? selectionSignature(selection);
7998
- return readAsync(`effInline:${signature}`, contentToken(), () => op({
7999
- target,
8000
- offsetSpace: "selection",
8077
+ return readAsync(effectiveInlineUniformityCacheKey(selection, input), contentToken(), () => op({
8078
+ ...input,
8001
8079
  keys: EFFECTIVE_INLINE_UNIFORMITY_KEYS
8002
8080
  }), (raw) => raw && typeof raw === "object" ? raw : null);
8003
8081
  };
8004
- const resolveEffectiveInlineUniformityValues = (selection) => {
8005
- const { value, status } = readEffectiveInlineUniformityCached(selection);
8082
+ const resolveEffectiveInlineUniformityValues = (selection, input = effectiveInlineUniformityInput(selection)) => {
8083
+ const { value, status } = readEffectiveInlineUniformityCached(selection, input);
8006
8084
  if (!value || value.success !== true) return {
8007
8085
  values: null,
8008
8086
  status
@@ -8056,16 +8134,12 @@ function createSuperDocUI(options) {
8056
8134
  const fromWorker = values?.[key];
8057
8135
  return fromWorker !== void 0 ? fromWorker : null;
8058
8136
  };
8059
- const readEffectiveInlineUniformityNow = async (selection) => {
8060
- const target = selection.selectionTarget;
8061
- if (!target) return null;
8137
+ const readEffectiveInlineUniformityNow = async (input) => {
8138
+ if (!input) return null;
8062
8139
  const op = resolveDocOperation(getDoc(), "format.readEffectiveInlineUniformity");
8063
8140
  if (!op) return null;
8064
8141
  try {
8065
- const raw = await Promise.resolve(op({
8066
- target,
8067
- offsetSpace: "selection"
8068
- }));
8142
+ const raw = await Promise.resolve(op(input));
8069
8143
  return raw && typeof raw === "object" && raw.success === true ? raw : null;
8070
8144
  } catch {
8071
8145
  return null;
@@ -8080,8 +8154,8 @@ function createSuperDocUI(options) {
8080
8154
  else delete projected[key];
8081
8155
  }
8082
8156
  };
8083
- const projectSelectionInlineValuesWithStatus = (selection) => completeProjectedInlineValues(selection, projectInlineValuesFromQueryItem(resolveSelectionTextQueryItem(selection), selection));
8084
- const projectSelectionInlineValues = (selection) => projectSelectionInlineValuesWithStatus(selection).values;
8157
+ const projectSelectionInlineValuesWithStatus = (selection, effectiveInput = effectiveInlineUniformityInput(selection)) => completeProjectedInlineValues(selection, projectInlineValuesFromQueryItem(resolveSelectionTextQueryItem(selection), selection), effectiveInput);
8158
+ const projectSelectionInlineValues = (selection, effectiveInput = effectiveInlineUniformityInput(selection)) => projectSelectionInlineValuesWithStatus(selection, effectiveInput).values;
8085
8159
  /**
8086
8160
  * Read command-critical inline values for format-painter capture. Reactive
8087
8161
  * command state intentionally serves stale values while its worker read is
@@ -8090,20 +8164,21 @@ function createSuperDocUI(options) {
8090
8164
  * without changing the non-blocking toolbar snapshot policy.
8091
8165
  */
8092
8166
  const readFormatPainterInlineValues = async (selection) => {
8167
+ const effectiveInput = effectiveInlineUniformityInput(selection);
8093
8168
  const query = getDoc()?.query;
8094
8169
  const request = selectionTextQueryRequest(selection);
8095
- if (typeof query?.match !== "function" || !request) return projectSelectionInlineValues(selection);
8170
+ if (typeof query?.match !== "function" || !request) return projectSelectionInlineValues(selection, effectiveInput);
8096
8171
  try {
8097
8172
  const raw = await Promise.resolve(query.match(request));
8098
8173
  const direct = projectInlineValuesFromQueryItem(pickSelectionTextQueryItem(raw && typeof raw === "object" ? raw : null, selection), selection);
8099
- const completed = completeProjectedInlineValues(selection, direct);
8174
+ const completed = completeProjectedInlineValues(selection, direct, effectiveInput);
8100
8175
  if (completed.effectiveUniformityStatus !== "ready" && (direct.fontFamily === void 0 || direct.fontSize === void 0)) {
8101
- const effective = await readEffectiveInlineUniformityNow(selection);
8176
+ const effective = await readEffectiveInlineUniformityNow(effectiveInput);
8102
8177
  if (effective) applyEffectiveInlineUniformity(completed.values, direct, effective);
8103
8178
  }
8104
8179
  return completed.values;
8105
8180
  } catch {
8106
- return projectSelectionInlineValues(selection);
8181
+ return projectSelectionInlineValues(selection, effectiveInput);
8107
8182
  }
8108
8183
  };
8109
8184
  const readBlockNode = async (address) => {
@@ -8346,7 +8421,7 @@ function createSuperDocUI(options) {
8346
8421
  supported: true,
8347
8422
  reason: lockReason
8348
8423
  }, "builtin");
8349
- const enabled = selectionBlockIds(selection).length > 0 || resolveInlineSelectionTarget(selection) != null;
8424
+ const enabled = selectionBlockIds(selection).length > 0 || resolveInlineCommandTarget(selection) != null;
8350
8425
  return normalizeCommandState({
8351
8426
  enabled,
8352
8427
  active: false,
@@ -8400,7 +8475,7 @@ function createSuperDocUI(options) {
8400
8475
  value,
8401
8476
  reason: SUPERDOC_UI_REASONS.documentReadonly
8402
8477
  }, "builtin");
8403
- if (descriptor.inline && !resolveInlineSelectionTarget(selection)) {
8478
+ if (descriptor.inline && !resolveInlineCommandTarget(selection)) {
8404
8479
  const lockReason = contentControlLockReason(lockModesById);
8405
8480
  if (lockReason) return normalizeCommandState({
8406
8481
  enabled: false,
@@ -10355,9 +10430,32 @@ function createSuperDocUI(options) {
10355
10430
  * option is not part of public `MutationOptions`; this is the same cast
10356
10431
  * pattern the delete/replace callers use.
10357
10432
  */
10358
- const callInlineFormatMutation = (route, op, input, selection = state.selection) => {
10433
+ function currentCellSelectionTarget() {
10434
+ const handles = safeCall(() => getHost()?.getHandles?.(), null);
10435
+ if (!(handles?.selection?.getSnapshot?.())?.tableCells) return null;
10436
+ const resolved = handles?.selection?.toSelectionTarget?.();
10437
+ return resolved?.kind === "ok" && resolved.mode === "range" ? capturedTableCellTarget(resolved.target) : null;
10438
+ }
10439
+ function resolveInlineCommandTarget(selection) {
10440
+ return currentCellSelectionTarget() ?? resolveInlineSelectionTarget(selection);
10441
+ }
10442
+ function tableCellSelectionForTarget(target) {
10443
+ const cellTarget = currentCellSelectionTarget();
10444
+ const candidate = target;
10445
+ if (!cellTarget || candidate?.start?.blockId !== cellTarget.start.blockId || candidate?.end?.blockId !== cellTarget.end.blockId || candidate?.start?.offset !== cellTarget.start.offset || candidate?.end?.offset !== cellTarget.end.offset) return null;
10446
+ return {
10447
+ anchorBlockId: cellTarget.start.blockId,
10448
+ focusBlockId: cellTarget.end.blockId
10449
+ };
10450
+ }
10451
+ const callInlineFormatMutation = (route, op, input, selection = state.selection, tableCellSelection = tableCellSelectionForTarget(input?.target)) => {
10359
10452
  const options = editorMutationOptionsForRoute(route);
10360
10453
  if (options && options.success === false) return options;
10454
+ if (tableCellSelection) return op(input, {
10455
+ ...options,
10456
+ offsetSpace: "selection",
10457
+ tableCellSelection
10458
+ });
10361
10459
  if (!selection.selectionTarget) return options ? op(input, options) : op(input);
10362
10460
  return op(input, {
10363
10461
  ...options,
@@ -10463,7 +10561,7 @@ function createSuperDocUI(options) {
10463
10561
  }
10464
10562
  };
10465
10563
  const defaultStyleId = getStyleCatalog().cache?.full.defaults.paragraphStyleId ?? DEFAULT_PARAGRAPH_STYLE_ID;
10466
- const rangeTarget = resolveInlineSelectionTarget(state.selection);
10564
+ const rangeTarget = resolveInlineCommandTarget(state.selection);
10467
10565
  if (rangeTarget) {
10468
10566
  const inlineOp = resolveDocOperation(doc, "format.apply");
10469
10567
  if (inlineOp) try {
@@ -11060,8 +11158,8 @@ function createSuperDocUI(options) {
11060
11158
  if (state.selection.status !== "ready") return false;
11061
11159
  if (trackDecisionCommand(id)?.scope === "id") return true;
11062
11160
  if (!descriptor || descriptor.disposition !== "routed") return true;
11063
- if (descriptor.inline?.kind === "clear") return selectionBlockIds(state.selection).length > 0 || resolveInlineSelectionTarget(state.selection) != null;
11064
- if (descriptor.inline) return resolveInlineSelectionTarget(state.selection) != null || canStorePendingInlineFormat(state.selection);
11161
+ if (descriptor.inline?.kind === "clear") return selectionBlockIds(state.selection).length > 0 || resolveInlineCommandTarget(state.selection) != null;
11162
+ if (descriptor.inline) return resolveInlineCommandTarget(state.selection) != null || canStorePendingInlineFormat(state.selection);
11065
11163
  if (descriptor.blockParagraph || descriptor.list) return selectionBlockIds(state.selection).length > 0;
11066
11164
  if (descriptor.link) return linkPayloadHasExplicitTarget(payload) || selectionTextAddresses(state.selection).length > 0 || collapsedTextAddressFromSelection(state.selection) != null || commandActiveState(descriptor, getDoc(), state.selection);
11067
11165
  return true;
@@ -11125,7 +11223,7 @@ function createSuperDocUI(options) {
11125
11223
  if (descriptor.inline) {
11126
11224
  const { lockModesById } = computeActiveContentControlLockModes(doc?.contentControls, state.selection);
11127
11225
  if (contentControlLockReason(lockModesById)) return false;
11128
- const target = resolveInlineSelectionTarget(state.selection);
11226
+ const target = resolveInlineCommandTarget(state.selection);
11129
11227
  if (!target) {
11130
11228
  if (!canStorePendingInlineFormat(state.selection)) return settleCommandExecution(false);
11131
11229
  return settleCommandExecution(storePendingInlineFormat(descriptor, normalized));
@@ -11133,6 +11231,8 @@ function createSuperDocUI(options) {
11133
11231
  const active = commandActiveState(descriptor, doc, state.selection);
11134
11232
  const input = buildInlineFormatInput(descriptor.inline, target, normalized, active);
11135
11233
  if (!input) return false;
11234
+ const commandSelection = state.selection;
11235
+ const tableCellSelection = tableCellSelectionForTarget(target);
11136
11236
  let releaseScheduledMutation = null;
11137
11237
  try {
11138
11238
  const commandEditor = getEditor();
@@ -11140,7 +11240,7 @@ function createSuperDocUI(options) {
11140
11240
  const commandMode = readDocumentMode();
11141
11241
  const mutate = () => {
11142
11242
  if (getEditor() !== commandEditor || commandEditor?.doc !== commandDocSource || readDocumentMode() !== commandMode) return false;
11143
- return callInlineFormatMutation(route, op, input);
11243
+ return callInlineFormatMutation(route, op, input, commandSelection, tableCellSelection);
11144
11244
  };
11145
11245
  const selectionSignature = selectionInlineValueSignature(state.selection) ?? selectionKey(state.selection);
11146
11246
  const scheduledMutation = descriptor.inline.kind === "toggle" ? scheduleInlineToggleMutation(`${descriptor.id}:${selectionSignature}`, mutate) : null;
@@ -11451,34 +11551,42 @@ function createSuperDocUI(options) {
11451
11551
  if (painter.pointerSelecting || painter.keyboardSelecting) return;
11452
11552
  const selectionApi = getDoc()?.selection;
11453
11553
  const readSelection = async () => {
11554
+ const cellTarget = currentCellSelectionTarget();
11555
+ const tableCellSelection = tableCellSelectionForTarget(cellTarget);
11454
11556
  const rawSelection = typeof selectionApi?.["current"] === "function" ? await Promise.resolve(selectionApi["current"]({ includeText: true })) : readSelectionInfoLive().value;
11455
- return normalizeSelectionInfo(rawSelection);
11557
+ return {
11558
+ selection: normalizeSelectionInfo(rawSelection),
11559
+ cellTarget,
11560
+ tableCellSelection
11561
+ };
11456
11562
  };
11457
11563
  const waitForSelectionSettle = () => new Promise((resolve) => setTimeout(resolve, 16));
11458
11564
  const MAX_SELECTION_ATTEMPTS = 8;
11459
- let sel = null;
11565
+ let selectionRead = null;
11460
11566
  let key = "";
11461
11567
  for (let attempt = 0; attempt < MAX_SELECTION_ATTEMPTS; attempt += 1) {
11462
11568
  if (attempt > 0) await waitForSelectionSettle();
11463
11569
  if (painter.mode === "idle" || painter.pointerSelecting || painter.keyboardSelecting) return;
11464
- sel = await readSelection();
11570
+ selectionRead = await readSelection();
11571
+ const sel = selectionRead.selection;
11465
11572
  if (!sel || sel["empty"]) continue;
11466
11573
  key = selectionKey(sel);
11467
11574
  if (key === painter.sourceSelectionKey) continue;
11468
11575
  break;
11469
11576
  }
11470
- if (sel && !sel["empty"] && key !== painter.sourceSelectionKey) {
11471
- await applyFormatPainter(sel);
11577
+ if (selectionRead?.selection && !selectionRead.selection["empty"] && key !== painter.sourceSelectionKey) {
11578
+ await applyFormatPainter(selectionRead.selection, selectionRead.cellTarget, selectionRead.tableCellSelection);
11472
11579
  return;
11473
11580
  }
11474
11581
  if (painter.snapshot?.paragraph) {
11475
- const caretSel = await readSelection();
11582
+ const caretRead = await readSelection();
11583
+ const caretSel = caretRead.selection;
11476
11584
  if (!caretSel) return;
11477
11585
  if (selectionKey(caretSel) === painter.sourceSelectionKey) return;
11478
- await applyFormatPainter(caretSel);
11586
+ await applyFormatPainter(caretSel, caretRead.cellTarget, caretRead.tableCellSelection);
11479
11587
  }
11480
11588
  };
11481
- const applyFormatPainter = async (selection) => {
11589
+ const applyFormatPainter = async (selection, cellTarget, tableCellSelection) => {
11482
11590
  const snap = painter.snapshot;
11483
11591
  if (!snap) {
11484
11592
  if (painter.mode === "armed") exitFormatPainter();
@@ -11493,14 +11601,14 @@ function createSuperDocUI(options) {
11493
11601
  return;
11494
11602
  }
11495
11603
  const selTarget = selection["target"];
11496
- const selectionTarget = selection["selectionTarget"];
11604
+ const selectionTarget = cellTarget ?? selection.selectionTarget;
11497
11605
  if (!(selection["empty"] === true) && Object.keys(snap.inline).length > 0) {
11498
11606
  const inlineOp = resolveDocOperation(doc, "format.apply");
11499
11607
  if (inlineOp && selectionTarget) try {
11500
11608
  if (!commandResultSucceeded(commandResultFromOperationResult(await Promise.resolve(callInlineFormatMutation("format.apply", inlineOp, {
11501
11609
  target: selectionTarget,
11502
11610
  inline: snap.inline
11503
- }, selection))))) {
11611
+ }, selection, tableCellSelection))))) {
11504
11612
  recompute();
11505
11613
  return;
11506
11614
  }
@@ -11689,10 +11797,13 @@ function createSuperDocUI(options) {
11689
11797
  current: () => readSelectionInfoLive().value,
11690
11798
  capture: () => {
11691
11799
  const snapshot = selectionSub.get();
11692
- if (snapshot.empty || !snapshot.target && !snapshot.selectionTarget) return null;
11800
+ if (snapshot.empty) return null;
11801
+ const cells = currentCellSelectionTarget();
11802
+ if (!snapshot.target && !snapshot.selectionTarget && !cells) return null;
11693
11803
  return {
11694
11804
  ...snapshot,
11695
- capturedAt: Date.now()
11805
+ capturedAt: Date.now(),
11806
+ ...cells ? { _tableCellSelectionTarget: cells } : {}
11696
11807
  };
11697
11808
  },
11698
11809
  restore: (capture) => {
@@ -11711,7 +11822,13 @@ function createSuperDocUI(options) {
11711
11822
  ok: false,
11712
11823
  reason: SUPERDOC_UI_REASONS.notReady
11713
11824
  });
11714
- const target = selectionTargetForRestore(capture);
11825
+ const hasCellTarget = "_tableCellSelectionTarget" in capture;
11826
+ const cellTarget = hasCellTarget ? capturedTableCellTarget(capture._tableCellSelectionTarget) : null;
11827
+ if (hasCellTarget && !cellTarget) return done({
11828
+ ok: false,
11829
+ reason: SUPERDOC_UI_REASONS.targetUnresolved
11830
+ });
11831
+ const target = cellTarget ?? selectionTargetForRestore(capture);
11715
11832
  if (!target) return done({
11716
11833
  ok: false,
11717
11834
  reason: SUPERDOC_UI_REASONS.targetUnresolved
@@ -11722,7 +11839,7 @@ function createSuperDocUI(options) {
11722
11839
  reason: resolved.reason
11723
11840
  });
11724
11841
  try {
11725
- return done(normalizeHostSelectionApplyResult(resolved.helper.apply(target)));
11842
+ return done(normalizeHostSelectionApplyResult(cellTarget ? resolved.helper.apply(target, { tableCells: true }) : resolved.helper.apply(target)));
11726
11843
  } catch {
11727
11844
  return done({
11728
11845
  ok: false,