@beyondwork/docx-react-component 1.0.133 → 1.0.134

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 (70) hide show
  1. package/dist/api/public-types.cjs +3 -1
  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 +1 -1
  5. package/dist/api/v3.cjs +688 -45
  6. package/dist/api/v3.d.cts +2 -2
  7. package/dist/api/v3.d.ts +2 -2
  8. package/dist/api/v3.js +3 -3
  9. package/dist/{chunk-S3PEKX6H.js → chunk-3YR47WTD.js} +53 -547
  10. package/dist/{chunk-57HTKX3P.js → chunk-74R5B2EZ.js} +1 -1
  11. package/dist/{chunk-KL4TZSZV.js → chunk-7Y6JCIK3.js} +1 -1
  12. package/dist/{chunk-3JEE5RJU.js → chunk-EBSI6VQX.js} +457 -16
  13. package/dist/{chunk-OTRVGNZQ.js → chunk-ESEEWELA.js} +547 -2
  14. package/dist/{chunk-224TSMEB.js → chunk-IJD6D7HU.js} +137 -41
  15. package/dist/{chunk-CVSD3UNK.js → chunk-O4EDZR44.js} +3 -1
  16. package/dist/{chunk-ZFCZ7XXH.js → chunk-VA24T4EB.js} +1 -1
  17. package/dist/core/commands/formatting-commands.d.cts +1 -1
  18. package/dist/core/commands/formatting-commands.d.ts +1 -1
  19. package/dist/core/commands/image-commands.d.cts +1 -1
  20. package/dist/core/commands/image-commands.d.ts +1 -1
  21. package/dist/core/commands/section-layout-commands.d.cts +1 -1
  22. package/dist/core/commands/section-layout-commands.d.ts +1 -1
  23. package/dist/core/commands/style-commands.d.cts +1 -1
  24. package/dist/core/commands/style-commands.d.ts +1 -1
  25. package/dist/core/commands/table-structure-commands.d.cts +1 -1
  26. package/dist/core/commands/table-structure-commands.d.ts +1 -1
  27. package/dist/core/commands/text-commands.d.cts +1 -1
  28. package/dist/core/commands/text-commands.d.ts +1 -1
  29. package/dist/core/selection/mapping.d.cts +1 -1
  30. package/dist/core/selection/mapping.d.ts +1 -1
  31. package/dist/core/state/editor-state.d.cts +1 -1
  32. package/dist/core/state/editor-state.d.ts +1 -1
  33. package/dist/index.cjs +1289 -615
  34. package/dist/index.d.cts +4 -4
  35. package/dist/index.d.ts +4 -4
  36. package/dist/index.js +105 -19
  37. package/dist/io/docx-session.d.cts +3 -3
  38. package/dist/io/docx-session.d.ts +3 -3
  39. package/dist/{loader-B2H99237.d.cts → loader-CK3lZy4h.d.cts} +2 -2
  40. package/dist/{loader-DfTjqVwn.d.ts → loader-CQXplstv.d.ts} +2 -2
  41. package/dist/{public-types-S8gTYwKo.d.cts → public-types-BR1SYK2F.d.cts} +140 -3
  42. package/dist/{public-types-B5lOUIrP.d.ts → public-types-DXNZVKrS.d.ts} +140 -3
  43. package/dist/public-types.cjs +3 -1
  44. package/dist/public-types.d.cts +1 -1
  45. package/dist/public-types.d.ts +1 -1
  46. package/dist/public-types.js +1 -1
  47. package/dist/runtime/collab.d.cts +2 -2
  48. package/dist/runtime/collab.d.ts +2 -2
  49. package/dist/runtime/document-runtime.cjs +591 -54
  50. package/dist/runtime/document-runtime.d.cts +1 -1
  51. package/dist/runtime/document-runtime.d.ts +1 -1
  52. package/dist/runtime/document-runtime.js +4 -4
  53. package/dist/{session-CBDIOYXA.d.ts → session-C9UjrhJF.d.ts} +2 -2
  54. package/dist/{session-CR2A1hGZ.d.cts → session-CSbwkgII.d.cts} +2 -2
  55. package/dist/session.d.cts +4 -4
  56. package/dist/session.d.ts +4 -4
  57. package/dist/tailwind.cjs +54 -546
  58. package/dist/tailwind.d.cts +1 -1
  59. package/dist/tailwind.d.ts +1 -1
  60. package/dist/tailwind.js +4 -4
  61. package/dist/{types-yty2K-hk.d.cts → types-CZtAueri.d.cts} +1 -1
  62. package/dist/{types-B-90ywjU.d.ts → types-RzkCXDNV.d.ts} +1 -1
  63. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +2 -2
  64. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +2 -2
  65. package/dist/ui-tailwind/editor-surface/search-plugin.js +2 -2
  66. package/dist/ui-tailwind.cjs +54 -546
  67. package/dist/ui-tailwind.d.cts +2 -2
  68. package/dist/ui-tailwind.d.ts +2 -2
  69. package/dist/ui-tailwind.js +4 -4
  70. package/package.json +1 -1
@@ -18846,9 +18846,11 @@ function applyRevisionAction(options) {
18846
18846
  );
18847
18847
  }
18848
18848
  const slice = story.units.slice(range.from, range.to);
