@beyondwork/docx-react-component 1.0.122 → 1.0.124

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 (102) hide show
  1. package/dist/api/public-types.cjs +318 -32
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +3 -3
  5. package/dist/api/v3.cjs +351 -56
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +10 -10
  9. package/dist/{canonical-document-ByIqTd4s.d.cts → canonical-document-CG2TgAzj.d.cts} +1 -1
  10. package/dist/{canonical-document-ByIqTd4s.d.ts → canonical-document-CG2TgAzj.d.ts} +1 -1
  11. package/dist/{chunk-B4YHWFE3.js → chunk-32ZAOQ54.js} +1 -1
  12. package/dist/{chunk-EMDH4IQN.js → chunk-4B74ETJI.js} +4 -3
  13. package/dist/{chunk-QNGJRZ2D.js → chunk-4IPEZYQX.js} +1 -1
  14. package/dist/{chunk-S4ANOS2M.js → chunk-7PC6XUNO.js} +2 -2
  15. package/dist/{chunk-TMU7JMXX.js → chunk-A74Y5NE4.js} +11 -15
  16. package/dist/{chunk-3OFSP2IX.js → chunk-BOHHIVQ2.js} +3 -3
  17. package/dist/{chunk-TFSXOIAI.js → chunk-FNWKE74J.js} +43 -3
  18. package/dist/{chunk-3TUQCHYT.js → chunk-H6IL5ABU.js} +47 -7
  19. package/dist/{chunk-GON2DNTE.js → chunk-HXHQA4BU.js} +1 -1
  20. package/dist/{chunk-3OHVK2D6.js → chunk-IR7QV2BX.js} +17 -1
  21. package/dist/{chunk-ZKSDVHGH.js → chunk-KOHQFZMM.js} +1 -1
  22. package/dist/{chunk-XVFENXLK.js → chunk-LGWNN3L2.js} +2 -2
  23. package/dist/{chunk-UHQOUTAX.js → chunk-MPH4ZQS4.js} +377 -50
  24. package/dist/{chunk-GZW2ERUO.js → chunk-N4VIXI2Z.js} +3 -3
  25. package/dist/{chunk-OBCP6VTG.js → chunk-NAMAWCXN.js} +1 -1
  26. package/dist/{chunk-QFU7ZOAD.js → chunk-PFYUJU3Q.js} +176 -36
  27. package/dist/{chunk-PCXTMEGY.js → chunk-Q76XPPTA.js} +24 -14
  28. package/dist/{chunk-37SEJQ3G.js → chunk-RSYN6FTS.js} +2 -2
  29. package/dist/{chunk-UWDWGQH5.js → chunk-TY4DIJO3.js} +1 -1
  30. package/dist/{chunk-IT2DK3A7.js → chunk-ZMRO6P3A.js} +9 -7
  31. package/dist/{chunk-G3B2OBCZ.js → chunk-ZRHLLPSJ.js} +271 -26
  32. package/dist/compare.d.cts +1 -1
  33. package/dist/compare.d.ts +1 -1
  34. package/dist/core/commands/formatting-commands.d.cts +2 -2
  35. package/dist/core/commands/formatting-commands.d.ts +2 -2
  36. package/dist/core/commands/image-commands.cjs +50 -9
  37. package/dist/core/commands/image-commands.d.cts +2 -2
  38. package/dist/core/commands/image-commands.d.ts +2 -2
  39. package/dist/core/commands/image-commands.js +5 -5
  40. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  41. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  42. package/dist/core/commands/style-commands.d.cts +2 -2
  43. package/dist/core/commands/style-commands.d.ts +2 -2
  44. package/dist/core/commands/table-structure-commands.cjs +50 -9
  45. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  46. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  47. package/dist/core/commands/table-structure-commands.js +4 -4
  48. package/dist/core/commands/text-commands.cjs +66 -9
  49. package/dist/core/commands/text-commands.d.cts +3 -2
  50. package/dist/core/commands/text-commands.d.ts +3 -2
  51. package/dist/core/commands/text-commands.js +5 -5
  52. package/dist/core/selection/mapping.d.cts +2 -2
  53. package/dist/core/selection/mapping.d.ts +2 -2
  54. package/dist/core/state/editor-state.d.cts +2 -2
  55. package/dist/core/state/editor-state.d.ts +2 -2
  56. package/dist/index.cjs +1198 -191
  57. package/dist/index.d.cts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +278 -85
  60. package/dist/io/docx-session.cjs +12 -15
  61. package/dist/io/docx-session.d.cts +4 -4
  62. package/dist/io/docx-session.d.ts +4 -4
  63. package/dist/io/docx-session.js +4 -4
  64. package/dist/legal.cjs +10 -14
  65. package/dist/legal.d.cts +1 -1
  66. package/dist/legal.d.ts +1 -1
  67. package/dist/legal.js +3 -3
  68. package/dist/{loader-BF8ju_LK.d.ts → loader-D9KCtj4m.d.cts} +4 -22
  69. package/dist/{loader-g54WRvj1.d.cts → loader-D9y4ZRjj.d.ts} +4 -22
  70. package/dist/{public-types-Dl1jiWjk.d.ts → public-types-CNnMHZM9.d.ts} +263 -213
  71. package/dist/{public-types-D_y4Ptcj.d.cts → public-types-DajNGKV4.d.cts} +263 -213
  72. package/dist/public-types.cjs +318 -32
  73. package/dist/public-types.d.cts +2 -2
  74. package/dist/public-types.d.ts +2 -2
  75. package/dist/public-types.js +3 -3
  76. package/dist/runtime/collab.d.cts +3 -3
  77. package/dist/runtime/collab.d.ts +3 -3
  78. package/dist/runtime/document-runtime.cjs +752 -77
  79. package/dist/runtime/document-runtime.d.cts +2 -2
  80. package/dist/runtime/document-runtime.d.ts +2 -2
  81. package/dist/runtime/document-runtime.js +14 -14
  82. package/dist/{session-C1EPAkcI.d.ts → session-DEmaOEjA.d.ts} +3 -3
  83. package/dist/{session-D15QOO0Q.d.cts → session-DyQGlryH.d.cts} +3 -3
  84. package/dist/session.cjs +14 -612
  85. package/dist/session.d.cts +5 -5
  86. package/dist/session.d.ts +5 -5
  87. package/dist/session.js +7 -9
  88. package/dist/tailwind.cjs +489 -63
  89. package/dist/tailwind.d.cts +2 -2
  90. package/dist/tailwind.d.ts +2 -2
  91. package/dist/tailwind.js +7 -7
  92. package/dist/{types-BoSRp2Vg.d.cts → types-CxE1aZiv.d.cts} +2 -2
  93. package/dist/{types-DEvRwq9C.d.ts → types-DjJNaE9c.d.ts} +2 -2
  94. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  95. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  96. package/dist/ui-tailwind/editor-surface/search-plugin.js +4 -4
  97. package/dist/ui-tailwind/theme/tokens.css +387 -0
  98. package/dist/ui-tailwind.cjs +489 -63
  99. package/dist/ui-tailwind.d.cts +3 -3
  100. package/dist/ui-tailwind.d.ts +3 -3
  101. package/dist/ui-tailwind.js +7 -7
  102. package/package.json +7 -3
package/dist/index.cjs CHANGED
@@ -6325,6 +6325,28 @@ function collectEditableTargetRefs(doc, cache) {
6325
6325
  collectReviewEditableTargets(doc, targets);
6326
6326
  return targets;
6327
6327
  }
