@beyondwork/docx-react-component 1.0.133 → 1.0.135

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 (83) hide show
  1. package/dist/api/public-types.cjs +23 -3
  2. package/dist/api/public-types.d.cts +1 -1
  3. package/dist/api/public-types.d.ts +1 -1
  4. package/dist/api/public-types.js +2 -2
  5. package/dist/api/v3.cjs +708 -47
  6. package/dist/api/v3.d.cts +2 -2
  7. package/dist/api/v3.d.ts +2 -2
  8. package/dist/api/v3.js +4 -4
  9. package/dist/{chunk-REFHJ2FN.js → chunk-2BNXARVO.js} +3 -3
  10. package/dist/{chunk-INLRCC4N.js → chunk-4CIHTMCH.js} +2 -2
  11. package/dist/{chunk-224TSMEB.js → chunk-5CCYF333.js} +138 -42
  12. package/dist/{chunk-MQ5GAJ54.js → chunk-BJXSMPHD.js} +1 -1
  13. package/dist/{chunk-OTRVGNZQ.js → chunk-EPFVMUKF.js} +548 -3
  14. package/dist/{chunk-XBQFDBXE.js → chunk-EZFF6GKF.js} +9 -2
  15. package/dist/{chunk-S3PEKX6H.js → chunk-FGJTOFZY.js} +72 -554
  16. package/dist/{chunk-3JEE5RJU.js → chunk-GIFXKIM5.js} +612 -34
  17. package/dist/{chunk-57HTKX3P.js → chunk-H4HI6RUE.js} +1 -1
  18. package/dist/{chunk-KL4TZSZV.js → chunk-HWMPNLEF.js} +1 -1
  19. package/dist/{chunk-ZFCZ7XXH.js → chunk-NEMOQ4QR.js} +1 -1
  20. package/dist/{chunk-CVSD3UNK.js → chunk-P7XDEVS6.js} +15 -2
  21. package/dist/{chunk-QTRJLKR2.js → chunk-TSNK4ECL.js} +1 -1
  22. package/dist/{chunk-WDDFU2N2.js → chunk-UR2LW63N.js} +1 -1
  23. package/dist/core/commands/formatting-commands.d.cts +1 -1
  24. package/dist/core/commands/formatting-commands.d.ts +1 -1
  25. package/dist/core/commands/image-commands.cjs +9 -2
  26. package/dist/core/commands/image-commands.d.cts +1 -1
  27. package/dist/core/commands/image-commands.d.ts +1 -1
  28. package/dist/core/commands/image-commands.js +4 -4
  29. package/dist/core/commands/section-layout-commands.d.cts +1 -1
  30. package/dist/core/commands/section-layout-commands.d.ts +1 -1
  31. package/dist/core/commands/style-commands.d.cts +1 -1
  32. package/dist/core/commands/style-commands.d.ts +1 -1
  33. package/dist/core/commands/table-structure-commands.cjs +9 -2
  34. package/dist/core/commands/table-structure-commands.d.cts +1 -1
  35. package/dist/core/commands/table-structure-commands.d.ts +1 -1
  36. package/dist/core/commands/table-structure-commands.js +3 -3
  37. package/dist/core/commands/text-commands.cjs +9 -2
  38. package/dist/core/commands/text-commands.d.cts +1 -1
  39. package/dist/core/commands/text-commands.d.ts +1 -1
  40. package/dist/core/commands/text-commands.js +4 -4
  41. package/dist/core/selection/mapping.d.cts +1 -1
  42. package/dist/core/selection/mapping.d.ts +1 -1
  43. package/dist/core/state/editor-state.d.cts +1 -1
  44. package/dist/core/state/editor-state.d.ts +1 -1
  45. package/dist/index.cjs +1478 -636
  46. package/dist/index.d.cts +4 -4
  47. package/dist/index.d.ts +4 -4
  48. package/dist/index.js +113 -26
  49. package/dist/io/docx-session.d.cts +3 -3
  50. package/dist/io/docx-session.d.ts +3 -3
  51. package/dist/{loader-B2H99237.d.cts → loader-BQ7AB-0v.d.cts} +2 -2
  52. package/dist/{loader-DfTjqVwn.d.ts → loader-Cy6OYBfn.d.ts} +2 -2
  53. package/dist/{public-types-S8gTYwKo.d.cts → public-types-D31xKNGc.d.cts} +146 -3
  54. package/dist/{public-types-B5lOUIrP.d.ts → public-types-DqYt8GdP.d.ts} +146 -3
  55. package/dist/public-types.cjs +23 -3
  56. package/dist/public-types.d.cts +1 -1
  57. package/dist/public-types.d.ts +1 -1
  58. package/dist/public-types.js +2 -2
  59. package/dist/runtime/collab.d.cts +2 -2
  60. package/dist/runtime/collab.d.ts +2 -2
  61. package/dist/runtime/document-runtime.cjs +760 -68
  62. package/dist/runtime/document-runtime.d.cts +1 -1
  63. package/dist/runtime/document-runtime.d.ts +1 -1
  64. package/dist/runtime/document-runtime.js +10 -10
  65. package/dist/{session-CR2A1hGZ.d.cts → session-DA-F2fCw.d.cts} +2 -2
  66. package/dist/{session-CBDIOYXA.d.ts → session-DqL8H0oZ.d.ts} +2 -2
  67. package/dist/session.d.cts +4 -4
  68. package/dist/session.d.ts +4 -4
  69. package/dist/tailwind.cjs +81 -554
  70. package/dist/tailwind.d.cts +1 -1
  71. package/dist/tailwind.d.ts +1 -1
  72. package/dist/tailwind.js +5 -5
  73. package/dist/{types-yty2K-hk.d.cts → types-B2y94n5t.d.cts} +1 -1
  74. package/dist/{types-B-90ywjU.d.ts → types-SllbCtGs.d.ts} +1 -1
  75. package/dist/ui-tailwind/editor-surface/search-plugin.cjs +11 -0
  76. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +2 -2
  77. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +2 -2
  78. package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
  79. package/dist/ui-tailwind.cjs +81 -554
  80. package/dist/ui-tailwind.d.cts +2 -2
  81. package/dist/ui-tailwind.d.ts +2 -2
  82. package/dist/ui-tailwind.js +5 -5
  83. package/package.json +1 -1
