@beyondwork/docx-react-component 1.0.124 → 1.0.126

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 (101) hide show
  1. package/dist/api/public-types.cjs +147 -35
  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 +796 -102
  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-CG2TgAzj.d.cts → canonical-document-CXCFCbAz.d.cts} +2 -0
  10. package/dist/{canonical-document-CG2TgAzj.d.ts → canonical-document-CXCFCbAz.d.ts} +2 -0
  11. package/dist/{chunk-PFYUJU3Q.js → chunk-2QL5DAKF.js} +98 -43
  12. package/dist/{chunk-4IPEZYQX.js → chunk-4EENH4FG.js} +1 -1
  13. package/dist/{chunk-BOHHIVQ2.js → chunk-4G3OS2H6.js} +3 -3
  14. package/dist/{chunk-A74Y5NE4.js → chunk-4YJVRIUB.js} +52 -21
  15. package/dist/{chunk-FNWKE74J.js → chunk-5DGKFNQT.js} +5 -1
  16. package/dist/{chunk-RSYN6FTS.js → chunk-6F5QW44A.js} +2 -2
  17. package/dist/{chunk-ZMRO6P3A.js → chunk-6IGWPAR4.js} +505 -44
  18. package/dist/{chunk-KOHQFZMM.js → chunk-BYSRJ4FE.js} +1 -1
  19. package/dist/{chunk-H6IL5ABU.js → chunk-CXSYRB37.js} +64 -20
  20. package/dist/{chunk-32ZAOQ54.js → chunk-D5HYZQTG.js} +1 -1
  21. package/dist/{chunk-TY4DIJO3.js → chunk-ESJ2MES5.js} +1 -1
  22. package/dist/{chunk-Q76XPPTA.js → chunk-FPRWV54X.js} +101 -14
  23. package/dist/{chunk-MPH4ZQS4.js → chunk-GL7XRYBY.js} +624 -87
  24. package/dist/{chunk-IR7QV2BX.js → chunk-KV435YXO.js} +2 -2
  25. package/dist/{chunk-N4VIXI2Z.js → chunk-MWSBGJQO.js} +137 -18
  26. package/dist/{chunk-7PC6XUNO.js → chunk-TQDQU2E3.js} +2 -2
  27. package/dist/{chunk-4B74ETJI.js → chunk-V6XVZFFH.js} +2 -2
  28. package/dist/{chunk-NAMAWCXN.js → chunk-YD2JE54B.js} +1 -1
  29. package/dist/{chunk-ZRHLLPSJ.js → chunk-YHZHPXDB.js} +85 -18
  30. package/dist/{chunk-HXHQA4BU.js → chunk-YIYM4ZAP.js} +1 -1
  31. package/dist/{chunk-LGWNN3L2.js → chunk-ZDOAUP3V.js} +2 -2
  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 +65 -20
  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 +65 -20
  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 -21
  49. package/dist/core/commands/text-commands.d.cts +2 -2
  50. package/dist/core/commands/text-commands.d.ts +2 -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 +1677 -240
  57. package/dist/index.d.cts +5 -5
  58. package/dist/index.d.ts +5 -5
  59. package/dist/index.js +62 -25
  60. package/dist/io/docx-session.cjs +51 -20
  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 +36 -12
  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-D9y4ZRjj.d.ts → loader-CS9-9KFa.d.ts} +3 -3
  69. package/dist/{loader-D9KCtj4m.d.cts → loader-OoWJ1_17.d.cts} +3 -3
  70. package/dist/{public-types-CNnMHZM9.d.ts → public-types-BP3vqJR5.d.cts} +157 -11
  71. package/dist/{public-types-DajNGKV4.d.cts → public-types-DdcHqcow.d.ts} +157 -11
  72. package/dist/public-types.cjs +147 -35
  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 +945 -134
  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-DyQGlryH.d.cts → session-Cq-fzx3B.d.cts} +3 -3
  83. package/dist/{session-DEmaOEjA.d.ts → session-DyFQt8Ph.d.ts} +3 -3
  84. package/dist/session.cjs +51 -20
  85. package/dist/session.d.cts +5 -5
  86. package/dist/session.d.ts +5 -5
  87. package/dist/session.js +5 -5
  88. package/dist/tailwind.cjs +238 -73
  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-CxE1aZiv.d.cts → types-Bg7D-GD3.d.cts} +2 -2
  93. package/dist/{types-DjJNaE9c.d.ts → types-bJAgMq1M.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.cjs +238 -73
  98. package/dist/ui-tailwind.d.cts +3 -3
  99. package/dist/ui-tailwind.d.ts +3 -3
  100. package/dist/ui-tailwind.js +7 -7
  101. 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-NAMAWCXN.js";
14
+ } from "./chunk-YD2JE54B.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-BOHHIVQ2.js";
25
+ } from "./chunk-4G3OS2H6.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-RSYN6FTS.js";
35
+ } from "./chunk-6F5QW44A.js";
36
36
  import {
37
37
  applyTextTransaction
38
- } from "./chunk-IR7QV2BX.js";
38
+ } from "./chunk-KV435YXO.js";
39
39
  import {
40
40
  applyTableStructureOperationForEditableTarget,
41
41
  removeCellFromRow,
42
42
  removeTableRowPure
43
- } from "./chunk-LGWNN3L2.js";
43
+ } from "./chunk-ZDOAUP3V.js";
44
44
  import {
45
45
  resolveParagraphScope
46
- } from "./chunk-KOHQFZMM.js";
46
+ } from "./chunk-BYSRJ4FE.js";
47
47
  import {
48
48
  buildGeometryDebugEntry,
49
49
  collectLineBoxesForRegion,
@@ -51,7 +51,7 @@ import {
51
51
  createRenderKernel,
52
52
  incrementInvalidationCounter,
53
53
  recordPerfSample
54
- } from "./chunk-N4VIXI2Z.js";
54
+ } from "./chunk-MWSBGJQO.js";
55
55
  import {
56
56
  AI_ACTION_POLICIES,
57
57
  buildFormattingDebugEntry,
@@ -74,7 +74,7 @@ import {
74
74
  resolveHeadingPath,
75
75
  resolveScope,
76
76
  serializeFragmentToWordML
77
- } from "./chunk-Q76XPPTA.js";
77
+ } from "./chunk-FPRWV54X.js";
78
78
  import {
79
79
  ISSUE_METADATA_ID,
80
80
  LAYOUT_ENGINE_VERSION,
@@ -109,7 +109,7 @@ import {
109
109
  setWorkspaceMode,
110
110
  setZoomLevel,
111
111
  snapCommentAnchorAwayFromTable
112
- } from "./chunk-ZRHLLPSJ.js";
112
+ } from "./chunk-YHZHPXDB.js";
113
113
  import {
114
114
  countLogicalPositions,
115
115
  createPlainText,
@@ -128,7 +128,7 @@ import {
128
128
  replaceStoryBlocks,
129
129
  resolvePageFieldDisplayText,
130
130
  storyTargetKey
131
- } from "./chunk-H6IL5ABU.js";
131
+ } from "./chunk-CXSYRB37.js";
132
132
  import {
133
133
  createCommentSidebarProjection,
134
134
  createCommentStoreFromRuntimeComments
@@ -152,20 +152,21 @@ import {
152
152
  persistedSnapshotFromEditorSessionState,
153
153
  remapRevisionStore,
154
154
  setRevisionStatus
155
- } from "./chunk-TY4DIJO3.js";
155
+ } from "./chunk-ESJ2MES5.js";
156
156
  import {
157
157
  isSupportedFieldFamily,
158
158
  parseTocLevelRange,
159
159
  resolveRefFieldText
160
- } from "./chunk-A74Y5NE4.js";
160
+ } from "./chunk-4YJVRIUB.js";
161
161
  import {
162
162
  collectEditableTargetRefs,
163
163
  collectEditableTargetRefsForStoryBlockRanges,
164
164
  collectStoryBlockContexts,
165
165
  createEditableTargetBlockCache,
166
166
  createHeaderFooterStoryKey,
167
- sha256TextHex
168
- } from "./chunk-FNWKE74J.js";
167
+ sha256TextHex,
168
+ validateEditableTargetRef
169
+ } from "./chunk-5DGKFNQT.js";
169
170
  import {
170
171
  setActiveSerializeTelemetryBus
171
172
  } from "./chunk-EB6M3GE6.js";
