@beyondwork/docx-react-component 1.0.128 → 1.0.129

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 (98) hide show
  1. package/dist/api/public-types.cjs +215 -61
  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 +2 -2
  5. package/dist/api/v3.cjs +896 -71
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +8 -8
  9. package/dist/{canonical-document-CXCFCbAz.d.cts → canonical-document-BMtONpgf.d.cts} +6 -0
  10. package/dist/{canonical-document-CXCFCbAz.d.ts → canonical-document-BMtONpgf.d.ts} +6 -0
  11. package/dist/{chunk-KV435YXO.js → chunk-5DSHUYSY.js} +1 -1
  12. package/dist/{chunk-TQDQU2E3.js → chunk-63FYIGCT.js} +2 -2
  13. package/dist/{chunk-ZDOAUP3V.js → chunk-DDN2AIGE.js} +1 -1
  14. package/dist/{chunk-6F5QW44A.js → chunk-DJU2W4E4.js} +2 -2
  15. package/dist/{chunk-4EENH4FG.js → chunk-EZKJXIPH.js} +1 -1
  16. package/dist/{chunk-CXSYRB37.js → chunk-HUIHBBAQ.js} +166 -49
  17. package/dist/{chunk-ESJ2MES5.js → chunk-JJGVE5J7.js} +1 -1
  18. package/dist/{chunk-LZVBNDGU.js → chunk-LJH64PV3.js} +3 -3
  19. package/dist/{chunk-MWSBGJQO.js → chunk-OTQIW2TC.js} +2 -2
  20. package/dist/{chunk-2QL5DAKF.js → chunk-PGKUJZXV.js} +3 -3
  21. package/dist/{chunk-6EROGFUF.js → chunk-PRAZBHNF.js} +441 -128
  22. package/dist/{chunk-4YJVRIUB.js → chunk-Q3QYGKFE.js} +51 -8
  23. package/dist/{chunk-YHZHPXDB.js → chunk-RMRTQGW3.js} +50 -13
  24. package/dist/{chunk-XRACP43Q.js → chunk-SKPTKQHF.js} +351 -13
  25. package/dist/{chunk-D5HYZQTG.js → chunk-VNLDQJ47.js} +1 -1
  26. package/dist/{chunk-BYSRJ4FE.js → chunk-W34X3KBR.js} +1 -1
  27. package/dist/{chunk-V6XVZFFH.js → chunk-XMHSGPLN.js} +2 -2
  28. package/dist/{chunk-LCYYR57Q.js → chunk-XQCAMKIQ.js} +421 -6
  29. package/dist/{chunk-YD2JE54B.js → chunk-YZDZ4FGR.js} +1 -1
  30. package/dist/compare.d.cts +1 -1
  31. package/dist/compare.d.ts +1 -1
  32. package/dist/core/commands/formatting-commands.d.cts +2 -2
  33. package/dist/core/commands/formatting-commands.d.ts +2 -2
  34. package/dist/core/commands/image-commands.cjs +166 -49
  35. package/dist/core/commands/image-commands.d.cts +2 -2
  36. package/dist/core/commands/image-commands.d.ts +2 -2
  37. package/dist/core/commands/image-commands.js +4 -4
  38. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  39. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  40. package/dist/core/commands/style-commands.d.cts +2 -2
  41. package/dist/core/commands/style-commands.d.ts +2 -2
  42. package/dist/core/commands/table-structure-commands.cjs +166 -49
  43. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  44. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  45. package/dist/core/commands/table-structure-commands.js +3 -3
  46. package/dist/core/commands/text-commands.cjs +166 -49
  47. package/dist/core/commands/text-commands.d.cts +2 -2
  48. package/dist/core/commands/text-commands.d.ts +2 -2
  49. package/dist/core/commands/text-commands.js +4 -4
  50. package/dist/core/selection/mapping.d.cts +2 -2
  51. package/dist/core/selection/mapping.d.ts +2 -2
  52. package/dist/core/state/editor-state.d.cts +2 -2
  53. package/dist/core/state/editor-state.d.ts +2 -2
  54. package/dist/index.cjs +1486 -211
  55. package/dist/index.d.cts +5 -5
  56. package/dist/index.d.ts +5 -5
  57. package/dist/index.js +46 -22
  58. package/dist/io/docx-session.cjs +51 -8
  59. package/dist/io/docx-session.d.cts +4 -4
  60. package/dist/io/docx-session.d.ts +4 -4
  61. package/dist/io/docx-session.js +3 -3
  62. package/dist/legal.d.cts +1 -1
  63. package/dist/legal.d.ts +1 -1
  64. package/dist/legal.js +2 -2
  65. package/dist/{loader-19ct2Be0.d.ts → loader-4qsw4eIU.d.ts} +3 -3
  66. package/dist/{loader-CoXQ2wGd.d.cts → loader-B8TKhmQi.d.cts} +3 -3
  67. package/dist/{public-types-B-CskQen.d.cts → public-types-B5CRoR6f.d.cts} +128 -1
  68. package/dist/{public-types-7KZsNGE2.d.ts → public-types-p9b8rfy8.d.ts} +128 -1
  69. package/dist/public-types.cjs +215 -61
  70. package/dist/public-types.d.cts +2 -2
  71. package/dist/public-types.d.ts +2 -2
  72. package/dist/public-types.js +2 -2
  73. package/dist/runtime/collab.d.cts +3 -3
  74. package/dist/runtime/collab.d.ts +3 -3
  75. package/dist/runtime/document-runtime.cjs +980 -185
  76. package/dist/runtime/document-runtime.d.cts +2 -2
  77. package/dist/runtime/document-runtime.d.ts +2 -2
  78. package/dist/runtime/document-runtime.js +13 -13
  79. package/dist/{session-B5015J4v.d.cts → session-BnGIjaex.d.cts} +3 -3
  80. package/dist/{session-C2i8-d6v.d.ts → session-vEYKf-w3.d.ts} +3 -3
  81. package/dist/session.cjs +51 -8
  82. package/dist/session.d.cts +5 -5
  83. package/dist/session.d.ts +5 -5
  84. package/dist/session.js +4 -4
  85. package/dist/tailwind.cjs +215 -61
  86. package/dist/tailwind.d.cts +2 -2
  87. package/dist/tailwind.d.ts +2 -2
  88. package/dist/tailwind.js +5 -5
  89. package/dist/{types-DNhN0WeN.d.cts → types-BLuvZ6cQ.d.cts} +2 -2
  90. package/dist/{types-yvrQuGX9.d.ts → types-Dutlyj0T.d.ts} +2 -2
  91. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  92. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  93. package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
  94. package/dist/ui-tailwind.cjs +215 -61
  95. package/dist/ui-tailwind.d.cts +3 -3
  96. package/dist/ui-tailwind.d.ts +3 -3
  97. package/dist/ui-tailwind.js +5 -5
  98. package/package.json +1 -1
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-M6XR534O.js";
12
12
  import {
13
13
  buildBookmarkNameMap
14
- } from "./chunk-YD2JE54B.js";
14
+ } from "./chunk-YZDZ4FGR.js";
15
15
  import {
16
16
  deleteSelectionOrBackward,
17
17
  deleteSelectionOrForward,
@@ -22,7 +22,7 @@ import {
22
22
  insertText,
23
23
  outdentParagraphAtSelection,
24
24
  splitParagraph
25
- } from "./chunk-LZVBNDGU.js";
25
+ } from "./chunk-LJH64PV3.js";
26
26
  import {
27
27
  applyFormattingOperationToDocument,
28
28
  applyTextMarkOperationToDocumentRange,
@@ -32,18 +32,18 @@ import {
32
32
  insertImage,
33
33
  repositionFloatingImage,
34
34
  resizeImage
35
- } from "./chunk-6F5QW44A.js";
35
+ } from "./chunk-DJU2W4E4.js";
36
36
  import {
37
37
  applyTextTransaction
38
- } from "./chunk-KV435YXO.js";
38
+ } from "./chunk-5DSHUYSY.js";
39
39
  import {
40
40
  applyTableStructureOperationForEditableTarget,
41
41
  removeCellFromRow,
42
42
  removeTableRowPure
43
- } from "./chunk-ZDOAUP3V.js";
43
+ } from "./chunk-DDN2AIGE.js";
44
44
  import {
45
45
  resolveParagraphScope
46
- } from "./chunk-BYSRJ4FE.js";
46
+ } from "./chunk-W34X3KBR.js";
47
47
  import {
48
48
  buildGeometryDebugEntry,
49
49
  collectLineBoxesForRegion,
@@ -51,30 +51,35 @@ import {
51
51
  createRenderKernel,
52
52
  incrementInvalidationCounter,
53
53
  recordPerfSample
54
- } from "./chunk-MWSBGJQO.js";
54
+ } from "./chunk-OTQIW2TC.js";
55
55
  import {
56
56
  AI_ACTION_POLICIES,
57
+ allocateNumberingInstance,
57
58
  buildFormattingDebugEntry,
59
+ cloneNumberingCatalog,
58
60
  collectScopeLocations,
59
61
  createDocumentOutlineSnapshot,
60
62
  createDocumentSectionSnapshots,
61
63
  createScopeCompilerService,
62
64
  createSectionLocations,
63
65
  createTocSnapshot,
66
+ ensureDefaultListInstance,
64
67
  findAllScopesAt,
65
68
  findBookmarkNameForOffset,
66
69
  findDocumentSectionSnapshot,
67
70
  findScopesIntersecting,
68
71
  findTextMatches,
69
72
  findTextWithStyleMatches,
73
+ getListKind,
70
74
  rebuildFieldRegistry,
71
75
  resolveEditableCommandTarget,
72
76
  resolveEditableTableStructureTarget,
73
77
  resolveEditableTextTarget,
74
78
  resolveHeadingPath,
75
79
  resolveScope,
76
- serializeFragmentToWordML
77
- } from "./chunk-XRACP43Q.js";
80
+ serializeFragmentToWordML,
81
+ setStartOverride
82
+ } from "./chunk-SKPTKQHF.js";
78
83
  import {
79
84
  ISSUE_METADATA_ID,
80
85
  LAYOUT_ENGINE_VERSION,
@@ -109,7 +114,7 @@ import {
109
114
  setWorkspaceMode,
110
115
  setZoomLevel,
111
116
  snapCommentAnchorAwayFromTable
112
- } from "./chunk-YHZHPXDB.js";
117
+ } from "./chunk-RMRTQGW3.js";
113
118
  import {
114
119
  countLogicalPositions,
115
120
  createPlainText,
@@ -128,7 +133,7 @@ import {
128
133
  replaceStoryBlocks,
129
134
  resolvePageFieldDisplayText,
130
135
  storyTargetKey
131
- } from "./chunk-CXSYRB37.js";
136
+ } from "./chunk-HUIHBBAQ.js";
132
137
  import {
133
138
  createCommentSidebarProjection,
134
139
  createCommentStoreFromRuntimeComments
@@ -152,12 +157,12 @@ import {
152
157
  persistedSnapshotFromEditorSessionState,
153
158
  remapRevisionStore,
154
159
  setRevisionStatus
155
- } from "./chunk-ESJ2MES5.js";
160
+ } from "./chunk-JJGVE5J7.js";
156
161
  import {
157
162
  isSupportedFieldFamily,
158
163
  parseTocLevelRange,
159
164
  resolveRefFieldText
160
- } from "./chunk-4YJVRIUB.js";
165
+ } from "./chunk-Q3QYGKFE.js";
161
166
  import {
162
167
  collectEditableTargetRefs,
163
168
  collectEditableTargetRefsForStoryBlockRanges,
@@ -1282,7 +1287,7 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1, option
1282
1287
  affectedParagraphIndexes: []
1283
1288
  };