@@ -22,7 +22,7 @@ import {
22
22
  insertText,
23
23
  outdentParagraphAtSelection,
24
24
  splitParagraph
25
- } from "./chunk-REFHJ2FN.js";
25
+ } from "./chunk-2BNXARVO.js";
26
26
  import {
27
27
  applyFormattingOperationToDocument,
28
28
  applyTextMarkOperationToDocumentRange,
@@ -32,23 +32,23 @@ import {
32
32
  insertImage,
33
33
  repositionFloatingImage,
34
34
  resizeImage
35
- } from "./chunk-INLRCC4N.js";
35
+ } from "./chunk-4CIHTMCH.js";
36
36
  import {
37
37
  applyTextTransaction
38
- } from "./chunk-MQ5GAJ54.js";
38
+ } from "./chunk-BJXSMPHD.js";
39
39
  import {
40
40
  applyTableStructureOperationForEditableTarget,
41
41
  removeCellFromRow,
42
42
  removeTableRowPure
43
- } from "./chunk-WDDFU2N2.js";
43
+ } from "./chunk-UR2LW63N.js";
44
44
  import {
45
45
  resolveParagraphScope
46
- } from "./chunk-QTRJLKR2.js";
46
+ } from "./chunk-TSNK4ECL.js";
47
47
  import {
48
48
  buildGeometryDebugEntry,
49
49
  collectLineBoxesForRegion,
50
50
  createGeometryFacet
51
- } from "./chunk-57HTKX3P.js";
51
+ } from "./chunk-H4HI6RUE.js";
52
52
  import {
53
53
  AI_ACTION_POLICIES,
54
54
  allocateNumberingInstance,
@@ -83,7 +83,7 @@ import {
83
83
  sameScopeParagraphPath,
84
84
  serializeFragmentToWordML,
85
85
  setStartOverride
86
- } from "./chunk-224TSMEB.js";
86
+ } from "./chunk-5CCYF333.js";
87
87
  import {
88
88
  ISSUE_METADATA_ID,
89
89
  LAYOUT_ENGINE_VERSION,
@@ -121,7 +121,7 @@ import {
121
121
  setWorkspaceMode,
122
122
  setZoomLevel,
123
123
  snapCommentAnchorAwayFromTable
124
- } from "./chunk-CVSD3UNK.js";
124
+ } from "./chunk-P7XDEVS6.js";
125
125
  import {
126
126
  countLogicalPositions,
127
127
  createPlainText,
@@ -130,6 +130,7 @@ import {
130
130
  serializeTextStory
131
131
  } from "./chunk-QIO6V46H.js";
132
132
  import {
133
+ NO_EDITABLE_TARGETS_INDEX,
133
134
  ThemeColorResolver,
134
135
  createEditorSurfaceSnapshot,
135
136
  createFieldResolver,
@@ -140,7 +141,7 @@ import {
140
141
  replaceStoryBlocks,
141
142
  resolvePageFieldDisplayText,
142
143
  storyTargetKey
143
- } from "./chunk-XBQFDBXE.js";
144
+ } from "./chunk-EZFF6GKF.js";
144
145
  import {
145
146
  createCommentSidebarProjection,
146
147
  createCommentStoreFromRuntimeComments
@@ -528,9 +529,11 @@ function applyRevisionAction(options) {
528
529
  );
529
530
  }
530
531
  const slice = story.units.slice(range.from, range.to);
531
- if (slice.some(
532
- (unit) => unit.kind === "paragraph_break" || unit.kind === "opaque_block" || unit.kind === "structural_block"
533
- )) {
532
+ const touchesStructuralContent = slice.some(
533
+ (unit) => unit.kind === "opaque_block" || unit.kind === "structural_block"
534
+ );
535
+ const touchesParagraphBoundary = slice.some((unit) => unit.kind === "paragraph_break");
536
+ if (touchesStructuralContent || touchesParagraphBoundary && !canApplyRuntimeTextBlockDeletion(revision, options.intent)) {
534
537
  return skippedResult(
535
538
  options,
536
539
  "structural-range",
@@ -538,7 +541,7 @@ function applyRevisionAction(options) {
538
541
  );
539
542
  }
540
543
  if (slice.some(
541
- (unit) => unit.kind === "image" || unit.kind === "opaque_inline"
544
+ (unit) => unit.kind === "image" || unit.kind === "opaque_inline" || unit.kind === "protected_inline"
542
545
  )) {
543
546
  return skippedResult(
544
547
  options,
@@ -593,6 +596,9 @@ function applyRevisionAction(options) {
593
596
  detachedRevisionIds: findNewDetachedRevisionIds(options.store, nextStore)
594
597
  };
595
598
  }
599
+ function canApplyRuntimeTextBlockDeletion(revision, intent) {
600
+ return revision.metadata.source === "runtime" && (intent === "accept" && revision.kind === "deletion" && (revision.metadata.semanticKind === "replacement" || revision.metadata.semanticKind === "deletion") || intent === "reject" && revision.kind === "insertion" && (revision.metadata.semanticKind === "replacement" || revision.metadata.semanticKind === "structural-change"));
601
+ }
596
602
  function applyPairedMoveAction(options, revision) {
597
603
  const resultingStatus = toResultingStatus(options.intent);
598
604
  return {
@@ -2235,6 +2241,11 @@ function executeEditorCommand(state, command, context) {
2235
2241
  );
2236
2242
  return buildDocumentReplaceTransaction(state, context, result);
2237
2243
  }
2244
+ case "fragment.insert-tracked": {
2245
+ const result = applySuggestingFragmentInsert(state, command.fragment, context);
2246
+ if (result) return result;
2247
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
2248
+ }
2238
2249
  case "runtime.set-read-only":
2239
2250
  return createTransaction(
2240
2251
  {
@@ -3480,7 +3491,7 @@ function applyTextCommand(state, timestamp, apply) {
3480
3491
  const reviewState = remapReviewStateAfterContentChange(
3481
3492
  state,
3482
3493
  result.document,
3483
- result.mapping
3494
+ result.mapping ?? createEmptyMapping()
3484
3495
  );
3485
3496
  const scopeTagTouches = collectScopeTagTouches(
3486
3497
  state.document.review.comments,
@@ -3820,6 +3831,38 @@ function isSingleParagraphSuggestingRange(document, from, to) {
3820
3831
  );
3821
3832
  return ranges.some((range) => from >= range.start && to <= range.end);
3822
3833
  }
3834
+ function isTextOnlySuggestingRange(document, from, to) {
3835
+ const story = parseTextStory(document.content);
3836
+ const range = normalizeTextStoryRange(story, from, to);
3837
+ if (!range) {
3838
+ return isSingleParagraphSuggestingRange(document, from, to);
3839
+ }
3840
+ const rootStoryTextOnly = story.units.slice(range.from, range.to).every(isSuggestingTextReplacementUnit);
3841
+ if (rootStoryTextOnly) return true;
3842
+ return isSingleParagraphSuggestingRange(document, from, to);
3843
+ }
3844
+ function normalizeTextStoryRange(story, from, to) {
3845
+ const start = Math.min(from, to);
3846
+ const end = Math.max(from, to);
3847
+ if (start < 0 || end > story.size) return null;
3848
+ return { from: start, to: end };
3849
+ }
3850
+ function isSuggestingTextReplacementUnit(unit) {
3851
+ switch (unit.kind) {
3852
+ case "text":
3853
+ case "tab":
3854
+ case "hard_break":
3855
+ case "paragraph_break":
3856
+ case "scope_marker":
3857
+ return true;
3858
+ case "protected_inline":
3859
+ case "image":
3860
+ case "opaque_inline":
3861
+ case "opaque_block":
3862
+ case "structural_block":
3863
+ return false;
3864
+ }
3865
+ }
3823
3866
  function collectSuggestingParagraphRanges(blocks, startCursor, output, addRootParagraphBoundaries) {
3824
3867
  let cursor = startCursor;
3825
3868
  for (let index = 0; index < blocks.length; index += 1) {
@@ -3892,10 +3935,10 @@ function applySuggestingInsert(state, text, context, formatting) {
3892
3935
  const from = Math.min(selection.anchor, selection.head);
3893
3936
  const to = Math.max(selection.anchor, selection.head);
3894
3937
  const isCollapsed = from === to;
3895
- if (!isCollapsed && !isSingleParagraphSuggestingRange(state.document, from, to)) {
3938
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
3896
3939
  return createSuggestingUnsupportedTransaction(
3897
3940
  state,
3898
- "Suggesting mode does not yet support multi-paragraph replacement ranges."
3941
+ "Suggesting mode text replacement ranges must contain only editable text and paragraph breaks."
3899
3942
  );
3900
3943
  }
3901
3944
  if (isCollapsed) {
@@ -4004,7 +4047,7 @@ function applySuggestingInsert(state, text, context, formatting) {
4004
4047
  const reviewState = remapReviewStateAfterContentChange(
4005
4048
  state,
4006
4049
  result.document,
4007
- result.mapping
4050
+ result.mapping ?? createEmptyMapping()
4008
4051
  );
4009
4052
  const replacementSuggestionId = createSuggestingRevisionId(
4010
4053
  reviewState.document.review.revisions,
@@ -4069,6 +4112,131 @@ function applySuggestingInsert(state, text, context, formatting) {
4069
4112
  activeCommentId: reviewState.activeCommentId
4070
4113
  }
4071
4114
  },
4115
+ {
4116
+ historyBoundary: "push",
4117
+ markDirty: true,
4118
+ mapping: result.mapping ?? createEmptyMapping(),
4119
+ effects: {
4120
+ ...reviewState.effects,
4121
+ revisionAuthored: { changeId: insertionRevision.changeId, kind: "insertion" }
4122
+ }
4123
+ }
4124
+ );
4125
+ }
4126
+ function applySuggestingFragmentInsert(state, fragment, context) {
4127
+ if (state.readOnly) {
4128
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
4129
+ }
4130
+ if (fragment.blocks.length === 0) {
4131
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
4132
+ }
4133
+ if (!isTrackableSuggestingFragment(fragment)) {
4134
+ return createSuggestingUnsupportedTransaction(
4135
+ state,
4136
+ "Suggesting mode structured fragment replacement supports paragraph/text fragments only."
4137
+ );
4138
+ }
4139
+ const authorId = context.defaultAuthorId ?? "unknown";
4140
+ const selection = state.selection;
4141
+ const from = Math.min(selection.anchor, selection.head);
4142
+ const to = Math.max(selection.anchor, selection.head);
4143
+ const isCollapsed = from === to;
4144
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
4145
+ return createSuggestingUnsupportedTransaction(
4146
+ state,
4147
+ "Suggesting mode structured fragment replacement ranges must contain only editable text and paragraph breaks."
4148
+ );
4149
+ }
4150
+ const storyBefore = parseTextStory(state.document.content);
4151
+ const insertSelection = createSelectionSnapshot(to, to);
4152
+ const result = structureLayer.applyFragmentInsert(
4153
+ state.document,
4154
+ insertSelection,
4155
+ fragment,
4156
+ context
4157
+ );
4158
+ if (!result.changed) {
4159
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
4160
+ }
4161
+ const storyAfter = parseTextStory(result.document.content);
4162
+ const insertedFrom = to;
4163
+ const insertedTo = to + Math.max(0, storyAfter.size - storyBefore.size);
4164
+ if (insertedTo <= insertedFrom) {
4165
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
4166
+ }
4167
+ const reviewState = remapReviewStateAfterContentChange(
4168
+ state,
4169
+ result.document,
4170
+ result.mapping ?? createEmptyMapping()
4171
+ );
4172
+ const replacementSuggestionId = !isCollapsed ? createSuggestingRevisionId(
4173
+ reviewState.document.review.revisions,
4174
+ context.timestamp,
4175
+ authorId
4176
+ ) : void 0;
4177
+ let deletionRevision = !isCollapsed ? createAuthoredRevision(
4178
+ reviewState.document.review.revisions,
4179
+ "deletion",
4180
+ from,
4181
+ to,
4182
+ authorId,
4183
+ context.timestamp,
4184
+ createSuggestionMetadata({
4185
+ suggestionId: replacementSuggestionId,
4186
+ semanticKind: "replacement"
4187
+ })
4188
+ ) : void 0;
4189
+ const insertionRevision = createAuthoredRevision(
4190
+ {
4191
+ ...reviewState.document.review.revisions,
4192
+ ...deletionRevision ? { [deletionRevision.changeId]: deletionRevision } : {}
4193
+ },
4194
+ "insertion",
4195
+ insertedFrom,
4196
+ insertedTo,
4197
+ authorId,
4198
+ context.timestamp,
4199
+ createSuggestionMetadata(
4200
+ deletionRevision ? {
4201
+ suggestionId: replacementSuggestionId,
4202
+ semanticKind: "replacement",
4203
+ linkedRevisionIds: [deletionRevision.changeId]
4204
+ } : {
4205
+ semanticKind: "structural-change"
4206
+ }
4207
+ )
4208
+ );
4209
+ if (deletionRevision) {
4210
+ deletionRevision = {
4211
+ ...deletionRevision,
4212
+ metadata: {
4213
+ ...deletionRevision.metadata,
4214
+ linkedRevisionIds: [insertionRevision.changeId]
4215
+ }
4216
+ };
4217
+ }
4218
+ const finalDocument = {
4219
+ ...reviewState.document,
4220
+ review: {
4221
+ ...reviewState.document.review,
4222
+ revisions: {
4223
+ ...reviewState.document.review.revisions,
4224
+ ...deletionRevision ? { [deletionRevision.changeId]: deletionRevision } : {},
4225
+ [insertionRevision.changeId]: insertionRevision
4226
+ }
4227
+ }
4228
+ };
4229
+ return createTransaction(
4230
+ {
4231
+ ...state,
4232
+ document: finalDocument,
4233
+ selection: createSelectionSnapshot(insertedTo, insertedTo),
4234
+ warnings: reviewState.warnings,
4235
+ runtime: {
4236
+ ...state.runtime,
4237
+ activeCommentId: reviewState.activeCommentId
4238
+ }
4239
+ },
4072
4240
  {
4073
4241
  historyBoundary: "push",
4074
4242
  markDirty: true,
@@ -4080,6 +4248,10 @@ function applySuggestingInsert(state, text, context, formatting) {
4080
4248
  }
4081
4249
  );
4082
4250
  }
4251
+ function isTrackableSuggestingFragment(fragment) {
4252
+ const story = parseTextStory({ type: "doc", children: fragment.blocks });
4253
+ return story.units.every(isSuggestingTextReplacementUnit);
4254
+ }
4083
4255
  function applySuggestingDelete(state, direction, context) {
4084
4256
  if (state.readOnly) {
4085
4257
  return createTransaction(state, { historyBoundary: "skip", markDirty: false });
@@ -4089,10 +4261,10 @@ function applySuggestingDelete(state, direction, context) {
4089
4261
  const from = Math.min(selection.anchor, selection.head);
4090
4262
  const to = Math.max(selection.anchor, selection.head);
4091
4263
  const isCollapsed = from === to;
4092
- if (!isCollapsed && !isSingleParagraphSuggestingRange(state.document, from, to)) {
4264
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
4093
4265
  return createSuggestingUnsupportedTransaction(
4094
4266
  state,
4095
- "Suggesting mode does not yet support multi-paragraph deletion ranges."
4267
+ "Suggesting mode text deletion ranges must contain only editable text and paragraph breaks."
4096
4268
  );
4097
4269
  }
4098
4270
  let deleteFrom;
@@ -12628,6 +12800,36 @@ function createDocumentRuntime(options) {
12628
12800
  let viewportBlockRanges = null;
12629
12801
  let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
12630
12802
  let viewportBlocksPerPageEstimate = null;
12803
+ let fullSurfaceWarmupScheduled = false;
12804
+ let fullSurfaceWarmupCompleted = false;
12805
+ function scheduleFullSurfaceWarmupAfterCull() {
12806
+ if (fullSurfaceWarmupScheduled || fullSurfaceWarmupCompleted) return;
12807
+ fullSurfaceWarmupScheduled = true;
12808
+ perfCounters.increment("surface.fullSurfaceWarmup.scheduled");
12809
+ runOnIdle(() => {
12810
+ fullSurfaceWarmupScheduled = false;
12811
+ if (cachedFullSurface) {
12812
+ perfCounters.increment("surface.fullSurfaceWarmup.alreadyCached");
12813
+ fullSurfaceWarmupCompleted = true;
12814
+ return;
12815
+ }
12816
+ const t0 = performance.now();
12817
+ try {
12818
+ getCachedFullSurface(state.document, activeStory);
12819
+ fullSurfaceWarmupCompleted = true;
12820
+ perfCounters.increment("surface.fullSurfaceWarmup.committed");
12821
+ } catch (error) {
12822
+ perfCounters.increment("surface.fullSurfaceWarmup.failed");
12823
+ fullSurfaceWarmupCompleted = false;
12824
+ void error;
12825
+ } finally {
12826
+ perfCounters.increment(
12827
+ "surface.fullSurfaceWarmup.us",
12828
+ Math.round((performance.now() - t0) * 1e3)
12829
+ );
12830
+ }
12831
+ });
12832
+ }
12631
12833
  const getRuntimeForLayoutFacet = () => {
12632
12834
  if (!runtimeRef) {
12633
12835
  throw new Error("Document runtime viewport methods are not initialized");
@@ -12820,6 +13022,15 @@ function createDocumentRuntime(options) {
12820
13022
  let cachedSurface;
12821
13023
  let cachedFullSurface;
12822
13024
  const editableTargetBlockCache = createEditableTargetBlockCache();
13025
+ let paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
13026
+ let paragraphCascadeCacheStylesRef = null;
13027
+ function ensureParagraphCascadeCacheForStyles(nextStyles) {
13028
+ if (paragraphCascadeCacheStylesRef !== nextStyles) {
13029
+ paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
13030
+ paragraphCascadeCacheStylesRef = nextStyles;
13031
+ }
13032
+ return paragraphCascadeCache;
13033
+ }
12823
13034
  let cachedEditableTargetMap = null;
12824
13035
  function getEditableTargetsByBlockPath(document) {
12825
13036
  if (cachedEditableTargetMap !== null && cachedEditableTargetMap.document === document) {
@@ -12873,6 +13084,7 @@ function createDocumentRuntime(options) {
12873
13084
  const snapshot = createEditorSurfaceSnapshot(document, state.selection, nextActiveStory, {
12874
13085
  viewportBlockRanges: null,
12875
13086
  editableTargetsByBlockPath: getEditableTargetsByBlockPath(document),
13087
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document.styles),
12876
13088
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
12877
13089
  });
12878
13090
  recordPerfSample("snapshot.surface");
@@ -12913,6 +13125,7 @@ function createDocumentRuntime(options) {
12913
13125
  activeStoryKey,
12914
13126
  surfaceViewportRanges
12915
13127
  ),
13128
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document.styles),
12916
13129
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
12917
13130
  });
12918
13131
  recordPerfSample("snapshot.surface");
@@ -13124,7 +13337,17 @@ function createDocumentRuntime(options) {
13124
13337
  }
13125
13338
  }
13126
13339
  function tryPatchNestedLocalTextSurface(previousSurface, editFrom, editTo, insertedText) {
13127
- const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, 0);
13340
+ const containerIndex = previousSurface.blocks.findIndex(
13341
+ (block) => editFrom >= block.from && editTo <= block.to
13342
+ );
13343
+ if (containerIndex < 0) {
13344
+ perfCounters.increment("surface.localText.patchMiss");
13345
+ return null;
13346
+ }
13347
+ const shiftBudget = estimateLocalTextPatchShiftBudget(
13348
+ previousSurface.blocks,
13349
+ containerIndex + 1
13350
+ );
13128
13351
  perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
13129
13352
  perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
13130
13353
  if (!shiftBudget.withinBudget) {
@@ -13204,19 +13427,9 @@ function createDocumentRuntime(options) {
13204
13427
  for (let index = startIndex; index < blocks.length; index += 1) {
13205
13428
  const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
13206
13429
  blocks[index],
13207
- Math.min(
13208
- policy.maxShiftedNodesPerBlock,
13209
- policy.maxShiftedSurfaceNodes - shiftedNodes
13210
- ) + 1
13430
+ policy.maxShiftedSurfaceNodes - shiftedNodes + 1
13211
13431
  );
13212
13432
  shiftedNodes += shiftedBlockNodes;
13213
- if (shiftedBlockNodes > policy.maxShiftedNodesPerBlock) {
13214
- return {
13215
- shiftedBlocks,
13216
- shiftedNodes,
13217
- withinBudget: false
13218
- };
13219
- }
13220
13433
  if (shiftedNodes > policy.maxShiftedSurfaceNodes) {
13221
13434
  return {
13222
13435
  shiftedBlocks,
@@ -13888,6 +14101,9 @@ function createDocumentRuntime(options) {
13888
14101
  viewportBlockRangesOverride: firstSurfaceViewportBlockRanges
13889
14102
  }) : getCachedSurface(state.document, activeStory)
13890
14103
  );
14104
+ if (firstSurfaceViewportBlockRanges) {
14105
+ scheduleFullSurfaceWarmupAfterCull();
14106
+ }
13891
14107
  const snapshot = {
13892
14108
  documentId: state.documentId,
13893
14109
  sessionId: state.sessionId,
@@ -14001,6 +14217,9 @@ function createDocumentRuntime(options) {
14001
14217
  activeStoryKey,
14002
14218
  viewportBlockRanges
14003
14219
  ),
14220
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(
14221
+ state.document.styles
14222
+ ),
14004
14223
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
14005
14224
  }
14006
14225
  );
@@ -14651,7 +14870,20 @@ function createDocumentRuntime(options) {
14651
14870
  selection: prepared.selection
14652
14871
  };
14653
14872
  resolvedReplayTextTarget = prepared.textTarget;
14654
- } else if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
14873
+ } else {
14874
+ const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
14875
+ command,
14876
+ document: replayState.document,
14877
+ selection: replayState.selection,
14878
+ surface: replaySnapshot.surface?.blocks ?? [],
14879
+ storyTarget: replayStory,
14880
+ timestamp: context.timestamp
14881
+ });
14882
+ if (selectedListItemDeleteCommand) {
14883
+ executableCommand = selectedListItemDeleteCommand;
14884
+ }
14885
+ }
14886
+ if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
14655
14887
  const prepared = prepareModeledTargetCommandForExecution(
14656
14888
  command,
14657
14889
  replayState.document,
@@ -14795,7 +15027,20 @@ function createDocumentRuntime(options) {
14795
15027
  selection: prepared.selection
14796
15028
  };
14797
15029
  resolvedReplayTextTarget = prepared.textTarget;
14798
- } else if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
15030
+ } else {
15031
+ const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
15032
+ command,
15033
+ document: stateForCommand.document,
15034
+ selection: stateForCommand.selection,
15035
+ surface: snapshotForCommand.surface?.blocks ?? [],
15036
+ storyTarget: replayStory,
15037
+ timestamp: context.timestamp
15038
+ });
15039
+ if (selectedListItemDeleteCommand) {
15040
+ executableCommand = selectedListItemDeleteCommand;
15041
+ }
15042
+ }
15043
+ if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
14799
15044
  const prepared = prepareModeledTargetCommandForExecution(
14800
15045
  command,
14801
15046
  stateForCommand.document,
@@ -15216,6 +15461,50 @@ function createDocumentRuntime(options) {
15216
15461
  } catch (error) {
15217
15462
  emitError(toRuntimeError(error));
15218
15463
  }
15464
+ } else if (step.kind === "fragment-replace-tracked" && step.range && step.fragment && Array.isArray(step.fragment.blocks)) {
15465
+ const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
15466
+ if (editableTarget === null) {
15467
+ emit({
15468
+ type: "command_blocked",
15469
+ documentId: state.documentId,
15470
+ command: "applyScopeReplacement",
15471
+ reasons: [{
15472
+ code: "unsupported_surface",
15473
+ message: "Scope replacement editable target no longer resolves."
15474
+ }]
15475
+ });
15476
+ continue;
15477
+ }
15478
+ const dispatchRange = mapSemanticStepRangeToEditableTarget(
15479
+ step.range,
15480
+ step.editableTargetHint,
15481
+ editableTarget?.range
15482
+ );
15483
+ const anchor = {
15484
+ kind: "range",
15485
+ from: dispatchRange.from,
15486
+ to: dispatchRange.to,
15487
+ assoc: { start: -1, end: 1 }
15488
+ };
15489
+ const timestamp = clock();
15490
+ try {
15491
+ applyTextCommandInActiveStory(
15492
+ {
15493
+ type: "fragment.insert-tracked",
15494
+ fragment: step.fragment,
15495
+ ...editableTarget?.target ? { editableTarget: editableTarget.target } : {},
15496
+ origin: createOrigin("api", timestamp)
15497
+ },
15498
+ {
15499
+ selection: createSelectionFromPublicAnchor(anchor),
15500
+ blockedCommandName: "applyScopeReplacement",
15501
+ documentModeOverride: "suggesting",
15502
+ skipWorkflowGuard: true
15503
+ }
15504
+ );
15505
+ } catch (error) {
15506
+ emitError(toRuntimeError(error));
15507
+ }
15219
15508
  } else if (step.kind === "text-insert-tracked" && step.range && typeof step.text === "string") {
15220
15509
  const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
15221
15510
  if (editableTarget === null) {
@@ -17198,6 +17487,39 @@ function createDocumentRuntime(options) {
17198
17487
  const preSelection = selection;
17199
17488
  const preActiveStory = activeStory;
17200
17489
  const priorDocument = state.document;
17490
+ const selectedListItemDelete = createSelectedListItemDeleteReplacement({
17491
+ command: commandForDispatch,
17492
+ document: state.document,
17493
+ editableTarget,
17494
+ selection,
17495
+ storyTarget: activeStory,
17496
+ targetResolution,
17497
+ timestamp
17498
+ });
17499
+ if (selectedListItemDelete && context.documentMode !== "suggesting") {
17500
+ const replacementCommand = {
17501
+ type: "document.replace",
17502
+ document: selectedListItemDelete.document,
17503
+ selection: selectedListItemDelete.selection,
17504
+ mapping: selectedListItemDelete.mapping,
17505
+ protectionSelection: selection,
17506
+ origin: commandForDispatch.origin
17507
+ };
17508
+ const transaction = executeEditorCommand(baseState, replacementCommand, context);
17509
+ commit(transaction);
17510
+ options.onCommandApplied?.(commandForDispatch, transaction, context, {
17511
+ preSelection,
17512
+ activeStory: preActiveStory,
17513
+ priorDocument
17514
+ });
17515
+ return completeDispatch(classifyAck({
17516
+ command: commandForDispatch,
17517
+ opId,
17518
+ priorState: baseState,
17519
+ transaction,
17520
+ newRevisionToken: state.revisionToken
17521
+ }));
17522
+ }
17201
17523
  if (activeStory.kind === "main") {
17202
17524
  const mainTransaction = executeEditorCommand(baseState, commandForDispatch, context);
17203
17525
  commit(mainTransaction);
@@ -17439,6 +17761,9 @@ function createDocumentRuntime(options) {
17439
17761
  });
17440
17762
  }
17441
17763
  function scheduleIdleContextAnalytics(callback) {
17764
+ runOnIdle(callback);
17765
+ }
17766
+ function runOnIdle(callback) {
17442
17767
  const requestIdle = globalThis.requestIdleCallback;
17443
17768
  if (typeof requestIdle === "function") {
17444
17769
  requestIdle(callback, { timeout: 250 });
@@ -18392,7 +18717,8 @@ function getStoryPlainText(document, storyTarget, cache) {
18392
18717
  const plainText = createEditorSurfaceSnapshot(
18393
18718
  document,
18394
18719
  createSelectionSnapshot(0, 0),
18395
- storyTarget
18720
+ storyTarget,
18721
+ { editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX }
18396
18722
  ).plainText;
18397
18723
  cache.set(key, plainText);
18398
18724
  return plainText;
@@ -20077,6 +20403,258 @@ function stripStoryTarget(selection) {
20077
20403
  function isTopLevelMainStoryBlockPath(blockPath) {
20078
20404
  return typeof blockPath === "string" && /^main\/block\[\d+\]$/u.test(blockPath);
20079
20405
  }
20406
+ function createSelectedListItemDeleteReplacement(input) {
20407
+ const { command, document, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
20408
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
20409
+ return null;
20410
+ }
20411
+ if (selection.isCollapsed || editableTarget?.listAddress?.operationScope !== "list-text" || targetResolution?.kind !== "accepted") {
20412
+ return null;
20413
+ }
20414
+ const selectionFrom = Math.min(selection.anchor, selection.head);
20415
+ const selectionTo = Math.max(selection.anchor, selection.head);
20416
+ if (selectionFrom !== targetResolution.range.from || selectionTo !== targetResolution.range.to) {
20417
+ return null;
20418
+ }
20419
+ const storyBlocks = getStoryBlocks(document, storyTarget);
20420
+ const replacement = removeNumberedParagraphAtStoryPath(storyBlocks, editableTarget.blockPath, storyTarget);
20421
+ if (!replacement) {
20422
+ return null;
20423
+ }
20424
+ const nextDocument = replaceStoryBlocks({
20425
+ ...document,
20426
+ updatedAt: timestamp
20427
+ }, storyTarget, replacement.blocks);
20428
+ const nextStorySize = parseTextStory({
20429
+ type: "doc",
20430
+ children: [...getStoryBlocks(nextDocument, storyTarget)]
20431
+ }).size;
20432
+ const nextAnchor = Math.min(selectionFrom, nextStorySize);
20433
+ return {
20434
+ document: nextDocument,
20435
+ selection: createSelectionSnapshot(nextAnchor, nextAnchor),
20436
+ mapping: {
20437
+ steps: [{
20438
+ from: selectionFrom,
20439
+ to: selectionTo,
20440
+ insertSize: 0
20441
+ }],
20442
+ metadata: {
20443
+ invalidatesStructures: true
20444
+ }
20445
+ }
20446
+ };
20447
+ }
20448
+ function removeNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget) {
20449
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
20450
+ if (!tokens) return null;
20451
+ return removeNumberedParagraphFromBlocks(blocks, tokens);
20452
+ }
20453
+ function removeNumberedParagraphFromBlocks(blocks, tokens) {
20454
+ const [token, ...rest] = tokens;
20455
+ if (!token || token.kind !== "block") return null;
20456
+ const block = blocks[token.index];
20457
+ if (!block) return null;
20458
+ if (rest.length === 0) {
20459
+ if (block.type !== "paragraph" || !block.numbering) {
20460
+ return null;
20461
+ }
20462
+ if (blocks.length === 1) {
20463
+ return { blocks: [{ type: "paragraph", children: [] }] };
20464
+ }
20465
+ return {
20466
+ blocks: [
20467
+ ...blocks.slice(0, token.index),
20468
+ ...blocks.slice(token.index + 1)
20469
+ ]
20470
+ };
20471
+ }
20472
+ const next = rest[0];
20473
+ if (block.type === "table" && next?.kind === "row") {
20474
+ const updatedTable = removeNumberedParagraphFromTable(block, rest);
20475
+ if (!updatedTable) return null;
20476
+ return {
20477
+ blocks: [
20478
+ ...blocks.slice(0, token.index),
20479
+ updatedTable,
20480
+ ...blocks.slice(token.index + 1)
20481
+ ]
20482
+ };
20483
+ }
20484
+ if ((block.type === "sdt" || block.type === "custom_xml") && next?.kind === "block") {
20485
+ const updatedChildren = removeNumberedParagraphFromBlocks(block.children, rest);
20486
+ if (!updatedChildren) return null;
20487
+ return {
20488
+ blocks: [
20489
+ ...blocks.slice(0, token.index),
20490
+ { ...block, children: updatedChildren.blocks },
20491
+ ...blocks.slice(token.index + 1)
20492
+ ]
20493
+ };
20494
+ }
20495
+ if (block.type === "paragraph" && next?.kind === "inline") {
20496
+ const updatedParagraph = removeNumberedParagraphFromTextBoxInline(block, rest);
20497
+ if (!updatedParagraph) return null;
20498
+ return {
20499
+ blocks: [
20500
+ ...blocks.slice(0, token.index),
20501
+ updatedParagraph,
20502
+ ...blocks.slice(token.index + 1)
20503
+ ]
20504
+ };
20505
+ }
20506
+ return null;
20507
+ }
20508
+ function removeNumberedParagraphFromTextBoxInline(paragraph, tokens) {
20509
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
20510
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
20511
+ return null;
20512
+ }
20513
+ const inline = paragraph.children[inlineToken.index];
20514
+ if (!inline) return null;
20515
+ const updatedInline = removeNumberedParagraphFromInlineTextBox(inline, childTokens);
20516
+ if (!updatedInline) return null;
20517
+ return {
20518
+ ...paragraph,
20519
+ children: [
20520
+ ...paragraph.children.slice(0, inlineToken.index),
20521
+ updatedInline,
20522
+ ...paragraph.children.slice(inlineToken.index + 1)
20523
+ ]
20524
+ };
20525
+ }
20526
+ function removeNumberedParagraphFromInlineTextBox(inline, tokens) {
20527
+ if (inline.type === "shape" && inline.txbxBlocks) {
20528
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.txbxBlocks, tokens);
20529
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
20530
+ }
20531
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
20532
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens);
20533
+ return updatedBlocks ? {
20534
+ ...inline,
20535
+ content: {
20536
+ ...inline.content,
20537
+ txbxBlocks: updatedBlocks.blocks
20538
+ }
20539
+ } : null;
20540
+ }
20541
+ return null;
20542
+ }
20543
+ function removeNumberedParagraphFromTable(table, tokens) {
20544
+ const [rowToken, cellToken, ...childTokens] = tokens;
20545
+ if (rowToken?.kind !== "row" || cellToken?.kind !== "cell" || childTokens[0]?.kind !== "block") {
20546
+ return null;
20547
+ }
20548
+ const row2 = table.rows[rowToken.index];
20549
+ const cell = row2?.cells[cellToken.index];
20550
+ if (!row2 || !cell) return null;
20551
+ const updatedChildren = removeNumberedParagraphFromBlocks(cell.children, childTokens);
20552
+ if (!updatedChildren) return null;
20553
+ const nextCells = [
20554
+ ...row2.cells.slice(0, cellToken.index),
20555
+ { ...cell, children: updatedChildren.blocks },
20556
+ ...row2.cells.slice(cellToken.index + 1)
20557
+ ];
20558
+ const nextRows = [
20559
+ ...table.rows.slice(0, rowToken.index),
20560
+ { ...row2, cells: nextCells },
20561
+ ...table.rows.slice(rowToken.index + 1)
20562
+ ];
20563
+ return { ...table, rows: nextRows };
20564
+ }
20565
+ function createSelectedListItemDeleteReplayCommand(input) {
20566
+ const { command, document, selection, surface, storyTarget, timestamp } = input;
20567
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
20568
+ return null;
20569
+ }
20570
+ const editableTarget = command.editableTarget;
20571
+ if (!editableTarget) {
20572
+ return null;
20573
+ }
20574
+ const targetResolution = resolveEditableTextTarget({
20575
+ document,
20576
+ selection,
20577
+ surface,
20578
+ target: editableTarget,
20579
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
20580
+ });
20581
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
20582
+ document,
20583
+ target: editableTarget,
20584
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
20585
+ commandFamilies: ["text-leaf"]
20586
+ }) : null;
20587
+ const selectedRange = {
20588
+ from: Math.min(selection.anchor, selection.head),
20589
+ to: Math.max(selection.anchor, selection.head)
20590
+ };
20591
+ const replacement = createSelectedListItemDeleteReplacement({
20592
+ command,
20593
+ document,
20594
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
20595
+ selection,
20596
+ storyTarget,
20597
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
20598
+ kind: "accepted",
20599
+ range: selectedRange
20600
+ } : targetResolution,
20601
+ timestamp
20602
+ });
20603
+ if (!replacement) {
20604
+ return null;
20605
+ }
20606
+ return {
20607
+ type: "document.replace",
20608
+ document: replacement.document,
20609
+ selection: replacement.selection,
20610
+ mapping: replacement.mapping,
20611
+ protectionSelection: selection,
20612
+ origin: command.origin
20613
+ };
20614
+ }
20615
+ function parseStoryBlockPathTokens(blockPath, storyTarget) {
20616
+ if (!blockPath) {
20617
+ return null;
20618
+ }
20619
+ const firstTokenMatch = /\/(?:block|row|cell)\[\d+\]/u.exec(blockPath);
20620
+ if (!firstTokenMatch?.index) {
20621
+ return null;
20622
+ }
20623
+ const storyPrefix = blockPath.slice(0, firstTokenMatch.index);
20624
+ if (!blockPathBelongsToStoryTarget(storyPrefix, storyTarget)) {
20625
+ return null;
20626
+ }
20627
+ const parts = blockPath.slice(firstTokenMatch.index + 1).split("/");
20628
+ const tokens = [];
20629
+ for (const part of parts) {
20630
+ if (part === "txbx") {
20631
+ tokens.push({ kind: "txbx" });
20632
+ continue;
20633
+ }
20634
+ const match = /^(block|row|cell|inline)\[(\d+)\]$/u.exec(part);
20635
+ if (!match) return null;
20636
+ const kind = match[1];
20637
+ tokens.push({
20638
+ kind,
20639
+ index: Number.parseInt(match[2], 10)
20640
+ });
20641
+ }
20642
+ return tokens;
20643
+ }
20644
+ function blockPathBelongsToStoryTarget(storyPrefix, storyTarget) {
20645
+ switch (storyTarget.kind) {
20646
+ case "main":
20647
+ return storyPrefix === "main" || storyPrefix.startsWith("main/");
20648
+ case "header":
20649
+ return storyPrefix.startsWith("header:");
20650
+ case "footer":
20651
+ return storyPrefix.startsWith("footer:");
20652
+ case "footnote":
20653
+ return storyPrefix === `footnote:${storyTarget.noteId}` || storyPrefix.startsWith(`footnote:${storyTarget.noteId}/`);
20654
+ case "endnote":
20655
+ return storyPrefix === `endnote:${storyTarget.noteId}` || storyPrefix.startsWith(`endnote:${storyTarget.noteId}/`);
20656
+ }
20657
+ }
20080
20658
  function toInternalSelectionSnapshot(selection) {
20081
20659
  return {
20082
20660
  anchor: selection.anchor,