6328
+ function collectEditableTargetRefsForStoryBlockRanges(doc, storyKey2, ranges, cache) {
6329
+ const targets = [];
6330
+ const context = collectStoryBlockContexts(doc).find((entry) => entry.storyKey === storyKey2);
6331
+ if (!context) return targets;
6332
+ const normalized = normalizeEditableTargetRanges(ranges, context.blocks.length);
6333
+ for (const range of normalized) {
6334
+ collectEditableTargetsInBlocks(
6335
+ context.blocks.slice(range.start, range.end),
6336
+ {
6337
+ storyKey: context.storyKey,
6338
+ basePath: context.basePath,
6339
+ insideSdt: false,
6340
+ insideTextBox: false,
6341
+ tableDepth: 0
6342
+ },
6343
+ targets,
6344
+ cache,
6345
+ range.start
6346
+ );
6347
+ }
6348
+ return targets;
6349
+ }
6328
6350
  function createEditableTargetBlockCache() {
6329
6351
  const map = /* @__PURE__ */ new WeakMap();
6330
6352
  return {
@@ -6360,12 +6382,13 @@ function buildBlockCacheSignature(context, blockIndex) {
6360
6382
  owner?.targetKey ?? ""
6361
6383
  ].join("|");
6362
6384
  }
6363
- function collectEditableTargetsInBlocks(blocks, context, targets, cache) {
6385
+ function collectEditableTargetsInBlocks(blocks, context, targets, cache, blockIndexOffset = 0) {
6364
6386
  for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
6365
6387
  const block = blocks[blockIndex];
6366
6388
  if (!block) continue;
6367
- const blockPath = `${context.basePath}/block[${blockIndex}]`;
6368
- const signature = cache !== void 0 ? buildBlockCacheSignature(context, blockIndex) : "";
6389
+ const absoluteBlockIndex = blockIndex + blockIndexOffset;
6390
+ const blockPath = `${context.basePath}/block[${absoluteBlockIndex}]`;
6391
+ const signature = cache !== void 0 ? buildBlockCacheSignature(context, absoluteBlockIndex) : "";
6369
6392
  if (cache !== void 0) {
6370
6393
  const cached = cache.get(block);
6371
6394
  if (cached !== void 0 && cached.blockPath === blockPath && cached.signature === signature) {
@@ -6549,6 +6572,22 @@ function collectEditableTargetsInTable(table, tablePath, context, targets, cache
6549
6572
  }
6550
6573
  }
6551
6574
  }
6575
+ function normalizeEditableTargetRanges(ranges, blockCount) {
6576
+ const normalized = [];
6577
+ const sortedRanges = [...ranges].sort((left, right) => left.start - right.start || left.end - right.end);
6578
+ for (const range of sortedRanges) {
6579
+ const start = Math.max(0, Math.min(blockCount, Math.floor(range.start)));
6580
+ const end = Math.max(start, Math.min(blockCount, Math.ceil(range.end)));
6581
+ if (start === end) continue;
6582
+ const previous = normalized[normalized.length - 1];
6583
+ if (previous && start <= previous.end) {
6584
+ previous.end = Math.max(previous.end, end);
6585
+ } else {
6586
+ normalized.push({ start, end });
6587
+ }
6588
+ }
6589
+ return normalized;
6590
+ }
6552
6591
  function findVerticalMergeOwner(owners, gridColumnStart2, gridSpan) {
6553
6592
  return owners.find(
6554
6593
  (owner) => owner.gridColumnStart === gridColumnStart2 && owner.gridSpan === gridSpan
@@ -11864,6 +11903,8 @@ function createSurfaceBlock(block, document2, cursor, counters, formattingContex
11864
11903
  formattingContext,
11865
11904
  promoteSecondaryStoryTextBoxes,
11866
11905
  cullBuild,
11906
+ editableTargetsByBlockPath,
11907
+ blockPath,
11867
11908
  blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0
11868
11909
  );
11869
11910
  }
@@ -12270,7 +12311,7 @@ function getRecursableSdtBlockedReasonCode(block) {
12270
12311
  ].filter(Boolean).join(" ").toLowerCase();
12271
12312
  return searchText.includes("table of contents") || /\btoc\b/u.test(searchText) ? "workflow_preserve_only" : null;
12272
12313
  }
12273
- function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTarget) {
12314
+ function createParagraphBlock(paragraphIndex, paragraph, document2, start, formattingContext, promoteSecondaryStoryTextBoxes, cullBuild = false, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, blockPath, editableTarget) {
12274
12315
  const themeResolver = formattingContext.theme;
12275
12316
  const effectiveNumbering = formattingContext.resolveEffectiveParagraphNumbering(paragraph);
12276
12317
  let resolvedNumbering = null;
@@ -12335,6 +12376,8 @@ function createParagraphBlock(paragraphIndex, paragraph, document2, start, forma
12335
12376
  document2,
12336
12377
  cursor,
12337
12378
  promoteSecondaryStoryTextBoxes,
12379
+ blockPath !== void 0 ? `${blockPath}/inline[${childIndex}]` : void 0,
12380
+ editableTargetsByBlockPath,
12338
12381
  void 0,
12339
12382
  cullBuild,
12340
12383
  themeResolver,
@@ -12391,7 +12434,7 @@ function isVisibleTocResultInline(node) {
12391
12434
  return false;
12392
12435
  }
12393
12436
  }
12394
- function appendInlineSegments(paragraph, node, document2, start, promoteSecondaryStoryTextBoxes, hyperlinkHref, cullBuild = false, themeResolver, formattingContext) {
12437
+ function appendInlineSegments(paragraph, node, document2, start, promoteSecondaryStoryTextBoxes, inlinePath, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH, hyperlinkHref, cullBuild = false, themeResolver, formattingContext) {
12395
12438
  switch (node.type) {
12396
12439
  case "text": {
12397
12440
  const cloned = node.marks ? cloneMarks2(node.marks) : { marks: [] };
@@ -12444,13 +12487,16 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
12444
12487
  return { nextCursor: start + 1, lockedFragmentIds: [] };
12445
12488
  case "hyperlink": {
12446
12489
  let cursor = start;
12447
- for (const child of node.children) {
12490
+ for (let childIndex = 0; childIndex < node.children.length; childIndex += 1) {
12491
+ const child = node.children[childIndex];
12448
12492
  const result = appendInlineSegments(
12449
12493
  paragraph,
12450
12494
  child,
12451
12495
  document2,
12452
12496
  cursor,
12453
12497
  promoteSecondaryStoryTextBoxes,
12498
+ inlinePath !== void 0 ? `${inlinePath}/child[${childIndex}]` : void 0,
12499
+ editableTargetsByBlockPath,
12454
12500
  node.href,
12455
12501
  cullBuild,
12456
12502
  themeResolver,
@@ -12509,6 +12555,33 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
12509
12555
  if (isMicrosoftSensitivityLabelShape(node)) {
12510
12556
  return { nextCursor: start + 1, lockedFragmentIds: [] };
12511
12557
  }
12558
+ if (node.isTextBox && node.txbxBlocks !== void 0) {
12559
+ const txbxTextSegment = extractTxbxFirstTextSegment(node.txbxBlocks);
12560
+ const txbxText = txbxTextSegment?.text ?? node.text;
12561
+ const txbxBody = surfaceTextBoxBodyFromShape(
12562
+ node,
12563
+ void 0,
12564
+ inlinePath,
12565
+ editableTargetsByBlockPath
12566
+ );
12567
+ paragraph.segments.push({
12568
+ segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
12569
+ kind: "shape",
12570
+ from: start,
12571
+ to: start + 1,
12572
+ label: "Text box",
12573
+ detail: createShapeDetail(node),
12574
+ ...node.geometry !== void 0 ? { geometry: node.geometry } : {},
12575
+ isTextBox: true,
12576
+ ...node.textBoxBody ? { textBoxBody: node.textBoxBody } : {},
12577
+ ...node.preserveOnlyObject ? { preserveOnlyObject: surfacePreserveOnlyObject(node.preserveOnlyObject) } : {},
12578
+ ...txbxText ? { txbxText } : {},
12579
+ ...txbxBody ? { txbxBody } : {},
12580
+ ...txbxTextSegment?.marks && txbxTextSegment.marks.length > 0 ? { txbxMarks: txbxTextSegment.marks } : {},
12581
+ ...txbxTextSegment?.markAttrs ? { txbxMarkAttrs: txbxTextSegment.markAttrs } : {}
12582
+ });
12583
+ return { nextCursor: start + 1, lockedFragmentIds: [] };
12584
+ }
12512
12585
  if (promoteSecondaryStoryTextBoxes && node.isTextBox && node.text) {
12513
12586
  return appendTextBoxSegment(
12514
12587
  paragraph,
@@ -12568,7 +12641,7 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
12568
12641
  const anchor = surfaceAnchorFromGeometry(node.anchor);
12569
12642
  const txbxTextSegment = c.isTextBox ? extractTxbxFirstTextSegment(c.txbxBlocks) : void 0;
12570
12643
  const txbxText = txbxTextSegment?.text ?? (c.isTextBox ? c.text : void 0);
12571
- const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef) : void 0;
12644
+ const txbxBody = c.isTextBox ? surfaceTextBoxBodyFromShape(c, node.sourceRef, inlinePath, editableTargetsByBlockPath) : void 0;
12572
12645
  const surfaceFill = c.fill;
12573
12646
  paragraph.segments.push({
12574
12647
  segmentId: `${paragraph.blockId}-segment-${paragraph.segments.length}`,
@@ -12745,13 +12818,16 @@ function appendInlineSegments(paragraph, node, document2, start, promoteSecondar
12745
12818
  const refHyperlinkHref = (node.fieldFamily === "REF" || node.fieldFamily === "PAGEREF" || node.fieldFamily === "NOTEREF") && node.switches?.hyperlink === true && node.fieldTarget ? `#${node.fieldTarget}` : void 0;
12746
12819
  let cursor = start;
12747
12820
  const lockedIds = [];
12748
- for (const child of node.children) {
12821
+ for (let childIndex = 0; childIndex < node.children.length; childIndex += 1) {
12822
+ const child = node.children[childIndex];
12749
12823
  const result = appendInlineSegments(
12750
12824
  paragraph,
12751
12825
  child,
12752
12826
  document2,
12753
12827
  cursor,
12754
12828
  promoteSecondaryStoryTextBoxes,
12829
+ inlinePath !== void 0 ? `${inlinePath}/child[${childIndex}]` : void 0,
12830
+ editableTargetsByBlockPath,
12755
12831
  refHyperlinkHref ?? hyperlinkHref,
12756
12832
  cullBuild,
12757
12833
  themeResolver,
@@ -12998,7 +13074,7 @@ function extractTxbxFirstTextSegment(blocks) {
12998
13074
  }
12999
13075
  return void 0;
13000
13076
  }
13001
- function surfaceTextBoxBodyFromShape(shape, sourceRef) {
13077
+ function surfaceTextBoxBodyFromShape(shape, sourceRef, inlinePath, editableTargetsByBlockPath = EMPTY_EDITABLE_TARGETS_BY_BLOCK_PATH) {
13002
13078
  if (!shape.isTextBox && shape.txbxContentXml === void 0 && shape.txbxBlocks === void 0) {
13003
13079
  return void 0;
13004
13080
  }
@@ -13024,9 +13100,12 @@ function surfaceTextBoxBodyFromShape(shape, sourceRef) {
13024
13100
  (run, inlineIndex) => surfaceTextBoxRunFromLegacyRun(run, inlineIndex)
13025
13101
  ) ?? [];
13026
13102
  const text = runs.map((run) => run.text ?? "").join("");
13103
+ const blockPath = inlinePath !== void 0 ? `${inlinePath}/txbx/block[${blockIndex}]` : void 0;
13104
+ const editableTarget = blockPath !== void 0 ? editableTargetsByBlockPath.get(blockPath) : void 0;
13027
13105
  return [{
13028
13106
  ...block.sourceRef !== void 0 ? { sourceRef: block.sourceRef } : {},
13029
13107
  blockIndex,
13108
+ ...editableTarget !== void 0 ? { editableTarget } : {},
13030
13109
  text,
13031
13110
  textLength: Array.from(text).length,
13032
13111
  ...block.borders !== void 0 ? { borders: block.borders } : {},
@@ -16710,6 +16789,7 @@ function buildPageGraph(inputOrPages, sectionsArg, storiesArg) {
16710
16789
  regions,
16711
16790
  divergences: frameDivergences,
16712
16791
  subParts: input.subParts,
16792
+ anchors: input.anchors,
16713
16793
  pageFieldCounts
16714
16794
  });
16715
16795
  const divergences = builtFrame.divergences;
@@ -16876,6 +16956,7 @@ function buildPageFrame(input) {
16876
16956
  stories: input.stories,
16877
16957
  regions,
16878
16958
  subParts: input.subParts,
16959
+ anchors: input.anchors,
16879
16960
  pageFieldCounts: input.pageFieldCounts
16880
16961
  });
16881
16962
  const divergences = [...input.divergences, ...pageLocalStoryResult.divergences];
@@ -16913,6 +16994,7 @@ function buildPageLocalStoryInstances(input) {
16913
16994
  input.stories.header,
16914
16995
  input.regions.header,
16915
16996
  findHeaderFooterPart(input.subParts?.headers, input.stories.header),
16997
+ input.anchors,
16916
16998
  input.pageFieldCounts
16917
16999
  );
16918
17000
  instances.push(built.instance);
@@ -16929,6 +17011,7 @@ function buildPageLocalStoryInstances(input) {
16929
17011
  input.stories.footer,
16930
17012
  input.regions.footer,
16931
17013
  findHeaderFooterPart(input.subParts?.footers, input.stories.footer),
17014
+ input.anchors,
16932
17015
  input.pageFieldCounts
16933
17016
  );
16934
17017
  instances.push(built.instance);
@@ -16936,7 +17019,7 @@ function buildPageLocalStoryInstances(input) {
16936
17019
  }
16937
17020
  return { instances, divergences };
16938
17021
  }
16939
- function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, displayPageNumber, layout, target, region, source, pageFieldCounts) {
17022
+ function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, displayPageNumber, layout, target, region, source, anchors, pageFieldCounts) {
16940
17023
  const measuredFrameHeightTwips = region?.heightTwips ?? 0;
16941
17024
  const sectionPart = target.sectionIndex === void 0 ? "section-unknown" : `section-${target.sectionIndex}`;
16942
17025
  const instanceId = `${frameId}:${target.kind}:${target.variant}:${target.relationshipId}`;
@@ -16957,7 +17040,9 @@ function buildPageLocalStoryInstance(frameId, pageId, pageIndex, sectionIndex, d
16957
17040
  kind: target.kind,
16958
17041
  variant: target.variant,
16959
17042
  relationshipId: target.relationshipId,
16960
- region
17043
+ region,
17044
+ storyBasePath: `${target.kind}:${source.partPath ?? `word/${target.kind}${target.relationshipId}.xml`}`,
17045
+ anchorsByInlinePath: buildAnchorsByInlinePath(anchors)
16961
17046
  }) : { objects: [], divergences: [] };
16962
17047
  const signature = buildPageLocalStorySignature({
16963
17048
  kind: target.kind,
@@ -17011,6 +17096,23 @@ function buildPageLocalStorySignature(input) {
17011
17096
  object.anchorRectTwips?.yTwips ?? "",
17012
17097
  object.anchorRectTwips?.widthTwips ?? "",
17013
17098
  object.anchorRectTwips?.heightTwips ?? "",
17099
+ object.textBoxBody?.bodyKey ?? "",
17100
+ object.textBoxBody?.status ?? "",
17101
+ object.textBoxBody?.unavailableReason ?? "",
17102
+ object.textBoxBody?.contentRectTwips?.xTwips ?? "",
17103
+ object.textBoxBody?.contentRectTwips?.yTwips ?? "",
17104
+ object.textBoxBody?.contentRectTwips?.widthTwips ?? "",
17105
+ object.textBoxBody?.contentRectTwips?.heightTwips ?? "",
17106
+ object.textBoxBody?.paragraphs.map(
17107
+ (paragraph) => [
17108
+ paragraph.paragraphKey,
17109
+ paragraph.rectTwips?.xTwips ?? "",
17110
+ paragraph.rectTwips?.yTwips ?? "",
17111
+ paragraph.rectTwips?.widthTwips ?? "",
17112
+ paragraph.rectTwips?.heightTwips ?? "",
17113
+ paragraph.unavailableReason ?? ""
17114
+ ].join("/")
17115
+ ).join(",") ?? "",
17014
17116
  object.relationshipIds?.join(",") ?? "",
17015
17117
  object.mediaIds?.join(",") ?? "",
17016
17118
  object.wrapMode ?? "",
@@ -17155,6 +17257,10 @@ function truncatePageLocalStoryPreview(text) {
17155
17257
  if (text.length <= MAX_PAGE_LOCAL_STORY_PREVIEW_CHARS) return text;
17156
17258
  return `${text.slice(0, MAX_PAGE_LOCAL_STORY_PREVIEW_CHARS - 1).trimEnd()}\u2026`;
17157
17259
  }
17260
+ function buildAnchorsByInlinePath(anchors) {
17261
+ if (!anchors || anchors.length === 0) return void 0;
17262
+ return new Map(anchors.map((anchor) => [anchor.inlinePath, anchor]));
17263
+ }
17158
17264
  function collectStoryAnchoredObjects(blocks, context) {
17159
17265
  const objects = [];
17160
17266
  const divergences = [];
@@ -17198,26 +17304,45 @@ function collectStoryAnchoredObjects(blocks, context) {
17198
17304
  });
17199
17305
  ordinal += 1;
17200
17306
  };
17201
- const visitBlock = (block) => {
17307
+ const visitBlocks = (blocksToVisit, basePath) => {
17308
+ for (let blockIndex = 0; blockIndex < blocksToVisit.length; blockIndex += 1) {
17309
+ const block = blocksToVisit[blockIndex];
17310
+ if (!block) continue;
17311
+ visitBlock(block, `${basePath}/block[${blockIndex}]`);
17312
+ }
17313
+ };
17314
+ const visitBlock = (block, blockPath) => {
17202
17315
  switch (block.type) {
17203
17316
  case "paragraph":
17204
- for (const child of block.children) visitInline(child);
17317
+ visitInlines(block.children, blockPath, `${blockPath}/inline`);
17205
17318
  break;
17206
17319
  case "table":
17207
- for (const row2 of block.rows) {
17208
- for (const cell of row2.cells) {
17209
- for (const child of cell.children) visitBlock(child);
17320
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
17321
+ const row2 = block.rows[rowIndex];
17322
+ if (!row2) continue;
17323
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
17324
+ const cell = row2.cells[cellIndex];
17325
+ if (!cell) continue;
17326
+ visitBlocks(cell.children, `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`);
17210
17327
  }
17211
17328
  }
17212
17329
  break;
17213
17330
  case "sdt":
17214
- for (const child of block.children) visitBlock(child);
17331
+ case "custom_xml":
17332
+ visitBlocks(block.children, blockPath);
17215
17333
  break;
17216
17334
  default:
17217
17335
  break;
17218
17336
  }
17219
17337
  };
17220
- const visitInline = (inline) => {
17338
+ const visitInlines = (inlines, blockPath, basePath) => {
17339
+ for (let inlineIndex = 0; inlineIndex < inlines.length; inlineIndex += 1) {
17340
+ const inline = inlines[inlineIndex];
17341
+ if (!inline) continue;
17342
+ visitInline(inline, blockPath, `${basePath}[${inlineIndex}]`);
17343
+ }
17344
+ };
17345
+ const visitInline = (inline, blockPath, inlinePath) => {
17221
17346
  switch (inline.type) {
17222
17347
  case "image": {
17223
17348
  pushObject({
@@ -17238,17 +17363,27 @@ function collectStoryAnchoredObjects(blocks, context) {
17238
17363
  inline.anchor.extent.widthEmu,
17239
17364
  inline.anchor.extent.heightEmu
17240
17365
  );
17366
+ const anchorRectTwips = resolveObjectAnchorRectTwips(
17367
+ context.region,
17368
+ extentTwips,
17369
+ inline.anchor.positionH,
17370
+ inline.anchor.positionV
17371
+ );
17372
+ const canonicalAnchor = context.anchorsByInlinePath?.get(inlinePath);
17373
+ const textBoxBody = buildDrawingFrameTextBoxBodyFacts(
17374
+ inline,
17375
+ canonicalAnchor,
17376
+ inlinePath,
17377
+ display,
17378
+ anchorRectTwips
17379
+ );
17241
17380
  pushObject({
17242
17381
  objectId: getDrawingFrameObjectId(inline, context.storyKey, ordinal),
17243
17382
  sourceType: "drawing-frame",
17244
17383
  display,
17245
17384
  extentTwips,
17246
- anchorRectTwips: resolveObjectAnchorRectTwips(
17247
- context.region,
17248
- extentTwips,
17249
- inline.anchor.positionH,
17250
- inline.anchor.positionV
17251
- ),
17385
+ anchorRectTwips,
17386
+ ...textBoxBody ? { textBoxBody } : {},
17252
17387
  ...relationshipIds.length > 0 ? { relationshipIds } : {},
17253
17388
  ...inline.content.type === "picture" && inline.content.mediaId ? { mediaIds: [inline.content.mediaId] } : {},
17254
17389
  preserveOnly: Boolean(preserveHint),
@@ -17256,7 +17391,7 @@ function collectStoryAnchoredObjects(blocks, context) {
17256
17391
  wrapMode: inline.anchor.wrapMode
17257
17392
  });
17258
17393
  if (inline.content.type === "shape") {
17259
- for (const child of inline.content.txbxBlocks ?? []) visitBlock(child);
17394
+ visitBlocks(inline.content.txbxBlocks ?? [], `${inlinePath}/txbx`);
17260
17395
  }
17261
17396
  break;
17262
17397
  }
@@ -17283,10 +17418,11 @@ function collectStoryAnchoredObjects(blocks, context) {
17283
17418
  } : {},
17284
17419
  ...preserveHint?.relationshipIds ? { relationshipIds: [...preserveHint.relationshipIds] } : {},
17285
17420
  preserveOnly: Boolean(preserveHint),
17286
- ...preserveHint ? { preserveHint } : {}
17421
+ ...preserveHint ? { preserveHint } : {},
17422
+ ...inline.type === "vml_shape" && inline.text ? { textBoxBody: buildUnsupportedVmlTextBoxFacts(inline, inlinePath) } : {}
17287
17423
  });
17288
17424
  if (inline.type === "shape") {
17289
- for (const child of inline.txbxBlocks ?? []) visitBlock(child);
17425
+ visitBlocks(inline.txbxBlocks ?? [], `${inlinePath}/txbx`);
17290
17426
  }
17291
17427
  break;
17292
17428
  }
@@ -17308,16 +17444,16 @@ function collectStoryAnchoredObjects(blocks, context) {
17308
17444
  });
17309
17445
  break;
17310
17446
  case "field":
17311
- for (const child of inline.children) visitInline(child);
17447
+ visitInlines(inline.children, blockPath, `${inlinePath}/child`);
17312
17448
  break;
17313
17449
  case "hyperlink":
17314
- for (const child of inline.children) visitInline(child);
17450
+ visitInlines(inline.children, blockPath, `${inlinePath}/child`);
17315
17451
  break;
17316
17452
  default:
17317
17453
  break;
17318
17454
  }
17319
17455
  };
17320
- for (const block of blocks) visitBlock(block);
17456
+ visitBlocks(blocks, context.storyBasePath);
17321
17457
  return { objects, divergences };
17322
17458
  }
17323
17459
  function getDrawingFramePreserveHint(inline) {
@@ -17325,6 +17461,170 @@ function getDrawingFramePreserveHint(inline) {
17325
17461
  if (content.type === "picture") return void 0;
17326
17462
  return content.preserveOnlyObject;
17327
17463
  }
17464
+ function buildDrawingFrameTextBoxBodyFacts(inline, canonicalAnchor, inlinePath, display, anchorRectTwips) {
17465
+ if (inline.content.type !== "shape") return void 0;
17466
+ const content = inline.content;
17467
+ const canonicalBody = canonicalAnchor?.textBoxBody;
17468
+ const hasTextBoxContent = Boolean(
17469
+ canonicalBody || content.isTextBox || content.textBoxBody || content.txbxBlocks?.length
17470
+ );
17471
+ if (!hasTextBoxContent) return void 0;
17472
+ if (!canonicalBody) {
17473
+ return unavailableTextBoxBodyFacts(
17474
+ `${canonicalAnchor?.objectKey ?? inlinePath}:txbx`,
17475
+ "unmodeled-txbx-blocks",
17476
+ content.textBoxBody,
17477
+ content.txbxBlocks?.length ?? 0,
17478
+ countParagraphBlocks(content.txbxBlocks ?? []),
17479
+ 0
17480
+ );
17481
+ }
17482
+ if (display !== "floating") {
17483
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "inline-textbox");
17484
+ }
17485
+ if (!anchorRectTwips) {
17486
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "missing-anchor-rect");
17487
+ }
17488
+ if (canonicalBody.status !== "modeled") {
17489
+ return unavailableTextBoxBodyFactsFromCanonical(
17490
+ canonicalBody,
17491
+ normalizeTextBoxBodyUnavailableReason(canonicalBody.unavailableReason)
17492
+ );
17493
+ }
17494
+ const bodyInsetsTwips = textBoxInsetsTwips(canonicalBody.bodyProperties);
17495
+ if (!bodyInsetsTwips) {
17496
+ return unavailableTextBoxBodyFactsFromCanonical(canonicalBody, "missing-body-insets");
17497
+ }
17498
+ const contentRectTwips = rect(
17499
+ anchorRectTwips.xTwips + bodyInsetsTwips.leftTwips,
17500
+ anchorRectTwips.yTwips + bodyInsetsTwips.topTwips,
17501
+ Math.max(0, anchorRectTwips.widthTwips - bodyInsetsTwips.leftTwips - bodyInsetsTwips.rightTwips),
17502
+ Math.max(0, anchorRectTwips.heightTwips - bodyInsetsTwips.topTwips - bodyInsetsTwips.bottomTwips)
17503
+ );
17504
+ return {
17505
+ bodyKey: canonicalBody.bodyKey,
17506
+ status: "modeled",
17507
+ ...canonicalBody.bodyProperties ? { bodyProperties: { ...canonicalBody.bodyProperties } } : {},
17508
+ bodyInsetsTwips,
17509
+ contentRectTwips,
17510
+ blockCount: canonicalBody.blockCount,
17511
+ paragraphCount: canonicalBody.paragraphCount,
17512
+ unsupportedBlockCount: canonicalBody.unsupportedBlockCount,
17513
+ paragraphs: buildTextBoxParagraphFacts(canonicalBody, contentRectTwips)
17514
+ };
17515
+ }
17516
+ function unavailableTextBoxBodyFactsFromCanonical(body, reason) {
17517
+ return {
17518
+ bodyKey: body.bodyKey,
17519
+ status: body.status === "preserve-only" ? "preserve-only" : "unavailable",
17520
+ unavailableReason: reason,
17521
+ ...body.bodyProperties ? { bodyProperties: { ...body.bodyProperties } } : {},
17522
+ blockCount: body.blockCount,
17523
+ paragraphCount: body.paragraphCount,
17524
+ unsupportedBlockCount: body.unsupportedBlockCount,
17525
+ paragraphs: body.paragraphs.map((paragraph) => ({
17526
+ paragraphKey: paragraph.paragraphKey,
17527
+ blockPath: paragraph.blockPath,
17528
+ blockIndex: paragraph.blockIndex,
17529
+ unavailableReason: reason,
17530
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
17531
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
17532
+ textLength: paragraph.textLength,
17533
+ runCount: paragraph.runCount
17534
+ }))
17535
+ };
17536
+ }
17537
+ function unavailableTextBoxBodyFacts(bodyKey, reason, bodyProperties, blockCount, paragraphCount, unsupportedBlockCount) {
17538
+ return {
17539
+ bodyKey,
17540
+ status: "unavailable",
17541
+ unavailableReason: reason,
17542
+ ...bodyProperties ? { bodyProperties: { ...bodyProperties } } : {},
17543
+ blockCount,
17544
+ paragraphCount,
17545
+ unsupportedBlockCount,
17546
+ paragraphs: []
17547
+ };
17548
+ }
17549
+ function buildUnsupportedVmlTextBoxFacts(inline, inlinePath) {
17550
+ const hasText = Boolean(inline.text?.length);
17551
+ return {
17552
+ bodyKey: `${inline.preserveOnlyObject?.sourceId ?? inlinePath}:vml-textbox`,
17553
+ status: "unavailable",
17554
+ unavailableReason: "unsupported-vml-textbox",
17555
+ blockCount: hasText ? 1 : 0,
17556
+ paragraphCount: hasText ? 1 : 0,
17557
+ unsupportedBlockCount: hasText ? 1 : 0,
17558
+ paragraphs: []
17559
+ };
17560
+ }
17561
+ function buildTextBoxParagraphFacts(body, contentRectTwips) {
17562
+ const paragraphCount = body.paragraphs.length;
17563
+ if (paragraphCount === 0) return [];
17564
+ const baseHeight = Math.floor(contentRectTwips.heightTwips / paragraphCount);
17565
+ return body.paragraphs.map((paragraph, index) => {
17566
+ const yTwips = contentRectTwips.yTwips + baseHeight * index;
17567
+ const heightTwips = index === paragraphCount - 1 ? Math.max(0, contentRectTwips.yTwips + contentRectTwips.heightTwips - yTwips) : Math.max(0, baseHeight);
17568
+ return {
17569
+ paragraphKey: paragraph.paragraphKey,
17570
+ blockPath: paragraph.blockPath,
17571
+ blockIndex: paragraph.blockIndex,
17572
+ rectTwips: rect(
17573
+ contentRectTwips.xTwips,
17574
+ yTwips,
17575
+ contentRectTwips.widthTwips,
17576
+ heightTwips
17577
+ ),
17578
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
17579
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
17580
+ textLength: paragraph.textLength,
17581
+ runCount: paragraph.runCount
17582
+ };
17583
+ });
17584
+ }
17585
+ function textBoxInsetsTwips(bodyProperties) {
17586
+ if (!bodyProperties || bodyProperties.insetLeftEmu === void 0 || bodyProperties.insetTopEmu === void 0 || bodyProperties.insetRightEmu === void 0 || bodyProperties.insetBottomEmu === void 0) {
17587
+ return void 0;
17588
+ }
17589
+ return {
17590
+ leftTwips: Math.max(0, Math.round(bodyProperties.insetLeftEmu / EMUS_PER_TWIP)),
17591
+ topTwips: Math.max(0, Math.round(bodyProperties.insetTopEmu / EMUS_PER_TWIP)),
17592
+ rightTwips: Math.max(0, Math.round(bodyProperties.insetRightEmu / EMUS_PER_TWIP)),
17593
+ bottomTwips: Math.max(0, Math.round(bodyProperties.insetBottomEmu / EMUS_PER_TWIP))
17594
+ };
17595
+ }
17596
+ function normalizeTextBoxBodyUnavailableReason(reason) {
17597
+ switch (reason) {
17598
+ case "txbx-blocks-unavailable":
17599
+ case "empty-body":
17600
+ case "unsupported-content":
17601
+ return reason;
17602
+ default:
17603
+ return "unmodeled-txbx-blocks";
17604
+ }
17605
+ }
17606
+ function countParagraphBlocks(blocks) {
17607
+ let count = 0;
17608
+ const visit = (block) => {
17609
+ if (block.type === "paragraph") {
17610
+ count += 1;
17611
+ return;
17612
+ }
17613
+ if (block.type === "table") {
17614
+ for (const row2 of block.rows) {
17615
+ for (const cell of row2.cells) {
17616
+ for (const child of cell.children) visit(child);
17617
+ }
17618
+ }
17619
+ return;
17620
+ }
17621
+ if (block.type === "sdt" || block.type === "custom_xml") {
17622
+ for (const child of block.children) visit(child);
17623
+ }
17624
+ };
17625
+ for (const block of blocks) visit(block);
17626
+ return count;
17627
+ }
17328
17628
  function collectDrawingRelationshipIds(inline) {
17329
17629
  const content = inline.content;
17330
17630
  if (content.type === "picture") return [content.blipRef];
@@ -17653,12 +17953,34 @@ function freezePageFrame(frame) {
17653
17953
  for (const story of frame.pageLocalStories) {
17654
17954
  Object.freeze(story.resolvedFields);
17655
17955
  Object.freeze(story.previewParts);
17956
+ for (const object of story.anchoredObjects) {
17957
+ freezeStoryAnchoredObject(object);
17958
+ }
17656
17959
  Object.freeze(story.anchoredObjects);
17657
17960
  Object.freeze(story);
17658
17961
  }
17659
17962
  Object.freeze(frame.pageLocalStories);
17660
17963
  Object.freeze(frame);
17661
17964
  }
17965
+ function freezeStoryAnchoredObject(object) {
17966
+ if (object.extentTwips) Object.freeze(object.extentTwips);
17967
+ if (object.anchorRectTwips) Object.freeze(object.anchorRectTwips);
17968
+ if (object.relationshipIds) Object.freeze(object.relationshipIds);
17969
+ if (object.mediaIds) Object.freeze(object.mediaIds);
17970
+ if (object.textBoxBody) {
17971
+ if (object.textBoxBody.bodyProperties) Object.freeze(object.textBoxBody.bodyProperties);
17972
+ if (object.textBoxBody.bodyInsetsTwips) Object.freeze(object.textBoxBody.bodyInsetsTwips);
17973
+ if (object.textBoxBody.contentRectTwips) Object.freeze(object.textBoxBody.contentRectTwips);
17974
+ for (const paragraph of object.textBoxBody.paragraphs) {
17975
+ if (paragraph.rectTwips) Object.freeze(paragraph.rectTwips);
17976
+ Object.freeze(paragraph);
17977
+ }
17978
+ Object.freeze(object.textBoxBody.paragraphs);
17979
+ Object.freeze(object.textBoxBody);
17980
+ }
17981
+ Object.freeze(object.divergenceIds);
17982
+ Object.freeze(object);
17983
+ }
17662
17984
  function normalizePageLocalStoryFieldsForPages(pages) {
17663
17985
  const pageFieldCounts = buildPageFieldCounts(pages);
17664
17986
  return pages.map((page) => {
@@ -18999,7 +19321,7 @@ async function createCanvasProvider(fontLoader) {
18999
19321
 
19000
19322
  // src/runtime/layout/layout-engine-version.ts
19001
19323
  var LAYOUT_ENGINE_VERSION = 87;
19002
- var LAYCACHE_SCHEMA_VERSION = 10;
19324
+ var LAYCACHE_SCHEMA_VERSION = 11;
19003
19325
 
19004
19326
  // src/runtime/layout/layout-engine-instance.ts
19005
19327
  var FULL_VIEWPORT_WINDOW_KEY = "full";
@@ -19345,7 +19667,8 @@ function createLayoutEngine(options = {}) {
19345
19667
  fragmentsByPageIndex,
19346
19668
  lineBoxesByPageIndex,
19347
19669
  noteAllocationsByPageIndex: pageStack.noteAllocationsByPageIndex,
19348
- subParts: document2.subParts
19670
+ subParts: document2.subParts,
19671
+ anchors: layoutInputs.anchors
19349
19672
  });
19350
19673
  const graph = applyViewportWindowMaterialization(
19351
19674
  measuredGraph,
@@ -19480,7 +19803,8 @@ function createLayoutEngine(options = {}) {
19480
19803
  fragmentsByPageIndex: freshFragmentsByPageIndex,
19481
19804
  lineBoxesByPageIndex: freshLineBoxesByPageIndex,
19482
19805
  noteAllocationsByPageIndex: freshResult.noteAllocationsByPageIndex,
19483
- subParts: document2.subParts
19806
+ subParts: document2.subParts,
19807
+ anchors: layoutInputs.anchors
19484
19808
  });
19485
19809
  const freshNodes = freshGraph.pages;
19486
19810
  const splicedGraph = spliceGraph(priorGraph, freshNodes, firstDirty, convergedTailStart);
@@ -25539,6 +25863,7 @@ function applyLinearTextTransaction(document2, selection, intent, options) {
25539
25863
  metadata: {
25540
25864
  affectsComments: true,
25541
25865
  affectsRevisions: true,
25866
+ ...createLocalTextPatchMetadata(story.units, unitFrom, unitTo, insertionUnits),
25542
25867
  ...containsParagraphBoundaryChange(story, normalizedRange, insertionUnits) ? { invalidatesStructures: true } : {}
25543
25868
  }
25544
25869
  },
@@ -25606,6 +25931,21 @@ function tryApplyTableParagraphTransaction(document2, selection, intent, options
25606
25931
  storyText: localResult.storyText
25607
25932
  };
25608
25933
  }
25934
+ function createLocalTextPatchMetadata(units, unitFrom, unitTo, insertionUnits) {
25935
+ if (!insertionUnits.every((unit) => unit.kind === "text")) {
25936
+ return {};
25937
+ }
25938
+ for (let index = unitFrom; index < unitTo; index += 1) {
25939
+ if (units[index]?.kind !== "text") {
25940
+ return {};
25941
+ }
25942
+ }
25943
+ return {
25944
+ localTextPatch: {
25945
+ insertedText: insertionUnits.map((unit) => unit.kind === "text" ? unit.value : "").join("")
25946
+ }
25947
+ };
25948
+ }
25609
25949
  function tryApplyTargetedTextLeafTransaction(document2, selection, intent, options) {
25610
25950
  const scope = resolveTargetedTextLeafScope(document2, selection, options.textTarget);
25611
25951
  if (!scope) {
@@ -30509,14 +30849,13 @@ var TOOLBAR_CHROME_REGISTRY = [
30509
30849
  surfaces: ["top-toolbar"],
30510
30850
  group: "text",
30511
30851
  presets: ["advanced", "review", "workflow"],
30512
- roles: ALL_ROLES,
30852
+ roles: EDITOR_AND_REVIEW,
30513
30853
  fullPlacement: "inline",
30514
30854
  compactPlacement: "overflow",
30515
30855
  runtimeBehavior: "formatting",
30516
30856
  rolePlacement: {
30517
30857
  editor: "inline",
30518
- review: "inline",
30519
- workflow: "overflow"
30858
+ review: "overflow"
30520
30859
  }
30521
30860
  },
30522
30861
  {
@@ -30524,14 +30863,13 @@ var TOOLBAR_CHROME_REGISTRY = [
30524
30863
  surfaces: ["top-toolbar"],
30525
30864
  group: "text",
30526
30865
  presets: ["simple", "advanced", "review", "workflow"],
30527
- roles: ALL_ROLES,
30866
+ roles: EDITOR_AND_REVIEW,
30528
30867
  fullPlacement: "inline",
30529
30868
  compactPlacement: "inline",
30530
30869
  runtimeBehavior: "formatting",
30531
30870
  rolePlacement: {
30532
30871
  editor: "inline",
30533
- review: "inline",
30534
- workflow: "overflow"
30872
+ review: "overflow"
30535
30873
  }
30536
30874
  },
30537
30875
  {
@@ -30658,10 +30996,9 @@ var TOOLBAR_CHROME_REGISTRY = [
30658
30996
  surfaces: ["top-toolbar"],
30659
30997
  group: "review",
30660
30998
  presets: ["simple", "advanced", "review", "workflow"],
30661
- // Visible in every role, but editor/review roles render it inside the
30662
- // role action region (see ROLE_ACTION_SETS) and the right cluster
30663
- // suppresses it via `isChromeItemOwnedByRoleRegion` to avoid duplication.
30664
- roles: ALL_ROLES,
30999
+ // Comment authoring belongs to Edit / Review. Workflow mode keeps scope
31000
+ // and work-item controls primary instead of carrying review chrome.
31001
+ roles: EDITOR_AND_REVIEW,
30665
31002
  fullPlacement: "inline",
30666
31003
  compactPlacement: "inline",
30667
31004
  runtimeBehavior: "comment"
@@ -33137,8 +33474,8 @@ function isNodeSelectableSegment(segment) {
33137
33474
  }
33138
33475
 
33139
33476
  // src/runtime/edit-ops/index.ts
33140
- function validateResult(result) {
33141
- const maxOffset = result.storyText.length;
33477
+ function validateResult(result, context) {
33478
+ const maxOffset = getPostMutationMaxOffset(result, context);
33142
33479
  const options = result.selection.activeRange.kind === "node" ? {
33143
33480
  isValidNodeTarget: createSurfaceNodeSelectionProbe(
33144
33481
  createEditorSurfaceSnapshot(result.document, result.selection)
@@ -33155,24 +33492,34 @@ function validateResult(result) {
33155
33492
  }
33156
33493
  return { ...result, selection: validated };
33157
33494
  }
33495
+ function getPostMutationMaxOffset(result, context) {
33496
+ if (typeof context.activeStorySize !== "number" || context.textTarget?.kind === "text-leaf") {
33497
+ return result.storyText.length;
33498
+ }
33499
+ let storySize = context.activeStorySize;
33500
+ for (const step of result.mapping.steps) {
33501
+ storySize += step.insertSize - Math.max(0, step.to - step.from);
33502
+ }
33503
+ return Math.max(result.storyText.length, storySize);
33504
+ }
33158
33505
  var editLayer = {
33159
33506
  applyTextInsert(doc, selection, text, context, formatting) {
33160
- return validateResult(insertText(doc, selection, text, context, formatting));
33507
+ return validateResult(insertText(doc, selection, text, context, formatting), context);
33161
33508
  },
33162
33509
  applyDeleteBackward(doc, selection, context) {
33163
- return validateResult(deleteSelectionOrBackward(doc, selection, context));
33510
+ return validateResult(deleteSelectionOrBackward(doc, selection, context), context);
33164
33511
  },
33165
33512
  applyDeleteForward(doc, selection, context) {
33166
- return validateResult(deleteSelectionOrForward(doc, selection, context));
33513
+ return validateResult(deleteSelectionOrForward(doc, selection, context), context);
33167
33514
  },
33168
33515
  applyInsertTab(doc, selection, context) {
33169
- return validateResult(insertTab(doc, selection, context));
33516
+ return validateResult(insertTab(doc, selection, context), context);
33170
33517
  },
33171
33518
  applyInsertHardBreak(doc, selection, context) {
33172
- return validateResult(insertHardBreak(doc, selection, context));
33519
+ return validateResult(insertHardBreak(doc, selection, context), context);
33173
33520
  },
33174
33521
  applySplitParagraph(doc, selection, context) {
33175
- return validateResult(splitParagraph(doc, selection, context));
33522
+ return validateResult(splitParagraph(doc, selection, context), context);
33176
33523
  }
33177
33524
  };
33178
33525
 
@@ -49506,7 +49853,7 @@ function deriveScopeEditableTargetEvidence(document2, scope, entry, options = {}
49506
49853
  facts.push(projectWorkflowBlockerFact(fact));
49507
49854
  factsByTargetKey.set(fact.targetKey, facts);
49508
49855
  }
49509
- const entries = collectEditableTargetRefs(document2).map((target) => {
49856
+ const entries = collectEditableTargetRefs(document2, options.editableTargetCache).map((target) => {
49510
49857
  const relation = relationForTarget(target, scope, entry);
49511
49858
  if (!relation) return null;
49512
49859
  const workflowBlockers = Object.freeze(
@@ -50485,7 +50832,8 @@ function composeEvidence(inputs) {
50485
50832
  scope,
50486
50833
  entry,
50487
50834
  {
50488
- ...inputs.editableTargetBlockerFacts ? { workflowBlockerFacts: inputs.editableTargetBlockerFacts } : {}
50835
+ ...inputs.editableTargetBlockerFacts ? { workflowBlockerFacts: inputs.editableTargetBlockerFacts } : {},
50836
+ ...inputs.editableTargetCache ? { editableTargetCache: inputs.editableTargetCache } : {}
50489
50837
  }
50490
50838
  ) : void 0;
50491
50839
  const contentControls = deriveScopeContentControlEvidence(document2, selfRange);
@@ -50574,7 +50922,8 @@ function compileScopeBundle(scope, inputs) {
50574
50922
  ...inputs.layout ? { layout: inputs.layout } : {},
50575
50923
  ...inputs.adjacentGeometry ? { adjacentGeometry: inputs.adjacentGeometry } : {},
50576
50924
  ...inputs.tableCellTextRange ? { tableCellTextRange: inputs.tableCellTextRange } : {},
50577
- ...inputs.editableTargetBlockerFacts ? { editableTargetBlockerFacts: inputs.editableTargetBlockerFacts } : {}
50925
+ ...inputs.editableTargetBlockerFacts ? { editableTargetBlockerFacts: inputs.editableTargetBlockerFacts } : {},
50926
+ ...inputs.editableTargetCache ? { editableTargetCache: inputs.editableTargetCache } : {}
50578
50927
  });
50579
50928
  return {
50580
50929
  scope,
@@ -51810,7 +52159,7 @@ function createScopeCompilerService(runtime) {
51810
52159
  const interactionGuard = runtime.getInteractionGuardSnapshot?.();
51811
52160
  const activeStory = runtime.getActiveStory?.();
51812
52161
  const editableTargetBlockerFacts = deriveWorkflowEditableTargetBlockerFacts({
51813
- targets: collectEditableTargetRefs(document2),
52162
+ targets: collectEditableTargetRefs(document2, runtime.getEditableTargetCache?.()),
51814
52163
  ...interactionGuard ? { guard: interactionGuard } : {},
51815
52164
  ...runtime.getProtectionSnapshot ? { protectionSnapshot: runtime.getProtectionSnapshot() } : {},
51816
52165
  ...activeStory ? { activeStoryKey: storyKeyForEditableTarget(activeStory) } : {}
@@ -51821,6 +52170,7 @@ function createScopeCompilerService(runtime) {
51821
52170
  runtime.getRenderSnapshot?.()
51822
52171
  )
51823
52172
  }) : void 0;
52173
+ const editableTargetCache = runtime.getEditableTargetCache?.();
51824
52174
  return compileScopeBundleById(scopeId, {
51825
52175
  document: document2,
51826
52176
  ...overlay ? { overlay } : {},
@@ -51830,7 +52180,8 @@ function createScopeCompilerService(runtime) {
51830
52180
  editableTargetBlockerFacts,
51831
52181
  ...runtime.geometry ? { geometry: runtime.geometry } : {},
51832
52182
  ...layout ? { layout } : {},
51833
- tableCellTextRange
52183
+ tableCellTextRange,
52184
+ ...editableTargetCache ? { editableTargetCache } : {}
51834
52185
  });
51835
52186
  },
51836
52187
  buildReplacementScope(targetHandle, input) {
@@ -55671,12 +56022,37 @@ function toPublicStoryAnchoredObject(object) {
55671
56022
  }
55672
56023
  } : {},
55673
56024
  ...object.anchorRectTwips ? { anchorRectTwips: toPublicTwipsRect(object.anchorRectTwips) } : {},
56025
+ ...object.textBoxBody ? { textBoxBody: toPublicTextBoxBodyFacts(object.textBoxBody) } : {},
55674
56026
  ...object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {},
55675
56027
  ...object.mediaIds ? { mediaIds: [...object.mediaIds] } : {},
55676
56028
  preserveOnly: object.preserveOnly,
55677
56029
  divergenceIds: [...object.divergenceIds]
55678
56030
  };
55679
56031
  }
56032
+ function toPublicTextBoxBodyFacts(textBoxBody) {
56033
+ return {
56034
+ bodyKey: textBoxBody.bodyKey,
56035
+ status: textBoxBody.status,
56036
+ ...textBoxBody.unavailableReason !== void 0 ? { unavailableReason: textBoxBody.unavailableReason } : {},
56037
+ ...textBoxBody.bodyProperties ? { bodyProperties: { ...textBoxBody.bodyProperties } } : {},
56038
+ ...textBoxBody.bodyInsetsTwips ? { bodyInsetsTwips: { ...textBoxBody.bodyInsetsTwips } } : {},
56039
+ ...textBoxBody.contentRectTwips ? { contentRectTwips: toPublicTwipsRect(textBoxBody.contentRectTwips) } : {},
56040
+ blockCount: textBoxBody.blockCount,
56041
+ paragraphCount: textBoxBody.paragraphCount,
56042
+ unsupportedBlockCount: textBoxBody.unsupportedBlockCount,
56043
+ paragraphs: textBoxBody.paragraphs.map((paragraph) => ({
56044
+ paragraphKey: paragraph.paragraphKey,
56045
+ blockPath: paragraph.blockPath,
56046
+ blockIndex: paragraph.blockIndex,
56047
+ ...paragraph.rectTwips ? { rectTwips: toPublicTwipsRect(paragraph.rectTwips) } : {},
56048
+ ...paragraph.unavailableReason !== void 0 ? { unavailableReason: paragraph.unavailableReason } : {},
56049
+ ...paragraph.styleId !== void 0 ? { styleId: paragraph.styleId } : {},
56050
+ ...paragraph.alignment !== void 0 ? { alignment: paragraph.alignment } : {},
56051
+ textLength: paragraph.textLength,
56052
+ runCount: paragraph.runCount
56053
+ }))
56054
+ };
56055
+ }
55680
56056
  function toPublicLayoutDivergence(divergence) {
55681
56057
  return {
55682
56058
  divergenceId: divergence.divergenceId,
@@ -58226,7 +58602,7 @@ async function collectEditorStateForSerialize(args) {
58226
58602
  // src/io/ooxml/parse-bookmark-references.ts
58227
58603
  var HYPERLINK_ANCHOR_RE = /<(?:\w+:)?hyperlink\b[^>]*\bw:anchor\s*=\s*"([^"]*)"/gi;
58228
58604
  var INSTR_TEXT_RE = /<(?:\w+:)?instrText\b[^>]*>([\s\S]*?)<\/(?:\w+:)?instrText>/gi;
58229
- var SIMPLE_FIELD_INSTR_RE = /<(?:\w+:)?fldSimple\b[^>]*\bw:instr\s*=\s*"([^"]*)"/gi;
58605
+ var FLD_SIMPLE_INSTR_RE = /<(?:\w+:)?fldSimple\b[^>]*(?:\bw:instr|\binstr)\s*=\s*(["'])([\s\S]*?)\1/gi;
58230
58606
  var TOC_FIELD_RE = /\bTOC\b/;
58231
58607
  var REFLIKE_FIELD_RE = /\b(?:HYPERLINK|REF|PAGEREF|NOTEREF)\s+([A-Za-z0-9_:.\-]+)/g;
58232
58608
  var DATA_BINDING_RE = /<(?:\w+:)?dataBinding\b/i;
@@ -58245,15 +58621,11 @@ function scanBookmarkReferences(documentXml, callerAllowlist = []) {
58245
58621
  }
58246
58622
  INSTR_TEXT_RE.lastIndex = 0;
58247
58623
  while ((m = INSTR_TEXT_RE.exec(documentXml)) !== null) {
58248
- if (scanInstructionForRetainedBookmarks(m[1] ?? "", retained)) {
58249
- retainAllToc = true;
58250
- }
58624
+ if (scanInstructionText(m[1] ?? "", retained)) retainAllToc = true;
58251
58625
  }
58252
- SIMPLE_FIELD_INSTR_RE.lastIndex = 0;
58253
- while ((m = SIMPLE_FIELD_INSTR_RE.exec(documentXml)) !== null) {
58254
- if (scanInstructionForRetainedBookmarks(m[1] ?? "", retained)) {
58255
- retainAllToc = true;
58256
- }
58626
+ FLD_SIMPLE_INSTR_RE.lastIndex = 0;
58627
+ while ((m = FLD_SIMPLE_INSTR_RE.exec(documentXml)) !== null) {
58628
+ if (scanInstructionText(m[2] ?? "", retained)) retainAllToc = true;
58257
58629
  }
58258
58630
  retainRevisionBoundedBookmarks(documentXml, retained);
58259
58631
  return {
@@ -58262,11 +58634,11 @@ function scanBookmarkReferences(documentXml, callerAllowlist = []) {
58262
58634
  retainAll
58263
58635
  };
58264
58636
  }
58265
- function scanInstructionForRetainedBookmarks(instruction, retained) {
58266
- const hasTocField = TOC_FIELD_RE.test(instruction);
58637
+ function scanInstructionText(instrText, retained) {
58638
+ const hasTocField = TOC_FIELD_RE.test(instrText);
58267
58639
  REFLIKE_FIELD_RE.lastIndex = 0;
58268
58640
  let r;
58269
- while ((r = REFLIKE_FIELD_RE.exec(instruction)) !== null) {
58641
+ while ((r = REFLIKE_FIELD_RE.exec(instrText)) !== null) {
58270
58642
  if (r[1]) retained.add(r[1]);
58271
58643
  }
58272
58644
  return hasTocField;
@@ -61767,7 +62139,7 @@ var SAFE_TABLE_FIELD_FAMILIES = /* @__PURE__ */ new Set([
61767
62139
  "FORMULA"
61768
62140
  ]);
61769
62141
  var RISKY_TABLE_MARKUP_RE = /<w:(ins|del|moveFrom|moveTo|rPrChange|pPrChange|tblPrChange|trPrChange|tcPrChange|sectPrChange|cellIns|cellDel|cellMerge|smartTag)\b/;
61770
- var SIMPLE_FIELD_INSTR_RE2 = /\bw:instr="([^"]*)"/g;
62142
+ var SIMPLE_FIELD_INSTR_RE = /\bw:instr="([^"]*)"/g;
61771
62143
  var COMPLEX_FIELD_TOKEN_RE = /<(?:\w+:)?fldChar\b[^>]*?(?:\w+:)?fldCharType="(begin|separate|end)"[^>]*?(?:\/>|>[\s\S]*?<\/(?:\w+:)?fldChar>)|<(?:\w+:)?instrText\b[^>]*>([\s\S]*?)<\/(?:\w+:)?instrText>/gu;
61772
62144
  function decodeXmlEntities4(text) {
61773
62145
  return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&");
@@ -61808,7 +62180,7 @@ function isSafeTableFieldInstruction(instruction) {
61808
62180
  }
61809
62181
  function tableRequiresOpaquePreservation(rawXml) {
61810
62182
  if (RISKY_TABLE_MARKUP_RE.test(rawXml)) return true;
61811
- const simpleInstructions = [...rawXml.matchAll(SIMPLE_FIELD_INSTR_RE2)].map(
62183
+ const simpleInstructions = [...rawXml.matchAll(SIMPLE_FIELD_INSTR_RE)].map(
61812
62184
  (match) => match[1] ?? ""
61813
62185
  );
61814
62186
  const complexInstructions = extractComplexFieldInstructionsFromRaw(rawXml);
@@ -65811,7 +66183,7 @@ function resolveEditableTextTarget(input) {
65811
66183
  "Editable target ref does not belong to the active story."
65812
66184
  );
65813
66185
  }
65814
- const currentTargets = collectEditableTargetRefs(input.document);
66186
+ const currentTargets = collectEditableTargetRefs(input.document, input.editableTargetCache);
65815
66187
  const current = currentTargets.find(
65816
66188
  (candidate) => candidate.targetKey === input.target.targetKey
65817
66189
  );
@@ -65920,7 +66292,7 @@ function resolveEditableCommandTarget(input) {
65920
66292
  `Editable target kind "${input.target.kind}" is not supported by this command.`
65921
66293
  );
65922
66294
  }
65923
- const currentTargets = collectEditableTargetRefs(input.document);
66295
+ const currentTargets = collectEditableTargetRefs(input.document, input.editableTargetCache);
65924
66296
  const current = currentTargets.find(
65925
66297
  (candidate) => candidate.targetKey === input.target?.targetKey
65926
66298
  );
@@ -65995,7 +66367,13 @@ function rejectCommand(code, message) {
65995
66367
  };
65996
66368
  }
65997
66369
  function sameResolvedTarget2(left, right) {
65998
- return left.kind === right.kind && left.storyKey === right.storyKey && left.blockPath === right.blockPath && left.leafPath === right.leafPath && left.commandFamily === right.commandFamily && left.editability === right.editability && left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength && left.staleCheck.inlineCount === right.staleCheck.inlineCount && left.staleCheck.targetHash === right.staleCheck.targetHash && left.staleCheck.targetTextLength === right.staleCheck.targetTextLength && left.staleCheck.childCount === right.staleCheck.childCount && left.staleCheck.blockType === right.staleCheck.blockType && left.staleCheck.wordParaId === right.staleCheck.wordParaId && left.staleCheck.wordTextId === right.staleCheck.wordTextId && jsonStable(left.staleCheck.sourceRef) === jsonStable(right.staleCheck.sourceRef) && jsonStable(left.sourceRef) === jsonStable(right.sourceRef) && jsonStable(left.table) === jsonStable(right.table) && jsonStable(left.editableOwner) === jsonStable(right.editableOwner);
66370
+ return left.kind === right.kind && left.storyKey === right.storyKey && left.blockPath === right.blockPath && left.leafPath === right.leafPath && left.commandFamily === right.commandFamily && left.editability === right.editability && sameTextTargetStaleCheck(left, right) && left.staleCheck.inlineCount === right.staleCheck.inlineCount && left.staleCheck.targetHash === right.staleCheck.targetHash && left.staleCheck.targetTextLength === right.staleCheck.targetTextLength && left.staleCheck.childCount === right.staleCheck.childCount && left.staleCheck.blockType === right.staleCheck.blockType && left.staleCheck.wordParaId === right.staleCheck.wordParaId && left.staleCheck.wordTextId === right.staleCheck.wordTextId && jsonStable(left.staleCheck.sourceRef) === jsonStable(right.staleCheck.sourceRef) && jsonStable(left.sourceRef) === jsonStable(right.sourceRef) && jsonStable(left.table) === jsonStable(right.table) && jsonStable(left.editableOwner) === jsonStable(right.editableOwner);
66371
+ }
66372
+ function sameTextTargetStaleCheck(left, right) {
66373
+ if (left.staleCheck.paragraphTextHash === right.staleCheck.paragraphTextHash && left.staleCheck.paragraphTextLength === right.staleCheck.paragraphTextLength) {
66374
+ return true;
66375
+ }
66376
+ return left.commandFamily === "text-leaf" && left.staleCheck.paragraphTextLength !== void 0 && right.staleCheck.paragraphTextLength !== void 0 && left.staleCheck.paragraphTextLength !== right.staleCheck.paragraphTextLength;
65999
66377
  }
66000
66378
  function locateTargetRange(document2, surface, target) {
66001
66379
  if (target.kind === "hyperlink-text") {
@@ -66314,7 +66692,7 @@ function resolveEditableTableStructureTarget(input) {
66314
66692
  `Editable target is not editable${input.target.posture.blockers.length > 0 ? `: ${input.target.posture.blockers.join(", ")}` : "."}`
66315
66693
  );
66316
66694
  }
66317
- const current = collectEditableTargetRefs(input.document).find(
66695
+ const current = collectEditableTargetRefs(input.document, input.editableTargetCache).find(
66318
66696
  (candidate) => candidate.targetKey === input.target?.targetKey
66319
66697
  );
66320
66698
  if (!current) {
@@ -66434,6 +66812,26 @@ function sortJson(value) {
66434
66812
  }
66435
66813
 
66436
66814
  // src/runtime/document-runtime.ts
66815
+ var CANONICAL_BLOCK_REFS_SYMBOL2 = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
66816
+ function getLocalTextPatchMetadata(mapping) {
66817
+ const metadata = mapping.metadata?.localTextPatch;
66818
+ if (!metadata || typeof metadata !== "object") {
66819
+ return null;
66820
+ }
66821
+ const insertedText = metadata.insertedText;
66822
+ return typeof insertedText === "string" ? { insertedText } : null;
66823
+ }
66824
+ function getSurfaceCanonicalBlockRefs(snapshot) {
66825
+ return snapshot[CANONICAL_BLOCK_REFS_SYMBOL2];
66826
+ }
66827
+ function attachSurfaceCanonicalBlockRefs(snapshot, refs) {
66828
+ Object.defineProperty(snapshot, CANONICAL_BLOCK_REFS_SYMBOL2, {
66829
+ value: refs,
66830
+ enumerable: false,
66831
+ configurable: true,
66832
+ writable: false
66833
+ });
66834
+ }
66437
66835
  function normalizeViewportRanges(ranges) {
66438
66836
  const cleaned = ranges.filter((r) => Number.isFinite(r.start) && Number.isFinite(r.end) && r.end > r.start).map((r) => ({ start: r.start, end: r.end }));
66439
66837
  if (cleaned.length === 0) return Object.freeze([]);
@@ -66797,6 +67195,22 @@ function createDocumentRuntime(options) {
66797
67195
  cachedEditableTargetMap = { document: document2, map: byBlockPath };
66798
67196
  return byBlockPath;
66799
67197
  }
67198
+ function getEditableTargetsByBlockPathForRanges(document2, storyKey2, ranges) {
67199
+ if (ranges === null) return getEditableTargetsByBlockPath(document2);
67200
+ perfCounters.increment("runtime.editableTargets.boundedBuilds");
67201
+ const targets = collectEditableTargetRefsForStoryBlockRanges(
67202
+ document2,
67203
+ storyKey2,
67204
+ ranges,
67205
+ editableTargetBlockCache
67206
+ );
67207
+ if (targets.length === 0) return /* @__PURE__ */ new Map();
67208
+ const byBlockPath = /* @__PURE__ */ new Map();
67209
+ for (const target of targets) {
67210
+ byBlockPath.set(target.blockPath, target);
67211
+ }
67212
+ return byBlockPath;
67213
+ }
66800
67214
  function invalidateEditableTargetMap() {
66801
67215
  cachedEditableTargetMap = null;
66802
67216
  }
@@ -66847,7 +67261,7 @@ function createDocumentRuntime(options) {
66847
67261
  }
66848
67262
  const snapshot = createEditorSurfaceSnapshot(document2, state.selection, nextActiveStory, {
66849
67263
  viewportBlockRanges: surfaceViewportRanges,
66850
- editableTargetsByBlockPath: getEditableTargetsByBlockPath(document2),
67264
+ editableTargetsByBlockPath: options2.editableTargetsByBlockPathOverride ?? getEditableTargetsByBlockPath(document2),
66851
67265
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
66852
67266
  });
66853
67267
  recordPerfSample("snapshot.surface");
@@ -66910,6 +67324,180 @@ function createDocumentRuntime(options) {
66910
67324
  }
66911
67325
  return -1;
66912
67326
  }
67327
+ function cachePatchedLocalTextSurface(surface) {
67328
+ const activeStoryKey = storyTargetKey(activeStory);
67329
+ const rangesKey = serializeViewportRanges(surface.viewportBlockRanges);
67330
+ cachedSurface = {
67331
+ content: state.document.content,
67332
+ subParts: state.document.subParts,
67333
+ styles: state.document.styles,
67334
+ numbering: state.document.numbering,
67335
+ media: state.document.media,
67336
+ preservation: state.document.preservation,
67337
+ review: state.document.review,
67338
+ effectiveMarkupModeProvider,
67339
+ activeStoryKey,
67340
+ viewportRangesKey: rangesKey,
67341
+ snapshot: surface
67342
+ };
67343
+ if (surface.viewportBlockRanges === null) {
67344
+ cachedFullSurface = {
67345
+ content: state.document.content,
67346
+ subParts: state.document.subParts,
67347
+ styles: state.document.styles,
67348
+ numbering: state.document.numbering,
67349
+ media: state.document.media,
67350
+ preservation: state.document.preservation,
67351
+ review: state.document.review,
67352
+ effectiveMarkupModeProvider,
67353
+ activeStoryKey,
67354
+ snapshot: surface
67355
+ };
67356
+ }
67357
+ cachedSurfaceFingerprint = `${activeStoryKey}|${rangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
67358
+ }
67359
+ function tryPatchLocalTextSurface(previousSurface, mapping) {
67360
+ const tTotal0 = performance.now();
67361
+ try {
67362
+ if (!previousSurface || activeStory.kind !== "main") {
67363
+ perfCounters.increment("surface.localText.patchMiss");
67364
+ return null;
67365
+ }
67366
+ const patch = getLocalTextPatchMetadata(mapping);
67367
+ if (!patch || mapping.steps.length !== 1) {
67368
+ perfCounters.increment("surface.localText.patchMiss");
67369
+ return null;
67370
+ }
67371
+ const step = mapping.steps[0];
67372
+ if (patch.insertedText.length !== step.insertSize) {
67373
+ perfCounters.increment("surface.localText.patchMiss");
67374
+ return null;
67375
+ }
67376
+ const editFrom = step.from;
67377
+ const editTo = step.to;
67378
+ if (editTo < editFrom || editFrom < 0) {
67379
+ perfCounters.increment("surface.localText.patchMiss");
67380
+ return null;
67381
+ }
67382
+ const blockIndex = previousSurface.blocks.findIndex(
67383
+ (block2) => block2.kind === "paragraph" && editFrom >= block2.from && editTo <= block2.to
67384
+ );
67385
+ if (blockIndex < 0) {
67386
+ perfCounters.increment("surface.localText.patchMiss");
67387
+ return null;
67388
+ }
67389
+ const block = previousSurface.blocks[blockIndex];
67390
+ if (block.kind !== "paragraph") {
67391
+ perfCounters.increment("surface.localText.patchMiss");
67392
+ return null;
67393
+ }
67394
+ const segmentIndex = block.segments.findIndex(
67395
+ (segment2) => segment2.kind === "text" && editFrom >= segment2.from && editTo <= segment2.to
67396
+ );
67397
+ if (segmentIndex < 0) {
67398
+ perfCounters.increment("surface.localText.patchMiss");
67399
+ return null;
67400
+ }
67401
+ const segment = block.segments[segmentIndex];
67402
+ if (segment.kind !== "text") {
67403
+ perfCounters.increment("surface.localText.patchMiss");
67404
+ return null;
67405
+ }
67406
+ if (segment.text.length !== segment.to - segment.from) {
67407
+ perfCounters.increment("surface.localText.patchMiss");
67408
+ return null;
67409
+ }
67410
+ const localFrom = editFrom - segment.from;
67411
+ const localTo = editTo - segment.from;
67412
+ const delta = patch.insertedText.length - (editTo - editFrom);
67413
+ const nextText = segment.text.slice(0, localFrom) + patch.insertedText + segment.text.slice(localTo);
67414
+ const nextSegments = block.segments.map((candidate, index) => {
67415
+ if (index < segmentIndex) return candidate;
67416
+ if (index === segmentIndex) {
67417
+ return {
67418
+ ...segment,
67419
+ text: nextText,
67420
+ to: segment.to + delta
67421
+ };
67422
+ }
67423
+ return shiftSurfaceInlineSegment(candidate, delta);
67424
+ });
67425
+ const nextBlock = {
67426
+ ...block,
67427
+ to: block.to + delta,
67428
+ segments: nextSegments
67429
+ };
67430
+ const nextBlocks = previousSurface.blocks.map((candidate, index) => {
67431
+ if (index < blockIndex) return candidate;
67432
+ if (index === blockIndex) return nextBlock;
67433
+ return shiftSurfaceBlock(candidate, delta);
67434
+ });
67435
+ const nextPlainText = previousSurface.plainText.slice(0, editFrom) + patch.insertedText + previousSurface.plainText.slice(editTo);
67436
+ const nextSurface = {
67437
+ ...previousSurface,
67438
+ storySize: previousSurface.storySize + delta,
67439
+ plainText: nextPlainText,
67440
+ blocks: nextBlocks
67441
+ };
67442
+ const refs = getSurfaceCanonicalBlockRefs(previousSurface);
67443
+ if (refs) {
67444
+ const nextRefs = [...refs];
67445
+ nextRefs[blockIndex] = state.document.content.children[blockIndex] ?? null;
67446
+ attachSurfaceCanonicalBlockRefs(nextSurface, nextRefs);
67447
+ }
67448
+ perfCounters.increment("surface.localText.patchHit");
67449
+ perfCounters.increment("surface.localText.patchDelta", delta);
67450
+ return nextSurface;
67451
+ } finally {
67452
+ perfCounters.increment("surface.localText.total.us", Math.round((performance.now() - tTotal0) * 1e3));
67453
+ }
67454
+ }
67455
+ function shiftSurfaceInlineSegment(segment, delta) {
67456
+ if (delta === 0) return segment;
67457
+ return {
67458
+ ...segment,
67459
+ from: segment.from + delta,
67460
+ to: segment.to + delta
67461
+ };
67462
+ }
67463
+ function shiftSurfaceBlock(block, delta) {
67464
+ if (delta === 0) return block;
67465
+ switch (block.kind) {
67466
+ case "paragraph":
67467
+ return {
67468
+ ...block,
67469
+ from: block.from + delta,
67470
+ to: block.to + delta,
67471
+ segments: block.segments.map((segment) => shiftSurfaceInlineSegment(segment, delta))
67472
+ };
67473
+ case "table":
67474
+ return {
67475
+ ...block,
67476
+ from: block.from + delta,
67477
+ to: block.to + delta,
67478
+ rows: block.rows.map((row2) => ({
67479
+ ...row2,
67480
+ cells: row2.cells.map((cell) => ({
67481
+ ...cell,
67482
+ content: cell.content.map((child) => shiftSurfaceBlock(child, delta))
67483
+ }))
67484
+ }))
67485
+ };
67486
+ case "sdt_block":
67487
+ return {
67488
+ ...block,
67489
+ from: block.from + delta,
67490
+ to: block.to + delta,
67491
+ children: block.children.map((child) => shiftSurfaceBlock(child, delta))
67492
+ };
67493
+ case "opaque_block":
67494
+ return {
67495
+ ...block,
67496
+ from: block.from + delta,
67497
+ to: block.to + delta
67498
+ };
67499
+ }
67500
+ }
66913
67501
  function enrichCulledPlaceholdersWithHeights(snapshot) {
66914
67502
  let heights;
66915
67503
  try {
@@ -67795,7 +68383,8 @@ function createDocumentRuntime(options) {
67795
68383
  document: document2,
67796
68384
  target: command.editableTarget,
67797
68385
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
67798
- selectionDescriptor: command.selectionDescriptor
68386
+ selectionDescriptor: command.selectionDescriptor,
68387
+ editableTargetCache: editableTargetBlockCache
67799
68388
  });
67800
68389
  if (resolution.kind === "rejected") {
67801
68390
  emit2({
@@ -67858,7 +68447,8 @@ function createDocumentRuntime(options) {
67858
68447
  document: document2,
67859
68448
  surface,
67860
68449
  target,
67861
- activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
68450
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
68451
+ editableTargetCache: editableTargetBlockCache
67862
68452
  });
67863
68453
  if (resolution.kind === "rejected") {
67864
68454
  emit2({
@@ -67888,7 +68478,8 @@ function createDocumentRuntime(options) {
67888
68478
  document: document2,
67889
68479
  surface,
67890
68480
  target: command.editableTarget,
67891
- activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
68481
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
68482
+ editableTargetCache: editableTargetBlockCache
67892
68483
  });
67893
68484
  if (resolution.kind === "rejected") {
67894
68485
  emit2({
@@ -67916,7 +68507,8 @@ function createDocumentRuntime(options) {
67916
68507
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
67917
68508
  commandFamilies: command.type === "field.refresh" || command.type === "toc.refresh" ? ["field"] : ["link-bookmark"],
67918
68509
  targetKinds: targetKindsForModeledCommand(command.type),
67919
- allowGeneratedPosture: true
68510
+ allowGeneratedPosture: true,
68511
+ editableTargetCache: editableTargetBlockCache
67920
68512
  });
67921
68513
  if (resolution.kind === "rejected") {
67922
68514
  emit2({
@@ -67958,7 +68550,8 @@ function createDocumentRuntime(options) {
67958
68550
  baseState.selection.head,
67959
68551
  storyTarget,
67960
68552
  getFullPageGraph(),
67961
- command.options
68553
+ command.options,
68554
+ command.editableTarget
67962
68555
  );
67963
68556
  if (!refreshed2.changed) return null;
67964
68557
  cachedFieldSnapshotEntry = null;
@@ -68000,6 +68593,9 @@ function createDocumentRuntime(options) {
68000
68593
  );
68001
68594
  }
68002
68595
  const runtime = {
68596
+ getEditableTargetCache() {
68597
+ return editableTargetBlockCache;
68598
+ },
68003
68599
  subscribe(listener) {
68004
68600
  listeners.add(listener);
68005
68601
  return () => {
@@ -70203,6 +70799,12 @@ function createDocumentRuntime(options) {
70203
70799
  }
70204
70800
  return !effects.commentAdded && !effects.commentResolved && !effects.commentReopened && !effects.commentReplyAdded && !effects.commentBodyEdited && !effects.changeAccepted && !effects.changeRejected && !effects.revisionAuthored && !effects.commandBlocked;
70205
70801
  }
70802
+ function canSkipOverlaySyncForLocalText(transaction) {
70803
+ if (transaction.mapping.steps.length !== 1) return false;
70804
+ if (transaction.mapping.metadata?.invalidatesStructures) return false;
70805
+ if (transaction.mapping.metadata?.scopeTagTouches) return false;
70806
+ return getLocalTextPatchMetadata(transaction.mapping) !== null;
70807
+ }
70206
70808
  function applyTransactionToState(transaction, options2 = {}) {
70207
70809
  const effects = transaction.effects;
70208
70810
  const selectionUnchanged = transaction.nextState.selection === state.selection;
@@ -70224,9 +70826,28 @@ function createDocumentRuntime(options) {
70224
70826
  state = finalizeState(transaction.nextState, transaction.markDirty, clock());
70225
70827
  perfCounters.increment("commit.finalizeState.us", Math.round((performance.now() - tFinalize0) * 1e3));
70226
70828
  storySelections.set(storyTargetKey(activeStory), state.selection);
70829
+ const tClassify0 = performance.now();
70830
+ const useLocalTextCommitSnapshot = options2.allowLocalTextFastPath === true && shouldUseLocalTextCommitSnapshot(
70831
+ previous,
70832
+ state,
70833
+ transaction,
70834
+ transaction.effects
70835
+ );
70836
+ perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
70227
70837
  const tOverlay0 = performance.now();
70228
- overlayStore.replaceOverlay(overlayStore.getOverlay(), state.document);
70229
- const detachedWorkflowScopeWarnings = syncDetachedWorkflowScopeWarningsInState();
70838
+ const skipOverlaySync = useLocalTextCommitSnapshot && canSkipOverlaySyncForLocalText(transaction);
70839
+ const detachedWorkflowScopeWarnings = skipOverlaySync ? { added: [], cleared: [] } : (() => {
70840
+ const tReplace0 = performance.now();
70841
+ overlayStore.replaceOverlay(overlayStore.getOverlay(), state.document);
70842
+ perfCounters.increment("commit.overlaySync.replaceOverlay.us", Math.round((performance.now() - tReplace0) * 1e3));
70843
+ const tWarnings0 = performance.now();
70844
+ const result = syncDetachedWorkflowScopeWarningsInState();
70845
+ perfCounters.increment("commit.overlaySync.detachedWarnings.us", Math.round((performance.now() - tWarnings0) * 1e3));
70846
+ return result;
70847
+ })();
70848
+ if (skipOverlaySync) {
70849
+ perfCounters.increment("commit.overlaySync.skipped");
70850
+ }
70230
70851
  perfCounters.increment("commit.overlaySync.us", Math.round((performance.now() - tOverlay0) * 1e3));
70231
70852
  const tInvalidate0 = performance.now();
70232
70853
  if (transaction.markDirty && transaction.mapping.steps.length > 0) {
@@ -70260,22 +70881,34 @@ function createDocumentRuntime(options) {
70260
70881
  ...detachedWorkflowScopeWarnings.cleared
70261
70882
  ]
70262
70883
  };
70263
- const tClassify0 = performance.now();
70264
- const useLocalTextCommitSnapshot = options2.allowLocalTextFastPath === true && shouldUseLocalTextCommitSnapshot(
70265
- previous,
70266
- state,
70267
- transaction,
70268
- notifyEffects
70269
- );
70270
- perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
70271
70884
  if (!useLocalTextCommitSnapshot && transaction.markDirty && previous.document !== state.document) {
70272
70885
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
70273
70886
  }
70274
70887
  const tValidation0 = performance.now();
70275
- const surfaceForValidation = useLocalTextCommitSnapshot ? getCachedSurface(state.document, activeStory, {
70276
- viewportBlockRangesOverride: getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface),
70277
- enrichCulledPlaceholders: false
70278
- }) : getCachedSurface(state.document, activeStory);
70888
+ const patchedLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(cachedRenderSnapshot.surface, transaction.mapping) : null;
70889
+ if (patchedLocalTextSurface) {
70890
+ cachePatchedLocalTextSurface(patchedLocalTextSurface);
70891
+ perfCounters.increment("commit.localTextValidation.storySizeOnly");
70892
+ }
70893
+ const localTextViewportRanges = useLocalTextCommitSnapshot && !patchedLocalTextSurface ? getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface) : void 0;
70894
+ const localTextEditableTargetsByBlockPath = useLocalTextCommitSnapshot && !patchedLocalTextSurface ? getEditableTargetsByBlockPathForRanges(
70895
+ state.document,
70896
+ storyTargetKey(activeStory),
70897
+ localTextViewportRanges ?? null
70898
+ ) : void 0;
70899
+ const surfaceForValidation = patchedLocalTextSurface ? patchedLocalTextSurface : useLocalTextCommitSnapshot ? (() => {
70900
+ const tSurface0 = performance.now();
70901
+ try {
70902
+ perfCounters.increment("surface.localText.fullProjectionFallback");
70903
+ return getCachedSurface(state.document, activeStory, {
70904
+ viewportBlockRangesOverride: localTextViewportRanges,
70905
+ enrichCulledPlaceholders: false,
70906
+ editableTargetsByBlockPathOverride: localTextEditableTargetsByBlockPath
70907
+ });
70908
+ } finally {
70909
+ perfCounters.increment("surface.localText.fullProjection.us", Math.round((performance.now() - tSurface0) * 1e3));
70910
+ }
70911
+ })() : getCachedSurface(state.document, activeStory);
70279
70912
  const validationOptions = state.selection.activeRange.kind === "node" ? {
70280
70913
  isValidNodeTarget: createSurfaceNodeSelectionProbe(surfaceForValidation)
70281
70914
  } : void 0;
@@ -70542,7 +71175,8 @@ function createDocumentRuntime(options) {
70542
71175
  selection,
70543
71176
  surface: cachedRenderSnapshot.surface?.blocks ?? [],
70544
71177
  target: editableTarget,
70545
- activeStoryKey: canonicalEditableTargetStoryKey(activeStory)
71178
+ activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
71179
+ editableTargetCache: editableTargetBlockCache
70546
71180
  }) : null;
70547
71181
  if (targetResolution?.kind === "rejected") {
70548
71182
  const blockedReason = targetResolution.blockedReason;
@@ -70594,6 +71228,7 @@ function createDocumentRuntime(options) {
70594
71228
  documentMode: textOptions.documentModeOverride ?? workflowCoordinator.getEffectiveDocumentMode(selection),
70595
71229
  defaultAuthorId: defaultAuthorId ?? void 0,
70596
71230
  renderSnapshot: cachedRenderSnapshot,
71231
+ activeStorySize: cachedRenderSnapshot.surface?.storySize,
70597
71232
  textTarget,
70598
71233
  rejectTargetlessTableStructureInsert: true
70599
71234
  };
@@ -72008,15 +72643,12 @@ function flattenInlineDisplayText(children) {
72008
72643
  }
72009
72644
  }).join("");
72010
72645
  }
72011
- function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph, options) {
72646
+ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph, options, target) {
72012
72647
  const supportedOnly = options?.supportedOnly ?? true;
72013
72648
  const bookmarkMap = buildBookmarkNameMap(document2);
72014
72649
  const paragraphs = collectParagraphContexts(document2.content.children);
72015
- const activePageIndex = resolveActivePageIndexFromPageGraph(
72016
- pageGraph,
72017
- selectionHead,
72018
- activeStory
72019
- );
72650
+ void selectionHead;
72651
+ void activeStory;
72020
72652
  let updatedCount = 0;
72021
72653
  let changed = false;
72022
72654
  let changedFrom;
@@ -72026,19 +72658,27 @@ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph,
72026
72658
  let storyChangedFrom;
72027
72659
  let storyChangedTo;
72028
72660
  const refreshed = refreshBlocksWithCursor(blocks, (field, range) => {
72661
+ if (target !== void 0 && !fieldMatchesRefreshTarget(field, target)) {
72662
+ return field;
72663
+ }
72029
72664
  if (!field.fieldFamily || !isSupportedFieldFamily(field.fieldFamily)) {
72030
72665
  return field;
72031
72666
  }
72032
72667
  if (supportedOnly && field.fieldFamily === "TOC") {
72033
72668
  return field;
72034
72669
  }
72670
+ const fieldPageIndex = resolveActivePageIndexFromPageGraph(
72671
+ pageGraph,
72672
+ range.from,
72673
+ storyTarget
72674
+ );
72035
72675
  const display = resolveSupportedFieldDisplay(
72036
72676
  field,
72037
72677
  document2,
72038
72678
  bookmarkMap,
72039
72679
  paragraphs,
72040
72680
  pageGraph,
72041
- activePageIndex,
72681
+ fieldPageIndex,
72042
72682
  storyTarget
72043
72683
  );
72044
72684
  if (!display) {
@@ -72188,6 +72828,34 @@ function refreshDocumentFields(document2, selectionHead, activeStory, pageGraph,
72188
72828
  ...protectionSelection ? { protectionSelection } : {}
72189
72829
  };
72190
72830
  }
72831
+ function fieldMatchesRefreshTarget(field, target) {
72832
+ if (target.kind !== "field-result-text" && target.kind !== "field-region-refresh") {
72833
+ return false;
72834
+ }
72835
+ const targetField = target.field;
72836
+ if (targetField?.canonicalFieldId !== void 0) {
72837
+ return field.canonicalFieldId === targetField.canonicalFieldId;
72838
+ }
72839
+ const resultText = flattenInlineDisplayText(field.children);
72840
+ const fieldResultHash = sha256TextHex(`${field.instruction}\0${resultText}`);
72841
+ if (target.kind === "field-result-text" && target.staleCheck.targetHash !== void 0) {
72842
+ return target.staleCheck.targetHash === fieldResultHash;
72843
+ }
72844
+ if (targetField?.fieldFamily !== void 0 && targetField.fieldFamily !== field.fieldFamily) {
72845
+ return false;
72846
+ }
72847
+ if (targetField?.fieldTarget !== void 0 && targetField.fieldTarget !== field.fieldTarget) {
72848
+ return false;
72849
+ }
72850
+ if (target.staleCheck.sourceRef !== void 0 || target.sourceRef !== void 0) {
72851
+ return sourceRefsEqual(target.staleCheck.sourceRef ?? target.sourceRef, field.sourceRef);
72852
+ }
72853
+ return false;
72854
+ }
72855
+ function sourceRefsEqual(left, right) {
72856
+ if (left === void 0 || right === void 0) return false;
72857
+ return left.sourceId === right.sourceId && left.partPath === right.partPath && left.storyKind === right.storyKind && left.element === right.element && left.xmlPath === right.xmlPath && left.tableCellPath === right.tableCellPath && left.tableDepth === right.tableDepth && left.ordinal === right.ordinal && left.startOffset === right.startOffset && left.endOffset === right.endOffset;
72858
+ }
72191
72859
  function refreshDocumentTableOfContents(document2, selectionHead, activeStory, options, resolveDisplayPageNumber, navigationSnapshot) {
72192
72860
  const selectedRegion = selectTocRegion(document2.fieldRegistry?.tocRegions, options?.tocId);
72193
72861
  const refreshMode = options?.mode ?? "regenerate";
@@ -83401,7 +84069,8 @@ function parseCommentDefinitions(commentsXml, extensions, durableIds) {
83401
84069
  const createdAt = normalizeImportedTimestamp2(
83402
84070
  readStringAttr(child, "w:date")
83403
84071
  );
83404
- const initials = readStringAttr(child, "w:initials");
84072
+ const rawInitials = readStringAttr(child, "w:initials");
84073
+ const initials = rawInitials !== void 0 && rawInitials.trim().length > 0 ? rawInitials : void 0;
83405
84074
  const paragraphNodes = child.children.filter(
83406
84075
  (node) => node.type === "element" && localName(node.name) === "p"
83407
84076
  );
@@ -91465,12 +92134,16 @@ function TwToolbar(props) {
91465
92134
  const showUpdateActions = isToolbarChromeItemVisible(scopedChromePolicy, "update-actions");
91466
92135
  const showSidebarToggle = (props.showSidebarToggle ?? false) && isToolbarChromeItemVisible(scopedChromePolicy, "sidebar-toggle");
91467
92136
  const showStyleSelectorsInRow = getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "inline";
92137
+ const showStyleSelectorsInOverflow = getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow";
92138
+ const showInlineFormattingInOverflow = getToolbarChromePlacement(scopedChromePolicy, "inline-formatting") === "overflow";
92139
+ const showTextColorsInOverflow = getToolbarChromePlacement(scopedChromePolicy, "text-colors") === "overflow";
92140
+ const showParagraphAlignmentInOverflow = getToolbarChromePlacement(scopedChromePolicy, "paragraph-alignment") === "overflow";
91468
92141
  const showListActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "inline";
91469
92142
  const showSpacingActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "indentation") === "inline";
91470
92143
  const showListContinuationInRow = getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "inline";
91471
92144
  const showInsertActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "inline";
91472
92145
  const showUpdateActionsInRow = getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "inline";
91473
- const showCompactOverflow = getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "indentation") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "overflow";
92146
+ const showCompactOverflow = getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "inline-formatting") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "text-colors") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "paragraph-alignment") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "indentation") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "overflow" || getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "overflow";
91474
92147
  const showPostFormattingDivider = showListActionsInRow || showSpacingActionsInRow || showInsertActionsInRow || showUpdateActionsInRow || showCompactOverflow;
91475
92148
  const zoomLabel = typeof zoomLevel === "number" ? `${zoomLevel}%` : zoomLevel === "pageWidth" ? "Fit width" : "Fit page";
91476
92149
  const showZoomSteppers = responsiveTier === "wide";
@@ -91765,14 +92438,26 @@ function TwToolbar(props) {
91765
92438
  insertDisabledReason,
91766
92439
  paragraphStyles,
91767
92440
  showInsertMenu: getToolbarChromePlacement(scopedChromePolicy, "insert-actions") === "overflow",
92441
+ showInlineFormatting: showInlineFormattingInOverflow,
91768
92442
  showListActions: getToolbarChromePlacement(scopedChromePolicy, "list-actions") === "overflow",
91769
92443
  showParagraphActions: getToolbarChromePlacement(scopedChromePolicy, "indentation") === "overflow",
92444
+ showParagraphAlignment: showParagraphAlignmentInOverflow,
91770
92445
  showListContinuation: getToolbarChromePlacement(scopedChromePolicy, "list-continuation") === "overflow",
91771
- showStyleSelectors: getToolbarChromePlacement(scopedChromePolicy, "text-style-selectors") === "overflow",
92446
+ showStyleSelectors: showStyleSelectorsInOverflow,
92447
+ showTextColors: showTextColorsInOverflow,
91772
92448
  showUpdateActions: getToolbarChromePlacement(scopedChromePolicy, "update-actions") === "overflow",
91773
92449
  onSetParagraphStyle: props.onSetParagraphStyle,
91774
92450
  onSetFontFamily: props.onSetFontFamily,
91775
92451
  onSetFontSize: props.onSetFontSize,
92452
+ onToggleBold: props.onToggleBold,
92453
+ onToggleItalic: props.onToggleItalic,
92454
+ onToggleUnderline: props.onToggleUnderline,
92455
+ onToggleStrikethrough: props.onToggleStrikethrough,
92456
+ onToggleSuperscript: props.onToggleSuperscript,
92457
+ onToggleSubscript: props.onToggleSubscript,
92458
+ onSetTextColor: props.onSetTextColor,
92459
+ onSetHighlightColor: props.onSetHighlightColor,
92460
+ onSetAlignment: props.onSetAlignment,
91776
92461
  onToggleBulletedList: props.onToggleBulletedList,
91777
92462
  onToggleNumberedList: props.onToggleNumberedList,
91778
92463
  onOutdent: props.onOutdent,
@@ -92282,8 +92967,8 @@ function ToolbarFontSizeSelect(props) {
92282
92967
  function ToolbarCompactOverflow(props) {
92283
92968
  const [open, setOpen] = import_react7.default.useState(false);
92284
92969
  const overflowGroups = [
92285
- props.showStyleSelectors ? "Format" : null,
92286
- props.showListActions || props.showParagraphActions || props.showListContinuation ? "Paragraph" : null,
92970
+ props.showStyleSelectors || props.showInlineFormatting || props.showTextColors ? "Format" : null,
92971
+ props.showListActions || props.showParagraphActions || props.showParagraphAlignment || props.showListContinuation ? "Paragraph" : null,
92287
92972
  props.showInsertMenu ? "Insert" : null,
92288
92973
  props.showUpdateActions ? "Update" : null
92289
92974
  ].filter((label) => Boolean(label));
@@ -92368,6 +93053,129 @@ function ToolbarCompactOverflow(props) {
92368
93053
  ] })
92369
93054
  ] })
92370
93055
  ] }) : null,
93056
+ props.showInlineFormatting || props.showTextColors ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
93057
+ !props.showStyleSelectors ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1 text-[10px] font-semibold uppercase tracking-[var(--tracking-status)] text-tertiary", children: "Text" }) : null,
93058
+ props.showInlineFormatting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
93059
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93060
+ ToolbarMenuButton,
93061
+ {
93062
+ ariaLabel: "Bold",
93063
+ disabled: !props.canEdit || !props.onToggleBold,
93064
+ disabledReason: props.editDisabledReason,
93065
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Bold, { className: "h-3.5 w-3.5" }),
93066
+ label: "Bold",
93067
+ onClick: () => {
93068
+ props.onToggleBold?.();
93069
+ setOpen(false);
93070
+ }
93071
+ }
93072
+ ),
93073
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93074
+ ToolbarMenuButton,
93075
+ {
93076
+ ariaLabel: "Italic",
93077
+ disabled: !props.canEdit || !props.onToggleItalic,
93078
+ disabledReason: props.editDisabledReason,
93079
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Italic, { className: "h-3.5 w-3.5" }),
93080
+ label: "Italic",
93081
+ onClick: () => {
93082
+ props.onToggleItalic?.();
93083
+ setOpen(false);
93084
+ }
93085
+ }
93086
+ ),
93087
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93088
+ ToolbarMenuButton,
93089
+ {
93090
+ ariaLabel: "Underline",
93091
+ disabled: !props.canEdit || !props.onToggleUnderline,
93092
+ disabledReason: props.editDisabledReason,
93093
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Underline, { className: "h-3.5 w-3.5" }),
93094
+ label: "Underline",
93095
+ onClick: () => {
93096
+ props.onToggleUnderline?.();
93097
+ setOpen(false);
93098
+ }
93099
+ }
93100
+ ),
93101
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93102
+ ToolbarMenuButton,
93103
+ {
93104
+ ariaLabel: "Strikethrough",
93105
+ disabled: !props.canEdit || !props.onToggleStrikethrough,
93106
+ disabledReason: props.editDisabledReason,
93107
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Strikethrough, { className: "h-3.5 w-3.5" }),
93108
+ label: "Strikethrough",
93109
+ onClick: () => {
93110
+ props.onToggleStrikethrough?.();
93111
+ setOpen(false);
93112
+ }
93113
+ }
93114
+ ),
93115
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93116
+ ToolbarMenuButton,
93117
+ {
93118
+ ariaLabel: "Superscript",
93119
+ disabled: !props.canEdit || !props.onToggleSuperscript,
93120
+ disabledReason: props.editDisabledReason,
93121
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Superscript, { className: "h-3.5 w-3.5" }),
93122
+ label: "Superscript",
93123
+ onClick: () => {
93124
+ props.onToggleSuperscript?.();
93125
+ setOpen(false);
93126
+ }
93127
+ }
93128
+ ),
93129
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93130
+ ToolbarMenuButton,
93131
+ {
93132
+ ariaLabel: "Subscript",
93133
+ disabled: !props.canEdit || !props.onToggleSubscript,
93134
+ disabledReason: props.editDisabledReason,
93135
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Subscript, { className: "h-3.5 w-3.5" }),
93136
+ label: "Subscript",
93137
+ onClick: () => {
93138
+ props.onToggleSubscript?.();
93139
+ setOpen(false);
93140
+ }
93141
+ }
93142
+ )
93143
+ ] }) : null,
93144
+ props.showTextColors ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-cols-2 gap-2 px-1 pt-1", children: [
93145
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93146
+ ToolbarColorPopover,
93147
+ {
93148
+ ariaLabel: "Text color",
93149
+ colors: TEXT_COLORS.map((value) => ({ value, label: value })),
93150
+ disabled: !props.canEdit || !props.onSetTextColor,
93151
+ disabledReason: props.editDisabledReason,
93152
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Baseline, { className: "h-3.5 w-3.5" }),
93153
+ onSelect: (value) => {
93154
+ if (value) {
93155
+ props.onSetTextColor?.(value);
93156
+ setOpen(false);
93157
+ }
93158
+ },
93159
+ title: "Text color"
93160
+ }
93161
+ ),
93162
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93163
+ ToolbarColorPopover,
93164
+ {
93165
+ ariaLabel: "Highlight color",
93166
+ colors: HIGHLIGHT_COLORS.map((entry) => ({ value: entry.value, label: entry.label })),
93167
+ disabled: !props.canEdit || !props.onSetHighlightColor,
93168
+ disabledReason: props.editDisabledReason,
93169
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Highlighter, { className: "h-3.5 w-3.5" }),
93170
+ onSelect: (value) => {
93171
+ props.onSetHighlightColor?.(value);
93172
+ setOpen(false);
93173
+ },
93174
+ title: "Highlight color"
93175
+ }
93176
+ )
93177
+ ] }) : null
93178
+ ] }) : null,
92371
93179
  props.showListActions ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
92372
93180
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1 text-[10px] font-semibold uppercase tracking-[var(--tracking-status)] text-tertiary", children: "Structure" }),
92373
93181
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -92399,8 +93207,20 @@ function ToolbarCompactOverflow(props) {
92399
93207
  }
92400
93208
  )
92401
93209
  ] }) : null,
92402
- props.showParagraphActions || props.showListContinuation && props.activeListContext ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
93210
+ props.showParagraphActions || props.showParagraphAlignment || props.showListContinuation && props.activeListContext ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
92403
93211
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1 text-[10px] font-semibold uppercase tracking-[var(--tracking-status)] text-tertiary", children: "Paragraph" }),
93212
+ props.showParagraphAlignment ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1 pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
93213
+ ToolbarAlignmentPopover,
93214
+ {
93215
+ activeAlignment: props.formattingState?.alignment,
93216
+ disabled: !props.canEdit || !props.onSetAlignment,
93217
+ disabledReason: props.editDisabledReason,
93218
+ onSelect: (alignment) => {
93219
+ props.onSetAlignment?.(alignment);
93220
+ setOpen(false);
93221
+ }
93222
+ }
93223
+ ) }) : null,
92404
93224
  props.showParagraphActions ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
92405
93225
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
92406
93226
  ToolbarMenuButton,
@@ -100897,10 +101717,7 @@ var TwPageStackOverlayLayer = ({
100897
101717
  null
100898
101718
  );
100899
101719
  if (warm) {
100900
- return extendPageOverlayRectsAcrossTableBoundaryGaps(
100901
- warm,
100902
- containsTableBoundaryRisk(scrollRoot) ? collectTableEmbeddedBoundaryIndices(scrollRoot) : []
100903
- );
101720
+ return warm;
100904
101721
  }
100905
101722
  }
100906
101723
  return resolveSkeletalPageOverlayRectsFromLayout(facet);
@@ -100941,7 +101758,7 @@ var TwPageStackOverlayLayer = ({
100941
101758
  );
100942
101759
  if (uiRects !== null) {
100943
101760
  incrementInvalidationCounter("overlay.page.ui_api.hit");
100944
- setRectsIfChanged(reconcilePaperRectsWithFlow(uiRects, pageCount));
101761
+ setRectsIfChanged(uiRects);
100945
101762
  return;
100946
101763
  }
100947
101764
  incrementInvalidationCounter("overlay.page.ui_api.fallthrough");
@@ -100956,7 +101773,7 @@ var TwPageStackOverlayLayer = ({
100956
101773
  );
100957
101774
  if (geometryRects !== null) {
100958
101775
  incrementInvalidationCounter("overlay.page.geometry.hit");
100959
- setRectsIfChanged(reconcilePaperRectsWithFlow(geometryRects, pageCount));
101776
+ setRectsIfChanged(geometryRects);
100960
101777
  return;
100961
101778
  }
100962
101779
  incrementInvalidationCounter("overlay.page.geometry.fallthrough");
@@ -101325,11 +102142,6 @@ function buildParagraphStyle(block) {
101325
102142
  style[cssKey] = `${width} ${bStyle} ${color}`;
101326
102143
  }
101327
102144
  }
101328
- if (block.pageBreakBefore) {
101329
- style.borderTop = "2px dashed rgba(0,0,0,0.1)";
101330
- style.paddingTop = "8px";
101331
- style.marginTop = "16px";
101332
- }
101333
102145
  const framePr = block.frameProperties;
101334
102146
  const hasPosition = typeof framePr?.xTwips === "number" || typeof framePr?.yTwips === "number" || typeof framePr?.xAlign === "string" || typeof framePr?.yAlign === "string";
101335
102147
  if (framePr && framePr.dropCap !== "drop" && framePr.dropCap !== "margin" && hasPosition) {
@@ -103141,7 +103953,7 @@ var TwPageStackChromeLayerInner = ({
103141
103953
  const [activeStoryPageIndex, setActiveStoryPageIndex] = import_react32.default.useState(null);
103142
103954
  const refreshRectsNow = import_react32.default.useCallback(() => {
103143
103955
  const pageCount = facet.getPageCount();
103144
- const reconcileRects = (baseRects) => reconcilePageStackRectsWithFlow({
103956
+ const reconcileDomRects = (baseRects) => reconcilePageStackRectsWithFlow({
103145
103957
  baseRects,
103146
103958
  pageCount,
103147
103959
  scrollRoot,
@@ -103149,7 +103961,7 @@ var TwPageStackChromeLayerInner = ({
103149
103961
  });
103150
103962
  const uiRects = resolveUiPageRects(pageCount);
103151
103963
  if (uiRects !== null) {
103152
- setRects(reconcileRects(uiRects));
103964
+ setRects(uiRects);
103153
103965
  return;
103154
103966
  }
103155
103967
  if (geometryFacet) {
@@ -103159,7 +103971,7 @@ var TwPageStackChromeLayerInner = ({
103159
103971
  visiblePageIndexRange
103160
103972
  );
103161
103973
  if (geometryRects !== null) {
103162
- setRects(reconcileRects(geometryRects));
103974
+ setRects(geometryRects);
103163
103975
  return;
103164
103976
  }
103165
103977
  setRects([]);
@@ -103187,7 +103999,7 @@ var TwPageStackChromeLayerInner = ({
103187
103999
  visiblePageIndexRange
103188
104000
  });
103189
104001
  setRects(
103190
- reconcileRects(domRects)
104002
+ reconcileDomRects(domRects)
103191
104003
  );
103192
104004
  } else {
103193
104005
  const widgets = measureWidgetsViaOffsetChain(scrollRoot, {
@@ -103202,7 +104014,7 @@ var TwPageStackChromeLayerInner = ({
103202
104014
  visiblePageIndexRange
103203
104015
  });
103204
104016
  setRects(
103205
- reconcileRects(domRects)
104017
+ reconcileDomRects(domRects)
103206
104018
  );
103207
104019
  }
103208
104020
  }, [facet, geometryFacet, resolveUiPageRects, scrollRoot, visiblePageIndexRange]);
@@ -110924,7 +111736,6 @@ var editorSchema = new import_prosemirror_model.Schema({
110924
111736
  }
110925
111737
  }
110926
111738
  const pageBreak = node.attrs.pageBreakBefore;
110927
- if (pageBreak) styles.push("border-top: 2px dashed rgba(0,0,0,0.1); padding-top: 8px; margin-top: 16px");
110928
111739
  const framePr = node.attrs.frameProperties;
110929
111740
  const hasPosition = typeof framePr?.xTwips === "number" || typeof framePr?.yTwips === "number" || typeof framePr?.xAlign === "string" || typeof framePr?.yAlign === "string";
110930
111741
  if (framePr && framePr.dropCap !== "drop" && framePr.dropCap !== "margin" && hasPosition) {
@@ -110988,15 +111799,7 @@ var editorSchema = new import_prosemirror_model.Schema({
110988
111799
  const numberingPicBulletSrc = node.attrs.numberingPicBulletSrc;
110989
111800
  const children = [];
110990
111801
  if (pageBreak) {
110991
- children.push([
110992
- "span",
110993
- {
110994
- class: "mb-2 inline-flex items-center gap-2 text-[10px] font-medium uppercase tracking-[var(--tracking-eyebrow)] text-tertiary",
110995
- contenteditable: "false",
110996
- "data-page-break-before": "true"
110997
- },
110998
- "Page break"
110999
- ]);
111802
+ attrs["data-page-break-before"] = "true";
111000
111803
  }
111001
111804
  if (numberingPrefix || numberingPicBulletSrc) {
111002
111805
  const hasResolvedMarkerWidth = typeof numberingMarkerWidth === "number" && numberingMarkerWidth > 0;
@@ -111321,7 +112124,6 @@ var editorSchema = new import_prosemirror_model.Schema({
111321
112124
  "section",
111322
112125
  {
111323
112126
  class: "my-0 border-0 bg-transparent p-0",
111324
- style: "min-height:var(--wre-page-frame-height-px,1056px);position:relative",
111325
112127
  "data-node-type": "sdt_block",
111326
112128
  "data-sdt-page-break": "true"
111327
112129
  },
@@ -111677,6 +112479,34 @@ var editorSchema = new import_prosemirror_model.Schema({
111677
112479
  ];
111678
112480
  }
111679
112481
  },
112482
+ textbox_inline: {
112483
+ inline: true,
112484
+ group: "inline",
112485
+ content: "text*",
112486
+ marks: "_",
112487
+ selectable: true,
112488
+ isolating: true,
112489
+ attrs: {
112490
+ label: { default: "Text box" },
112491
+ detail: { default: null },
112492
+ targetKey: { default: null },
112493
+ geometry: { default: null }
112494
+ },
112495
+ toDOM(node) {
112496
+ const title = node.attrs.detail ?? node.attrs.label;
112497
+ return [
112498
+ "span",
112499
+ {
112500
+ class: "inline-block min-w-[2ch] max-w-full align-middle mx-0.5 rounded-[2px] border border-border bg-surface px-1 py-0.5 text-primary",
112501
+ "data-node-type": "textbox_inline",
112502
+ "data-editable-target-key": node.attrs.targetKey ?? "",
112503
+ "data-shape-geometry": node.attrs.geometry ?? "",
112504
+ title
112505
+ },
112506
+ 0
112507
+ ];
112508
+ }
112509
+ },
111680
112510
  wordart_atom: {
111681
112511
  inline: true,
111682
112512
  group: "inline",
@@ -112055,16 +112885,16 @@ function buildPositionMap(surface) {
112055
112885
  const pmDocSize = walkBlocks2(surface.blocks, 1, entries, protectedInlineEntries, { rootLevel: true });
112056
112886
  const runtimeStorySize = surface.storySize;
112057
112887
  const runtimeToPm = (runtimePos) => {
112058
- const firstEditable = entries.find(isRuntimeRestorableEntry);
112888
+ const firstEditable = entries.find(isStoryRuntimeRestorableEntry);
112059
112889
  if (runtimePos <= 0) {
112060
112890
  return firstEditable?.pmStart ?? 1;
112061
112891
  }
112062
112892
  if (runtimePos >= runtimeStorySize) {
112063
- return lastRestorableEntry(entries)?.pmEnd ?? pmDocSize - 1;
112893
+ return lastStoryRestorableEntry(entries)?.pmEnd ?? pmDocSize - 1;
112064
112894
  }
112065
112895
  let previous = null;
112066
112896
  for (const entry of entries) {
112067
- if (!isRuntimeRestorableEntry(entry)) {
112897
+ if (!isStoryRuntimeRestorableEntry(entry)) {
112068
112898
  continue;
112069
112899
  }
112070
112900
  if (entry.runtimeStart === entry.runtimeEnd && runtimePos === entry.runtimeStart) {
@@ -112078,12 +112908,12 @@ function buildPositionMap(surface) {
112078
112908
  }
112079
112909
  previous = entry;
112080
112910
  }
112081
- return lastRestorableEntry(entries)?.pmEnd ?? 1;
112911
+ return lastStoryRestorableEntry(entries)?.pmEnd ?? 1;
112082
112912
  };
112083
112913
  return {
112084
112914
  runtimeToPm,
112085
112915
  runtimeToPmWithContext(input) {
112086
- const targetEntry = input.editableTarget ? findRestorableEntryForTarget(entries, input.editableTarget) : void 0;
112916
+ const targetEntry = input.editableTarget ? findRestorableEntryForTarget(entries, input.editableTarget, input.runtimePos) : void 0;
112087
112917
  if (targetEntry) {
112088
112918
  return pmForRuntimeInTargetEntry(targetEntry, input.runtimePos, protectedInlineEntries);
112089
112919
  }
@@ -112184,7 +113014,7 @@ function isEditablePmRange(entries, protectedInlineEntries, pmDocSize, runtimeSt
112184
113014
  if (entry.editable === false) return false;
112185
113015
  }
112186
113016
  for (const entry of protectedInlineEntries) {
112187
- if (pmRangeTouchesEntry(start, end, entry)) return false;
113017
+ if (entry.editable === false && pmRangeTouchesEntry(start, end, entry)) return false;
112188
113018
  }
112189
113019
  return true;
112190
113020
  }
@@ -112192,9 +113022,9 @@ function protectedInlineEntryAtPm(protectedInlineEntries, pmPos) {
112192
113022
  return protectedInlineEntries.find((entry) => pmPos > entry.pmStart && pmPos < entry.pmEnd);
112193
113023
  }
112194
113024
  function pmForRuntimeInTargetEntry(entry, runtimePos, protectedInlineEntries) {
112195
- const runtimeDelta = Math.max(
112196
- 0,
112197
- Math.min(runtimePos - entry.runtimeStart, entry.runtimeEnd - entry.runtimeStart)
113025
+ const runtimeDelta = Math.min(
113026
+ runtimePos - entry.runtimeStart,
113027
+ entry.runtimeEnd - entry.runtimeStart
112198
113028
  );
112199
113029
  let pmPos = entry.pmStart + runtimeDelta;
112200
113030
  for (const protectedEntry of protectedInlineEntries) {
@@ -112223,10 +113053,13 @@ function nearestRuntimeGapPm(runtimePos, previous, next) {
112223
113053
  function isRuntimeRestorableEntry(entry) {
112224
113054
  return entry.editable !== false && entry.restorable !== false;
112225
113055
  }
112226
- function lastRestorableEntry(entries) {
113056
+ function isStoryRuntimeRestorableEntry(entry) {
113057
+ return isRuntimeRestorableEntry(entry) && entry.runtimeSpace !== "target";
113058
+ }
113059
+ function lastStoryRestorableEntry(entries) {
112227
113060
  for (let index = entries.length - 1; index >= 0; index -= 1) {
112228
113061
  const entry = entries[index];
112229
- if (isRuntimeRestorableEntry(entry)) {
113062
+ if (isStoryRuntimeRestorableEntry(entry)) {
112230
113063
  return entry;
112231
113064
  }
112232
113065
  }
@@ -112257,27 +113090,90 @@ function walkBlocks2(blocks, pmCursor, entries, protectedInlineEntries, context)
112257
113090
  const runtimeLength = block.to - block.from;
112258
113091
  const tableCell = context.tableCell ?? tableCellFromEditableTarget(block.editableTarget);
112259
113092
  const editable = context.editable !== false;
112260
- entries.push({
112261
- runtimeStart: block.from,
112262
- pmStart: pmContentStart,
112263
- runtimeEnd: block.to,
112264
- pmEnd: pmContentStart + runtimeLength,
112265
- editable,
112266
- insideTable: context.insideTable === true || context.tableCell !== void 0,
112267
- editableTarget: block.editableTarget,
112268
- textTarget: editable && tableCell ? {
112269
- kind: "table-paragraph",
112270
- tableBlockIndex: tableCell.tableBlockIndex,
112271
- rowIndex: tableCell.rowIndex,
112272
- cellIndex: tableCell.cellIndex,
112273
- childIndex: blockIndex,
112274
- paragraphStart: block.from,
112275
- paragraphEnd: block.to,
112276
- ...block.editableTarget ? { blockPath: block.editableTarget.blockPath } : {}
112277
- } : void 0
112278
- });
112279
- addProtectedInlineEntries(block, pmContentStart, protectedInlineEntries);
112280
- nextPmCursor += runtimeLength + 2;
113093
+ const textTarget = editable && tableCell ? {
113094
+ kind: "table-paragraph",
113095
+ tableBlockIndex: tableCell.tableBlockIndex,
113096
+ rowIndex: tableCell.rowIndex,
113097
+ cellIndex: tableCell.cellIndex,
113098
+ childIndex: blockIndex,
113099
+ paragraphStart: block.from,
113100
+ paragraphEnd: block.to,
113101
+ ...block.editableTarget ? { blockPath: block.editableTarget.blockPath } : {}
113102
+ } : void 0;
113103
+ const insideTable = context.insideTable === true || context.tableCell !== void 0;
113104
+ let pmSegmentCursor = pmContentStart;
113105
+ let emittedStoryEntry = false;
113106
+ if (block.editableTarget !== void 0) {
113107
+ entries.push({
113108
+ runtimeStart: block.from,
113109
+ pmStart: pmContentStart,
113110
+ runtimeEnd: block.from,
113111
+ pmEnd: pmContentStart,
113112
+ editable,
113113
+ insideTable,
113114
+ runtimeSpace: "target",
113115
+ editableTarget: block.editableTarget,
113116
+ textTarget
113117
+ });
113118
+ }
113119
+ for (const segment of block.segments) {
113120
+ const pmSize = pmSizeForSegment(segment);
113121
+ const textBoxParagraph = firstEditableTextBoxParagraph(segment);
113122
+ if (textBoxParagraph?.editableTarget) {
113123
+ const textLength = Math.max(0, textBoxParagraph.textLength);
113124
+ const textStart = pmSegmentCursor + 1;
113125
+ entries.push({
113126
+ runtimeStart: 0,
113127
+ pmStart: textStart,
113128
+ runtimeEnd: textLength,
113129
+ pmEnd: textStart + textLength,
113130
+ editable: true,
113131
+ restorable: true,
113132
+ runtimeSpace: "target",
113133
+ editableTarget: textBoxParagraph.editableTarget
113134
+ });
113135
+ } else if (isStoryTextSegment(segment)) {
113136
+ entries.push({
113137
+ runtimeStart: segment.from,
113138
+ pmStart: pmSegmentCursor,
113139
+ runtimeEnd: segment.to,
113140
+ pmEnd: pmSegmentCursor + Math.max(0, segment.to - segment.from),
113141
+ editable,
113142
+ insideTable,
113143
+ editableTarget: block.editableTarget,
113144
+ textTarget
113145
+ });
113146
+ emittedStoryEntry = true;
113147
+ }
113148
+ addProtectedInlineEntryForSegment(segment, pmSegmentCursor, protectedInlineEntries);
113149
+ pmSegmentCursor += pmSize;
113150
+ }
113151
+ if (block.editableTarget !== void 0 && block.to !== block.from) {
113152
+ entries.push({
113153
+ runtimeStart: block.to,
113154
+ pmStart: pmSegmentCursor,
113155
+ runtimeEnd: block.to,
113156
+ pmEnd: pmSegmentCursor,
113157
+ editable,
113158
+ insideTable,
113159
+ runtimeSpace: "target",
113160
+ editableTarget: block.editableTarget,
113161
+ textTarget
113162
+ });
113163
+ }
113164
+ if (!emittedStoryEntry || runtimeLength === 0) {
113165
+ entries.push({
113166
+ runtimeStart: block.from,
113167
+ pmStart: pmContentStart,
113168
+ runtimeEnd: block.to,
113169
+ pmEnd: pmContentStart,
113170
+ editable,
113171
+ insideTable,
113172
+ editableTarget: block.editableTarget,
113173
+ textTarget
113174
+ });
113175
+ }
113176
+ nextPmCursor += pmSegmentCursor - pmContentStart + 2;
112281
113177
  break;
112282
113178
  }
112283
113179
  case "opaque_block": {
@@ -112334,21 +113230,39 @@ function walkBlocks2(blocks, pmCursor, entries, protectedInlineEntries, context)
112334
113230
  }
112335
113231
  return nextPmCursor;
112336
113232
  }
112337
- function addProtectedInlineEntries(block, pmContentStart, protectedInlineEntries) {
112338
- for (const segment of block.segments) {
112339
- if (segment.kind !== "opaque_inline" && segment.kind !== "shape") {
112340
- continue;
112341
- }
112342
- const runtimeLength = Math.max(1, segment.to - segment.from);
112343
- const pmStart = pmContentStart + Math.max(0, segment.from - block.from);
112344
- protectedInlineEntries.push({
112345
- runtimeStart: segment.from,
112346
- pmStart,
112347
- runtimeEnd: segment.to,
112348
- pmEnd: pmStart + runtimeLength,
112349
- editable: false
112350
- });
113233
+ function pmSizeForSegment(segment) {
113234
+ const textBoxParagraph = firstEditableTextBoxParagraph(segment);
113235
+ if (textBoxParagraph) {
113236
+ return Math.max(0, textBoxParagraph.textLength) + 2;
112351
113237
  }
113238
+ return Math.max(1, segment.to - segment.from);
113239
+ }
113240
+ function isStoryTextSegment(segment) {
113241
+ return segment.kind === "text" || segment.kind === "tab" || segment.kind === "hard_break";
113242
+ }
113243
+ function firstEditableTextBoxParagraph(segment) {
113244
+ if (segment.kind !== "shape" || segment.isTextBox !== true || segment.txbxBody?.status !== "modeled") {
113245
+ return null;
113246
+ }
113247
+ return segment.txbxBody.paragraphs.find(
113248
+ (paragraph) => paragraph.editableTarget?.editability === "editable" && paragraph.editableTarget.posture.blockers.length === 0
113249
+ ) ?? null;
113250
+ }
113251
+ function addProtectedInlineEntryForSegment(segment, pmStart, protectedInlineEntries) {
113252
+ if (segment.kind !== "opaque_inline" && segment.kind !== "shape") {
113253
+ return;
113254
+ }
113255
+ if (firstEditableTextBoxParagraph(segment)) {
113256
+ return;
113257
+ }
113258
+ const runtimeLength = Math.max(1, segment.to - segment.from);
113259
+ protectedInlineEntries.push({
113260
+ runtimeStart: segment.from,
113261
+ pmStart,
113262
+ runtimeEnd: segment.to,
113263
+ pmEnd: pmStart + runtimeLength,
113264
+ editable: false
113265
+ });
112352
113266
  }
112353
113267
  function hasEditableTargetInBlocks(blocks) {
112354
113268
  for (const block of blocks) {
@@ -112379,21 +113293,46 @@ function findInertEntryForTarget(entries, target) {
112379
113293
  return entry.editable === false && candidate?.targetKey === target.targetKey && candidate.storyKey === target.storyKey && candidate.blockPath === target.blockPath && candidate.leafPath === target.leafPath && candidate.kind === target.kind;
112380
113294
  });
112381
113295
  }
112382
- function findRestorableEntryForTarget(entries, target) {
113296
+ function findRestorableEntryForTarget(entries, target, runtimePos) {
112383
113297
  if ("editableOwner" in target && target.editableOwner && isSyntheticLayoutContinuationTarget2(target)) {
112384
- return findRestorableEntryForOwner(entries, target.editableOwner);
113298
+ return findRestorableEntryForOwner(entries, target.editableOwner, runtimePos);
112385
113299
  }
112386
- return entries.find((entry) => {
113300
+ return selectRestorableEntryForRuntime(entries, runtimePos, (entry) => {
112387
113301
  const candidate = entry.editableTarget;
112388
113302
  return isRuntimeRestorableEntry(entry) && candidate?.targetKey === target.targetKey && candidate.storyKey === target.storyKey && candidate.blockPath === target.blockPath && candidate.leafPath === target.leafPath && candidate.kind === target.kind;
112389
113303
  });
112390
113304
  }
112391
- function findRestorableEntryForOwner(entries, owner) {
112392
- return entries.find((entry) => {
113305
+ function findRestorableEntryForOwner(entries, owner, runtimePos) {
113306
+ return selectRestorableEntryForRuntime(entries, runtimePos, (entry) => {
112393
113307
  const candidate = entry.editableTarget;
112394
113308
  return isRuntimeRestorableEntry(entry) && candidate?.targetKey === owner.targetKey && candidate.storyKey === owner.storyKey && candidate.blockPath === owner.blockPath && candidate.leafPath === owner.leafPath && candidate.kind === owner.kind && candidate.commandFamily === owner.commandFamily;
112395
113309
  });
112396
113310
  }
113311
+ function selectRestorableEntryForRuntime(entries, runtimePos, predicate) {
113312
+ const candidates = entries.filter(predicate);
113313
+ if (candidates.length === 0 || runtimePos === void 0) {
113314
+ return candidates[0];
113315
+ }
113316
+ const containing = candidates.filter(
113317
+ (entry) => runtimePos >= entry.runtimeStart && runtimePos <= entry.runtimeEnd
113318
+ );
113319
+ if (containing.length > 0) {
113320
+ return containing.sort(
113321
+ (left, right) => left.runtimeEnd - left.runtimeStart - (right.runtimeEnd - right.runtimeStart)
113322
+ )[0];
113323
+ }
113324
+ return candidates.sort((left, right) => {
113325
+ const leftDistance = Math.min(
113326
+ Math.abs(runtimePos - left.runtimeStart),
113327
+ Math.abs(runtimePos - left.runtimeEnd)
113328
+ );
113329
+ const rightDistance = Math.min(
113330
+ Math.abs(runtimePos - right.runtimeStart),
113331
+ Math.abs(runtimePos - right.runtimeEnd)
113332
+ );
113333
+ return leftDistance - rightDistance;
113334
+ })[0];
113335
+ }
112397
113336
  function isSyntheticLayoutContinuationTarget2(target) {
112398
113337
  return target.commandFamily === "text-leaf" && target.table?.operationScope === "text" && target.table.verticalMerge === "continue" && target.posture.blockers.includes("synthetic-layout-cell");
112399
113338
  }
@@ -113078,9 +114017,9 @@ function createChartFamily(_runtime) {
113078
114017
  }
113079
114018
 
113080
114019
  // src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts
113081
- var CANONICAL_BLOCK_REFS_SYMBOL2 = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
114020
+ var CANONICAL_BLOCK_REFS_SYMBOL3 = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
113082
114021
  function getCanonicalBlockRefs2(snapshot) {
113083
- const refs = snapshot[CANONICAL_BLOCK_REFS_SYMBOL2];
114022
+ const refs = snapshot[CANONICAL_BLOCK_REFS_SYMBOL3];
113084
114023
  return refs ?? null;
113085
114024
  }
113086
114025
  var pmNodeCache = /* @__PURE__ */ new WeakMap();
@@ -113515,6 +114454,24 @@ function buildInlineContent(segment, mediaPreviews, showUnsupportedObjectPreview
113515
114454
  case "opaque_inline":
113516
114455
  return [buildOpaqueInlineOrComplexAtom(segment, mediaPreviews, showUnsupportedObjectPreviews)];
113517
114456
  case "shape": {
114457
+ const textBoxParagraph = firstEditableTextBoxParagraph2(segment);
114458
+ if (textBoxParagraph) {
114459
+ const content = textBoxParagraph.runs.flatMap(
114460
+ (run) => textBoxRunToPMNodes(run)
114461
+ );
114462
+ const fallbackContent = content.length > 0 && textBoxParagraph.text.length > 0 ? content : textBoxParagraph.text.length > 0 ? [editorSchema.text(textBoxParagraph.text)] : [];
114463
+ return [
114464
+ editorSchema.nodes.textbox_inline.create(
114465
+ {
114466
+ label: segment.label,
114467
+ detail: segment.detail,
114468
+ targetKey: textBoxParagraph.editableTarget?.targetKey ?? null,
114469
+ geometry: segment.geometry ?? null
114470
+ },
114471
+ fallbackContent
114472
+ )
114473
+ ];
114474
+ }
113518
114475
  const renderInPageOverlay = renderAbsoluteFloatingObjectsInPageOverlay && shouldRenderAbsoluteFloatingImageInPageOverlay(segment.anchor);
113519
114476
  return [
113520
114477
  editorSchema.nodes.shape_atom.create({
@@ -113555,6 +114512,28 @@ function buildInlineContent(segment, mediaPreviews, showUnsupportedObjectPreview
113555
114512
  return [];
113556
114513
  }
113557
114514
  }
114515
+ function firstEditableTextBoxParagraph2(segment) {
114516
+ if (segment.isTextBox !== true || segment.txbxBody?.status !== "modeled") {
114517
+ return null;
114518
+ }
114519
+ return segment.txbxBody.paragraphs.find(
114520
+ (paragraph) => paragraph.editableTarget?.editability === "editable" && paragraph.editableTarget.posture.blockers.length === 0
114521
+ ) ?? null;
114522
+ }
114523
+ function textBoxRunToPMNodes(run) {
114524
+ if (run.kind !== "text" || !run.text) return [];
114525
+ const segment = {
114526
+ segmentId: `textbox-run-${run.inlineIndex}`,
114527
+ kind: "text",
114528
+ from: 0,
114529
+ to: run.textLength ?? Array.from(run.text).length,
114530
+ text: run.text,
114531
+ ...run.marks && run.marks.length > 0 ? { marks: run.marks } : {},
114532
+ ...run.markAttrs ? { markAttrs: run.markAttrs } : {}
114533
+ };
114534
+ const marks = applyEffectiveMarks(segment, editorSchema);
114535
+ return [editorSchema.text(run.text, marks.length > 0 ? marks : void 0)];
114536
+ }
113558
114537
  function buildTable(block, mediaPreviews, showUnsupportedObjectPreviews, renderAbsoluteFloatingObjectsInPageOverlay) {
113559
114538
  const rows = [];
113560
114539
  for (const row2 of block.rows) {
@@ -115130,13 +116109,20 @@ function createPredictedPositionMap(canonical, pendingOps) {
115130
116109
  },
115131
116110
  pmToRuntimeWithContext(pmPos) {
115132
116111
  let adjusted = pmPos;
115133
- for (const op of pendingOps) {
115134
- const opPmStart = canonical.runtimeToPm(op.fromRuntime);
116112
+ for (let index = 0; index < pendingOps.length; index += 1) {
116113
+ const op = pendingOps[index];
116114
+ const opPmStart = canonical.runtimeToPm(
116115
+ canonicalRuntimeForPredictedOp(pendingOps, index)
116116
+ );
115135
116117
  if (adjusted > opPmStart) {
115136
116118
  adjusted -= opSizeDelta(op);
115137
116119
  }
115138
116120
  }
115139
- return canonical.pmToRuntimeWithContext(Math.max(1, adjusted));
116121
+ const context = canonical.pmToRuntimeWithContext(Math.max(1, adjusted));
116122
+ return {
116123
+ ...context,
116124
+ runtimePos: applyPendingOpsToCanonicalRuntime(context.runtimePos, pendingOps)
116125
+ };
115140
116126
  },
115141
116127
  ...canonical.isPmRangeEditable ? {
115142
116128
  isPmRangeEditable(fromPm, toPm) {
@@ -115156,6 +116142,25 @@ function createPredictedPositionMap(canonical, pendingOps) {
115156
116142
  }
115157
116143
  };
115158
116144
  }
116145
+ function canonicalRuntimeForPredictedOp(pendingOps, opIndex) {
116146
+ let runtimePos = pendingOps[opIndex]?.fromRuntime ?? 0;
116147
+ for (let index = 0; index < opIndex; index += 1) {
116148
+ const op = pendingOps[index];
116149
+ if (op.fromRuntime <= runtimePos) {
116150
+ runtimePos -= opSizeDelta(op);
116151
+ }
116152
+ }
116153
+ return Math.max(0, runtimePos);
116154
+ }
116155
+ function applyPendingOpsToCanonicalRuntime(runtimePos, pendingOps) {
116156
+ let transformed = runtimePos;
116157
+ for (const op of pendingOps) {
116158
+ if (op.fromRuntime <= transformed) {
116159
+ transformed += opSizeDelta(op);
116160
+ }
116161
+ }
116162
+ return Math.max(0, transformed);
116163
+ }
115159
116164
  function totalDelta(pendingOps) {
115160
116165
  let delta = 0;
115161
116166
  for (const op of pendingOps) {
@@ -123387,6 +124392,8 @@ function toV3PageLocalStoryObject(object) {
123387
124392
  heightTwips: object.extentTwips.heightTwips
123388
124393
  }
123389
124394
  } : {},
124395
+ ...object.anchorRectTwips ? { anchorRectTwips: cloneRect2(object.anchorRectTwips) } : {},
124396
+ ...object.textBoxBody ? { textBoxBody: object.textBoxBody } : {},
123390
124397
  ...object.relationshipIds ? { relationshipIds: [...object.relationshipIds] } : {},
123391
124398
  ...object.mediaIds ? { mediaIds: [...object.mediaIds] } : {},
123392
124399
  preserveOnly: object.preserveOnly,