1284
1289
  }
1285
- const catalog = ensureNumberingCatalog(working.numbering);
1290
+ const catalog = cloneNumberingCatalog(working.numbering);
1286
1291
  const existingInstance = catalog.instances[target.numbering.numberingInstanceId];
1287
1292
  if (!existingInstance) {
1288
1293
  return {
@@ -1290,15 +1295,12 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1, option
1290
1295
  affectedParagraphIndexes: []
1291
1296
  };
1292
1297
  }
1293
- const numberingInstanceId = createNumberingInstanceId(catalog);
1294
- catalog.instances[numberingInstanceId] = {
1295
- numberingInstanceId,
1296
- abstractNumberingId: existingInstance.abstractNumberingId,
1297
- overrides: mergeOverride(existingInstance.overrides, {
1298
- level: target.numbering.level,
1299
- startAt
1300
- })
1301
- };
1298
+ const numberingInstanceId = allocateNumberingInstance(
1299
+ catalog,
1300
+ existingInstance.abstractNumberingId,
1301
+ existingInstance.overrides
1302
+ );
1303
+ setStartOverride(catalog, numberingInstanceId, target.numbering.level, startAt);
1302
1304
  const affectedParagraphIndexes = [];
1303
1305
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
1304
1306
  const paragraph = paragraphs[index];