18849
- if (slice.some(
18850
- (unit) => unit.kind === "paragraph_break" || unit.kind === "opaque_block" || unit.kind === "structural_block"
18851
- )) {
18849
+ const touchesStructuralContent = slice.some(
18850
+ (unit) => unit.kind === "opaque_block" || unit.kind === "structural_block"
18851
+ );
18852
+ const touchesParagraphBoundary = slice.some((unit) => unit.kind === "paragraph_break");
18853
+ if (touchesStructuralContent || touchesParagraphBoundary && !canApplyRuntimeTextBlockDeletion(revision, options.intent)) {
18852
18854
  return skippedResult(
18853
18855
  options,
18854
18856
  "structural-range",
@@ -18856,7 +18858,7 @@ function applyRevisionAction(options) {
18856
18858
  );
18857
18859
  }
18858
18860
  if (slice.some(
18859
- (unit) => unit.kind === "image" || unit.kind === "opaque_inline"
18861
+ (unit) => unit.kind === "image" || unit.kind === "opaque_inline" || unit.kind === "protected_inline"
18860
18862
  )) {
18861
18863
  return skippedResult(
18862
18864
  options,
@@ -18911,6 +18913,9 @@ function applyRevisionAction(options) {
18911
18913
  detachedRevisionIds: findNewDetachedRevisionIds(options.store, nextStore)
18912
18914
  };
18913
18915
  }
18916
+ function canApplyRuntimeTextBlockDeletion(revision, intent) {
18917
+ 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"));
18918
+ }
18914
18919
  function applyPairedMoveAction(options, revision) {
18915
18920
  const resultingStatus = toResultingStatus(options.intent);
18916
18921
  return {
@@ -21294,6 +21299,11 @@ function executeEditorCommand(state, command, context) {
21294
21299
  );
21295
21300
  return buildDocumentReplaceTransaction(state, context, result);
21296
21301
  }
21302
+ case "fragment.insert-tracked": {
21303
+ const result = applySuggestingFragmentInsert(state, command.fragment, context);
21304
+ if (result) return result;
21305
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
21306
+ }
21297
21307
  case "runtime.set-read-only":
21298
21308
  return createTransaction(
21299
21309
  {
@@ -22539,7 +22549,7 @@ function applyTextCommand(state, timestamp, apply) {
22539
22549
  const reviewState = remapReviewStateAfterContentChange(
22540
22550
  state,
22541
22551
  result.document,
22542
- result.mapping
22552
+ result.mapping ?? createEmptyMapping()
22543
22553
  );
22544
22554
  const scopeTagTouches = collectScopeTagTouches(
22545
22555
  state.document.review.comments,
@@ -22879,6 +22889,38 @@ function isSingleParagraphSuggestingRange(document2, from, to) {
22879
22889
  );
22880
22890
  return ranges.some((range) => from >= range.start && to <= range.end);
22881
22891
  }
22892
+ function isTextOnlySuggestingRange(document2, from, to) {
22893
+ const story = parseTextStory(document2.content);
22894
+ const range = normalizeTextStoryRange(story, from, to);
22895
+ if (!range) {
22896
+ return isSingleParagraphSuggestingRange(document2, from, to);
22897
+ }
22898
+ const rootStoryTextOnly = story.units.slice(range.from, range.to).every(isSuggestingTextReplacementUnit);
22899
+ if (rootStoryTextOnly) return true;
22900
+ return isSingleParagraphSuggestingRange(document2, from, to);
22901
+ }
22902
+ function normalizeTextStoryRange(story, from, to) {
22903
+ const start = Math.min(from, to);
22904
+ const end = Math.max(from, to);
22905
+ if (start < 0 || end > story.size) return null;
22906
+ return { from: start, to: end };
22907
+ }
22908
+ function isSuggestingTextReplacementUnit(unit) {
22909
+ switch (unit.kind) {
22910
+ case "text":
22911
+ case "tab":
22912
+ case "hard_break":
22913
+ case "paragraph_break":
22914
+ case "scope_marker":
22915
+ return true;
22916
+ case "protected_inline":
22917
+ case "image":
22918
+ case "opaque_inline":
22919
+ case "opaque_block":
22920
+ case "structural_block":
22921
+ return false;
22922
+ }
22923
+ }
22882
22924
  function collectSuggestingParagraphRanges(blocks, startCursor, output, addRootParagraphBoundaries) {
22883
22925
  let cursor = startCursor;
22884
22926
  for (let index = 0; index < blocks.length; index += 1) {
@@ -22951,10 +22993,10 @@ function applySuggestingInsert(state, text, context, formatting) {
22951
22993
  const from = Math.min(selection.anchor, selection.head);
22952
22994
  const to = Math.max(selection.anchor, selection.head);
22953
22995
  const isCollapsed = from === to;
22954
- if (!isCollapsed && !isSingleParagraphSuggestingRange(state.document, from, to)) {
22996
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
22955
22997
  return createSuggestingUnsupportedTransaction(
22956
22998
  state,
22957
- "Suggesting mode does not yet support multi-paragraph replacement ranges."
22999
+ "Suggesting mode text replacement ranges must contain only editable text and paragraph breaks."
22958
23000
  );
22959
23001
  }
22960
23002
  if (isCollapsed) {
@@ -23063,7 +23105,7 @@ function applySuggestingInsert(state, text, context, formatting) {
23063
23105
  const reviewState = remapReviewStateAfterContentChange(
23064
23106
  state,
23065
23107
  result.document,
23066
- result.mapping
23108
+ result.mapping ?? createEmptyMapping()
23067
23109
  );
23068
23110
  const replacementSuggestionId = createSuggestingRevisionId(
23069
23111
  reviewState.document.review.revisions,
@@ -23128,6 +23170,131 @@ function applySuggestingInsert(state, text, context, formatting) {
23128
23170
  activeCommentId: reviewState.activeCommentId
23129
23171
  }
23130
23172
  },
23173
+ {
23174
+ historyBoundary: "push",
23175
+ markDirty: true,
23176
+ mapping: result.mapping ?? createEmptyMapping(),
23177
+ effects: {
23178
+ ...reviewState.effects,
23179
+ revisionAuthored: { changeId: insertionRevision.changeId, kind: "insertion" }
23180
+ }
23181
+ }
23182
+ );
23183
+ }
23184
+ function applySuggestingFragmentInsert(state, fragment, context) {
23185
+ if (state.readOnly) {
23186
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
23187
+ }
23188
+ if (fragment.blocks.length === 0) {
23189
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
23190
+ }
23191
+ if (!isTrackableSuggestingFragment(fragment)) {
23192
+ return createSuggestingUnsupportedTransaction(
23193
+ state,
23194
+ "Suggesting mode structured fragment replacement supports paragraph/text fragments only."
23195
+ );
23196
+ }
23197
+ const authorId = context.defaultAuthorId ?? "unknown";
23198
+ const selection = state.selection;
23199
+ const from = Math.min(selection.anchor, selection.head);
23200
+ const to = Math.max(selection.anchor, selection.head);
23201
+ const isCollapsed = from === to;
23202
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
23203
+ return createSuggestingUnsupportedTransaction(
23204
+ state,
23205
+ "Suggesting mode structured fragment replacement ranges must contain only editable text and paragraph breaks."
23206
+ );
23207
+ }
23208
+ const storyBefore = parseTextStory(state.document.content);
23209
+ const insertSelection = createSelectionSnapshot(to, to);
23210
+ const result = structureLayer.applyFragmentInsert(
23211
+ state.document,
23212
+ insertSelection,
23213
+ fragment,
23214
+ context
23215
+ );
23216
+ if (!result.changed) {
23217
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
23218
+ }
23219
+ const storyAfter = parseTextStory(result.document.content);
23220
+ const insertedFrom = to;
23221
+ const insertedTo = to + Math.max(0, storyAfter.size - storyBefore.size);
23222
+ if (insertedTo <= insertedFrom) {
23223
+ return createTransaction(state, { historyBoundary: "skip", markDirty: false });
23224
+ }
23225
+ const reviewState = remapReviewStateAfterContentChange(
23226
+ state,
23227
+ result.document,
23228
+ result.mapping ?? createEmptyMapping()
23229
+ );
23230
+ const replacementSuggestionId = !isCollapsed ? createSuggestingRevisionId(
23231
+ reviewState.document.review.revisions,
23232
+ context.timestamp,
23233
+ authorId
23234
+ ) : void 0;
23235
+ let deletionRevision = !isCollapsed ? createAuthoredRevision(
23236
+ reviewState.document.review.revisions,
23237
+ "deletion",
23238
+ from,
23239
+ to,
23240
+ authorId,
23241
+ context.timestamp,
23242
+ createSuggestionMetadata({
23243
+ suggestionId: replacementSuggestionId,
23244
+ semanticKind: "replacement"
23245
+ })
23246
+ ) : void 0;
23247
+ const insertionRevision = createAuthoredRevision(
23248
+ {
23249
+ ...reviewState.document.review.revisions,
23250
+ ...deletionRevision ? { [deletionRevision.changeId]: deletionRevision } : {}
23251
+ },
23252
+ "insertion",
23253
+ insertedFrom,
23254
+ insertedTo,
23255
+ authorId,
23256
+ context.timestamp,
23257
+ createSuggestionMetadata(
23258
+ deletionRevision ? {
23259
+ suggestionId: replacementSuggestionId,
23260
+ semanticKind: "replacement",
23261
+ linkedRevisionIds: [deletionRevision.changeId]
23262
+ } : {
23263
+ semanticKind: "structural-change"
23264
+ }
23265
+ )
23266
+ );
23267
+ if (deletionRevision) {
23268
+ deletionRevision = {
23269
+ ...deletionRevision,
23270
+ metadata: {
23271
+ ...deletionRevision.metadata,
23272
+ linkedRevisionIds: [insertionRevision.changeId]
23273
+ }
23274
+ };
23275
+ }
23276
+ const finalDocument = {
23277
+ ...reviewState.document,
23278
+ review: {
23279
+ ...reviewState.document.review,
23280
+ revisions: {
23281
+ ...reviewState.document.review.revisions,
23282
+ ...deletionRevision ? { [deletionRevision.changeId]: deletionRevision } : {},
23283
+ [insertionRevision.changeId]: insertionRevision
23284
+ }
23285
+ }
23286
+ };
23287
+ return createTransaction(
23288
+ {
23289
+ ...state,
23290
+ document: finalDocument,
23291
+ selection: createSelectionSnapshot(insertedTo, insertedTo),
23292
+ warnings: reviewState.warnings,
23293
+ runtime: {
23294
+ ...state.runtime,
23295
+ activeCommentId: reviewState.activeCommentId
23296
+ }
23297
+ },
23131
23298
  {
23132
23299
  historyBoundary: "push",
23133
23300
  markDirty: true,
@@ -23139,6 +23306,10 @@ function applySuggestingInsert(state, text, context, formatting) {
23139
23306
  }
23140
23307
  );
23141
23308
  }
23309
+ function isTrackableSuggestingFragment(fragment) {
23310
+ const story = parseTextStory({ type: "doc", children: fragment.blocks });
23311
+ return story.units.every(isSuggestingTextReplacementUnit);
23312
+ }
23142
23313
  function applySuggestingDelete(state, direction, context) {
23143
23314
  if (state.readOnly) {
23144
23315
  return createTransaction(state, { historyBoundary: "skip", markDirty: false });
@@ -23148,10 +23319,10 @@ function applySuggestingDelete(state, direction, context) {
23148
23319
  const from = Math.min(selection.anchor, selection.head);
23149
23320
  const to = Math.max(selection.anchor, selection.head);
23150
23321
  const isCollapsed = from === to;
23151
- if (!isCollapsed && !isSingleParagraphSuggestingRange(state.document, from, to)) {
23322
+ if (!isCollapsed && !isTextOnlySuggestingRange(state.document, from, to)) {
23152
23323
  return createSuggestingUnsupportedTransaction(
23153
23324
  state,
23154
- "Suggesting mode does not yet support multi-paragraph deletion ranges."
23325
+ "Suggesting mode text deletion ranges must contain only editable text and paragraph breaks."
23155
23326
  );
23156
23327
  }
23157
23328
  let deleteFrom;
@@ -35534,11 +35705,9 @@ function compileParagraphReplacement(entry, proposed, options) {
35534
35705
  };
35535
35706
  }
35536
35707
  if (proposed.proposedContent.kind === "structured") {
35537
- if (options.posture === "suggest-mode") {
35538
- return null;
35539
- }
35540
35708
  const fragment = proposed.proposedContent.structured;
35541
35709
  if (!isStructuredReplacementContent(fragment)) return null;
35710
+ const stepKind = options.posture === "suggest-mode" ? "fragment-replace-tracked" : "fragment-replace";
35542
35711
  const blockCount = fragment.blocks.length;
35543
35712
  const summaryScope = rangeKind === "inline-marker" ? `paragraph #${entry.blockIndex} inline-marker range [${effectiveRange.from}..${effectiveRange.to}]` : rangeKind === "opaque-preserving-text" ? `paragraph #${entry.blockIndex} opaque-preserving text range [${effectiveRange.from}..${effectiveRange.to}]` : `paragraph #${entry.blockIndex}`;
35544
35713
  const actionVerb = proposed.operation === "insert-before" ? "insert before" : proposed.operation === "insert-after" ? "insert after" : "replace";
@@ -35549,8 +35718,8 @@ function compileParagraphReplacement(entry, proposed, options) {
35549
35718
  operation: proposed.operation,
35550
35719
  steps: Object.freeze([
35551
35720
  {
35552
- kind: "fragment-replace",
35553
- summary: actionSummary,
35721
+ kind: stepKind,
35722
+ summary: stepKind === "fragment-replace" ? actionSummary : `suggest-mode ${actionSummary}`,
35554
35723
  ...textLeafEditableTargetHint(entry, blockRange) ? { editableTargetHint: textLeafEditableTargetHint(entry, blockRange) } : {},
35555
35724
  range: { from: operationRange.from, to: operationRange.to },
35556
35725
  fragment
@@ -35637,7 +35806,7 @@ function compileScopeKind(entry, options) {
35637
35806
  };
35638
35807
  }
35639
35808
  function compileScopeReplacement(entry, proposed, options) {
35640
- if (entry.handle.provenance !== "marker-backed" || proposed.operation !== "replace" || options.posture !== "direct-edit") {
35809
+ if (entry.handle.provenance !== "marker-backed" || proposed.operation !== "replace") {
35641
35810
  return null;
35642
35811
  }
35643
35812
  const markerRange = buildScopePositionMap(options.document).markerScopes.get(
@@ -35646,14 +35815,15 @@ function compileScopeReplacement(entry, proposed, options) {
35646
35815
  if (!markerRange) return null;
35647
35816
  if (proposed.proposedContent.kind === "text") {
35648
35817
  const text = proposed.proposedContent.text ?? "";
35818
+ const stepKind = options.posture === "suggest-mode" ? "text-insert-tracked" : "text-replace";
35649
35819
  return {
35650
35820
  scopeId: entry.handle.scopeId,
35651
35821
  targetKind: "scope",
35652
35822
  operation: proposed.operation,
35653
35823
  steps: Object.freeze([
35654
35824
  {
35655
- kind: "text-replace",
35656
- summary: `replace multi-paragraph scope ${entry.handle.scopeId} text [${markerRange.from}..${markerRange.to}] (len ${text.length})`,
35825
+ kind: stepKind,
35826
+ summary: stepKind === "text-replace" ? `replace multi-paragraph scope ${entry.handle.scopeId} text [${markerRange.from}..${markerRange.to}] (len ${text.length})` : `suggest-mode replace multi-paragraph scope ${entry.handle.scopeId} text [${markerRange.from}..${markerRange.to}] (len ${text.length})`,
35657
35827
  range: { from: markerRange.from, to: markerRange.to },
35658
35828
  text,
35659
35829
  ...proposed.formatting ? { formatting: proposed.formatting } : {}
@@ -35666,14 +35836,15 @@ function compileScopeReplacement(entry, proposed, options) {
35666
35836
  if (proposed.proposedContent.kind === "structured") {
35667
35837
  const fragment = proposed.proposedContent.structured;
35668
35838
  if (!isStructuredReplacementContent(fragment)) return null;
35839
+ const stepKind = options.posture === "suggest-mode" ? "fragment-replace-tracked" : "fragment-replace";
35669
35840
  return {
35670
35841
  scopeId: entry.handle.scopeId,
35671
35842
  targetKind: "scope",
35672
35843
  operation: proposed.operation,
35673
35844
  steps: Object.freeze([
35674
35845
  {
35675
- kind: "fragment-replace",
35676
- summary: `replace multi-paragraph scope ${entry.handle.scopeId} with structured fragment [${markerRange.from}..${markerRange.to}] (${fragment.blocks.length} block(s))`,
35846
+ kind: stepKind,
35847
+ summary: stepKind === "fragment-replace" ? `replace multi-paragraph scope ${entry.handle.scopeId} with structured fragment [${markerRange.from}..${markerRange.to}] (${fragment.blocks.length} block(s))` : `suggest-mode replace multi-paragraph scope ${entry.handle.scopeId} with structured fragment [${markerRange.from}..${markerRange.to}] (${fragment.blocks.length} block(s))`,
35677
35848
  range: { from: markerRange.from, to: markerRange.to },
35678
35849
  fragment
35679
35850
  }
@@ -36055,6 +36226,99 @@ function paragraphFirstMarkerStart(paragraph, knownScopeIds) {
36055
36226
  }
36056
36227
  return null;
36057
36228
  }
36229
+ function paragraphHasMarkerEnd(paragraph, scopeId) {
36230
+ return paragraph.children.some(
36231
+ (child) => child.type === "scope_marker_end" && child.scopeId === scopeId
36232
+ );
36233
+ }
36234
+ function paragraphSameParagraphMarkerScopeId(paragraph, knownScopeIds) {
36235
+ const markerScopeId = paragraphFirstMarkerStart(paragraph, knownScopeIds);
36236
+ if (!markerScopeId) return null;
36237
+ return paragraphHasMarkerEnd(paragraph, markerScopeId) ? markerScopeId : null;
36238
+ }
36239
+ function markerStableRefOverride(markerScopeId, semanticPath, overlay) {
36240
+ const hint = stableRefHintForScopeId(markerScopeId, overlay);
36241
+ if (hint === "semantic-path") {
36242
+ return {
36243
+ kind: "semantic-path",
36244
+ value: semanticPath.join("/")
36245
+ };
36246
+ }
36247
+ return { kind: "scope-id", value: markerScopeId };
36248
+ }
36249
+ function enumerateNestedMarkerBackedParagraphs(blocks, input) {
36250
+ const out = [];
36251
+ for (let childIndex = 0; childIndex < blocks.length; childIndex += 1) {
36252
+ const block = blocks[childIndex];
36253
+ if (!block) continue;
36254
+ if (block.type === "paragraph") {
36255
+ const markerScopeId = paragraphSameParagraphMarkerScopeId(
36256
+ block,
36257
+ input.knownOverlayScopeIds
36258
+ );
36259
+ if (!markerScopeId) continue;
36260
+ const kind = detectParagraphKind(block);
36261
+ const semanticPath = [
36262
+ ...input.semanticPrefix,
36263
+ kind,
36264
+ String(childIndex)
36265
+ ];
36266
+ const handle = buildHandle(
36267
+ markerScopeId,
36268
+ input.documentId,
36269
+ semanticPath,
36270
+ "marker-backed",
36271
+ "marker-backed",
36272
+ input.parentScopeId,
36273
+ markerStableRefOverride(markerScopeId, semanticPath, input.overlay)
36274
+ );
36275
+ out.push({
36276
+ kind,
36277
+ handle,
36278
+ paragraph: block,
36279
+ blockIndex: input.rootBlockIndex,
36280
+ classifications: input.classificationIndex.get(markerScopeId) ?? Object.freeze([])
36281
+ });
36282
+ continue;
36283
+ }
36284
+ if (block.type === "sdt") {
36285
+ out.push(
36286
+ ...enumerateNestedMarkerBackedParagraphs(block.children, {
36287
+ ...input,
36288
+ semanticPrefix: [
36289
+ ...input.semanticPrefix,
36290
+ "sdt",
36291
+ String(childIndex)
36292
+ ]
36293
+ })
36294
+ );
36295
+ continue;
36296
+ }
36297
+ if (block.type === "table") {
36298
+ for (let rowIdx = 0; rowIdx < block.rows.length; rowIdx += 1) {
36299
+ const row2 = block.rows[rowIdx];
36300
+ for (let cellIdx = 0; cellIdx < row2.cells.length; cellIdx += 1) {
36301
+ const cell = row2.cells[cellIdx];
36302
+ out.push(
36303
+ ...enumerateNestedMarkerBackedParagraphs(cell.children, {
36304
+ ...input,
36305
+ semanticPrefix: [
36306
+ ...input.semanticPrefix,
36307
+ "table",
36308
+ String(childIndex),
36309
+ "row",
36310
+ String(rowIdx),
36311
+ "cell",
36312
+ String(cellIdx)
36313
+ ]
36314
+ })
36315
+ );
36316
+ }
36317
+ }
36318
+ }
36319
+ }
36320
+ return out;
36321
+ }
36058
36322
  function enumerateFieldsInParagraph(paragraph, blockIndex, documentId, parentScopeId) {
36059
36323
  const out = [];
36060
36324
  for (let i = 0; i < paragraph.children.length; i += 1) {
@@ -36337,6 +36601,17 @@ function enumerateScopes(document2, inputs = {}) {
36337
36601
  cellIndex: cellIdx,
36338
36602
  classifications: Object.freeze([])
36339
36603
  });
36604
+ for (const nested of enumerateNestedMarkerBackedParagraphs(cell.children, {
36605
+ documentId,
36606
+ rootBlockIndex: index,
36607
+ semanticPrefix: cellSemanticPath,
36608
+ parentScopeId: cellScopeId,
36609
+ knownOverlayScopeIds,
36610
+ classificationIndex,
36611
+ overlay: inputs.overlay
36612
+ })) {
36613
+ results.push(nested);
36614
+ }
36340
36615
  }
36341
36616
  }
36342
36617
  }
@@ -36822,16 +37097,12 @@ function replaceTextCapability(scope, context) {
36822
37097
  );
36823
37098
  }
36824
37099
  if (scope.kind === "scope") {
36825
- if (scope.workflow.effectiveMode === "suggest") {
36826
- return unsupported(
36827
- "compile-refused:scope:multi-paragraph-suggesting-not-implemented",
36828
- ["compile-refused:scope:multi-paragraph-suggesting-not-implemented"],
36829
- ["guard:suggest-mode", ...evidenceWarnings(context)]
36830
- );
36831
- }
36832
37100
  return supported(
36833
37101
  "compile-supported:scope:multi-paragraph-text-replace",
36834
- evidenceWarnings(context)
37102
+ [
37103
+ ...scope.workflow.effectiveMode === "suggest" ? ["guard:suggest-mode"] : [],
37104
+ ...evidenceWarnings(context)
37105
+ ]
36835
37106
  );
36836
37107
  }
36837
37108
  if (!PARAGRAPH_LIKE.has(scope.kind)) {
@@ -36885,34 +37156,24 @@ function replaceFragmentCapability(scope, context) {
36885
37156
  );
36886
37157
  }
36887
37158
  if (scope.kind === "scope") {
36888
- if (scope.workflow.effectiveMode === "suggest") {
36889
- return unsupported(
36890
- "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented",
36891
- [
36892
- "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented"
36893
- ],
36894
- ["guard:suggest-mode", ...evidenceWarnings(context)]
36895
- );
36896
- }
36897
37159
  return supported(
36898
37160
  "compile-supported:scope:multi-paragraph-fragment-replace",
36899
- evidenceWarnings(context)
37161
+ [
37162
+ ...scope.workflow.effectiveMode === "suggest" ? ["guard:suggest-mode"] : [],
37163
+ ...evidenceWarnings(context)
37164
+ ]
36900
37165
  );
36901
37166
  }
36902
37167
  if (!PARAGRAPH_LIKE.has(scope.kind)) {
36903
37168
  const reason = `compile-refused:${scope.kind}`;
36904
37169
  return unsupported(reason, [reason], evidenceWarnings(context));
36905
37170
  }
36906
- if (scope.workflow.effectiveMode === "suggest") {
36907
- return unsupported(
36908
- `compile-refused:${scope.kind}:structured-suggesting-not-implemented`,
36909
- [`compile-refused:${scope.kind}:structured-suggesting-not-implemented`],
36910
- ["guard:suggest-mode"]
36911
- );
36912
- }
36913
37171
  return supported(
36914
- "compile-supported:paragraph-like:fragment-replace",
36915
- evidenceWarnings(context)
37172
+ scope.workflow.effectiveMode === "suggest" ? "compile-supported:paragraph-like:fragment-replace-tracked" : "compile-supported:paragraph-like:fragment-replace",
37173
+ [
37174
+ ...scope.workflow.effectiveMode === "suggest" ? ["guard:suggest-mode"] : [],
37175
+ ...evidenceWarnings(context)
37176
+ ]
36916
37177
  );
36917
37178
  }
36918
37179
  function formattingCapability(scope, context) {
@@ -37966,6 +38227,14 @@ function supportedNonTextCommandEvidence(target) {
37966
38227
  if (target.commandFamily === "link-bookmark") {
37967
38228
  return linkBookmarkCommandEvidence(target, []);
37968
38229
  }
38230
+ if (target.commandFamily === "object" && isImageObjectTarget(target) && typeof target.object?.mediaId === "string" && target.object.mediaId.length > 0 && onlyBlockers(target.posture.blockers, ["unmodeled-target"])) {
38231
+ return {
38232
+ status: "supported",
38233
+ commandFamily: target.commandFamily,
38234
+ intents: commandIntentsForTarget(target),
38235
+ reason: "l07:image-layout-target-supported"
38236
+ };
38237
+ }
37969
38238
  return null;
37970
38239
  }
37971
38240
  function onlyBlockers(blockers, allowed) {
@@ -40466,9 +40735,7 @@ function applyScopeReplacement(inputs) {
40466
40735
  });
40467
40736
  if (!plan) {
40468
40737
  const paragraphLike = resolvedScope.kind === "paragraph" || resolvedScope.kind === "heading" || resolvedScope.kind === "list-item";
40469
- const blockers = resolvedScope.kind === "scope" && posture === "suggest-mode" ? [
40470
- proposed.proposedContent.kind === "structured" ? "compile-refused:scope:multi-paragraph-structured-suggesting-not-implemented" : "compile-refused:scope:multi-paragraph-suggesting-not-implemented"
40471
- ] : resolvedScope.kind === "scope" && proposed.operation !== "replace" ? [
40738
+ const blockers = resolvedScope.kind === "scope" && proposed.operation !== "replace" ? [
40472
40739
  `compile-refused:scope:operation-not-implemented:${proposed.operation}`
40473
40740
  ] : resolvedScope.kind === "scope" ? multiParagraphReplacementBlockers(
40474
40741
  proposed.proposedContent.kind === "structured" ? "fragment" : "text"
@@ -41904,7 +42171,8 @@ function buildResolvedSections(document2) {
41904
42171
  const mainSurface = createEditorSurfaceSnapshot(
41905
42172
  document2,
41906
42173
  createSelectionSnapshot(0, 0),
41907
- MAIN_STORY_TARGET
42174
+ MAIN_STORY_TARGET,
42175
+ { editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX }
41908
42176
  );
41909
42177
  const sections = [];
41910
42178
  let sectionStart = 0;
@@ -57965,7 +58233,20 @@ function createDocumentRuntime(options) {
57965
58233
  selection: prepared.selection
57966
58234
  };
57967
58235
  resolvedReplayTextTarget = prepared.textTarget;
57968
- } else if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
58236
+ } else {
58237
+ const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
58238
+ command,
58239
+ document: replayState.document,
58240
+ selection: replayState.selection,
58241
+ surface: replaySnapshot.surface?.blocks ?? [],
58242
+ storyTarget: replayStory,
58243
+ timestamp: context.timestamp
58244
+ });
58245
+ if (selectedListItemDeleteCommand) {
58246
+ executableCommand = selectedListItemDeleteCommand;
58247
+ }
58248
+ }
58249
+ if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
57969
58250
  const prepared = prepareModeledTargetCommandForExecution(
57970
58251
  command,
57971
58252
  replayState.document,
@@ -58109,7 +58390,20 @@ function createDocumentRuntime(options) {
58109
58390
  selection: prepared.selection
58110
58391
  };
58111
58392
  resolvedReplayTextTarget = prepared.textTarget;
58112
- } else if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
58393
+ } else {
58394
+ const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
58395
+ command,
58396
+ document: stateForCommand.document,
58397
+ selection: stateForCommand.selection,
58398
+ surface: snapshotForCommand.surface?.blocks ?? [],
58399
+ storyTarget: replayStory,
58400
+ timestamp: context.timestamp
58401
+ });
58402
+ if (selectedListItemDeleteCommand) {
58403
+ executableCommand = selectedListItemDeleteCommand;
58404
+ }
58405
+ }
58406
+ if (command.type === "field.refresh" || command.type === "toc.refresh" || command.type === "bookmark.edit-content" || command.type === "hyperlink.update-destination") {
58113
58407
  const prepared = prepareModeledTargetCommandForExecution(
58114
58408
  command,
58115
58409
  stateForCommand.document,
@@ -58530,6 +58824,50 @@ function createDocumentRuntime(options) {
58530
58824
  } catch (error) {
58531
58825
  emitError(toRuntimeError(error));
58532
58826
  }
58827
+ } else if (step.kind === "fragment-replace-tracked" && step.range && step.fragment && Array.isArray(step.fragment.blocks)) {
58828
+ const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
58829
+ if (editableTarget === null) {
58830
+ emit({
58831
+ type: "command_blocked",
58832
+ documentId: state.documentId,
58833
+ command: "applyScopeReplacement",
58834
+ reasons: [{
58835
+ code: "unsupported_surface",
58836
+ message: "Scope replacement editable target no longer resolves."
58837
+ }]
58838
+ });
58839
+ continue;
58840
+ }
58841
+ const dispatchRange = mapSemanticStepRangeToEditableTarget(
58842
+ step.range,
58843
+ step.editableTargetHint,
58844
+ editableTarget?.range
58845
+ );
58846
+ const anchor = {
58847
+ kind: "range",
58848
+ from: dispatchRange.from,
58849
+ to: dispatchRange.to,
58850
+ assoc: { start: -1, end: 1 }
58851
+ };
58852
+ const timestamp = clock();
58853
+ try {
58854
+ applyTextCommandInActiveStory(
58855
+ {
58856
+ type: "fragment.insert-tracked",
58857
+ fragment: step.fragment,
58858
+ ...editableTarget?.target ? { editableTarget: editableTarget.target } : {},
58859
+ origin: createOrigin("api", timestamp)
58860
+ },
58861
+ {
58862
+ selection: createSelectionFromPublicAnchor(anchor),
58863
+ blockedCommandName: "applyScopeReplacement",
58864
+ documentModeOverride: "suggesting",
58865
+ skipWorkflowGuard: true
58866
+ }
58867
+ );
58868
+ } catch (error) {
58869
+ emitError(toRuntimeError(error));
58870
+ }
58533
58871
  } else if (step.kind === "text-insert-tracked" && step.range && typeof step.text === "string") {
58534
58872
  const editableTarget = resolveEditableTargetHint(step.editableTargetHint);
58535
58873
  if (editableTarget === null) {
@@ -60512,6 +60850,38 @@ function createDocumentRuntime(options) {
60512
60850
  const preSelection = selection;
60513
60851
  const preActiveStory = activeStory;
60514
60852
  const priorDocument = state.document;
60853
+ const selectedListItemDelete = createSelectedListItemDeleteReplacement({
60854
+ command: commandForDispatch,
60855
+ document: state.document,
60856
+ editableTarget,
60857
+ selection,
60858
+ targetResolution,
60859
+ timestamp
60860
+ });
60861
+ if (selectedListItemDelete && activeStory.kind === "main" && context.documentMode !== "suggesting") {
60862
+ const replacementCommand = {
60863
+ type: "document.replace",
60864
+ document: selectedListItemDelete.document,
60865
+ selection: selectedListItemDelete.selection,
60866
+ mapping: selectedListItemDelete.mapping,
60867
+ protectionSelection: selection,
60868
+ origin: commandForDispatch.origin
60869
+ };
60870
+ const transaction = executeEditorCommand(baseState, replacementCommand, context);
60871
+ commit(transaction);
60872
+ options.onCommandApplied?.(commandForDispatch, transaction, context, {
60873
+ preSelection,
60874
+ activeStory: preActiveStory,
60875
+ priorDocument
60876
+ });
60877
+ return completeDispatch(classifyAck({
60878
+ command: commandForDispatch,
60879
+ opId,
60880
+ priorState: baseState,
60881
+ transaction,
60882
+ newRevisionToken: state.revisionToken
60883
+ }));
60884
+ }
60515
60885
  if (activeStory.kind === "main") {
60516
60886
  const mainTransaction = executeEditorCommand(baseState, commandForDispatch, context);
60517
60887
  commit(mainTransaction);
@@ -61706,7 +62076,8 @@ function getStoryPlainText(document2, storyTarget, cache) {
61706
62076
  const plainText = createEditorSurfaceSnapshot(
61707
62077
  document2,
61708
62078
  createSelectionSnapshot(0, 0),
61709
- storyTarget
62079
+ storyTarget,
62080
+ { editableTargetsByBlockPath: NO_EDITABLE_TARGETS_INDEX }
61710
62081
  ).plainText;
61711
62082
  cache.set(key, plainText);
61712
62083
  return plainText;
@@ -63391,6 +63762,172 @@ function stripStoryTarget(selection) {
63391
63762
  function isTopLevelMainStoryBlockPath(blockPath) {
63392
63763
  return typeof blockPath === "string" && /^main\/block\[\d+\]$/u.test(blockPath);
63393
63764
  }
63765
+ function createSelectedListItemDeleteReplacement(input) {
63766
+ const { command, document: document2, editableTarget, selection, targetResolution, timestamp } = input;
63767
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
63768
+ return null;
63769
+ }
63770
+ if (selection.isCollapsed || editableTarget?.listAddress?.operationScope !== "list-text" || targetResolution?.kind !== "accepted") {
63771
+ return null;
63772
+ }
63773
+ const selectionFrom = Math.min(selection.anchor, selection.head);
63774
+ const selectionTo = Math.max(selection.anchor, selection.head);
63775
+ if (selectionFrom !== targetResolution.range.from || selectionTo !== targetResolution.range.to) {
63776
+ return null;
63777
+ }
63778
+ const root = document2.content;
63779
+ const replacement = removeNumberedParagraphAtMainStoryPath(root.children, editableTarget.blockPath);
63780
+ if (!replacement) {
63781
+ return null;
63782
+ }
63783
+ const nextDocument = {
63784
+ ...document2,
63785
+ updatedAt: timestamp,
63786
+ content: {
63787
+ ...root,
63788
+ children: replacement.blocks
63789
+ }
63790
+ };
63791
+ const nextStorySize = parseTextStory(nextDocument.content).size;
63792
+ const nextAnchor = Math.min(selectionFrom, nextStorySize);
63793
+ return {
63794
+ document: nextDocument,
63795
+ selection: createSelectionSnapshot(nextAnchor, nextAnchor),
63796
+ mapping: {
63797
+ steps: [{
63798
+ from: selectionFrom,
63799
+ to: selectionTo,
63800
+ insertSize: 0
63801
+ }],
63802
+ metadata: {
63803
+ invalidatesStructures: true
63804
+ }
63805
+ }
63806
+ };
63807
+ }
63808
+ function removeNumberedParagraphAtMainStoryPath(blocks, blockPath) {
63809
+ const tokens = parseMainStoryBlockPathTokens(blockPath);
63810
+ if (!tokens) return null;
63811
+ return removeNumberedParagraphFromBlocks(blocks, tokens);
63812
+ }
63813
+ function removeNumberedParagraphFromBlocks(blocks, tokens) {
63814
+ const [token, ...rest] = tokens;
63815
+ if (!token || token.kind !== "block") return null;
63816
+ const block = blocks[token.index];
63817
+ if (!block) return null;
63818
+ if (rest.length === 0) {
63819
+ if (block.type !== "paragraph" || !block.numbering) {
63820
+ return null;
63821
+ }
63822
+ if (blocks.length === 1) {
63823
+ return { blocks: [{ type: "paragraph", children: [] }] };
63824
+ }
63825
+ return {
63826
+ blocks: [
63827
+ ...blocks.slice(0, token.index),
63828
+ ...blocks.slice(token.index + 1)
63829
+ ]
63830
+ };
63831
+ }
63832
+ const next = rest[0];
63833
+ if (block.type === "table" && next?.kind === "row") {
63834
+ const updatedTable = removeNumberedParagraphFromTable(block, rest);
63835
+ if (!updatedTable) return null;
63836
+ return {
63837
+ blocks: [
63838
+ ...blocks.slice(0, token.index),
63839
+ updatedTable,
63840
+ ...blocks.slice(token.index + 1)
63841
+ ]
63842
+ };
63843
+ }
63844
+ if ((block.type === "sdt" || block.type === "custom_xml") && next?.kind === "block") {
63845
+ const updatedChildren = removeNumberedParagraphFromBlocks(block.children, rest);
63846
+ if (!updatedChildren) return null;
63847
+ return {
63848
+ blocks: [
63849
+ ...blocks.slice(0, token.index),
63850
+ { ...block, children: updatedChildren.blocks },
63851
+ ...blocks.slice(token.index + 1)
63852
+ ]
63853
+ };
63854
+ }
63855
+ return null;
63856
+ }
63857
+ function removeNumberedParagraphFromTable(table, tokens) {
63858
+ const [rowToken, cellToken, ...childTokens] = tokens;
63859
+ if (rowToken?.kind !== "row" || cellToken?.kind !== "cell" || childTokens[0]?.kind !== "block") {
63860
+ return null;
63861
+ }
63862
+ const row2 = table.rows[rowToken.index];
63863
+ const cell = row2?.cells[cellToken.index];
63864
+ if (!row2 || !cell) return null;
63865
+ const updatedChildren = removeNumberedParagraphFromBlocks(cell.children, childTokens);
63866
+ if (!updatedChildren) return null;
63867
+ const nextCells = [
63868
+ ...row2.cells.slice(0, cellToken.index),
63869
+ { ...cell, children: updatedChildren.blocks },
63870
+ ...row2.cells.slice(cellToken.index + 1)
63871
+ ];
63872
+ const nextRows = [
63873
+ ...table.rows.slice(0, rowToken.index),
63874
+ { ...row2, cells: nextCells },
63875
+ ...table.rows.slice(rowToken.index + 1)
63876
+ ];
63877
+ return { ...table, rows: nextRows };
63878
+ }
63879
+ function createSelectedListItemDeleteReplayCommand(input) {
63880
+ const { command, document: document2, selection, surface, storyTarget, timestamp } = input;
63881
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
63882
+ return null;
63883
+ }
63884
+ const editableTarget = command.editableTarget;
63885
+ if (!editableTarget) {
63886
+ return null;
63887
+ }
63888
+ const targetResolution = resolveEditableTextTarget({
63889
+ document: document2,
63890
+ selection,
63891
+ surface,
63892
+ target: editableTarget,
63893
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
63894
+ });
63895
+ const replacement = createSelectedListItemDeleteReplacement({
63896
+ command,
63897
+ document: document2,
63898
+ editableTarget,
63899
+ selection,
63900
+ targetResolution,
63901
+ timestamp
63902
+ });
63903
+ if (!replacement || storyTarget.kind !== "main") {
63904
+ return null;
63905
+ }
63906
+ return {
63907
+ type: "document.replace",
63908
+ document: replacement.document,
63909
+ selection: replacement.selection,
63910
+ mapping: replacement.mapping,
63911
+ protectionSelection: selection,
63912
+ origin: command.origin
63913
+ };
63914
+ }
63915
+ function parseMainStoryBlockPathTokens(blockPath) {
63916
+ const parts = blockPath?.split("/") ?? [];
63917
+ if (parts[0] !== "main" || parts.length < 2) {
63918
+ return null;
63919
+ }
63920
+ const tokens = [];
63921
+ for (const part of parts.slice(1)) {
63922
+ const match = /^(block|row|cell)\[(\d+)\]$/u.exec(part);
63923
+ if (!match) return null;
63924
+ tokens.push({
63925
+ kind: match[1],
63926
+ index: Number.parseInt(match[2], 10)
63927
+ });
63928
+ }
63929
+ return tokens;
63930
+ }
63394
63931
  function toInternalSelectionSnapshot2(selection) {
63395
63932
  return {
63396
63933
  anchor: selection.anchor,