@@ -1131,19 +1132,19 @@ function listBatchRevisionIds(store) {
1131
1132
  }
1132
1133
 
1133
1134
  // src/core/commands/list-commands.ts
1134
- function toggleNumberedList(document, paragraphIndexes, context) {
1135
- return toggleListKind(document, paragraphIndexes, "numbered", context);
1135
+ function toggleNumberedList(document, paragraphIndexes, context, options = {}) {
1136
+ return toggleListKind(document, paragraphIndexes, "numbered", context, options);
1136
1137
  }
1137
- function toggleBulletedList(document, paragraphIndexes, context) {
1138
- return toggleListKind(document, paragraphIndexes, "bulleted", context);
1138
+ function toggleBulletedList(document, paragraphIndexes, context, options = {}) {
1139
+ return toggleListKind(document, paragraphIndexes, "bulleted", context, options);
1139
1140
  }
1140
- function indentListItems(document, paragraphIndexes, context) {
1141
- return adjustListLevels(document, paragraphIndexes, 1, context);
1141
+ function indentListItems(document, paragraphIndexes, context, options = {}) {
1142
+ return adjustListLevels(document, paragraphIndexes, 1, context, options);
1142
1143
  }
1143
- function outdentListItems(document, paragraphIndexes, context) {
1144
- return adjustListLevels(document, paragraphIndexes, -1, context);
1144
+ function outdentListItems(document, paragraphIndexes, context, options = {}) {
1145
+ return adjustListLevels(document, paragraphIndexes, -1, context, options);
1145
1146
  }
1146
- function splitListParagraph(document, paragraphIndex, paragraphIsEmpty, context) {
1147
+ function splitListParagraph(document, paragraphIndex, paragraphIsEmpty, context, options = {}) {
1147
1148
  if (!paragraphIsEmpty) {
1148
1149
  return {
1149
1150
  document,
@@ -1153,7 +1154,30 @@ function splitListParagraph(document, paragraphIndex, paragraphIsEmpty, context)
1153
1154
  }
1154
1155
  const working = cloneEnvelope(document, context.timestamp);
1155
1156
  const paragraphs = captureEditableParagraphs(working);
1156
- const target = paragraphs[paragraphIndex];
1157
+ const resolved = resolveListCommandParagraphIndexes(
1158
+ working,
1159
+ paragraphs,
1160
+ [paragraphIndex],
1161
+ context,
1162
+ normalizeListCommandTargets(options)
1163
+ );
1164
+ if (resolved.blockedReason) {
1165
+ return {
1166
+ document: working,
1167
+ affectedParagraphIndexes: [],
1168
+ action: "blocked",
1169
+ blockedReason: resolved.blockedReason
1170
+ };
1171
+ }
1172
+ const resolvedParagraphIndex = resolved.paragraphIndexes[0];
1173
+ if (resolvedParagraphIndex === void 0) {
1174
+ return {
1175
+ document: working,
1176
+ affectedParagraphIndexes: [],
1177
+ action: "split"
1178
+ };
1179
+ }
1180
+ const target = paragraphs[resolvedParagraphIndex];
1157
1181
  if (!target?.numbering) {
1158
1182
  return {
1159
1183
  document: working,
@@ -1168,21 +1192,44 @@ function splitListParagraph(document, paragraphIndex, paragraphIsEmpty, context)
1168
1192
  };
1169
1193
  return {
1170
1194
  document: working,
1171
- affectedParagraphIndexes: [paragraphIndex],
1195
+ affectedParagraphIndexes: [resolvedParagraphIndex],
1172
1196
  action: "outdented"
1173
1197
  };
1174
1198
  }
1175
1199
  delete target.numbering;
1176
1200
  return {
1177
1201
  document: working,
1178
- affectedParagraphIndexes: [paragraphIndex],
1202
+ affectedParagraphIndexes: [resolvedParagraphIndex],
1179
1203
  action: "removed"
1180
1204
  };
1181
1205
  }
1182
- function backspaceAtListStart(document, paragraphIndex, context) {
1206
+ function backspaceAtListStart(document, paragraphIndex, context, options = {}) {
1183
1207
  const working = cloneEnvelope(document, context.timestamp);
1184
1208
  const paragraphs = captureEditableParagraphs(working);
1185
- const target = paragraphs[paragraphIndex];
1209
+ const resolved = resolveListCommandParagraphIndexes(
1210
+ working,
1211
+ paragraphs,
1212
+ [paragraphIndex],
1213
+ context,
1214
+ normalizeListCommandTargets(options)
1215
+ );
1216
+ if (resolved.blockedReason) {
1217
+ return {
1218
+ document: working,
1219
+ affectedParagraphIndexes: [],
1220
+ handled: true,
1221
+ blockedReason: resolved.blockedReason
1222
+ };
1223
+ }
1224
+ const resolvedParagraphIndex = resolved.paragraphIndexes[0];
1225
+ if (resolvedParagraphIndex === void 0) {
1226
+ return {
1227
+ document: working,
1228
+ affectedParagraphIndexes: [],
1229
+ handled: false
1230
+ };
1231
+ }
1232
+ const target = paragraphs[resolvedParagraphIndex];
1186
1233
  if (!target?.numbering) {
1187
1234
  return {
1188
1235
  document: working,
@@ -1200,14 +1247,35 @@ function backspaceAtListStart(document, paragraphIndex, context) {
1200
1247
  }
1201
1248
  return {
1202
1249
  document: working,
1203
- affectedParagraphIndexes: [paragraphIndex],
1250
+ affectedParagraphIndexes: [resolvedParagraphIndex],
1204
1251
  handled: true
1205
1252
  };
1206
1253
  }
1207
- function restartNumbering(document, paragraphIndex, context, startAt = 1) {
1254
+ function restartNumbering(document, paragraphIndex, context, startAt = 1, options = {}) {
1208
1255
  const working = cloneEnvelope(document, context.timestamp);
1209
1256
  const paragraphs = captureEditableParagraphs(working);
1210
- const target = paragraphs[paragraphIndex];
1257
+ const resolved = resolveListCommandParagraphIndexes(
1258
+ working,
1259
+ paragraphs,
1260
+ [paragraphIndex],
1261
+ context,
1262
+ normalizeListCommandTargets(options)
1263
+ );
1264
+ if (resolved.blockedReason) {
1265
+ return {
1266
+ document: working,
1267
+ affectedParagraphIndexes: [],
1268
+ blockedReason: resolved.blockedReason
1269
+ };
1270
+ }
1271
+ const resolvedParagraphIndex = resolved.paragraphIndexes[0];
1272
+ if (resolvedParagraphIndex === void 0) {
1273
+ return {
1274
+ document: working,
1275
+ affectedParagraphIndexes: []
1276
+ };
1277
+ }
1278
+ const target = paragraphs[resolvedParagraphIndex];
1211
1279
  if (!target?.numbering) {
1212
1280
  return {
1213
1281
  document: working,
@@ -1232,7 +1300,7 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1) {
1232
1300
  })
1233
1301
  };
1234
1302
  const affectedParagraphIndexes = [];
1235
- for (let index = paragraphIndex; index < paragraphs.length; index += 1) {
1303
+ for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
1236
1304
  const paragraph = paragraphs[index];
1237
1305
  if (!paragraph?.numbering) {
1238
1306
  break;
@@ -1253,10 +1321,31 @@ function restartNumbering(document, paragraphIndex, context, startAt = 1) {
1253
1321
  createdNumberingInstanceId: numberingInstanceId
1254
1322
  };
1255
1323
  }
1256
- function continueNumbering(document, paragraphIndex, context) {
1324
+ function continueNumbering(document, paragraphIndex, context, options = {}) {
1257
1325
  const working = cloneEnvelope(document, context.timestamp);
1258
1326
  const paragraphs = captureEditableParagraphs(working);
1259
- const target = paragraphs[paragraphIndex];
1327
+ const resolved = resolveListCommandParagraphIndexes(
1328
+ working,
1329
+ paragraphs,
1330
+ [paragraphIndex],
1331
+ context,
1332
+ normalizeListCommandTargets(options)
1333
+ );
1334
+ if (resolved.blockedReason) {
1335
+ return {
1336
+ document: working,
1337
+ affectedParagraphIndexes: [],
1338
+ blockedReason: resolved.blockedReason
1339
+ };
1340
+ }
1341
+ const resolvedParagraphIndex = resolved.paragraphIndexes[0];
1342
+ if (resolvedParagraphIndex === void 0) {
1343
+ return {
1344
+ document: working,
1345
+ affectedParagraphIndexes: []
1346
+ };
1347
+ }
1348
+ const target = paragraphs[resolvedParagraphIndex];
1260
1349
  if (!target?.numbering) {
1261
1350
  return {
1262
1351
  document: working,
@@ -1275,7 +1364,7 @@ function continueNumbering(document, paragraphIndex, context) {
1275
1364
  const compatibleInstanceId = findPreviousCompatibleInstance(
1276
1365
  paragraphs,
1277
1366
  catalog,
1278
- paragraphIndex,
1367
+ resolvedParagraphIndex,
1279
1368
  currentKind
1280
1369
  );
1281
1370
  if (!compatibleInstanceId || compatibleInstanceId === currentInstanceId) {
@@ -1285,7 +1374,7 @@ function continueNumbering(document, paragraphIndex, context) {
1285
1374
  };
1286
1375
  }
1287
1376
  const affectedParagraphIndexes = [];
1288
- for (let index = paragraphIndex; index < paragraphs.length; index += 1) {
1377
+ for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
1289
1378
  const paragraph = paragraphs[index];
1290
1379
  if (!paragraph?.numbering) {
1291
1380
  break;
@@ -1306,10 +1395,24 @@ function continueNumbering(document, paragraphIndex, context) {
1306
1395
  createdNumberingInstanceId: compatibleInstanceId
1307
1396
  };
1308
1397
  }
1309
- function toggleListKind(document, paragraphIndexes, kind, context) {
1398
+ function toggleListKind(document, paragraphIndexes, kind, context, options) {
1310
1399
  const working = cloneEnvelope(document, context.timestamp);
1311
1400
  const paragraphs = captureEditableParagraphs(working);
1312
- const normalizedIndexes = normalizeParagraphIndexes(paragraphs, paragraphIndexes);
1401
+ const resolved = resolveListCommandParagraphIndexes(
1402
+ working,
1403
+ paragraphs,
1404
+ paragraphIndexes,
1405
+ context,
1406
+ normalizeListCommandTargets(options)
1407
+ );
1408
+ if (resolved.blockedReason) {
1409
+ return {
1410
+ document: working,
1411
+ affectedParagraphIndexes: [],
1412
+ blockedReason: resolved.blockedReason
1413
+ };
1414
+ }
1415
+ const normalizedIndexes = resolved.paragraphIndexes;
1313
1416
  if (normalizedIndexes.length === 0) {
1314
1417
  return {
1315
1418
  document: working,
@@ -1346,10 +1449,24 @@ function toggleListKind(document, paragraphIndexes, kind, context) {
1346
1449
  createdNumberingInstanceId: numberingInstanceId
1347
1450
  };
1348
1451
  }
1349
- function adjustListLevels(document, paragraphIndexes, delta, context) {
1452
+ function adjustListLevels(document, paragraphIndexes, delta, context, options) {
1350
1453
  const working = cloneEnvelope(document, context.timestamp);
1351
1454
  const paragraphs = captureEditableParagraphs(working);
1352
- const affectedParagraphIndexes = normalizeParagraphIndexes(paragraphs, paragraphIndexes).filter(
1455
+ const resolved = resolveListCommandParagraphIndexes(
1456
+ working,
1457
+ paragraphs,
1458
+ paragraphIndexes,
1459
+ context,
1460
+ normalizeListCommandTargets(options)
1461
+ );
1462
+ if (resolved.blockedReason) {
1463
+ return {
1464
+ document: working,
1465
+ affectedParagraphIndexes: [],
1466
+ blockedReason: resolved.blockedReason
1467
+ };
1468
+ }
1469
+ const affectedParagraphIndexes = resolved.paragraphIndexes.filter(
1353
1470
  (index) => Boolean(paragraphs[index]?.numbering)
1354
1471
  );
1355
1472
  for (const index of affectedParagraphIndexes) {
@@ -1367,6 +1484,121 @@ function adjustListLevels(document, paragraphIndexes, delta, context) {
1367
1484
  affectedParagraphIndexes
1368
1485
  };
1369
1486
  }
1487
+ function normalizeListCommandTargets(options) {
1488
+ if (options.editableTargets !== void 0) return options.editableTargets;
1489
+ return options.editableTarget ? [options.editableTarget] : [];
1490
+ }
1491
+ function resolveListCommandParagraphIndexes(document, paragraphs, paragraphIndexes, context, editableTargets) {
1492
+ if (editableTargets.length === 0) {
1493
+ return { paragraphIndexes: normalizeParagraphIndexes(paragraphs, paragraphIndexes) };
1494
+ }
1495
+ const currentTargets = collectEditableTargetRefs(document, context.editableTargetCache);
1496
+ const paragraphIndexByTargetKey = /* @__PURE__ */ new Map();
1497
+ let paragraphIndex = 0;
1498
+ for (const target of currentTargets) {
1499
+ if (!isParagraphTextTarget(target)) continue;
1500
+ if (!paragraphIndexByTargetKey.has(target.targetKey)) {
1501
+ paragraphIndexByTargetKey.set(target.targetKey, paragraphIndex);
1502
+ paragraphIndex += 1;
1503
+ }
1504
+ }
1505
+ const resolvedIndexes = [];
1506
+ for (const target of editableTargets) {
1507
+ const blockedReason = validateListCommandTarget(target, currentTargets, context);
1508
+ if (blockedReason) return { paragraphIndexes: [], blockedReason };
1509
+ const current = findCurrentListCommandTarget(target, currentTargets);
1510
+ if (!current) {
1511
+ return {
1512
+ paragraphIndexes: [],
1513
+ blockedReason: {
1514
+ code: "list_target_not_found",
1515
+ message: "List editable target no longer resolves in the current canonical document."
1516
+ }
1517
+ };
1518
+ }
1519
+ if (!sameResolvedListCommandTarget(target, current)) {
1520
+ return {
1521
+ paragraphIndexes: [],
1522
+ blockedReason: {
1523
+ code: "list_target_stale",
1524
+ message: "List editable target is stale for the current canonical document."
1525
+ }
1526
+ };
1527
+ }
1528
+ const currentIndex = paragraphIndexByTargetKey.get(current.targetKey);
1529
+ if (currentIndex === void 0) {
1530
+ return {
1531
+ paragraphIndexes: [],
1532
+ blockedReason: {
1533
+ code: "list_target_position_unavailable",
1534
+ message: "List editable target resolved but could not be mapped to a current paragraph."
1535
+ }
1536
+ };
1537
+ }
1538
+ resolvedIndexes.push(currentIndex);
1539
+ }
1540
+ return { paragraphIndexes: normalizeParagraphIndexes(paragraphs, resolvedIndexes) };
1541
+ }
1542
+ function validateListCommandTarget(target, currentTargets, context) {
1543
+ const shapeIssues = validateEditableTargetRef(target);
1544
+ if (shapeIssues.length > 0) {
1545
+ return {
1546
+ code: "list_target_malformed",
1547
+ message: `List editable target is malformed: ${shapeIssues[0]?.path ?? "$"}.`
1548
+ };
1549
+ }
1550
+ if (context.activeStoryKey !== void 0 && target.storyKey !== context.activeStoryKey) {
1551
+ return {
1552
+ code: "list_target_wrong_story",
1553
+ message: "List editable target does not belong to the active story."
1554
+ };
1555
+ }
1556
+ if (target.commandFamily !== "text-leaf" || target.listAddress === void 0) {
1557
+ return {
1558
+ code: "list_target_required",
1559
+ message: "List commands require a validated list item editable target."
1560
+ };
1561
+ }
1562
+ if (target.editability !== "editable" || target.posture.blockers.length > 0) {
1563
+ return {
1564
+ code: "list_target_non_editable",
1565
+ message: target.posture.blockers.length > 0 ? `List editable target is not editable: ${target.posture.blockers.join(", ")}.` : "List editable target is not editable."
1566
+ };
1567
+ }
1568
+ if (!findCurrentListCommandTarget(target, currentTargets)) {
1569
+ return {
1570
+ code: "list_target_not_found",
1571
+ message: "List editable target no longer resolves in the current canonical document."
1572
+ };
1573
+ }
1574
+ return void 0;
1575
+ }
1576
+ function findCurrentListCommandTarget(target, currentTargets) {
1577
+ return currentTargets.find(
1578
+ (candidate) => isParagraphTextTarget(candidate) && candidate.listAddress !== void 0 && (candidate.targetKey === target.targetKey || candidate.listAddress.addressKey === target.listAddress?.addressKey)
1579
+ );
1580
+ }
1581
+ function sameResolvedListCommandTarget(left, right) {
1582
+ 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.blockType === right.staleCheck.blockType && left.listAddress?.addressKey === right.listAddress?.addressKey && left.listAddress?.resolver?.staleHash === right.listAddress?.resolver?.staleHash && jsonStable(left.sourceRef) === jsonStable(right.sourceRef);
1583
+ }
1584
+ function isParagraphTextTarget(target) {
1585
+ return target.commandFamily === "text-leaf" && target.staleCheck.blockType === "paragraph" && target.leafPath.endsWith("/inline");
1586
+ }
1587
+ function jsonStable(value) {
1588
+ return JSON.stringify(sortJson(value));
1589
+ }
1590
+ function sortJson(value) {
1591
+ if (Array.isArray(value)) return value.map(sortJson);
1592
+ if (value && typeof value === "object") {
1593
+ const record = value;
1594
+ const sorted = {};
1595
+ for (const key of Object.keys(record).sort()) {
1596
+ sorted[key] = sortJson(record[key]);
1597
+ }
1598
+ return sorted;
1599
+ }
1600
+ return value;
1601
+ }
1370
1602
  function ensureDefaultInstance(catalog, kind) {
1371
1603
  const existing = Object.values(catalog.instances).find(
1372
1604
  (instance) => getListKind(catalog, instance.numberingInstanceId) === kind
@@ -1602,7 +1834,7 @@ function validateResult(result, context) {
1602
1834
  return { ...result, selection: validated };
1603
1835
  }
1604
1836
  function getPostMutationMaxOffset(result, context) {
1605
- if (typeof context.activeStorySize !== "number" || context.textTarget?.kind === "text-leaf") {
1837
+ if (typeof context.activeStorySize !== "number" || isTargetLocalTextLeaf(context.textTarget)) {
1606
1838
  return result.storyText.length;
1607
1839
  }
1608
1840
  let storySize = context.activeStorySize;
@@ -1611,6 +1843,9 @@ function getPostMutationMaxOffset(result, context) {
1611
1843
  }
1612
1844
  return Math.max(result.storyText.length, storySize);
1613
1845
  }
1846
+ function isTargetLocalTextLeaf(textTarget) {
1847
+ return textTarget?.kind === "text-leaf" && textTarget.blockPath.includes("/txbx/");
1848
+ }
1614
1849
  var editLayer = {
1615
1850
  applyTextInsert(doc, selection, text, context, formatting) {
1616
1851
  return validateResult(insertText(doc, selection, text, context, formatting), context);
@@ -1873,6 +2108,13 @@ function withCommandTextTarget(context, command) {
1873
2108
  textTarget: command.textTarget
1874
2109
  };
1875
2110
  }
2111
+ function listCommandContext(context) {
2112
+ return {
2113
+ timestamp: context.timestamp,
2114
+ ...context.activeStoryKey !== void 0 ? { activeStoryKey: context.activeStoryKey } : {},
2115
+ ...context.editableTargetCache !== void 0 ? { editableTargetCache: context.editableTargetCache } : {}
2116
+ };
2117
+ }
1876
2118
  function executeEditorCommand(state, command, context) {
1877
2119
  switch (command.type) {
1878
2120
  case "selection.set":
@@ -2514,7 +2756,17 @@ function executeEditorCommand(state, command, context) {
2514
2756
  });
2515
2757
  }
2516
2758
  case "list.toggle": {
2517
- const result = command.kind === "bulleted" ? toggleBulletedList(state.document, command.paragraphIndexes, { timestamp: context.timestamp }) : toggleNumberedList(state.document, command.paragraphIndexes, { timestamp: context.timestamp });
2759
+ const result = command.kind === "bulleted" ? toggleBulletedList(
2760
+ state.document,
2761
+ command.paragraphIndexes ?? [],
2762
+ listCommandContext(context),
2763
+ { editableTargets: command.editableTargets }
2764
+ ) : toggleNumberedList(
2765
+ state.document,
2766
+ command.paragraphIndexes ?? [],
2767
+ listCommandContext(context),
2768
+ { editableTargets: command.editableTargets }
2769
+ );
2518
2770
  return buildDocumentReplaceTransaction(state, context, {
2519
2771
  changed: result.affectedParagraphIndexes.length > 0,
2520
2772
  document: result.document,
@@ -2522,7 +2774,12 @@ function executeEditorCommand(state, command, context) {
2522
2774
  });
2523
2775
  }
2524
2776
  case "list.indent": {
2525
- const result = indentListItems(state.document, command.paragraphIndexes, { timestamp: context.timestamp });
2777
+ const result = indentListItems(
2778
+ state.document,
2779
+ command.paragraphIndexes ?? [],
2780
+ listCommandContext(context),
2781
+ { editableTargets: command.editableTargets }
2782
+ );
2526
2783
  return buildDocumentReplaceTransaction(state, context, {
2527
2784
  changed: result.affectedParagraphIndexes.length > 0,
2528
2785
  document: result.document,
@@ -2530,7 +2787,12 @@ function executeEditorCommand(state, command, context) {
2530
2787
  });
2531
2788
  }
2532
2789
  case "list.outdent": {
2533
- const result = outdentListItems(state.document, command.paragraphIndexes, { timestamp: context.timestamp });
2790
+ const result = outdentListItems(
2791
+ state.document,
2792
+ command.paragraphIndexes ?? [],
2793
+ listCommandContext(context),
2794
+ { editableTargets: command.editableTargets }
2795
+ );
2534
2796
  return buildDocumentReplaceTransaction(state, context, {
2535
2797
  changed: result.affectedParagraphIndexes.length > 0,
2536
2798
  document: result.document,
@@ -2540,9 +2802,10 @@ function executeEditorCommand(state, command, context) {
2540
2802
  case "list.restart-numbering": {
2541
2803
  const result = restartNumbering(
2542
2804
  state.document,
2543
- command.paragraphIndex,
2544
- { timestamp: context.timestamp },
2545
- command.startAt
2805
+ command.paragraphIndex ?? -1,
2806
+ listCommandContext(context),
2807
+ command.startAt,
2808
+ { editableTarget: command.editableTarget }
2546
2809
  );
2547
2810
  return buildDocumentReplaceTransaction(state, context, {
2548
2811
  changed: result.affectedParagraphIndexes.length > 0,
@@ -2553,8 +2816,9 @@ function executeEditorCommand(state, command, context) {
2553
2816
  case "list.continue-numbering": {
2554
2817
  const result = continueNumbering(
2555
2818
  state.document,
2556
- command.paragraphIndex,
2557
- { timestamp: context.timestamp }
2819
+ command.paragraphIndex ?? -1,
2820
+ listCommandContext(context),
2821
+ { editableTarget: command.editableTarget }
2558
2822
  );
2559
2823
  return buildDocumentReplaceTransaction(state, context, {
2560
2824
  changed: result.affectedParagraphIndexes.length > 0,
@@ -8731,6 +8995,16 @@ function createLayoutFacet(input) {
8731
8995
  function currentGraph() {
8732
8996
  return engine.getPageGraph(getQueryInput());
8733
8997
  }
8998
+ function fullGraphForViewportIndependentReads() {
8999
+ const query = getQueryInput();
9000
+ if (!query.viewportPageWindow) {
9001
+ return engine.getPageGraph(query);
9002
+ }
9003
+ return engine.getPageGraph({
9004
+ document: query.document,
9005
+ ...query.viewState ? { viewState: query.viewState } : {}
9006
+ });
9007
+ }
8734
9008
  function currentMapper() {
8735
9009
  return engine.getFragmentMapper(getQueryInput());
8736
9010
  }
@@ -8868,7 +9142,7 @@ function createLayoutFacet(input) {
8868
9142
  return graph.sections.map((section) => toPublicSectionNode(graph, section.index)).filter((node) => node !== null);
8869
9143
  },
8870
9144
  getPageForOffset(offset, story) {
8871
- const graph = currentGraph();
9145
+ const graph = fullGraphForViewportIndependentReads();
8872
9146
  const page = findPageForOffsetAndStory(graph, offset, story);
8873
9147
  return page ? toPublicPageNode(page, graph) : null;
8874
9148
  },
@@ -9180,7 +9454,7 @@ function createLayoutFacet(input) {
9180
9454
  return null;
9181
9455
  },
9182
9456
  getBlockHeightsTwips() {
9183
- const graph = currentGraph();
9457
+ const graph = fullGraphForViewportIndependentReads();
9184
9458
  if (blockHeightsCache.revision === graph.revision && blockHeightsCache.map) {
9185
9459
  return blockHeightsCache.map;
9186
9460
  }
@@ -11971,6 +12245,8 @@ function mapLocalSelectionOnRemoteReplay(selection, mapping) {
11971
12245
 
11972
12246
  // src/runtime/document-runtime.ts
11973
12247
  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;
11974
12250
  function getLocalTextPatchMetadata(mapping) {
11975
12251
  const metadata = mapping.metadata?.localTextPatch;
11976
12252
  if (!metadata || typeof metadata !== "object") {
@@ -12143,8 +12419,10 @@ function createDocumentRuntime(options) {
12143
12419
  void upgradeMeasurementProvider(layoutEngine, fontLoader);
12144
12420
  let renderKernelRef = null;
12145
12421
  let runtimeRef = null;
12422
+ const normalizedInitialSurfaceViewportRanges = options.initialSurfaceViewportBlockRanges && options.initialSurfaceViewportBlockRanges.length > 0 ? normalizeViewportRanges(options.initialSurfaceViewportBlockRanges) : null;
12423
+ let initialSurfaceViewportBlockRanges = normalizedInitialSurfaceViewportRanges && normalizedInitialSurfaceViewportRanges.length > 0 ? normalizedInitialSurfaceViewportRanges : null;
12146
12424
  let viewportBlockRanges = null;
12147
- let viewportRangesKey = serializeViewportRanges(null);
12425
+ let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
12148
12426
  let viewportBlocksPerPageEstimate = null;
12149
12427
  const EDITING_CORRIDOR_BLOCK_RADIUS = 8;
12150
12428
  const getRuntimeForLayoutFacet = () => {
@@ -12384,10 +12662,11 @@ function createDocumentRuntime(options) {
12384
12662
  const cachedContextAnalyticsSnapshots = /* @__PURE__ */ new Map();
12385
12663
  let lastEmittedContextAnalyticsSnapshots;
12386
12664
  function getCachedFullSurface(document, nextActiveStory) {
12387
- const activeStoryKey = storyTargetKey(nextActiveStory);
12388
- if (cachedFullSurface && cachedFullSurface.content === document.content && cachedFullSurface.subParts === document.subParts && cachedFullSurface.styles === document.styles && cachedFullSurface.numbering === document.numbering && cachedFullSurface.media === document.media && cachedFullSurface.preservation === document.preservation && cachedFullSurface.review === document.review && cachedFullSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedFullSurface.activeStoryKey === activeStoryKey) {
12389
- return cachedFullSurface.snapshot;
12665
+ const cached = getReusableCachedFullSurface(document, nextActiveStory);
12666
+ if (cached) {
12667
+ return cached;
12390
12668
  }
12669
+ const activeStoryKey = storyTargetKey(nextActiveStory);
12391
12670
  const snapshot = createEditorSurfaceSnapshot(document, state.selection, nextActiveStory, {
12392
12671
  viewportBlockRanges: null,
12393
12672
  editableTargetsByBlockPath: getEditableTargetsByBlockPath(document),
@@ -12409,6 +12688,13 @@ function createDocumentRuntime(options) {
12409
12688
  };
12410
12689
  return snapshot;
12411
12690
  }
12691
+ function getReusableCachedFullSurface(document, nextActiveStory) {
12692
+ const activeStoryKey = storyTargetKey(nextActiveStory);
12693
+ if (cachedFullSurface && cachedFullSurface.content === document.content && cachedFullSurface.subParts === document.subParts && cachedFullSurface.styles === document.styles && cachedFullSurface.numbering === document.numbering && cachedFullSurface.media === document.media && cachedFullSurface.preservation === document.preservation && cachedFullSurface.review === document.review && cachedFullSurface.effectiveMarkupModeProvider === effectiveMarkupModeProvider && cachedFullSurface.activeStoryKey === activeStoryKey) {
12694
+ return cachedFullSurface.snapshot;
12695
+ }
12696
+ return void 0;
12697
+ }
12412
12698
  function getCachedSurface(document, nextActiveStory, options2 = {}) {
12413
12699
  const activeStoryKey = storyTargetKey(nextActiveStory);
12414
12700
  const surfaceViewportRanges = "viewportBlockRangesOverride" in options2 ? options2.viewportBlockRangesOverride ?? null : viewportBlockRanges;
@@ -12419,12 +12705,20 @@ function createDocumentRuntime(options) {
12419
12705
  }
12420
12706
  const snapshot = createEditorSurfaceSnapshot(document, state.selection, nextActiveStory, {
12421
12707
  viewportBlockRanges: surfaceViewportRanges,
12422
- editableTargetsByBlockPath: options2.editableTargetsByBlockPathOverride ?? getEditableTargetsByBlockPath(document),
12708
+ editableTargetsByBlockPath: options2.editableTargetsByBlockPathOverride ?? getEditableTargetsByBlockPathForRanges(
12709
+ document,
12710
+ activeStoryKey,
12711
+ surfaceViewportRanges
12712
+ ),
12423
12713
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
12424
12714
  });
12425
12715
  recordPerfSample("snapshot.surface");
12426
12716
  incrementInvalidationCounter("runtime.snapshot.surfaceMisses");
12427
- const enrichedSnapshot = options2.enrichCulledPlaceholders === false ? snapshot : enrichCulledPlaceholdersWithHeights(snapshot);
12717
+ const enrichedSnapshot = options2.enrichCulledPlaceholders === false ? snapshot : enrichCulledPlaceholdersWithHeights(
12718
+ snapshot,
12719
+ document,
12720
+ nextActiveStory
12721
+ );
12428
12722
  if (surfaceViewportRanges === null) {
12429
12723
  cachedFullSurface = {
12430
12724
  content: document.content,
@@ -12482,7 +12776,7 @@ function createDocumentRuntime(options) {
12482
12776
  }
12483
12777
  return -1;
12484
12778
  }
12485
- function cachePatchedLocalTextSurface(surface) {
12779
+ function cachePatchedLocalTextSurface(surface, fullSurfaceForCache) {
12486
12780
  const activeStoryKey = storyTargetKey(activeStory);
12487
12781
  const rangesKey = serializeViewportRanges(surface.viewportBlockRanges);
12488
12782
  cachedSurface = {
@@ -12498,7 +12792,8 @@ function createDocumentRuntime(options) {
12498
12792
  viewportRangesKey: rangesKey,
12499
12793
  snapshot: surface
12500
12794
  };
12501
- if (surface.viewportBlockRanges === null) {
12795
+ const fullSurface = fullSurfaceForCache ?? (surface.viewportBlockRanges === null ? surface : void 0);
12796
+ if (fullSurface) {
12502
12797
  cachedFullSurface = {
12503
12798
  content: state.document.content,
12504
12799
  subParts: state.document.subParts,
@@ -12509,11 +12804,15 @@ function createDocumentRuntime(options) {
12509
12804
  review: state.document.review,
12510
12805
  effectiveMarkupModeProvider,
12511
12806
  activeStoryKey,
12512
- snapshot: surface
12807
+ snapshot: fullSurface
12513
12808
  };
12514
12809
  }
12515
12810
  cachedSurfaceFingerprint = `${activeStoryKey}|${rangesKey}|${String(state.selection.anchor)}:${String(state.selection.head)}`;
12516
12811
  }
12812
+ function createLocalTextCorridorSurfaceFromFullSurface(fullSurface) {
12813
+ const ranges = getSelectionCorridorViewportRanges(fullSurface);
12814
+ return ranges ? createViewportCulledSurfaceFromFullSurface(fullSurface, ranges) : fullSurface;
12815
+ }
12517
12816
  function tryPatchLocalTextSurface(previousSurface, mapping) {
12518
12817
  const tTotal0 = performance.now();
12519
12818
  try {
@@ -12549,6 +12848,13 @@ function createDocumentRuntime(options) {
12549
12848
  perfCounters.increment("surface.localText.patchMiss");
12550
12849
  return null;
12551
12850
  }
12851
+ const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, blockIndex + 1);
12852
+ perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
12853
+ perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
12854
+ if (!shiftBudget.withinBudget) {
12855
+ perfCounters.increment("surface.localText.patchBudgetFallback");
12856
+ return null;
12857
+ }
12552
12858
  const segmentIndex = block.segments.findIndex(
12553
12859
  (segment2) => segment2.kind === "text" && editFrom >= segment2.from && editTo <= segment2.to
12554
12860
  );
@@ -12656,7 +12962,83 @@ function createDocumentRuntime(options) {
12656
12962
  };
12657
12963
  }
12658
12964
  }
12659
- function enrichCulledPlaceholdersWithHeights(snapshot) {
12965
+ function estimateLocalTextPatchShiftBudget(blocks, startIndex) {
12966
+ const shiftedBlocks = Math.max(0, blocks.length - startIndex);
12967
+ let shiftedNodes = 0;
12968
+ for (let index = startIndex; index < blocks.length; index += 1) {
12969
+ const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
12970
+ blocks[index],
12971
+ Math.min(
12972
+ LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK,
12973
+ LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES - shiftedNodes
12974
+ ) + 1
12975
+ );
12976
+ shiftedNodes += shiftedBlockNodes;
12977
+ if (shiftedBlockNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_NODES_PER_BLOCK) {
12978
+ return {
12979
+ shiftedBlocks,
12980
+ shiftedNodes,
12981
+ withinBudget: false
12982
+ };
12983
+ }
12984
+ if (shiftedNodes > LOCAL_TEXT_PATCH_MAX_SHIFTED_SURFACE_NODES) {
12985
+ return {
12986
+ shiftedBlocks,
12987
+ shiftedNodes,
12988
+ withinBudget: false
12989
+ };
12990
+ }
12991
+ }
12992
+ return {
12993
+ shiftedBlocks,
12994
+ shiftedNodes,
12995
+ withinBudget: true
12996
+ };
12997
+ }
12998
+ function countSurfaceShiftNodesUpTo(block, limit) {
12999
+ if (limit <= 0) {
13000
+ return 1;
13001
+ }
13002
+ switch (block.kind) {
13003
+ case "paragraph":
13004
+ return 1 + block.segments.length;
13005
+ case "opaque_block":
13006
+ return 1;
13007
+ case "sdt_block": {
13008
+ let total = 1;
13009
+ for (const child of block.children) {
13010
+ total += countSurfaceShiftNodesUpTo(child, limit - total);
13011
+ if (total > limit) {
13012
+ return total;
13013
+ }
13014
+ }
13015
+ return total;
13016
+ }
13017
+ case "table": {
13018
+ let total = 1;
13019
+ for (const row2 of block.rows) {
13020
+ total += 1;
13021
+ if (total > limit) {
13022
+ return total;
13023
+ }
13024
+ for (const cell of row2.cells) {
13025
+ total += 1;
13026
+ if (total > limit) {
13027
+ return total;
13028
+ }
13029
+ for (const child of cell.content) {
13030
+ total += countSurfaceShiftNodesUpTo(child, limit - total);
13031
+ if (total > limit) {
13032
+ return total;
13033
+ }
13034
+ }
13035
+ }
13036
+ }
13037
+ return total;
13038
+ }
13039
+ }
13040
+ }
13041
+ function enrichCulledPlaceholdersWithHeights(snapshot, document, nextActiveStory, fullSurfaceForPlaceholders) {
12660
13042
  let heights;
12661
13043
  try {
12662
13044
  heights = layoutFacet.getBlockHeightsTwips();
@@ -12664,17 +13046,19 @@ function createDocumentRuntime(options) {
12664
13046
  return snapshot;
12665
13047
  }
12666
13048
  if (heights.size === 0) return snapshot;
13049
+ const fullSurface = fullSurfaceForPlaceholders ?? getReusableCachedFullSurface(document, nextActiveStory);
13050
+ if (!fullSurface) return snapshot;
12667
13051
  let changed = false;
12668
13052
  const enrichedBlocks = snapshot.blocks.map((block) => {
12669
13053
  if (block.kind !== "opaque_block" || block.state !== "placeholder-culled") {
12670
13054
  return block;
12671
13055
  }
12672
- const realBlockIdFromOffset = resolveBlockIdFromRuntimeOffset(
12673
- layoutFacet,
12674
- block.from
13056
+ const realBlock = resolveFullSurfaceBlockForPlaceholder(
13057
+ fullSurface,
13058
+ block
12675
13059
  );
12676
- if (!realBlockIdFromOffset) return block;
12677
- const heightTwips = heights.get(realBlockIdFromOffset);
13060
+ if (!realBlock) return block;
13061
+ const heightTwips = heights.get(realBlock.blockId);
12678
13062
  if (typeof heightTwips !== "number" || heightTwips <= 0) return block;
12679
13063
  changed = true;
12680
13064
  return { ...block, placeholderHeightTwips: heightTwips };
@@ -12682,13 +13066,20 @@ function createDocumentRuntime(options) {
12682
13066
  if (!changed) return snapshot;
12683
13067
  return { ...snapshot, blocks: enrichedBlocks };
12684
13068
  }
12685
- function resolveBlockIdFromRuntimeOffset(facet, runtimeOffset) {
12686
- try {
12687
- const frag = facet.getFragmentForOffset?.(runtimeOffset);
12688
- return frag?.blockId ?? null;
12689
- } catch {
12690
- return null;
13069
+ function resolveFullSurfaceBlockForPlaceholder(fullSurface, placeholder) {
13070
+ const index = parsePlaceholderCulledIndex(placeholder.blockId);
13071
+ if (index !== null) {
13072
+ return fullSurface.blocks[index] ?? null;
12691
13073
  }
13074
+ return fullSurface.blocks.find(
13075
+ (block) => block.from === placeholder.from && block.to === placeholder.to
13076
+ ) ?? null;
13077
+ }
13078
+ function parsePlaceholderCulledIndex(blockId) {
13079
+ const match = /^placeholder-culled-(\d+)$/.exec(blockId);
13080
+ if (!match) return null;
13081
+ const index = Number(match[1]);
13082
+ return Number.isSafeInteger(index) ? index : null;
12692
13083
  }
12693
13084
  function getCachedFieldSnapshot(document) {
12694
13085
  const blockCount = document.content.children.length;
@@ -13253,7 +13644,14 @@ function createDocumentRuntime(options) {
13253
13644
  revisionToken: state.revisionToken
13254
13645
  });
13255
13646
  perfCounters.increment("refresh.all");
13256
- const surface = timeFacet("surface", () => getCachedSurface(state.document, activeStory));
13647
+ const firstSurfaceViewportBlockRanges = initialSurfaceViewportBlockRanges;
13648
+ initialSurfaceViewportBlockRanges = null;
13649
+ const surface = timeFacet(
13650
+ "surface",
13651
+ () => firstSurfaceViewportBlockRanges ? getCachedSurface(state.document, activeStory, {
13652
+ viewportBlockRangesOverride: firstSurfaceViewportBlockRanges
13653
+ }) : getCachedSurface(state.document, activeStory)
13654
+ );
13257
13655
  const snapshot = {
13258
13656
  documentId: state.documentId,
13259
13657
  sessionId: state.sessionId,
@@ -13351,8 +13749,10 @@ function createDocumentRuntime(options) {
13351
13749
  if (options2.forceProjection) {
13352
13750
  cachedFullSurface = void 0;
13353
13751
  }
13354
- const newSurface = viewportBlockRanges !== null && options2.forceProjection !== true ? createViewportCulledSurfaceFromFullSurface(
13355
- getCachedFullSurface(state.document, activeStory),
13752
+ const reusableFullSurface = viewportBlockRanges !== null && options2.forceProjection !== true ? getReusableCachedFullSurface(state.document, activeStory) : void 0;
13753
+ const derivedFromFull = viewportBlockRanges !== null && reusableFullSurface !== void 0;
13754
+ const projectedSurface = derivedFromFull ? createViewportCulledSurfaceFromFullSurface(
13755
+ reusableFullSurface,
13356
13756
  viewportBlockRanges
13357
13757
  ) : createEditorSurfaceSnapshot(
13358
13758
  state.document,
@@ -13360,11 +13760,21 @@ function createDocumentRuntime(options) {
13360
13760
  activeStory,
13361
13761
  {
13362
13762
  viewportBlockRanges,
13363
- editableTargetsByBlockPath: getEditableTargetsByBlockPath(state.document),
13763
+ editableTargetsByBlockPath: getEditableTargetsByBlockPathForRanges(
13764
+ state.document,
13765
+ activeStoryKey,
13766
+ viewportBlockRanges
13767
+ ),
13364
13768
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
13365
13769
  }
13366
13770
  );
13367
- if (viewportBlockRanges !== null && options2.forceProjection !== true) {
13771
+ const newSurface = viewportBlockRanges !== null ? enrichCulledPlaceholdersWithHeights(
13772
+ projectedSurface,
13773
+ state.document,
13774
+ activeStory,
13775
+ reusableFullSurface
13776
+ ) : projectedSurface;
13777
+ if (derivedFromFull) {
13368
13778
  perfCounters.increment("runtime.viewport.derivedSurfaceRefreshes");
13369
13779
  } else {
13370
13780
  recordPerfSample("snapshot.surface");
@@ -13908,6 +14318,8 @@ function createDocumentRuntime(options) {
13908
14318
  documentMode: workflowCoordinator.getEffectiveDocumentMode(commandSelection),
13909
14319
  defaultAuthorId: defaultAuthorId ?? void 0,
13910
14320
  renderSnapshot: cachedRenderSnapshot,
14321
+ activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
14322
+ editableTargetCache: editableTargetBlockCache,
13911
14323
  ...resolvedFragmentTextTarget ? { textTarget: resolvedFragmentTextTarget } : {}
13912
14324
  };
13913
14325
  const preSelection = commandSelection;
@@ -14435,12 +14847,86 @@ function createDocumentRuntime(options) {
14435
14847
  }
14436
14848
  },
14437
14849
  applyScopeReplacement(plan) {
14850
+ const resolveEditableTargetHint = (hint) => {
14851
+ if (!hint) return void 0;
14852
+ const activeStoryKey = storyTargetKey(activeStory);
14853
+ if (hint.storyKey !== activeStoryKey) return null;
14854
+ const currentTargets = collectEditableTargetRefs(
14855
+ state.document,
14856
+ editableTargetBlockCache
14857
+ );
14858
+ const target = currentTargets.find(
14859
+ (target2) => target2.storyKey === hint.storyKey && target2.blockPath === hint.blockPath && target2.commandFamily === "text-leaf"
14860
+ );
14861
+ if (!target) return null;
14862
+ const fallbackTextTarget = {
14863
+ kind: "text-leaf",
14864
+ blockPath: target.blockPath,
14865
+ paragraphStart: hint.semanticBlockRange.from,
14866
+ paragraphEnd: hint.semanticBlockRange.to
14867
+ };
14868
+ const resolved = resolveEditableTextTarget({
14869
+ document: state.document,
14870
+ surface: cachedRenderSnapshot.surface?.blocks ?? [],
14871
+ target,
14872
+ activeStoryKey,
14873
+ editableTargetCache: editableTargetBlockCache
14874
+ });
14875
+ if (resolved.kind === "rejected") {
14876
+ return {
14877
+ textTarget: fallbackTextTarget,
14878
+ range: hint.semanticBlockRange
14879
+ };
14880
+ }
14881
+ return {
14882
+ target,
14883
+ textTarget: resolved.textTarget ?? fallbackTextTarget,
14884
+ range: resolved.range
14885
+ };
14886
+ };
14887
+ const mapSemanticStepRangeToEditableTarget = (stepRange, hint, editableRange) => {
14888
+ if (!hint || !editableRange) return stepRange;
14889
+ const semanticFrom = hint.semanticBlockRange.from;
14890
+ const semanticTo = hint.semanticBlockRange.to;
14891
+ const localFrom = Math.max(0, stepRange.from - semanticFrom);
14892
+ const localTo = Math.max(localFrom, stepRange.to - semanticFrom);
14893
+ const semanticLength = Math.max(0, semanticTo - semanticFrom);
14894
+ const editableLength = Math.max(0, editableRange.to - editableRange.from);
14895
+ if (semanticLength === editableLength) {
14896
+ return {
14897
+ from: editableRange.from + localFrom,
14898
+ to: editableRange.from + localTo
14899
+ };
14900
+ }
14901
+ if (stepRange.from === semanticFrom && stepRange.to === semanticTo) {
14902
+ return editableRange;
14903
+ }
14904
+ return stepRange;
14905
+ };
14438
14906
  for (const step of plan.steps) {
14439
14907
  if (step.kind === "text-replace" && step.range && typeof step.text === "string") {
14908
+ const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
14909
+ if (editableTarget === null) {
14910
+ emit({
14911
+ type: "command_blocked",
14912
+ documentId: state.documentId,
14913
+ command: "applyScopeReplacement",
14914
+ reasons: [{
14915
+ code: "unsupported_surface",
14916
+ message: "Scope replacement editable target no longer resolves."
14917
+ }]
14918
+ });
14919
+ continue;
14920
+ }
14921
+ const dispatchRange = mapSemanticStepRangeToEditableTarget(
14922
+ step.range,
14923
+ step.editableTargetHint,
14924
+ editableTarget?.range
14925
+ );
14440
14926
  const anchor = {
14441
14927
  kind: "range",
14442
- from: step.range.from,
14443
- to: step.range.to,
14928
+ from: dispatchRange.from,
14929
+ to: dispatchRange.to,
14444
14930
  assoc: { start: -1, end: 1 }
14445
14931
  };
14446
14932
  const timestamp = clock();
@@ -14449,6 +14935,8 @@ function createDocumentRuntime(options) {
14449
14935
  {
14450
14936
  type: "text.insert",
14451
14937
  text: step.text,
14938
+ ...editableTarget?.target ? { editableTarget: editableTarget.target } : {},
14939
+ ...editableTarget?.textTarget ? { textTarget: editableTarget.textTarget } : {},
14452
14940
  ...step.formatting ? { formatting: step.formatting } : {},
14453
14941
  origin: createOrigin("api", timestamp)
14454
14942
  },
@@ -14486,10 +14974,28 @@ function createDocumentRuntime(options) {
14486
14974
  emitError(toRuntimeError(error));
14487
14975
  }
14488
14976
  } else if (step.kind === "text-insert-tracked" && step.range && typeof step.text === "string") {
14977
+ const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
14978
+ if (editableTarget === null) {
14979
+ emit({
14980
+ type: "command_blocked",
14981
+ documentId: state.documentId,
14982
+ command: "applyScopeReplacement",
14983
+ reasons: [{
14984
+ code: "unsupported_surface",
14985
+ message: "Scope replacement editable target no longer resolves."
14986
+ }]
14987
+ });
14988
+ continue;
14989
+ }
14990
+ const dispatchRange = mapSemanticStepRangeToEditableTarget(
14991
+ step.range,
14992
+ step.editableTargetHint,
14993
+ editableTarget?.range
14994
+ );
14489
14995
  const anchor = {
14490
14996
  kind: "range",
14491
- from: step.range.from,
14492
- to: step.range.to,
14997
+ from: dispatchRange.from,
14998
+ to: dispatchRange.to,
14493
14999
  assoc: { start: -1, end: 1 }
14494
15000
  };
14495
15001
  const timestamp = clock();
@@ -14498,6 +15004,8 @@ function createDocumentRuntime(options) {
14498
15004
  {
14499
15005
  type: "text.insert",
14500
15006
  text: step.text,
15007
+ ...editableTarget?.target ? { editableTarget: editableTarget.target } : {},
15008
+ ...editableTarget?.textTarget ? { textTarget: editableTarget.textTarget } : {},
14501
15009
  ...step.formatting ? { formatting: step.formatting } : {},
14502
15010
  origin: createOrigin("api", timestamp)
14503
15011
  },
@@ -14512,10 +15020,28 @@ function createDocumentRuntime(options) {
14512
15020
  emitError(toRuntimeError(error));
14513
15021
  }
14514
15022
  } else if (step.kind === "text-delete-tracked" && step.range && step.range.to > step.range.from) {
15023
+ const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
15024
+ if (editableTarget === null) {
15025
+ emit({
15026
+ type: "command_blocked",
15027
+ documentId: state.documentId,
15028
+ command: "applyScopeReplacement",
15029
+ reasons: [{
15030
+ code: "unsupported_surface",
15031
+ message: "Scope replacement editable target no longer resolves."
15032
+ }]
15033
+ });
15034
+ continue;
15035
+ }
15036
+ const dispatchRange = mapSemanticStepRangeToEditableTarget(
15037
+ step.range,
15038
+ step.editableTargetHint,
15039
+ editableTarget?.range
15040
+ );
14515
15041
  const anchor = {
14516
15042
  kind: "range",
14517
- from: step.range.from,
14518
- to: step.range.to,
15043
+ from: dispatchRange.from,
15044
+ to: dispatchRange.to,
14519
15045
  assoc: { start: -1, end: 1 }
14520
15046
  };
14521
15047
  const timestamp = clock();
@@ -14523,6 +15049,8 @@ function createDocumentRuntime(options) {
14523
15049
  applyTextCommandInActiveStory(
14524
15050
  {
14525
15051
  type: "text.delete-forward",
15052
+ ...editableTarget?.target ? { editableTarget: editableTarget.target } : {},
15053
+ ...editableTarget?.textTarget ? { textTarget: editableTarget.textTarget } : {},
14526
15054
  origin: createOrigin("api", timestamp)
14527
15055
  },
14528
15056
  {
@@ -16043,9 +16571,13 @@ function createDocumentRuntime(options) {
16043
16571
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
16044
16572
  }
16045
16573
  const tValidation0 = performance.now();
16046
- const patchedLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(cachedRenderSnapshot.surface, transaction.mapping) : null;
16574
+ const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(cachedRenderSnapshot.surface, transaction.mapping) : null;
16575
+ const patchedLocalTextSurface = patchedFullLocalTextSurface ? createLocalTextCorridorSurfaceFromFullSurface(patchedFullLocalTextSurface) : null;
16047
16576
  if (patchedLocalTextSurface) {
16048
- cachePatchedLocalTextSurface(patchedLocalTextSurface);
16577
+ cachePatchedLocalTextSurface(
16578
+ patchedLocalTextSurface,
16579
+ patchedFullLocalTextSurface ?? void 0
16580
+ );
16049
16581
  perfCounters.increment("commit.localTextValidation.storySizeOnly");
16050
16582
  }
16051
16583
  const localTextViewportRanges = useLocalTextCommitSnapshot && !patchedLocalTextSurface ? getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface) : void 0;
@@ -16085,7 +16617,8 @@ function createDocumentRuntime(options) {
16085
16617
  cachedRenderSnapshot = useLocalTextCommitSnapshot ? refreshLocalTextCommitSnapshot(surfaceForValidation, transaction.mapping) : refreshRenderSnapshot();
16086
16618
  perfCounters.increment("commit.refresh.us", Math.round((performance.now() - tRefresh0) * 1e3));
16087
16619
  const tNotify0 = performance.now();
16088
- deferNextContextAnalyticsEmit = useLocalTextCommitSnapshot;
16620
+ const shouldDeferContextAnalyticsEmit = transaction.markDirty && transaction.mapping.steps.length > 0;
16621
+ deferNextContextAnalyticsEmit = shouldDeferContextAnalyticsEmit;
16089
16622
  try {
16090
16623
  notify(previous, state, {
16091
16624
  ...transaction,
@@ -16386,6 +16919,8 @@ function createDocumentRuntime(options) {
16386
16919
  documentMode: textOptions.documentModeOverride ?? workflowCoordinator.getEffectiveDocumentMode(selection),
16387
16920
  defaultAuthorId: defaultAuthorId ?? void 0,
16388
16921
  renderSnapshot: cachedRenderSnapshot,
16922
+ activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
16923
+ editableTargetCache: editableTargetBlockCache,
16389
16924
  activeStorySize: cachedRenderSnapshot.surface?.storySize,
16390
16925
  textTarget,
16391
16926
  rejectTargetlessTableStructureInsert: true
@@ -16686,7 +17221,9 @@ function createDocumentRuntime(options) {
16686
17221
  timestamp: clock(),
16687
17222
  documentMode: workflowCoordinator.getEffectiveDocumentMode(state.selection),
16688
17223
  defaultAuthorId: defaultAuthorId ?? void 0,
16689
- renderSnapshot: cachedRenderSnapshot
17224
+ renderSnapshot: cachedRenderSnapshot,
17225
+ activeStoryKey: canonicalEditableTargetStoryKey(activeStory),
17226
+ editableTargetCache: editableTargetBlockCache
16690
17227
  };
16691
17228
  try {
16692
17229
  const transaction = executeEditorCommand(