@@ -1352,7 +1354,7 @@ function continueNumbering(document, paragraphIndex, context, options = {}) {
1352
1354
  affectedParagraphIndexes: []
1353
1355
  };
1354
1356
  }
1355
- const catalog = ensureNumberingCatalog(working.numbering);
1357
+ const catalog = cloneNumberingCatalog(working.numbering);
1356
1358
  const currentInstanceId = target.numbering.numberingInstanceId;
1357
1359
  const currentKind = getListKind(catalog, currentInstanceId);
1358
1360
  if (!currentKind) {
@@ -1419,7 +1421,7 @@ function toggleListKind(document, paragraphIndexes, kind, context, options) {
1419
1421
  affectedParagraphIndexes: []
1420
1422
  };
1421
1423
  }
1422
- const catalog = ensureNumberingCatalog(working.numbering);
1424
+ const catalog = cloneNumberingCatalog(working.numbering);
1423
1425
  const allAlreadyKind = normalizedIndexes.every((index) => {
1424
1426
  const paragraph = paragraphs[index];
1425
1427
  return paragraph.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
@@ -1434,7 +1436,7 @@ function toggleListKind(document, paragraphIndexes, kind, context, options) {
1434
1436
  affectedParagraphIndexes: normalizedIndexes
1435
1437
  };
1436
1438
  }
1437
- const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultInstance(catalog, kind);
1439
+ const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultListInstance(catalog, kind);
1438
1440
  for (const index of normalizedIndexes) {
1439
1441
  const paragraph = paragraphs[index];
1440
1442
  paragraph.numbering = {
@@ -1599,23 +1601,6 @@ function sortJson(value) {
1599
1601
  }
1600
1602
  return value;
1601
1603
  }
1602
- function ensureDefaultInstance(catalog, kind) {
1603
- const existing = Object.values(catalog.instances).find(
1604
- (instance) => getListKind(catalog, instance.numberingInstanceId) === kind
1605
- );
1606
- if (existing) {
1607
- return existing.numberingInstanceId;
1608
- }
1609
- const abstractNumberingId = createAbstractNumberingId(catalog);
1610
- catalog.abstractDefinitions[abstractNumberingId] = kind === "bulleted" ? createDefaultBulletedDefinition(abstractNumberingId) : createDefaultNumberedDefinition(abstractNumberingId);
1611
- const numberingInstanceId = createNumberingInstanceId(catalog);
1612
- catalog.instances[numberingInstanceId] = {
1613
- numberingInstanceId,
1614
- abstractNumberingId,
1615
- overrides: []
1616
- };
1617
- return numberingInstanceId;
1618
- }
1619
1604
  function findAdjacentCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
1620
1605
  const previous = paragraphs[fromIndex - 1];
1621
1606
  if (previous?.numbering) {
@@ -1638,69 +1623,6 @@ function findPreviousCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
1638
1623
  }
1639
1624
  return void 0;
1640
1625
  }
1641
- function getListKind(catalog, numberingInstanceId) {
1642
- const instance = catalog.instances[numberingInstanceId];
1643
- const definition = instance ? catalog.abstractDefinitions[instance.abstractNumberingId] : void 0;
1644
- const levelZero = definition?.levels.find((level) => level.level === 0);
1645
- if (!levelZero) {
1646
- return void 0;
1647
- }
1648
- return levelZero.format === "bullet" ? "bulleted" : "numbered";
1649
- }
1650
- function mergeOverride(overrides, nextOverride) {
1651
- const filtered = overrides.filter((override) => override.level !== nextOverride.level);
1652
- filtered.push(nextOverride);
1653
- return filtered.sort((left, right) => left.level - right.level);
1654
- }
1655
- function createDefaultNumberedDefinition(abstractNumberingId) {
1656
- return {
1657
- abstractNumberingId,
1658
- levels: [
1659
- { level: 0, format: "decimal", text: "%1." },
1660
- { level: 1, format: "decimal", text: "%1.%2." },
1661
- { level: 2, format: "lowerLetter", text: "(%3)" },
1662
- { level: 3, format: "lowerRoman", text: "(%4)" },
1663
- { level: 4, format: "decimal", text: "%5." },
1664
- { level: 5, format: "lowerLetter", text: "(%6)" },
1665
- { level: 6, format: "lowerRoman", text: "(%7)" },
1666
- { level: 7, format: "decimal", text: "%8." },
1667
- { level: 8, format: "lowerLetter", text: "(%9)" }
1668
- ]
1669
- };
1670
- }
1671
- function createDefaultBulletedDefinition(abstractNumberingId) {
1672
- return {
1673
- abstractNumberingId,
1674
- levels: [
1675
- { level: 0, format: "bullet", text: "\u2022" },
1676
- { level: 1, format: "bullet", text: "o" },
1677
- { level: 2, format: "bullet", text: "\u25A0" },
1678
- { level: 3, format: "bullet", text: "\u2022" },
1679
- { level: 4, format: "bullet", text: "o" },
1680
- { level: 5, format: "bullet", text: "\u25A0" },
1681
- { level: 6, format: "bullet", text: "\u2022" },
1682
- { level: 7, format: "bullet", text: "o" },
1683
- { level: 8, format: "bullet", text: "\u25A0" }
1684
- ]
1685
- };
1686
- }
1687
- function createAbstractNumberingId(catalog) {
1688
- let index = 1;
1689
- while (catalog.abstractDefinitions[`abstract-num:generated-${index}`]) {
1690
- index += 1;
1691
- }
1692
- return `abstract-num:generated-${index}`;
1693
- }
1694
- function createNumberingInstanceId(catalog) {
1695
- let index = 1;
1696
- while (catalog.instances[`num:generated-${index}`]) {
1697
- index += 1;
1698
- }
1699
- return `num:generated-${index}`;
1700
- }
1701
- function ensureNumberingCatalog(value) {
1702
- return structuredClone(value);
1703
- }
1704
1626
  function cloneEnvelope(document, timestamp) {
1705
1627
  return {
1706
1628
  ...structuredClone(document),
@@ -1889,7 +1811,7 @@ function applyFragmentInsert(document, selection, fragment, context) {
1889
1811
  );
1890
1812
  workingDocument = collapseResult.document;
1891
1813
  workingSelection = collapseResult.selection;
1892
- if (context.textTarget?.kind === "table-paragraph") {
1814
+ if (context.textTarget?.kind === "table-paragraph" || context.textTarget?.kind === "text-leaf") {
1893
1815
  workingContext = {
1894
1816
  ...context,
1895
1817
  textTarget: {
@@ -1911,11 +1833,11 @@ function applyFragmentInsert(document, selection, fragment, context) {
1911
1833
  selection
1912
1834
  };
1913
1835
  }
1914
- const targetedTablePath = workingContext.textTarget?.kind === "table-paragraph" ? workingContext.textTarget.blockPath : void 0;
1915
- if (targetedTablePath) {
1836
+ const targetedBlockPath = workingContext.textTarget?.kind === "table-paragraph" || workingContext.textTarget?.kind === "text-leaf" ? workingContext.textTarget.blockPath : void 0;
1837
+ if (targetedBlockPath) {
1916
1838
  const targeted = insertFragmentBlocksAfterPath(
1917
1839
  splitResult.document,
1918
- targetedTablePath,
1840
+ targetedBlockPath,
1919
1841
  fragment.blocks
1920
1842
  );
1921
1843
  if (targeted) {
@@ -5827,7 +5749,7 @@ function emptyCompatibilityReport() {
5827
5749
  }
5828
5750
 
5829
5751
  // src/runtime/debug/runtime-debug-facet.ts
5830
- function createRuntimeDebugFacet(getRuntime, bus) {
5752
+ function createRuntimeDebugFacet(getRuntime, bus, options = {}) {
5831
5753
  return {
5832
5754
  bus,
5833
5755
  getSnapshot(query) {
@@ -5845,10 +5767,321 @@ function createRuntimeDebugFacet(getRuntime, bus) {
5845
5767
  },
5846
5768
  getChannels() {
5847
5769
  return bus.getChannels();
5770
+ },
5771
+ getHotEditTraces() {
5772
+ return options.getHotEditTraces?.() ?? [];
5848
5773
  }
5849
5774
  };
5850
5775
  }
5851
5776
 
5777
+ // src/runtime/hot-edit/hot-edit-trace.ts
5778
+ var HOT_EDIT_TRACE_LIMIT = 64;
5779
+ var HotEditTraceRecorder = class {
5780
+ traces = [];
5781
+ sequence = 0;
5782
+ begin(input) {
5783
+ this.sequence += 1;
5784
+ return {
5785
+ sequence: this.sequence,
5786
+ commandType: input.commandType,
5787
+ startedAtUtc: input.nowUtc,
5788
+ startedAtMs: nowMs(),
5789
+ startCounters: input.counters.snapshot()
5790
+ };
5791
+ }
5792
+ complete(pending, input) {
5793
+ const endCounters = input.counters.snapshot();
5794
+ const refreshAllCount = counterDelta(pending.startCounters, endCounters, "refresh.all");
5795
+ const patchHitCount = counterDelta(pending.startCounters, endCounters, "surface.localText.patchHit");
5796
+ const patchBudgetFallbackCount = counterDelta(
5797
+ pending.startCounters,
5798
+ endCounters,
5799
+ "surface.localText.patchBudgetFallback"
5800
+ );
5801
+ const boundedEditableTargetBuildCount = counterDelta(
5802
+ pending.startCounters,
5803
+ endCounters,
5804
+ "runtime.editableTargets.boundedBuilds"
5805
+ );
5806
+ const tier = refineTier(input.tier, {
5807
+ refreshAllCount,
5808
+ patchHitCount,
5809
+ patchBudgetFallbackCount,
5810
+ boundedEditableTargetBuildCount
5811
+ });
5812
+ const trace = {
5813
+ sequence: pending.sequence,
5814
+ startedAtUtc: pending.startedAtUtc,
5815
+ commandType: pending.commandType,
5816
+ tier,
5817
+ patchMissReason: input.patchMissReason,
5818
+ totalDurationUs: Math.max(0, Math.round((nowMs() - pending.startedAtMs) * 1e3)),
5819
+ refreshAllCount,
5820
+ patchHitCount,
5821
+ patchBudgetFallbackCount,
5822
+ boundedEditableTargetBuildCount
5823
+ };
5824
+ this.traces.push(trace);
5825
+ if (this.traces.length > HOT_EDIT_TRACE_LIMIT) {
5826
+ this.traces.splice(0, this.traces.length - HOT_EDIT_TRACE_LIMIT);
5827
+ }
5828
+ input.counters.increment(`hotEdit.tier.${trace.tier}`);
5829
+ if (trace.patchMissReason !== "none") {
5830
+ input.counters.increment(`hotEdit.patchMiss.${trace.patchMissReason}`);
5831
+ }
5832
+ return trace;
5833
+ }
5834
+ getTraces() {
5835
+ return Object.freeze([...this.traces]);
5836
+ }
5837
+ clear() {
5838
+ this.traces.splice(0, this.traces.length);
5839
+ }
5840
+ };
5841
+ function refineTier(requested, counters) {
5842
+ if (requested === "blocked") return requested;
5843
+ if (counters.refreshAllCount > 0) return "full-refresh";
5844
+ if (counters.patchBudgetFallbackCount > 0 || counters.boundedEditableTargetBuildCount > 0) {
5845
+ return "bounded-projection";
5846
+ }
5847
+ if (counters.patchHitCount > 0) return "patch";
5848
+ return requested;
5849
+ }
5850
+ function counterDelta(start, end, key) {
5851
+ return (end[key] ?? 0) - (start[key] ?? 0);
5852
+ }
5853
+ function nowMs() {
5854
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
5855
+ }
5856
+
5857
+ // src/runtime/hot-edit/surface-local-patcher.ts
5858
+ function patchSurfaceTextSegment(surface, patch) {
5859
+ const delta = patch.insertedText.length - Math.max(0, patch.to - patch.from);
5860
+ let patched = false;
5861
+ const blocks = surface.blocks.map((block) => {
5862
+ const result = patchBlock(block, patch, delta);
5863
+ if (result.patched) patched = true;
5864
+ return result.block;
5865
+ });
5866
+ if (!patched) {
5867
+ return { status: "miss", reason: "segment-not-found" };
5868
+ }
5869
+ return {
5870
+ status: "patched",
5871
+ surface: {
5872
+ ...surface,
5873
+ storySize: surface.storySize + delta,
5874
+ plainText: surface.plainText.slice(0, patch.from) + patch.insertedText + surface.plainText.slice(patch.to),
5875
+ blocks
5876
+ }
5877
+ };
5878
+ }
5879
+ function patchBlock(block, patch, delta) {
5880
+ if (patch.to < block.from) return { block, patched: false };
5881
+ if (patch.from > block.to) {
5882
+ return { block: shiftBlock(block, delta), patched: false };
5883
+ }
5884
+ switch (block.kind) {
5885
+ case "paragraph":
5886
+ return patchParagraph(block, patch, delta);
5887
+ case "sdt_block": {
5888
+ let patched = false;
5889
+ const children = block.children.map((child) => {
5890
+ const result = patchBlock(child, patch, delta);
5891
+ patched ||= result.patched;
5892
+ return result.block;
5893
+ });
5894
+ return {
5895
+ block: patched ? { ...block, to: block.to + delta, children } : block,
5896
+ patched
5897
+ };
5898
+ }
5899
+ case "table": {
5900
+ let patched = false;
5901
+ const rows = block.rows.map((row2) => ({
5902
+ ...row2,
5903
+ cells: row2.cells.map((cell) => ({
5904
+ ...cell,
5905
+ content: cell.content.map((child) => {
5906
+ const result = patchBlock(child, patch, delta);
5907
+ patched ||= result.patched;
5908
+ return result.block;
5909
+ })
5910
+ }))
5911
+ }));
5912
+ return {
5913
+ block: patched ? { ...block, to: block.to + delta, rows } : block,
5914
+ patched
5915
+ };
5916
+ }
5917
+ case "opaque_block":
5918
+ return { block, patched: false };
5919
+ }
5920
+ }
5921
+ function patchParagraph(block, patch, delta) {
5922
+ if (patch.from < block.from || patch.to > block.to) {
5923
+ return { block, patched: false };
5924
+ }
5925
+ const segmentIndex = block.segments.findIndex(
5926
+ (segment2) => segment2.kind === "text" && patch.from >= segment2.from && patch.to <= segment2.to
5927
+ );
5928
+ if (segmentIndex < 0) return { block, patched: false };
5929
+ const segment = block.segments[segmentIndex];
5930
+ if (segment.kind !== "text") return { block, patched: false };
5931
+ const localFrom = patch.from - segment.from;
5932
+ const localTo = patch.to - segment.from;
5933
+ const segments = block.segments.map((candidate, index) => {
5934
+ if (index < segmentIndex) return candidate;
5935
+ if (index === segmentIndex) {
5936
+ return {
5937
+ ...segment,
5938
+ text: segment.text.slice(0, localFrom) + patch.insertedText + segment.text.slice(localTo),
5939
+ to: segment.to + delta
5940
+ };
5941
+ }
5942
+ return shiftInlineSegment(candidate, delta);
5943
+ });
5944
+ return {
5945
+ block: {
5946
+ ...block,
5947
+ to: block.to + delta,
5948
+ segments
5949
+ },
5950
+ patched: true
5951
+ };
5952
+ }
5953
+ function shiftBlock(block, delta) {
5954
+ if (delta === 0) return block;
5955
+ switch (block.kind) {
5956
+ case "paragraph":
5957
+ return {
5958
+ ...block,
5959
+ from: block.from + delta,
5960
+ to: block.to + delta,
5961
+ segments: block.segments.map((segment) => shiftInlineSegment(segment, delta))
5962
+ };
5963
+ case "sdt_block":
5964
+ return {
5965
+ ...block,
5966
+ from: block.from + delta,
5967
+ to: block.to + delta,
5968
+ children: block.children.map((child) => shiftBlock(child, delta))
5969
+ };
5970
+ case "table":
5971
+ return {
5972
+ ...block,
5973
+ from: block.from + delta,
5974
+ to: block.to + delta,
5975
+ rows: block.rows.map((row2) => ({
5976
+ ...row2,
5977
+ cells: row2.cells.map((cell) => ({
5978
+ ...cell,
5979
+ content: cell.content.map((child) => shiftBlock(child, delta))
5980
+ }))
5981
+ }))
5982
+ };
5983
+ case "opaque_block":
5984
+ return {
5985
+ ...block,
5986
+ from: block.from + delta,
5987
+ to: block.to + delta
5988
+ };
5989
+ }
5990
+ }
5991
+ function shiftInlineSegment(segment, delta) {
5992
+ if (delta === 0) return segment;
5993
+ return {
5994
+ ...segment,
5995
+ from: segment.from + delta,
5996
+ to: segment.to + delta
5997
+ };
5998
+ }
5999
+
6000
+ // src/runtime/hot-edit/hot-edit-profiler.ts
6001
+ var HEAVY_REVIEW_ITEM_THRESHOLD = 24;
6002
+ var DENSE_BLOCK_NODE_THRESHOLD = 256;
6003
+ function deriveHotEditDocumentProfile(document) {
6004
+ const blocks = document.content.children ?? [];
6005
+ let tableBlockCount = 0;
6006
+ let maxNestedSurfaceNodesPerBlock = 0;
6007
+ for (const block of blocks) {
6008
+ if (block.type === "table") tableBlockCount += 1;
6009
+ maxNestedSurfaceNodesPerBlock = Math.max(
6010
+ maxNestedSurfaceNodesPerBlock,
6011
+ countBlockNodes(block)
6012
+ );
6013
+ }
6014
+ const commentCount = Object.keys(document.review.comments ?? {}).length;
6015
+ const revisionCount = Object.keys(document.review.revisions ?? {}).length;
6016
+ const secondaryStoryBlockCount = countSecondaryStoryBlocks(document);
6017
+ return {
6018
+ blockCount: blocks.length,
6019
+ tableBlockCount,
6020
+ maxNestedSurfaceNodesPerBlock,
6021
+ commentCount,
6022
+ revisionCount,
6023
+ secondaryStoryBlockCount,
6024
+ hasHeavyReview: commentCount + revisionCount >= HEAVY_REVIEW_ITEM_THRESHOLD,
6025
+ hasDenseTables: tableBlockCount > 0 && maxNestedSurfaceNodesPerBlock > DENSE_BLOCK_NODE_THRESHOLD
6026
+ };
6027
+ }
6028
+ function countBlockNodes(block) {
6029
+ const value = block;
6030
+ let total = 1;
6031
+ if (Array.isArray(value.children)) {
6032
+ total += value.children.length;
6033
+ for (const child of value.children) {
6034
+ if (isBlockLike(child)) total += countBlockNodes(child);
6035
+ }
6036
+ }
6037
+ if (Array.isArray(value.rows)) {
6038
+ for (const row2 of value.rows) {
6039
+ total += 1;
6040
+ for (const cell of row2.cells ?? []) {
6041
+ total += 1;
6042
+ for (const child of cell.children ?? []) {
6043
+ total += countBlockNodes(child);
6044
+ }
6045
+ }
6046
+ }
6047
+ }
6048
+ return total;
6049
+ }
6050
+ function isBlockLike(value) {
6051
+ return Boolean(value && typeof value === "object" && "type" in value);
6052
+ }
6053
+ function countSecondaryStoryBlocks(document) {
6054
+ const subParts = document.subParts;
6055
+ if (!subParts) return 0;
6056
+ let count = 0;
6057
+ for (const value of Object.values(subParts)) {
6058
+ count += countBlocksInUnknownStory(value);
6059
+ }
6060
+ return count;
6061
+ }
6062
+ function countBlocksInUnknownStory(value) {
6063
+ if (!value || typeof value !== "object") return 0;
6064
+ const candidate = value;
6065
+ if (Array.isArray(candidate.children)) return candidate.children.length;
6066
+ if (Array.isArray(candidate.content?.children)) return candidate.content.children.length;
6067
+ return Object.values(value).reduce((total, entry) => total + countBlocksInUnknownStory(entry), 0);
6068
+ }
6069
+
6070
+ // src/runtime/hot-edit/hot-edit-policy.ts
6071
+ var DEFAULT_MAX_SHIFTED_SURFACE_NODES = 5e3;
6072
+ var DEFAULT_MAX_SHIFTED_NODES_PER_BLOCK = 256;
6073
+ var DEFAULT_SELECTION_CORRIDOR_BLOCK_RADIUS = 8;
6074
+ var HEAVY_DOCUMENT_SELECTION_CORRIDOR_BLOCK_RADIUS = 12;
6075
+ function resolveHotEditPolicy(profile) {
6076
+ const complexGeometry = profile.hasDenseTables || profile.secondaryStoryBlockCount > 0;
6077
+ return {
6078
+ maxShiftedSurfaceNodes: DEFAULT_MAX_SHIFTED_SURFACE_NODES,
6079
+ maxShiftedNodesPerBlock: DEFAULT_MAX_SHIFTED_NODES_PER_BLOCK,
6080
+ selectionCorridorBlockRadius: complexGeometry ? HEAVY_DOCUMENT_SELECTION_CORRIDOR_BLOCK_RADIUS : DEFAULT_SELECTION_CORRIDOR_BLOCK_RADIUS,
6081
+ preferBoundedProjectionForDenseTails: profile.hasDenseTables
6082
+ };
6083
+ }
6084
+
5852
6085
  // src/runtime/workflow/query-scopes.ts
5853
6086
  function storyTargetsEqual2(a, b) {
5854
6087
  if (a.kind !== b.kind) return false;
@@ -12245,8 +12478,6 @@ function mapLocalSelectionOnRemoteReplay(selection, mapping) {
12245
12478
 
12246
12479
  // src/runtime/document-runtime.ts
12247
12480
  var CANONICAL_BLOCK_REFS_SYMBOL = /* @__PURE__ */ Symbol.for("wre.canonical-block-refs");
12248
- var LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES = 5e3;
12249
- var LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK = 256;
12250
12481
  function getLocalTextPatchMetadata(mapping) {
12251
12482
  const metadata = mapping.metadata?.localTextPatch;
12252
12483
  if (!metadata || typeof metadata !== "object") {
@@ -12353,6 +12584,17 @@ function createDocumentRuntime(options) {
12353
12584
  const loadScheduler = options.loadScheduler ?? createLoadScheduler({ backendOverride: "sync" });
12354
12585
  let effectiveMarkupModeProvider;
12355
12586
  const perfCounters = new PerfCounters();
12587
+ const hotEditTraces = new HotEditTraceRecorder();
12588
+ let cachedHotEditPolicy = null;
12589
+ function getHotEditPolicy() {
12590
+ if (cachedHotEditPolicy?.document === state.document) {
12591
+ return cachedHotEditPolicy.policy;
12592
+ }
12593
+ const profile = deriveHotEditDocumentProfile(state.document);
12594
+ const policy = resolveHotEditPolicy(profile);
12595
+ cachedHotEditPolicy = { document: state.document, profile, policy };
12596
+ return policy;
12597
+ }
12356
12598
  let analyticsEmitScheduled = false;
12357
12599
  let analyticsEmitScheduleMode = "none";
12358
12600
  let deferNextContextAnalyticsEmit = false;
@@ -12424,7 +12666,6 @@ function createDocumentRuntime(options) {
12424
12666
  let viewportBlockRanges = null;
12425
12667
  let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
12426
12668
  let viewportBlocksPerPageEstimate = null;
12427
- const EDITING_CORRIDOR_BLOCK_RADIUS = 8;
12428
12669
  const getRuntimeForLayoutFacet = () => {
12429
12670
  if (!runtimeRef) {
12430
12671
  throw new Error("Document runtime viewport methods are not initialized");
@@ -12758,8 +12999,8 @@ function createDocumentRuntime(options) {
12758
12999
  return viewportBlockRanges;
12759
13000
  }
12760
13001
  const corridor = {
12761
- start: Math.max(0, caretBlockIndex - EDITING_CORRIDOR_BLOCK_RADIUS),
12762
- end: Math.min(previousSurface.blocks.length, caretBlockIndex + EDITING_CORRIDOR_BLOCK_RADIUS + 1)
13002
+ start: Math.max(0, caretBlockIndex - getHotEditPolicy().selectionCorridorBlockRadius),
13003
+ end: Math.min(previousSurface.blocks.length, caretBlockIndex + getHotEditPolicy().selectionCorridorBlockRadius + 1)
12763
13004
  };
12764
13005
  return normalizeViewportRanges([...viewportBlockRanges ?? [], corridor]);
12765
13006
  }
@@ -12840,8 +13081,12 @@ function createDocumentRuntime(options) {
12840
13081
  (block2) => block2.kind === "paragraph" && editFrom >= block2.from && editTo <= block2.to
12841
13082
  );
12842
13083
  if (blockIndex < 0) {
12843
- perfCounters.increment("surface.localText.patchMiss");
12844
- return null;
13084
+ return tryPatchNestedLocalTextSurface(
13085
+ previousSurface,
13086
+ editFrom,
13087
+ editTo,
13088
+ patch.insertedText
13089
+ );
12845
13090
  }
12846
13091
  const block = previousSurface.blocks[blockIndex];
12847
13092
  if (block.kind !== "paragraph") {
@@ -12916,6 +13161,34 @@ function createDocumentRuntime(options) {
12916
13161
  perfCounters.increment("surface.localText.total.us", Math.round((performance.now() - tTotal0) * 1e3));
12917
13162
  }
12918
13163
  }
13164
+ function tryPatchNestedLocalTextSurface(previousSurface, editFrom, editTo, insertedText) {
13165
+ const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, 0);
13166
+ perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
13167
+ perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
13168
+ if (!shiftBudget.withinBudget) {
13169
+ perfCounters.increment("surface.localText.patchBudgetFallback");
13170
+ return null;
13171
+ }
13172
+ const patched = patchSurfaceTextSegment(previousSurface, {
13173
+ from: editFrom,
13174
+ to: editTo,
13175
+ insertedText
13176
+ });
13177
+ if (patched.status !== "patched") {
13178
+ perfCounters.increment("surface.localText.patchMiss");
13179
+ return null;
13180
+ }
13181
+ const refs = getSurfaceCanonicalBlockRefs(previousSurface);
13182
+ if (refs) {
13183
+ const nextRefs = state.document.content.children.map(
13184
+ (block, index) => block ?? refs[index] ?? null
13185
+ );
13186
+ attachSurfaceCanonicalBlockRefs(patched.surface, nextRefs);
13187
+ }
13188
+ perfCounters.increment("surface.localText.patchHit");
13189
+ perfCounters.increment("surface.localText.patchDelta", insertedText.length - (editTo - editFrom));
13190
+ return patched.surface;
13191
+ }
12919
13192
  function shiftSurfaceInlineSegment(segment, delta) {
12920
13193
  if (delta === 0) return segment;
12921
13194
  return {
@@ -12963,25 +13236,26 @@ function createDocumentRuntime(options) {
12963
13236
  }
12964
13237
  }
12965
13238
  function estimateLocalTextPatchShiftBudget(blocks, startIndex) {
13239
+ const policy = getHotEditPolicy();
12966
13240
  const shiftedBlocks = Math.max(0, blocks.length - startIndex);
12967
13241
  let shiftedNodes = 0;
12968
13242
  for (let index = startIndex; index < blocks.length; index += 1) {
12969
13243
  const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
12970
13244
  blocks[index],
12971
13245
  Math.min(
12972
- LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK,
12973
- LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES - shiftedNodes
13246
+ policy.maxShiftedNodesPerBlock,
13247
+ policy.maxShiftedSurfaceNodes - shiftedNodes
12974
13248
  ) + 1
12975
13249
  );
12976
13250
  shiftedNodes += shiftedBlockNodes;
12977
- if (shiftedBlockNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK) {
13251
+ if (shiftedBlockNodes > policy.maxShiftedNodesPerBlock) {
12978
13252
  return {
12979
13253
  shiftedBlocks,
12980
13254
  shiftedNodes,
12981
13255
  withinBudget: false
12982
13256
  };
12983
13257
  }
12984
- if (shiftedNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES) {
13258
+ if (shiftedNodes > policy.maxShiftedSurfaceNodes) {
12985
13259
  return {
12986
13260
  shiftedBlocks,
12987
13261
  shiftedNodes,
@@ -13945,7 +14219,9 @@ function createDocumentRuntime(options) {
13945
14219
  });
13946
14220
  const r5ScratchReplayState = { ...state };
13947
14221
  const r5ScratchReplaySnapshot = { ...cachedRenderSnapshot };
13948
- const debugFacet = createRuntimeDebugFacet(() => runtime, telemetryBus);
14222
+ const debugFacet = createRuntimeDebugFacet(() => runtime, telemetryBus, {
14223
+ getHotEditTraces: () => hotEditTraces.getTraces()
14224
+ });
13949
14225
  function prepareTableStructureCommandForExecution(command, document, storyTarget) {
13950
14226
  const resolution = resolveEditableTableStructureTarget({
13951
14227
  document,
@@ -14042,13 +14318,12 @@ function createDocumentRuntime(options) {
14042
14318
  if (!command.editableTarget) {
14043
14319
  return { kind: "accepted", selection };
14044
14320
  }
14045
- const preserveCallerSelection = command.editableTarget.listAddress?.operationScope === "list-text";
14046
14321
  const resolution = resolveEditableTextTarget({
14047
14322
  document,
14048
14323
  surface,
14049
14324
  target: command.editableTarget,
14050
14325
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
14051
- ...preserveCallerSelection ? { selection } : {},
14326
+ selection,
14052
14327
  editableTargetCache: editableTargetBlockCache
14053
14328
  });
14054
14329
  if (resolution.kind === "rejected") {
@@ -14066,7 +14341,7 @@ function createDocumentRuntime(options) {
14066
14341
  }
14067
14342
  return {
14068
14343
  kind: "accepted",
14069
- selection: preserveCallerSelection ? selection : createSelectionSnapshot(resolution.range.from, resolution.range.to),
14344
+ selection,
14070
14345
  ...resolution.textTarget ? { textTarget: resolution.textTarget } : {}
14071
14346
  };
14072
14347
  }
@@ -15242,12 +15517,23 @@ function createDocumentRuntime(options) {
15242
15517
  return actionDepth > 0;
15243
15518
  },
15244
15519
  applyActiveStoryTextCommand(command) {
15520
+ const pendingHotEditTrace = hotEditTraces.begin({
15521
+ commandType: command.type,
15522
+ nowUtc: clock(),
15523
+ counters: perfCounters
15524
+ });
15245
15525
  try {
15246
- return applyTextCommandInActiveStory(command);
15526
+ const ack = applyTextCommandInActiveStory(command);
15527
+ hotEditTraces.complete(pendingHotEditTrace, {
15528
+ tier: classifyHotEditTier(ack),
15529
+ patchMissReason: classifyHotEditPatchMissReason(ack),
15530
+ counters: perfCounters
15531
+ });
15532
+ return ack;
15247
15533
  } catch (error) {
15248
15534
  const runtimeError = toRuntimeError(error);
15249
15535
  emitError(runtimeError);
15250
- return {
15536
+ const ack = {
15251
15537
  kind: "rejected",
15252
15538
  refreshClass: "blocked",
15253
15539
  opId: command.origin?.opId,
@@ -15259,6 +15545,12 @@ function createDocumentRuntime(options) {
15259
15545
  }
15260
15546
  ]
15261
15547
  };
15548
+ hotEditTraces.complete(pendingHotEditTrace, {
15549
+ tier: "blocked",
15550
+ patchMissReason: "participant-blocked",
15551
+ counters: perfCounters
15552
+ });
15553
+ return ack;
15262
15554
  }
15263
15555
  },
15264
15556
  addComment(params) {
@@ -17034,6 +17326,27 @@ function createDocumentRuntime(options) {
17034
17326
  newRevisionToken: state.revisionToken
17035
17327
  }));
17036
17328
  }
17329
+ function classifyHotEditTier(ack) {
17330
+ if (ack.kind === "rejected" || ack.refreshClass === "blocked") {
17331
+ return "blocked";
17332
+ }
17333
+ if (ack.refreshClass === "full-projection" || ack.kind === "structural-divergence") {
17334
+ return "full-refresh";
17335
+ }
17336
+ if (ack.refreshClass === "local-text-equivalent" || ack.refreshClass === "selection-only" || ack.refreshClass === "surface-only") {
17337
+ return "patch";
17338
+ }
17339
+ return "full-refresh";
17340
+ }
17341
+ function classifyHotEditPatchMissReason(ack) {
17342
+ if (ack.kind === "rejected" || ack.refreshClass === "blocked") {
17343
+ return "participant-blocked";
17344
+ }
17345
+ if (ack.refreshClass === "full-projection" || ack.kind === "structural-divergence") {
17346
+ return "effect-disqualified";
17347
+ }
17348
+ return "none";
17349
+ }
17037
17350
  function classifyAck(params) {
17038
17351
  const { opId, priorState, transaction, newRevisionToken } = params;
17039
17352
  const meta = transaction.mapping.metadata ?? {};