@beyondwork/docx-react-component 1.0.134 → 1.0.136

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 (89) hide show
  1. package/dist/api/public-types.cjs +20 -2
  2. package/dist/api/public-types.d.cts +2 -2
  3. package/dist/api/public-types.d.ts +2 -2
  4. package/dist/api/public-types.js +2 -2
  5. package/dist/api/v3.cjs +203 -41
  6. package/dist/api/v3.d.cts +3 -3
  7. package/dist/api/v3.d.ts +3 -3
  8. package/dist/api/v3.js +4 -4
  9. package/dist/{canonical-document-CfZIc-fC.d.cts → canonical-document-COmM7v11.d.cts} +1 -1
  10. package/dist/{canonical-document-CfZIc-fC.d.ts → canonical-document-COmM7v11.d.ts} +1 -1
  11. package/dist/{chunk-REFHJ2FN.js → chunk-2BNXARVO.js} +3 -3
  12. package/dist/{chunk-INLRCC4N.js → chunk-4CIHTMCH.js} +2 -2
  13. package/dist/{chunk-MQ5GAJ54.js → chunk-BJXSMPHD.js} +1 -1
  14. package/dist/{chunk-XBQFDBXE.js → chunk-EZFF6GKF.js} +9 -2
  15. package/dist/{chunk-3YR47WTD.js → chunk-FGJTOFZY.js} +21 -9
  16. package/dist/{chunk-74R5B2EZ.js → chunk-H4HI6RUE.js} +1 -1
  17. package/dist/{chunk-IJD6D7HU.js → chunk-HUWZ7AHE.js} +125 -2
  18. package/dist/{chunk-7Y6JCIK3.js → chunk-HWMPNLEF.js} +1 -1
  19. package/dist/{chunk-EBSI6VQX.js → chunk-JZZKTL7K.js} +800 -93
  20. package/dist/{chunk-VA24T4EB.js → chunk-NEMOQ4QR.js} +1 -1
  21. package/dist/{chunk-ESEEWELA.js → chunk-NX7W6T7L.js} +171 -39
  22. package/dist/{chunk-O4EDZR44.js → chunk-P7XDEVS6.js} +12 -1
  23. package/dist/{chunk-QTRJLKR2.js → chunk-TSNK4ECL.js} +1 -1
  24. package/dist/{chunk-WDDFU2N2.js → chunk-UR2LW63N.js} +1 -1
  25. package/dist/compare.d.cts +1 -1
  26. package/dist/compare.d.ts +1 -1
  27. package/dist/core/commands/formatting-commands.d.cts +2 -2
  28. package/dist/core/commands/formatting-commands.d.ts +2 -2
  29. package/dist/core/commands/image-commands.cjs +9 -2
  30. package/dist/core/commands/image-commands.d.cts +2 -2
  31. package/dist/core/commands/image-commands.d.ts +2 -2
  32. package/dist/core/commands/image-commands.js +4 -4
  33. package/dist/core/commands/section-layout-commands.d.cts +2 -2
  34. package/dist/core/commands/section-layout-commands.d.ts +2 -2
  35. package/dist/core/commands/style-commands.d.cts +2 -2
  36. package/dist/core/commands/style-commands.d.ts +2 -2
  37. package/dist/core/commands/table-structure-commands.cjs +9 -2
  38. package/dist/core/commands/table-structure-commands.d.cts +2 -2
  39. package/dist/core/commands/table-structure-commands.d.ts +2 -2
  40. package/dist/core/commands/table-structure-commands.js +3 -3
  41. package/dist/core/commands/text-commands.cjs +9 -2
  42. package/dist/core/commands/text-commands.d.cts +2 -2
  43. package/dist/core/commands/text-commands.d.ts +2 -2
  44. package/dist/core/commands/text-commands.js +4 -4
  45. package/dist/core/selection/mapping.d.cts +2 -2
  46. package/dist/core/selection/mapping.d.ts +2 -2
  47. package/dist/core/state/editor-state.d.cts +2 -2
  48. package/dist/core/state/editor-state.d.ts +2 -2
  49. package/dist/index.cjs +1287 -198
  50. package/dist/index.d.cts +5 -5
  51. package/dist/index.d.ts +5 -5
  52. package/dist/index.js +135 -34
  53. package/dist/io/docx-session.d.cts +4 -4
  54. package/dist/io/docx-session.d.ts +4 -4
  55. package/dist/legal.d.cts +1 -1
  56. package/dist/legal.d.ts +1 -1
  57. package/dist/{loader-CK3lZy4h.d.cts → loader-Cr35kVUi.d.cts} +3 -3
  58. package/dist/{loader-CQXplstv.d.ts → loader-uGY6nDZP.d.ts} +3 -3
  59. package/dist/{public-types-DXNZVKrS.d.ts → public-types-8kVIB5HW.d.ts} +22 -8
  60. package/dist/{public-types-BR1SYK2F.d.cts → public-types-CSSH2Whc.d.cts} +22 -8
  61. package/dist/public-types.cjs +20 -2
  62. package/dist/public-types.d.cts +2 -2
  63. package/dist/public-types.d.ts +2 -2
  64. package/dist/public-types.js +2 -2
  65. package/dist/runtime/collab.d.cts +3 -3
  66. package/dist/runtime/collab.d.ts +3 -3
  67. package/dist/runtime/document-runtime.cjs +929 -83
  68. package/dist/runtime/document-runtime.d.cts +2 -2
  69. package/dist/runtime/document-runtime.d.ts +2 -2
  70. package/dist/runtime/document-runtime.js +10 -10
  71. package/dist/{session-CSbwkgII.d.cts → session-Beg8ihOi.d.cts} +3 -3
  72. package/dist/{session-C9UjrhJF.d.ts → session-Dgp-2uYw.d.ts} +3 -3
  73. package/dist/session.d.cts +5 -5
  74. package/dist/session.d.ts +5 -5
  75. package/dist/tailwind.cjs +27 -8
  76. package/dist/tailwind.d.cts +2 -2
  77. package/dist/tailwind.d.ts +2 -2
  78. package/dist/tailwind.js +5 -5
  79. package/dist/{types-RzkCXDNV.d.ts → types-Cin_abw3.d.ts} +2 -2
  80. package/dist/{types-CZtAueri.d.cts → types-qsS39ZkQ.d.cts} +2 -2
  81. package/dist/ui-tailwind/editor-surface/search-plugin.cjs +11 -0
  82. package/dist/ui-tailwind/editor-surface/search-plugin.d.cts +3 -3
  83. package/dist/ui-tailwind/editor-surface/search-plugin.d.ts +3 -3
  84. package/dist/ui-tailwind/editor-surface/search-plugin.js +3 -3
  85. package/dist/ui-tailwind.cjs +27 -8
  86. package/dist/ui-tailwind.d.cts +3 -3
  87. package/dist/ui-tailwind.d.ts +3 -3
  88. package/dist/ui-tailwind.js +5 -5
  89. package/package.json +1 -1
@@ -11011,10 +11011,16 @@ var FormattingContextImpl = class {
11011
11011
  // surface-projection calls `resolveParagraphCascade` on the same
11012
11012
  // paragraph via `resolveParagraph` + numbering resolve + marker-rPr;
11013
11013
  // each of those re-walked the style catalog before.
11014
- paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
11014
+ //
11015
+ // Defaults to a per-context instance, but the runtime can supply a
11016
+ // persistent `WeakMap` via `FormattingContextOptions.paragraphCascadeCache`
11017
+ // so unchanged paragraphs don't re-cascade on every keystroke. See the
11018
+ // contract on the option for invalidation semantics.
11019
+ paragraphCascadeCache;
11015
11020
  constructor(doc, opts) {
11016
11021
  this.doc = doc;
11017
11022
  this.opts = opts;
11023
+ this.paragraphCascadeCache = opts.paragraphCascadeCache ?? /* @__PURE__ */ new WeakMap();
11018
11024
  const canonicalTheme = doc.subParts?.canonicalTheme;
11019
11025
  this.theme = opts.themeResolver ?? (canonicalTheme ? new ThemeColorResolver(canonicalTheme) : void 0);
11020
11026
  this.numbering = opts.numberingPrefixResolver ?? createNumberingPrefixResolver(doc.numbering);
@@ -11580,7 +11586,8 @@ function createEditorSurfaceSnapshot(document2, _selection, activeStory = { kind
11580
11586
  const formattingContext = createFormattingContext(document2, {
11581
11587
  ...options.revisionMarkupMode ? { revisionMarkupMode: options.revisionMarkupMode } : {},
11582
11588
  ...options.getEffectiveMarkupMode ? { getEffectiveMarkupMode: options.getEffectiveMarkupMode } : {},
11583
- ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {}
11589
+ ...options.authorColorPalette ? { authorColorPalette: options.authorColorPalette } : {},
11590
+ ...options.paragraphCascadeCache ? { paragraphCascadeCache: options.paragraphCascadeCache } : {}
11584
11591
  });
11585
11592
  const editableTargetsByBlockPath = options.editableTargetsByBlockPath ?? indexEditableTargetsByBlockPath(document2);
11586
11593
  const layoutIdentitiesByBlockPath = options.layoutIdentitiesByBlockPath;
@@ -19705,6 +19712,106 @@ function setStartOverride(catalog, numberingInstanceId, level, startAt) {
19705
19712
  overrides: mergeOverride(instance.overrides, { level, startAt })
19706
19713
  };
19707
19714
  }
19715
+ function mergeFragmentNumberingCatalog(target, fragment) {
19716
+ const catalog = cloneNumberingCatalog(target);
19717
+ const abstractIdMap = /* @__PURE__ */ new Map();
19718
+ const instanceIdMap = /* @__PURE__ */ new Map();
19719
+ const picBulletIdMap = /* @__PURE__ */ new Map();
19720
+ if (!fragment) {
19721
+ return { catalog, abstractIdMap, instanceIdMap, picBulletIdMap };
19722
+ }
19723
+ for (const [picBulletId, entry] of Object.entries(fragment.numPicBullets ?? {})) {
19724
+ const mappedId = mapPicBulletId(catalog, picBulletId, entry);
19725
+ picBulletIdMap.set(picBulletId, mappedId);
19726
+ }
19727
+ for (const [abstractId, definition] of Object.entries(fragment.abstractDefinitions)) {
19728
+ const mappedId = mapAbstractDefinition(catalog, definition, picBulletIdMap);
19729
+ abstractIdMap.set(abstractId, mappedId);
19730
+ }
19731
+ for (const [instanceId, instance] of Object.entries(fragment.instances)) {
19732
+ const mappedAbstractId = abstractIdMap.get(instance.abstractNumberingId) ?? instance.abstractNumberingId;
19733
+ const mappedId = mapNumberingInstance(
19734
+ catalog,
19735
+ instance,
19736
+ mappedAbstractId,
19737
+ picBulletIdMap
19738
+ );
19739
+ instanceIdMap.set(instanceId, mappedId);
19740
+ }
19741
+ return { catalog, abstractIdMap, instanceIdMap, picBulletIdMap };
19742
+ }
19743
+ function mapPicBulletId(catalog, picBulletId, entry) {
19744
+ const existing = catalog.numPicBullets?.[picBulletId];
19745
+ if (existing && existing.rawXml === entry.rawXml) return picBulletId;
19746
+ const mappedId = existing ? nextNumericString(Object.keys(catalog.numPicBullets ?? {})) : picBulletId;
19747
+ const numPicBullets = { ...catalog.numPicBullets ?? {} };
19748
+ numPicBullets[mappedId] = {
19749
+ ...stripSourceRef(structuredClone(entry)),
19750
+ numPicBulletId: mappedId
19751
+ };
19752
+ catalog.numPicBullets = numPicBullets;
19753
+ return mappedId;
19754
+ }
19755
+ function mapAbstractDefinition(catalog, definition, picBulletIdMap) {
19756
+ const existing = catalog.abstractDefinitions[definition.abstractNumberingId];
19757
+ if (existing && sameJson(comparableAbstract(existing), comparableAbstract(definition))) {
19758
+ return definition.abstractNumberingId;
19759
+ }
19760
+ const mappedId = existing ? nextCanonicalNumericId("abstract-num:", Object.keys(catalog.abstractDefinitions)) : definition.abstractNumberingId;
19761
+ catalog.abstractDefinitions[mappedId] = {
19762
+ ...stripSourceRef(structuredClone(definition)),
19763
+ abstractNumberingId: mappedId,
19764
+ nsid: freshLongHex(catalog, mappedId, "nsid"),
19765
+ tplc: freshLongHex(catalog, mappedId, "tmpl"),
19766
+ levels: definition.levels.map((level) => remapLevelPicBullet(level, picBulletIdMap))
19767
+ };
19768
+ return mappedId;
19769
+ }
19770
+ function mapNumberingInstance(catalog, instance, abstractNumberingId, picBulletIdMap) {
19771
+ const existing = catalog.instances[instance.numberingInstanceId];
19772
+ const candidate = {
19773
+ ...instance,
19774
+ abstractNumberingId,
19775
+ overrides: instance.overrides.map(
19776
+ (override) => remapOverridePicBullet(override, picBulletIdMap)
19777
+ )
19778
+ };
19779
+ if (existing && sameJson(comparableInstance(existing), comparableInstance(candidate))) {
19780
+ return instance.numberingInstanceId;
19781
+ }
19782
+ const mappedId = existing ? nextCanonicalNumericId("num:", Object.keys(catalog.instances)) : instance.numberingInstanceId;
19783
+ catalog.instances[mappedId] = {
19784
+ ...stripSourceRef(structuredClone(instance)),
19785
+ overrides: candidate.overrides.map((override) => stripOverrideSourceRefs(override)),
19786
+ numberingInstanceId: mappedId,
19787
+ abstractNumberingId
19788
+ };
19789
+ return mappedId;
19790
+ }
19791
+ function remapLevelPicBullet(level, picBulletIdMap) {
19792
+ const cloned = stripSourceRef(structuredClone(level));
19793
+ if (!level.picBulletId) return cloned;
19794
+ return {
19795
+ ...cloned,
19796
+ picBulletId: picBulletIdMap.get(level.picBulletId) ?? level.picBulletId
19797
+ };
19798
+ }
19799
+ function remapOverridePicBullet(override, picBulletIdMap) {
19800
+ const cloned = stripOverrideSourceRefs(structuredClone(override));
19801
+ if (!override.levelDefinition) return cloned;
19802
+ return {
19803
+ ...cloned,
19804
+ levelDefinition: remapLevelPicBullet(override.levelDefinition, picBulletIdMap)
19805
+ };
19806
+ }
19807
+ function stripOverrideSourceRefs(override) {
19808
+ const cloned = stripSourceRef(override);
19809
+ if (!override.levelDefinition) return cloned;
19810
+ return {
19811
+ ...cloned,
19812
+ levelDefinition: stripSourceRef(override.levelDefinition)
19813
+ };
19814
+ }
19708
19815
  function mergeOverride(overrides, nextOverride) {
19709
19816
  return [
19710
19817
  ...overrides.filter((override) => override.level !== nextOverride.level),
@@ -19776,6 +19883,28 @@ function hashLongHex(input) {
19776
19883
  }
19777
19884
  return hash.toString(16).toUpperCase().padStart(8, "0").slice(-8);
19778
19885
  }
19886
+ function stripSourceRef(value) {
19887
+ const { sourceRef: _sourceRef, ...rest } = value;
19888
+ return rest;
19889
+ }
19890
+ function comparableAbstract(definition) {
19891
+ return {
19892
+ ...stripSourceRef(definition),
19893
+ levels: definition.levels.map((level) => stripSourceRef(level))
19894
+ };
19895
+ }
19896
+ function comparableInstance(instance) {
19897
+ return {
19898
+ ...stripSourceRef(instance),
19899
+ overrides: instance.overrides.map((override) => ({
19900
+ ...stripSourceRef(override),
19901
+ ...override.levelDefinition ? { levelDefinition: stripSourceRef(override.levelDefinition) } : {}
19902
+ }))
19903
+ };
19904
+ }
19905
+ function sameJson(left, right) {
19906
+ return JSON.stringify(left) === JSON.stringify(right);
19907
+ }
19779
19908
 
19780
19909
  // src/core/commands/list-commands.ts
19781
19910
  function toggleNumberedList(document2, paragraphIndexes, context, options = {}) {
@@ -19814,7 +19943,7 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
19814
19943
  affectedParagraphIndexes: []
19815
19944
  };
19816
19945
  }
19817
- const target = paragraphs[resolvedParagraphIndex];
19946
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
19818
19947
  if (!target?.numbering) {
19819
19948
  return {
19820
19949
  document: working,
@@ -19836,8 +19965,13 @@ function restartNumbering(document2, paragraphIndex, context, startAt = 1, optio
19836
19965
  );
19837
19966
  setStartOverride(catalog, numberingInstanceId, target.numbering.level, startAt);
19838
19967
  const affectedParagraphIndexes = [];
19968
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
19839
19969
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
19840
- const paragraph = paragraphs[index];
19970
+ const entry = paragraphs[index];
19971
+ if (entry?.storyKey !== targetStoryKey) {
19972
+ break;
19973
+ }
19974
+ const paragraph = entry.paragraph;
19841
19975
  if (!paragraph?.numbering) {
19842
19976
  break;
19843
19977
  }
@@ -19881,7 +20015,7 @@ function continueNumbering(document2, paragraphIndex, context, options = {}) {
19881
20015
  affectedParagraphIndexes: []
19882
20016
  };
19883
20017
  }
19884
- const target = paragraphs[resolvedParagraphIndex];
20018
+ const target = paragraphs[resolvedParagraphIndex]?.paragraph;
19885
20019
  if (!target?.numbering) {
19886
20020
  return {
19887
20021
  document: working,
@@ -19910,8 +20044,13 @@ function continueNumbering(document2, paragraphIndex, context, options = {}) {
19910
20044
  };
19911
20045
  }
19912
20046
  const affectedParagraphIndexes = [];
20047
+ const targetStoryKey = paragraphs[resolvedParagraphIndex]?.storyKey;
19913
20048
  for (let index = resolvedParagraphIndex; index < paragraphs.length; index += 1) {
19914
- const paragraph = paragraphs[index];
20049
+ const entry = paragraphs[index];
20050
+ if (entry?.storyKey !== targetStoryKey) {
20051
+ break;
20052
+ }
20053
+ const paragraph = entry.paragraph;
19915
20054
  if (!paragraph?.numbering) {
19916
20055
  break;
19917
20056
  }
@@ -19957,12 +20096,13 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
19957
20096
  }
19958
20097
  const catalog = cloneNumberingCatalog(working.numbering);
19959
20098
  const allAlreadyKind = normalizedIndexes.every((index) => {
19960
- const paragraph = paragraphs[index];
19961
- return paragraph.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
20099
+ const paragraph = paragraphs[index]?.paragraph;
20100
+ return paragraph?.numbering ? getListKind(catalog, paragraph.numbering.numberingInstanceId) === kind : false;
19962
20101
  });
19963
20102
  if (allAlreadyKind) {
19964
20103
  for (const index of normalizedIndexes) {
19965
- delete paragraphs[index].numbering;
20104
+ const paragraph = paragraphs[index]?.paragraph;
20105
+ if (paragraph) delete paragraph.numbering;
19966
20106
  }
19967
20107
  working.numbering = catalog;
19968
20108
  return {
@@ -19972,7 +20112,8 @@ function toggleListKind(document2, paragraphIndexes, kind, context, options) {
19972
20112
  }
19973
20113
  const numberingInstanceId = findAdjacentCompatibleInstance(paragraphs, catalog, normalizedIndexes[0], kind) ?? ensureDefaultListInstance(catalog, kind);
19974
20114
  for (const index of normalizedIndexes) {
19975
- const paragraph = paragraphs[index];
20115
+ const paragraph = paragraphs[index]?.paragraph;
20116
+ if (!paragraph) continue;
19976
20117
  paragraph.numbering = {
19977
20118
  numberingInstanceId,
19978
20119
  level: clampLevel(paragraph.numbering?.level ?? 0)
@@ -20003,10 +20144,11 @@ function adjustListLevels(document2, paragraphIndexes, delta, context, options)
20003
20144
  };
20004
20145
  }
20005
20146
  const affectedParagraphIndexes = resolved.paragraphIndexes.filter(
20006
- (index) => Boolean(paragraphs[index]?.numbering)
20147
+ (index) => Boolean(paragraphs[index]?.paragraph.numbering)
20007
20148
  );
20008
20149
  for (const index of affectedParagraphIndexes) {
20009
- const paragraph = paragraphs[index];
20150
+ const paragraph = paragraphs[index]?.paragraph;
20151
+ if (!paragraph) continue;
20010
20152
  if (!paragraph.numbering) {
20011
20153
  continue;
20012
20154
  }
@@ -20026,17 +20168,21 @@ function normalizeListCommandTargets(options) {
20026
20168
  }
20027
20169
  function resolveListCommandParagraphIndexes(document2, paragraphs, paragraphIndexes, context, editableTargets) {
20028
20170
  if (editableTargets.length === 0) {
20029
- return { paragraphIndexes: normalizeParagraphIndexes(paragraphs, paragraphIndexes) };
20171
+ return {
20172
+ paragraphIndexes: normalizeParagraphIndexesForStory(
20173
+ paragraphs,
20174
+ paragraphIndexes,
20175
+ context.activeStoryKey
20176
+ )
20177
+ };
20030
20178
  }
20031
20179
  const currentTargets = collectEditableTargetRefs(document2, context.editableTargetCache);
20032
- const paragraphIndexByTargetKey = /* @__PURE__ */ new Map();
20033
- let paragraphIndex = 0;
20034
- for (const target of currentTargets) {
20035
- if (!isParagraphTextTarget(target)) continue;
20036
- if (!paragraphIndexByTargetKey.has(target.targetKey)) {
20037
- paragraphIndexByTargetKey.set(target.targetKey, paragraphIndex);
20038
- paragraphIndex += 1;
20039
- }
20180
+ const paragraphIndexByAddress = /* @__PURE__ */ new Map();
20181
+ for (let index = 0; index < paragraphs.length; index += 1) {
20182
+ const entry = paragraphs[index];
20183
+ if (!entry) continue;
20184
+ paragraphIndexByAddress.set(`${entry.storyKey}
20185
+ ${entry.blockPath}`, index);
20040
20186
  }
20041
20187
  const resolvedIndexes = [];
20042
20188
  for (const target of editableTargets) {
@@ -20061,7 +20207,8 @@ function resolveListCommandParagraphIndexes(document2, paragraphs, paragraphInde
20061
20207
  }
20062
20208
  };
20063
20209
  }
20064
- const currentIndex = paragraphIndexByTargetKey.get(current.targetKey);
20210
+ const currentIndex = paragraphIndexByAddress.get(`${current.storyKey}
20211
+ ${current.blockPath}`);
20065
20212
  if (currentIndex === void 0) {
20066
20213
  return {
20067
20214
  paragraphIndexes: [],
@@ -20136,18 +20283,28 @@ function sortJson(value) {
20136
20283
  return value;
20137
20284
  }
20138
20285
  function findAdjacentCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
20286
+ const current = paragraphs[fromIndex];
20139
20287
  const previous = paragraphs[fromIndex - 1];
20140
- if (previous?.numbering) {
20141
- const previousKind = getListKind(catalog, previous.numbering.numberingInstanceId);
20288
+ if (previous?.storyKey !== current?.storyKey) {
20289
+ return void 0;
20290
+ }
20291
+ const previousParagraph = previous?.paragraph;
20292
+ if (previousParagraph?.numbering) {
20293
+ const previousKind = getListKind(catalog, previousParagraph.numbering.numberingInstanceId);
20142
20294
  if (previousKind === kind) {
20143
- return previous.numbering.numberingInstanceId;
20295
+ return previousParagraph.numbering.numberingInstanceId;
20144
20296
  }
20145
20297
  }
20146
20298
  return void 0;
20147
20299
  }
20148
20300
  function findPreviousCompatibleInstance(paragraphs, catalog, fromIndex, kind) {
20301
+ const storyKey2 = paragraphs[fromIndex]?.storyKey;
20149
20302
  for (let index = fromIndex - 1; index >= 0; index -= 1) {
20150
- const paragraph = paragraphs[index];
20303
+ const entry = paragraphs[index];
20304
+ if (entry?.storyKey !== storyKey2) {
20305
+ break;
20306
+ }
20307
+ const paragraph = entry.paragraph;
20151
20308
  if (!paragraph?.numbering) {
20152
20309
  continue;
20153
20310
  }
@@ -20166,7 +20323,14 @@ function cloneEnvelope(document2, timestamp) {
20166
20323
  function captureEditableParagraphs(document2) {
20167
20324
  if (isDocumentRoot(document2.content)) {
20168
20325
  const paragraphs = [];
20169
- collectEditableParagraphs(document2.content.children, paragraphs);
20326
+ for (const context of collectStoryBlockContexts(document2)) {
20327
+ collectEditableParagraphs(
20328
+ context.blocks,
20329
+ paragraphs,
20330
+ context.storyKey,
20331
+ context.basePath
20332
+ );
20333
+ }
20170
20334
  return paragraphs;
20171
20335
  }
20172
20336
  const fallback = {
@@ -20174,23 +20338,39 @@ function captureEditableParagraphs(document2) {
20174
20338
  children: [{ type: "paragraph", children: [] }]
20175
20339
  };
20176
20340
  document2.content = fallback;
20177
- return fallback.children;
20341
+ return [{
20342
+ paragraph: fallback.children[0],
20343
+ storyKey: "main",
20344
+ blockPath: "main/block[0]"
20345
+ }];
20178
20346
  }
20179
- function collectEditableParagraphs(blocks, output) {
20180
- for (const block of blocks) {
20347
+ function collectEditableParagraphs(blocks, output, storyKey2, basePath) {
20348
+ for (let blockIndex = 0; blockIndex < blocks.length; blockIndex += 1) {
20349
+ const block = blocks[blockIndex];
20350
+ if (!block) continue;
20351
+ const blockPath = `${basePath}/block[${blockIndex}]`;
20181
20352
  switch (block.type) {
20182
20353
  case "paragraph":
20183
- output.push(block);
20354
+ output.push({ paragraph: block, storyKey: storyKey2, blockPath });
20184
20355
  break;
20185
20356
  case "table":
20186
- for (const row2 of block.rows) {
20187
- for (const cell of row2.cells) {
20188
- collectEditableParagraphs(cell.children, output);
20357
+ for (let rowIndex = 0; rowIndex < block.rows.length; rowIndex += 1) {
20358
+ const row2 = block.rows[rowIndex];
20359
+ if (!row2) continue;
20360
+ for (let cellIndex = 0; cellIndex < row2.cells.length; cellIndex += 1) {
20361
+ const cell = row2.cells[cellIndex];
20362
+ if (!cell) continue;
20363
+ collectEditableParagraphs(
20364
+ cell.children,
20365
+ output,
20366
+ storyKey2,
20367
+ `${blockPath}/row[${rowIndex}]/cell[${cellIndex}]`
20368
+ );
20189
20369
  }
20190
20370
  }
20191
20371
  break;
20192
20372
  case "sdt":
20193
- collectEditableParagraphs(block.children, output);
20373
+ collectEditableParagraphs(block.children, output, storyKey2, blockPath);
20194
20374
  break;
20195
20375
  case "custom_xml":
20196
20376
  break;
@@ -20202,6 +20382,18 @@ function collectEditableParagraphs(blocks, output) {
20202
20382
  function normalizeParagraphIndexes(paragraphs, paragraphIndexes) {
20203
20383
  return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < paragraphs.length).sort((left, right) => left - right);
20204
20384
  }
20385
+ function normalizeParagraphIndexesForStory(paragraphs, paragraphIndexes, storyKey2) {
20386
+ if (storyKey2 === void 0) {
20387
+ return normalizeParagraphIndexes(paragraphs, paragraphIndexes);
20388
+ }
20389
+ const storyParagraphIndexes = [];
20390
+ for (let index = 0; index < paragraphs.length; index += 1) {
20391
+ if (paragraphs[index]?.storyKey === storyKey2) {
20392
+ storyParagraphIndexes.push(index);
20393
+ }
20394
+ }
20395
+ return [...new Set(paragraphIndexes)].filter((index) => Number.isInteger(index) && index >= 0 && index < storyParagraphIndexes.length).map((index) => storyParagraphIndexes[index]).sort((left, right) => left - right);
20396
+ }
20205
20397
  function clampLevel(level) {
20206
20398
  return Math.max(0, Math.min(8, level));
20207
20399
  }
@@ -20883,8 +21075,9 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20883
21075
  workingDocument = collapseResult.document;
20884
21076
  workingSelection = collapseResult.selection;
20885
21077
  if (context.textTarget?.kind === "table-paragraph" || context.textTarget?.kind === "text-leaf") {
21078
+ const { precomputedSurface: _precomputedSurface, ...contextWithoutPrecomputedSurface } = context;
20886
21079
  workingContext = {
20887
- ...context,
21080
+ ...contextWithoutPrecomputedSurface,
20888
21081
  textTarget: {
20889
21082
  ...context.textTarget,
20890
21083
  paragraphEnd: Math.max(
@@ -20896,7 +21089,11 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20896
21089
  }
20897
21090
  }
20898
21091
  const splitResult = splitParagraph(workingDocument, workingSelection, workingContext);
20899
- const splitRoot = splitResult.document.content;
21092
+ const preparedFragment = prepareFragmentNumberingForInsertion(
21093
+ splitResult.document,
21094
+ fragment
21095
+ );
21096
+ const splitRoot = preparedFragment.document.content;
20900
21097
  if (!splitRoot || splitRoot.type !== "doc") {
20901
21098
  return {
20902
21099
  changed: false,
@@ -20907,9 +21104,9 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20907
21104
  const targetedBlockPath = workingContext.textTarget?.kind === "table-paragraph" || workingContext.textTarget?.kind === "text-leaf" ? workingContext.textTarget.blockPath : void 0;
20908
21105
  if (targetedBlockPath) {
20909
21106
  const targeted = insertFragmentBlocksAfterPath(
20910
- splitResult.document,
21107
+ preparedFragment.document,
20911
21108
  targetedBlockPath,
20912
- fragment.blocks
21109
+ preparedFragment.blocks
20913
21110
  );
20914
21111
  if (targeted) {
20915
21112
  return {
@@ -20941,7 +21138,7 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20941
21138
  const rightHalfIndex = scope.blockIndex + 1;
20942
21139
  const splicedChildren = [
20943
21140
  ...splitRoot.children.slice(0, rightHalfIndex),
20944
- ...fragment.blocks.map((block) => cloneBlock(block)),
21141
+ ...preparedFragment.blocks.map((block) => cloneBlock(block)),
20945
21142
  ...splitRoot.children.slice(rightHalfIndex)
20946
21143
  ];
20947
21144
  const nextRoot = {
@@ -20949,7 +21146,7 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20949
21146
  children: splicedChildren
20950
21147
  };
20951
21148
  const nextDocument = {
20952
- ...splitResult.document,
21149
+ ...preparedFragment.document,
20953
21150
  updatedAt: context.timestamp,
20954
21151
  content: nextRoot
20955
21152
  };
@@ -20961,14 +21158,47 @@ function applyFragmentInsert(document2, selection, fragment, context) {
20961
21158
  mapping: createEmptyMapping()
20962
21159
  };
20963
21160
  }
20964
- function cloneBlock(block) {
20965
- if (block.type === "paragraph") {
20966
- return {
20967
- ...block,
20968
- children: block.children.map((child) => ({ ...child }))
21161
+ function prepareFragmentNumberingForInsertion(document2, fragment) {
21162
+ if (!fragment.numbering) {
21163
+ return { document: document2, blocks: fragment.blocks };
21164
+ }
21165
+ const merged = mergeFragmentNumberingCatalog(document2.numbering, fragment.numbering);
21166
+ return {
21167
+ document: {
21168
+ ...document2,
21169
+ numbering: merged.catalog
21170
+ },
21171
+ blocks: fragment.blocks.map((block) => cloneBlock(block, merged.instanceIdMap))
21172
+ };
21173
+ }
21174
+ function cloneBlock(block, numberingInstanceIdMap) {
21175
+ const cloned = structuredClone(block);
21176
+ remapNumberingReferences(cloned, numberingInstanceIdMap);
21177
+ return cloned;
21178
+ }
21179
+ function remapNumberingReferences(value, numberingInstanceIdMap) {
21180
+ if (!numberingInstanceIdMap?.size || !value || typeof value !== "object") {
21181
+ return;
21182
+ }
21183
+ if (Array.isArray(value)) {
21184
+ for (const entry of value) {
21185
+ remapNumberingReferences(entry, numberingInstanceIdMap);
21186
+ }
21187
+ return;
21188
+ }
21189
+ const record = value;
21190
+ if (record.numbering?.numberingInstanceId) {
21191
+ const mappedId = numberingInstanceIdMap.get(record.numbering.numberingInstanceId) ?? record.numbering.numberingInstanceId;
21192
+ record.numbering = {
21193
+ ...record.numbering,
21194
+ numberingInstanceId: mappedId
20969
21195
  };
20970
21196
  }
20971
- return JSON.parse(JSON.stringify(block));
21197
+ remapNumberingReferences(record.children, numberingInstanceIdMap);
21198
+ remapNumberingReferences(record.rows, numberingInstanceIdMap);
21199
+ remapNumberingReferences(record.cells, numberingInstanceIdMap);
21200
+ remapNumberingReferences(record.txbxBlocks, numberingInstanceIdMap);
21201
+ remapNumberingReferences(record.content, numberingInstanceIdMap);
20972
21202
  }
20973
21203
  function insertFragmentBlocksAfterPath(document2, blockPath, fragmentBlocks) {
20974
21204
  const tokens = parseCanonicalBlockPath2(blockPath);
@@ -41526,6 +41756,8 @@ function buildSearchPattern(query, options = {}) {
41526
41756
  function findSearchMatches(text, query, options = {}) {
41527
41757
  const pattern = buildSearchPattern(query, options);
41528
41758
  if (!pattern) return [];
41759
+ const limit = normalizeSearchLimit(options.limit);
41760
+ if (limit === 0) return [];
41529
41761
  const results = [];
41530
41762
  let match;
41531
41763
  pattern.lastIndex = 0;
@@ -41536,12 +41768,21 @@ function findSearchMatches(text, query, options = {}) {
41536
41768
  text: match[0],
41537
41769
  index: results.length
41538
41770
  });
41771
+ if (results.length >= limit) {
41772
+ break;
41773
+ }
41539
41774
  if (match[0].length === 0) {
41540
41775
  pattern.lastIndex += 1;
41541
41776
  }
41542
41777
  }
41543
41778
  return results;
41544
41779
  }
41780
+ function normalizeSearchLimit(limit) {
41781
+ if (limit === void 0 || !Number.isFinite(limit)) {
41782
+ return Number.POSITIVE_INFINITY;
41783
+ }
41784
+ return Math.max(0, Math.floor(limit));
41785
+ }
41545
41786
  function createSearchExcerpt(text, from, to, radius = 24) {
41546
41787
  const safeFrom = Math.max(0, Math.min(from, text.length));
41547
41788
  const safeTo = Math.max(safeFrom, Math.min(to, text.length));
@@ -49174,6 +49415,16 @@ function coerceIssueValue2(value) {
49174
49415
  function insertScopeMarkers(document2, params) {
49175
49416
  const { scopeId } = params;
49176
49417
  const root = document2.content;
49418
+ if (!Number.isFinite(params.from) || !Number.isFinite(params.to)) {
49419
+ const from = Number.isFinite(params.from) ? params.from : 0;
49420
+ const to = Number.isFinite(params.to) ? params.to : from;
49421
+ return {
49422
+ status: "non-finite-range",
49423
+ scopeId,
49424
+ from,
49425
+ to
49426
+ };
49427
+ }
49177
49428
  const normalizedFrom = Math.min(params.from, params.to);
49178
49429
  const normalizedTo = Math.max(params.from, params.to);
49179
49430
  if (!root || root.type !== "doc" || root.children.length === 0) {
@@ -49626,6 +49877,14 @@ function isRecord3(value) {
49626
49877
  }
49627
49878
 
49628
49879
  // src/runtime/workflow/coordinator.ts
49880
+ function createScopeMarkerMutationMapping() {
49881
+ return {
49882
+ steps: [],
49883
+ metadata: {
49884
+ layoutNeutralScopeMarkers: true
49885
+ }
49886
+ };
49887
+ }
49629
49888
  var MODE_RESTRICTIVENESS = {
49630
49889
  edit: 0,
49631
49890
  suggest: 1,
@@ -49933,6 +50192,60 @@ function createWorkflowCoordinator(deps) {
49933
50192
  activeStory: deps.getActiveStory()
49934
50193
  };
49935
50194
  }
50195
+ function createPlantFailureResult(input) {
50196
+ const { scopeId, anchor, assoc, plantResult } = input;
50197
+ return {
50198
+ scopeId: "",
50199
+ anchor: {
50200
+ kind: "range",
50201
+ from: anchor.from,
50202
+ to: anchor.to,
50203
+ assoc
50204
+ },
50205
+ plantStatus: {
50206
+ planted: false,
50207
+ reason: plantResult.status,
50208
+ ...plantResult.status === "non-paragraph-target" ? {
50209
+ blockIndex: plantResult.blockIndex,
50210
+ blockKind: plantResult.blockKind
50211
+ } : {},
50212
+ ...plantResult.status === "range-out-of-bounds" ? { storyLength: plantResult.storyLength } : {},
50213
+ requestedFrom: plantResult.from,
50214
+ requestedTo: plantResult.to
50215
+ }
50216
+ };
50217
+ }
50218
+ function buildWorkflowScope(input) {
50219
+ const { params, scopeId, publicAnchor } = input;
50220
+ return {
50221
+ scopeId,
50222
+ mode: params.mode ?? "comment",
50223
+ anchor: publicAnchor,
50224
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
50225
+ ...params.label ? { label: params.label } : {},
50226
+ ...params.visibility ? { visibility: params.visibility } : {},
50227
+ ...params.guardPolicy ? { guardPolicy: params.guardPolicy } : {},
50228
+ ...params.scopeMetadataFields && params.scopeMetadataFields.length > 0 ? { metadata: [...params.scopeMetadataFields] } : {}
50229
+ };
50230
+ }
50231
+ function buildWorkflowMetadataEntry(input) {
50232
+ const { params, scopeId, publicAnchor } = input;
50233
+ if (!params.persistence || params.persistence === "runtime-only") return null;
50234
+ const requestedMetadata = params.metadata ?? {};
50235
+ const entryPersistence = requestedMetadata.metadataPersistence ?? (params.persistence === "session" ? "external" : "internal");
50236
+ return {
50237
+ entryId: requestedMetadata.entryId ?? `scope-metadata-${scopeId}`,
50238
+ metadataId: requestedMetadata.metadataId ?? "workflow.scope",
50239
+ anchor: publicAnchor,
50240
+ ...params.storyTarget ? { storyTarget: params.storyTarget } : {},
50241
+ scopeId,
50242
+ ...requestedMetadata.workItemId ? { workItemId: requestedMetadata.workItemId } : {},
50243
+ ...requestedMetadata.value !== void 0 ? { value: requestedMetadata.value } : params.persistence === "document-metadata" && params.label ? { value: { label: params.label } } : {},
50244
+ metadataPersistence: entryPersistence,
50245
+ ...requestedMetadata.storageRef !== void 0 ? { storageRef: requestedMetadata.storageRef } : {},
50246
+ ...requestedMetadata.metadataVersion !== void 0 ? { metadataVersion: requestedMetadata.metadataVersion } : {}
50247
+ };
50248
+ }
49936
50249
  function addScope(params) {
49937
50250
  const state = deps.getState();
49938
50251
  const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
@@ -49975,6 +50288,7 @@ function createWorkflowCoordinator(deps) {
49975
50288
  deps.dispatch({
49976
50289
  type: "document.replace",
49977
50290
  document: nextDocument,
50291
+ mapping: createScopeMarkerMutationMapping(),
49978
50292
  origin: { source: "api", at: clock() }
49979
50293
  });
49980
50294
  const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
@@ -50031,6 +50345,84 @@ function createWorkflowCoordinator(deps) {
50031
50345
  }
50032
50346
  return { scopeId, anchor: publicAnchor };
50033
50347
  }
50348
+ function addScopes(paramsList) {
50349
+ if (paramsList.length === 0) return [];
50350
+ let nextDocument = deps.getDocument();
50351
+ let documentChanged = false;
50352
+ const results = [];
50353
+ const scopesToAdd = [];
50354
+ const metadataEntriesToAdd = [];
50355
+ const newScopeIds = /* @__PURE__ */ new Set();
50356
+ for (const params of paramsList) {
50357
+ const scopeId = params.scopeId ?? `scope-${clock().replace(/[^0-9]/gu, "")}-${Math.floor(Math.random() * 1e6)}`;
50358
+ const anchor = params.anchor.kind === "range" ? { from: params.anchor.from, to: params.anchor.to } : null;
50359
+ if (!anchor) {
50360
+ results.push({ scopeId, anchor: params.anchor });
50361
+ continue;
50362
+ }
50363
+ const callerAssoc = params.anchor.kind === "range" ? params.anchor.assoc : { start: -1, end: 1 };
50364
+ const plantResult = insertScopeMarkers(nextDocument, {
50365
+ scopeId,
50366
+ from: anchor.from,
50367
+ to: anchor.to
50368
+ });
50369
+ if (plantResult.status !== "planted") {
50370
+ results.push(
50371
+ createPlantFailureResult({
50372
+ scopeId,
50373
+ anchor,
50374
+ assoc: callerAssoc,
50375
+ plantResult
50376
+ })
50377
+ );
50378
+ continue;
50379
+ }
50380
+ nextDocument = plantResult.document;
50381
+ documentChanged = true;
50382
+ const publicAnchor = {
50383
+ kind: "range",
50384
+ from: plantResult.plantedRange.from,
50385
+ to: plantResult.plantedRange.to,
50386
+ assoc: callerAssoc
50387
+ };
50388
+ newScopeIds.add(scopeId);
50389
+ scopesToAdd.push(buildWorkflowScope({ params, scopeId, publicAnchor }));
50390
+ const entry = buildWorkflowMetadataEntry({ params, scopeId, publicAnchor });
50391
+ if (entry) metadataEntriesToAdd.push(entry);
50392
+ results.push({ scopeId, anchor: publicAnchor });
50393
+ }
50394
+ if (documentChanged) {
50395
+ deps.dispatch({
50396
+ type: "document.replace",
50397
+ document: nextDocument,
50398
+ mapping: createScopeMarkerMutationMapping(),
50399
+ origin: { source: "api", at: clock() }
50400
+ });
50401
+ }
50402
+ if (scopesToAdd.length > 0) {
50403
+ const currentOverlay = overlayStore.getOverlay() ?? {
50404
+ overlayVersion: "workflow-overlay/1",
50405
+ scopes: []
50406
+ };
50407
+ const existingScopes = currentOverlay.scopes.filter(
50408
+ (existing) => !newScopeIds.has(existing.scopeId)
50409
+ );
50410
+ deps.dispatch({
50411
+ type: "workflow.set-overlay",
50412
+ overlay: { ...currentOverlay, scopes: [...existingScopes, ...scopesToAdd] },
50413
+ origin: { source: "api", at: clock() }
50414
+ });
50415
+ }
50416
+ if (metadataEntriesToAdd.length > 0) {
50417
+ const priorEntries = overlayStore.getMetadataEntries();
50418
+ deps.dispatch({
50419
+ type: "workflow.set-metadata-entries",
50420
+ entries: [...priorEntries, ...metadataEntriesToAdd],
50421
+ origin: { source: "api", at: clock() }
50422
+ });
50423
+ }
50424
+ return results;
50425
+ }
50034
50426
  function removeScope(scopeId) {
50035
50427
  const overlay = overlayStore.getOverlay();
50036
50428
  if (overlay) {
@@ -50048,6 +50440,7 @@ function createWorkflowCoordinator(deps) {
50048
50440
  deps.dispatch({
50049
50441
  type: "document.replace",
50050
50442
  document: nextDocument,
50443
+ mapping: createScopeMarkerMutationMapping(),
50051
50444
  origin: { source: "api", at: clock() }
50052
50445
  });
50053
50446
  }
@@ -50441,6 +50834,7 @@ function createWorkflowCoordinator(deps) {
50441
50834
  }
50442
50835
  return {
50443
50836
  addScope,
50837
+ addScopes,
50444
50838
  removeScope,
50445
50839
  addInvisibleScope,
50446
50840
  setScopeVisibility,
@@ -56210,6 +56604,36 @@ function createDocumentRuntime(options) {
56210
56604
  let viewportBlockRanges = null;
56211
56605
  let viewportRangesKey = serializeViewportRanges(viewportBlockRanges);
56212
56606
  let viewportBlocksPerPageEstimate = null;
56607
+ let fullSurfaceWarmupScheduled = false;
56608
+ let fullSurfaceWarmupCompleted = false;
56609
+ function scheduleFullSurfaceWarmupAfterCull() {
56610
+ if (fullSurfaceWarmupScheduled || fullSurfaceWarmupCompleted) return;
56611
+ fullSurfaceWarmupScheduled = true;
56612
+ perfCounters.increment("surface.fullSurfaceWarmup.scheduled");
56613
+ runOnIdle(() => {
56614
+ fullSurfaceWarmupScheduled = false;
56615
+ if (cachedFullSurface) {
56616
+ perfCounters.increment("surface.fullSurfaceWarmup.alreadyCached");
56617
+ fullSurfaceWarmupCompleted = true;
56618
+ return;
56619
+ }
56620
+ const t0 = performance.now();
56621
+ try {
56622
+ getCachedFullSurface(state.document, activeStory);
56623
+ fullSurfaceWarmupCompleted = true;
56624
+ perfCounters.increment("surface.fullSurfaceWarmup.committed");
56625
+ } catch (error) {
56626
+ perfCounters.increment("surface.fullSurfaceWarmup.failed");
56627
+ fullSurfaceWarmupCompleted = false;
56628
+ void error;
56629
+ } finally {
56630
+ perfCounters.increment(
56631
+ "surface.fullSurfaceWarmup.us",
56632
+ Math.round((performance.now() - t0) * 1e3)
56633
+ );
56634
+ }
56635
+ });
56636
+ }
56213
56637
  const getRuntimeForLayoutFacet = () => {
56214
56638
  if (!runtimeRef) {
56215
56639
  throw new Error("Document runtime viewport methods are not initialized");
@@ -56402,6 +56826,15 @@ function createDocumentRuntime(options) {
56402
56826
  let cachedSurface;
56403
56827
  let cachedFullSurface;
56404
56828
  const editableTargetBlockCache = createEditableTargetBlockCache();
56829
+ let paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
56830
+ let paragraphCascadeCacheStylesRef = null;
56831
+ function ensureParagraphCascadeCacheForStyles(nextStyles) {
56832
+ if (paragraphCascadeCacheStylesRef !== nextStyles) {
56833
+ paragraphCascadeCache = /* @__PURE__ */ new WeakMap();
56834
+ paragraphCascadeCacheStylesRef = nextStyles;
56835
+ }
56836
+ return paragraphCascadeCache;
56837
+ }
56405
56838
  let cachedEditableTargetMap = null;
56406
56839
  function getEditableTargetsByBlockPath(document2) {
56407
56840
  if (cachedEditableTargetMap !== null && cachedEditableTargetMap.document === document2) {
@@ -56455,6 +56888,7 @@ function createDocumentRuntime(options) {
56455
56888
  const snapshot = createEditorSurfaceSnapshot(document2, state.selection, nextActiveStory, {
56456
56889
  viewportBlockRanges: null,
56457
56890
  editableTargetsByBlockPath: getEditableTargetsByBlockPath(document2),
56891
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document2.styles),
56458
56892
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
56459
56893
  });
56460
56894
  recordPerfSample("snapshot.surface");
@@ -56495,6 +56929,7 @@ function createDocumentRuntime(options) {
56495
56929
  activeStoryKey,
56496
56930
  surfaceViewportRanges
56497
56931
  ),
56932
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(document2.styles),
56498
56933
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
56499
56934
  });
56500
56935
  recordPerfSample("snapshot.surface");
@@ -56706,7 +57141,17 @@ function createDocumentRuntime(options) {
56706
57141
  }
56707
57142
  }
56708
57143
  function tryPatchNestedLocalTextSurface(previousSurface, editFrom, editTo, insertedText) {
56709
- const shiftBudget = estimateLocalTextPatchShiftBudget(previousSurface.blocks, 0);
57144
+ const containerIndex = previousSurface.blocks.findIndex(
57145
+ (block) => editFrom >= block.from && editTo <= block.to
57146
+ );
57147
+ if (containerIndex < 0) {
57148
+ perfCounters.increment("surface.localText.patchMiss");
57149
+ return null;
57150
+ }
57151
+ const shiftBudget = estimateLocalTextPatchShiftBudget(
57152
+ previousSurface.blocks,
57153
+ containerIndex + 1
57154
+ );
56710
57155
  perfCounters.increment("surface.localText.shiftedBlocks", shiftBudget.shiftedBlocks);
56711
57156
  perfCounters.increment("surface.localText.shiftedNodes", shiftBudget.shiftedNodes);
56712
57157
  if (!shiftBudget.withinBudget) {
@@ -56786,19 +57231,9 @@ function createDocumentRuntime(options) {
56786
57231
  for (let index = startIndex; index < blocks.length; index += 1) {
56787
57232
  const shiftedBlockNodes = countSurfaceShiftNodesUpTo(
56788
57233
  blocks[index],
56789
- Math.min(
56790
- policy.maxShiftedNodesPerBlock,
56791
- policy.maxShiftedSurfaceNodes - shiftedNodes
56792
- ) + 1
57234
+ policy.maxShiftedSurfaceNodes - shiftedNodes + 1
56793
57235
  );
56794
57236
  shiftedNodes += shiftedBlockNodes;
56795
- if (shiftedBlockNodes > policy.maxShiftedNodesPerBlock) {
56796
- return {
56797
- shiftedBlocks,
56798
- shiftedNodes,
56799
- withinBudget: false
56800
- };
56801
- }
56802
57237
  if (shiftedNodes > policy.maxShiftedSurfaceNodes) {
56803
57238
  return {
56804
57239
  shiftedBlocks,
@@ -57470,6 +57905,9 @@ function createDocumentRuntime(options) {
57470
57905
  viewportBlockRangesOverride: firstSurfaceViewportBlockRanges
57471
57906
  }) : getCachedSurface(state.document, activeStory)
57472
57907
  );
57908
+ if (firstSurfaceViewportBlockRanges) {
57909
+ scheduleFullSurfaceWarmupAfterCull();
57910
+ }
57473
57911
  const snapshot = {
57474
57912
  documentId: state.documentId,
57475
57913
  sessionId: state.sessionId,
@@ -57583,6 +58021,9 @@ function createDocumentRuntime(options) {
57583
58021
  activeStoryKey,
57584
58022
  viewportBlockRanges
57585
58023
  ),
58024
+ paragraphCascadeCache: ensureParagraphCascadeCacheForStyles(
58025
+ state.document.styles
58026
+ ),
57586
58027
  ...effectiveMarkupModeProvider ? { getEffectiveMarkupMode: effectiveMarkupModeProvider } : {}
57587
58028
  }
57588
58029
  );
@@ -58234,6 +58675,17 @@ function createDocumentRuntime(options) {
58234
58675
  };
58235
58676
  resolvedReplayTextTarget = prepared.textTarget;
58236
58677
  } else {
58678
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
58679
+ command,
58680
+ document: replayState.document,
58681
+ selection: replayState.selection,
58682
+ surface: replaySnapshot.surface?.blocks ?? [],
58683
+ storyTarget: replayStory,
58684
+ timestamp: context.timestamp
58685
+ });
58686
+ if (listBoundaryJoinCommand) {
58687
+ executableCommand = listBoundaryJoinCommand;
58688
+ }
58237
58689
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
58238
58690
  command,
58239
58691
  document: replayState.document,
@@ -58391,6 +58843,17 @@ function createDocumentRuntime(options) {
58391
58843
  };
58392
58844
  resolvedReplayTextTarget = prepared.textTarget;
58393
58845
  } else {
58846
+ const listBoundaryJoinCommand = createListItemBoundaryJoinReplayCommand({
58847
+ command,
58848
+ document: stateForCommand.document,
58849
+ selection: stateForCommand.selection,
58850
+ surface: snapshotForCommand.surface?.blocks ?? [],
58851
+ storyTarget: replayStory,
58852
+ timestamp: context.timestamp
58853
+ });
58854
+ if (listBoundaryJoinCommand) {
58855
+ executableCommand = listBoundaryJoinCommand;
58856
+ }
58394
58857
  const selectedListItemDeleteCommand = createSelectedListItemDeleteReplayCommand({
58395
58858
  command,
58396
58859
  document: stateForCommand.document,
@@ -59420,6 +59883,9 @@ function createDocumentRuntime(options) {
59420
59883
  addScope(params) {
59421
59884
  return workflowCoordinator.addScope(params);
59422
59885
  },
59886
+ addScopes(params) {
59887
+ return workflowCoordinator.addScopes(params);
59888
+ },
59423
59889
  getScope(scopeId) {
59424
59890
  return workflowCoordinator.getScope(scopeId);
59425
59891
  },
@@ -60403,6 +60869,9 @@ function createDocumentRuntime(options) {
60403
60869
  if (transaction.mapping.metadata?.scopeTagTouches) return false;
60404
60870
  return getLocalTextPatchMetadata(transaction.mapping) !== null;
60405
60871
  }
60872
+ function isLayoutNeutralScopeMarkerCommit(previous, next, transaction) {
60873
+ return transaction.markDirty && previous.document !== next.document && transaction.mapping.steps.length === 0 && transaction.mapping.metadata?.layoutNeutralScopeMarkers === true;
60874
+ }
60406
60875
  function applyTransactionToState(transaction, options2 = {}) {
60407
60876
  const effects = transaction.effects;
60408
60877
  const selectionUnchanged = transaction.nextState.selection === state.selection;
@@ -60431,6 +60900,11 @@ function createDocumentRuntime(options) {
60431
60900
  transaction,
60432
60901
  transaction.effects
60433
60902
  );
60903
+ const layoutNeutralScopeMarkerCommit = isLayoutNeutralScopeMarkerCommit(
60904
+ previous,
60905
+ state,
60906
+ transaction
60907
+ );
60434
60908
  perfCounters.increment("commit.refreshClassify.us", Math.round((performance.now() - tClassify0) * 1e3));
60435
60909
  const tOverlay0 = performance.now();
60436
60910
  const skipOverlaySync = useLocalTextCommitSnapshot && canSkipOverlaySyncForLocalText(transaction);
@@ -60479,9 +60953,12 @@ function createDocumentRuntime(options) {
60479
60953
  ...detachedWorkflowScopeWarnings.cleared
60480
60954
  ]
60481
60955
  };
60482
- if (!useLocalTextCommitSnapshot && transaction.markDirty && previous.document !== state.document) {
60956
+ if (!useLocalTextCommitSnapshot && !layoutNeutralScopeMarkerCommit && transaction.markDirty && previous.document !== state.document) {
60483
60957
  applyViewportRanges(getSelectionCorridorViewportRanges(cachedRenderSnapshot.surface));
60484
60958
  }
60959
+ if (layoutNeutralScopeMarkerCommit && viewportBlockRanges !== null) {
60960
+ getCachedFullSurface(state.document, activeStory);
60961
+ }
60485
60962
  const tValidation0 = performance.now();
60486
60963
  const patchSourceSurface = getReusableCachedFullSurface(previous.document, activeStory) ?? cachedRenderSnapshot.surface;
60487
60964
  const patchedFullLocalTextSurface = useLocalTextCommitSnapshot ? tryPatchLocalTextSurface(patchSourceSurface, transaction.mapping) : null;
@@ -60850,15 +61327,49 @@ function createDocumentRuntime(options) {
60850
61327
  const preSelection = selection;
60851
61328
  const preActiveStory = activeStory;
60852
61329
  const priorDocument = state.document;
61330
+ const listBoundaryJoin = createListItemBoundaryJoinReplacement({
61331
+ command: commandForDispatch,
61332
+ document: state.document,
61333
+ editableTarget,
61334
+ selection,
61335
+ storyTarget: activeStory,
61336
+ targetResolution,
61337
+ timestamp
61338
+ });
61339
+ if (listBoundaryJoin && context.documentMode !== "suggesting") {
61340
+ const replacementCommand = {
61341
+ type: "document.replace",
61342
+ document: listBoundaryJoin.document,
61343
+ selection: listBoundaryJoin.selection,
61344
+ mapping: listBoundaryJoin.mapping,
61345
+ protectionSelection: selection,
61346
+ origin: commandForDispatch.origin
61347
+ };
61348
+ const transaction = executeEditorCommand(baseState, replacementCommand, context);
61349
+ commit(transaction);
61350
+ options.onCommandApplied?.(commandForDispatch, transaction, context, {
61351
+ preSelection,
61352
+ activeStory: preActiveStory,
61353
+ priorDocument
61354
+ });
61355
+ return completeDispatch(classifyAck({
61356
+ command: commandForDispatch,
61357
+ opId,
61358
+ priorState: baseState,
61359
+ transaction,
61360
+ newRevisionToken: state.revisionToken
61361
+ }));
61362
+ }
60853
61363
  const selectedListItemDelete = createSelectedListItemDeleteReplacement({
60854
61364
  command: commandForDispatch,
60855
61365
  document: state.document,
60856
61366
  editableTarget,
60857
61367
  selection,
61368
+ storyTarget: activeStory,
60858
61369
  targetResolution,
60859
61370
  timestamp
60860
61371
  });
60861
- if (selectedListItemDelete && activeStory.kind === "main" && context.documentMode !== "suggesting") {
61372
+ if (selectedListItemDelete && context.documentMode !== "suggesting") {
60862
61373
  const replacementCommand = {
60863
61374
  type: "document.replace",
60864
61375
  document: selectedListItemDelete.document,
@@ -61123,6 +61634,9 @@ function createDocumentRuntime(options) {
61123
61634
  });
61124
61635
  }
61125
61636
  function scheduleIdleContextAnalytics(callback) {
61637
+ runOnIdle(callback);
61638
+ }
61639
+ function runOnIdle(callback) {
61126
61640
  const requestIdle = globalThis.requestIdleCallback;
61127
61641
  if (typeof requestIdle === "function") {
61128
61642
  requestIdle(callback, { timeout: 250 });
@@ -63762,8 +64276,58 @@ function stripStoryTarget(selection) {
63762
64276
  function isTopLevelMainStoryBlockPath(blockPath) {
63763
64277
  return typeof blockPath === "string" && /^main\/block\[\d+\]$/u.test(blockPath);
63764
64278
  }
64279
+ function createListItemBoundaryJoinReplacement(input) {
64280
+ const { command, document: document2, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
64281
+ const direction = listItemBoundaryJoinDirection(command, selection, targetResolution);
64282
+ if (!direction || editableTarget?.listAddress?.operationScope !== "list-text" || targetResolution?.kind !== "accepted") {
64283
+ return null;
64284
+ }
64285
+ const storyBlocks = getStoryBlocks(document2, storyTarget);
64286
+ const replacement = joinNumberedParagraphAtStoryPath(
64287
+ storyBlocks,
64288
+ editableTarget.blockPath,
64289
+ storyTarget,
64290
+ direction
64291
+ );
64292
+ if (!replacement) {
64293
+ return null;
64294
+ }
64295
+ const nextDocument = replaceStoryBlocks({
64296
+ ...document2,
64297
+ updatedAt: timestamp
64298
+ }, storyTarget, replacement.blocks);
64299
+ const deletedFrom = direction === "backward" ? Math.max(0, selection.anchor - 1) : selection.anchor;
64300
+ const deletedTo = direction === "backward" ? selection.anchor : selection.anchor + 1;
64301
+ const nextAnchor = direction === "backward" ? deletedFrom : selection.anchor;
64302
+ return {
64303
+ document: nextDocument,
64304
+ selection: createSelectionSnapshot(nextAnchor, nextAnchor),
64305
+ mapping: {
64306
+ steps: [{
64307
+ from: deletedFrom,
64308
+ to: deletedTo,
64309
+ insertSize: 0
64310
+ }],
64311
+ metadata: {
64312
+ invalidatesStructures: true
64313
+ }
64314
+ }
64315
+ };
64316
+ }
64317
+ function listItemBoundaryJoinDirection(command, selection, targetResolution) {
64318
+ if (selection.isCollapsed !== true || targetResolution?.kind !== "accepted") {
64319
+ return null;
64320
+ }
64321
+ if (command.type === "text.delete-backward" && selection.anchor === targetResolution.range.from) {
64322
+ return "backward";
64323
+ }
64324
+ if (command.type === "text.delete-forward" && selection.anchor === targetResolution.range.to) {
64325
+ return "forward";
64326
+ }
64327
+ return null;
64328
+ }
63765
64329
  function createSelectedListItemDeleteReplacement(input) {
63766
- const { command, document: document2, editableTarget, selection, targetResolution, timestamp } = input;
64330
+ const { command, document: document2, editableTarget, selection, storyTarget, targetResolution, timestamp } = input;
63767
64331
  if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
63768
64332
  return null;
63769
64333
  }
@@ -63775,20 +64339,19 @@ function createSelectedListItemDeleteReplacement(input) {
63775
64339
  if (selectionFrom !== targetResolution.range.from || selectionTo !== targetResolution.range.to) {
63776
64340
  return null;
63777
64341
  }
63778
- const root = document2.content;
63779
- const replacement = removeNumberedParagraphAtMainStoryPath(root.children, editableTarget.blockPath);
64342
+ const storyBlocks = getStoryBlocks(document2, storyTarget);
64343
+ const replacement = removeNumberedParagraphAtStoryPath(storyBlocks, editableTarget.blockPath, storyTarget);
63780
64344
  if (!replacement) {
63781
64345
  return null;
63782
64346
  }
63783
- const nextDocument = {
64347
+ const nextDocument = replaceStoryBlocks({
63784
64348
  ...document2,
63785
- updatedAt: timestamp,
63786
- content: {
63787
- ...root,
63788
- children: replacement.blocks
63789
- }
63790
- };
63791
- const nextStorySize = parseTextStory(nextDocument.content).size;
64349
+ updatedAt: timestamp
64350
+ }, storyTarget, replacement.blocks);
64351
+ const nextStorySize = parseTextStory({
64352
+ type: "doc",
64353
+ children: [...getStoryBlocks(nextDocument, storyTarget)]
64354
+ }).size;
63792
64355
  const nextAnchor = Math.min(selectionFrom, nextStorySize);
63793
64356
  return {
63794
64357
  document: nextDocument,
@@ -63805,11 +64368,157 @@ function createSelectedListItemDeleteReplacement(input) {
63805
64368
  }
63806
64369
  };
63807
64370
  }
63808
- function removeNumberedParagraphAtMainStoryPath(blocks, blockPath) {
63809
- const tokens = parseMainStoryBlockPathTokens(blockPath);
64371
+ function removeNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget) {
64372
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
63810
64373
  if (!tokens) return null;
63811
64374
  return removeNumberedParagraphFromBlocks(blocks, tokens);
63812
64375
  }
64376
+ function joinNumberedParagraphAtStoryPath(blocks, blockPath, storyTarget, direction) {
64377
+ const tokens = parseStoryBlockPathTokens(blockPath, storyTarget);
64378
+ if (!tokens) return null;
64379
+ return joinNumberedParagraphFromBlocks(blocks, tokens, direction);
64380
+ }
64381
+ function joinNumberedParagraphFromBlocks(blocks, tokens, direction) {
64382
+ const [token, ...rest] = tokens;
64383
+ if (!token || token.kind !== "block") return null;
64384
+ const block = blocks[token.index];
64385
+ if (!block) return null;
64386
+ if (rest.length === 0) {
64387
+ return joinAdjacentNumberedParagraphs(blocks, token.index, direction);
64388
+ }
64389
+ const next = rest[0];
64390
+ if (block.type === "table" && next?.kind === "row") {
64391
+ const updatedTable = joinNumberedParagraphInTable(block, rest, direction);
64392
+ if (!updatedTable) return null;
64393
+ return {
64394
+ blocks: [
64395
+ ...blocks.slice(0, token.index),
64396
+ updatedTable,
64397
+ ...blocks.slice(token.index + 1)
64398
+ ]
64399
+ };
64400
+ }
64401
+ if ((block.type === "sdt" || block.type === "custom_xml") && next?.kind === "block") {
64402
+ const updatedChildren = joinNumberedParagraphFromBlocks(block.children, rest, direction);
64403
+ if (!updatedChildren) return null;
64404
+ return {
64405
+ blocks: [
64406
+ ...blocks.slice(0, token.index),
64407
+ { ...block, children: updatedChildren.blocks },
64408
+ ...blocks.slice(token.index + 1)
64409
+ ]
64410
+ };
64411
+ }
64412
+ if (block.type === "paragraph" && next?.kind === "inline") {
64413
+ const updatedParagraph = joinNumberedParagraphInTextBoxInline(block, rest, direction);
64414
+ if (!updatedParagraph) return null;
64415
+ return {
64416
+ blocks: [
64417
+ ...blocks.slice(0, token.index),
64418
+ updatedParagraph,
64419
+ ...blocks.slice(token.index + 1)
64420
+ ]
64421
+ };
64422
+ }
64423
+ return null;
64424
+ }
64425
+ function joinAdjacentNumberedParagraphs(blocks, targetIndex, direction) {
64426
+ const target = blocks[targetIndex];
64427
+ if (target?.type !== "paragraph" || !target.numbering) {
64428
+ return null;
64429
+ }
64430
+ if (direction === "backward") {
64431
+ const previousIndex = targetIndex - 1;
64432
+ const previous = blocks[previousIndex];
64433
+ if (previous?.type !== "paragraph" || !previous.numbering) {
64434
+ return null;
64435
+ }
64436
+ const merged2 = {
64437
+ ...previous,
64438
+ children: [...previous.children, ...target.children]
64439
+ };
64440
+ return {
64441
+ blocks: [
64442
+ ...blocks.slice(0, previousIndex),
64443
+ merged2,
64444
+ ...blocks.slice(targetIndex + 1)
64445
+ ]
64446
+ };
64447
+ }
64448
+ const nextIndex = targetIndex + 1;
64449
+ const next = blocks[nextIndex];
64450
+ if (next?.type !== "paragraph" || !next.numbering) {
64451
+ return null;
64452
+ }
64453
+ const merged = {
64454
+ ...target,
64455
+ children: [...target.children, ...next.children]
64456
+ };
64457
+ return {
64458
+ blocks: [
64459
+ ...blocks.slice(0, targetIndex),
64460
+ merged,
64461
+ ...blocks.slice(nextIndex + 1)
64462
+ ]
64463
+ };
64464
+ }
64465
+ function joinNumberedParagraphInTable(table, tokens, direction) {
64466
+ const [rowToken, cellToken, ...childTokens] = tokens;
64467
+ if (rowToken?.kind !== "row" || cellToken?.kind !== "cell" || childTokens[0]?.kind !== "block") {
64468
+ return null;
64469
+ }
64470
+ const row2 = table.rows[rowToken.index];
64471
+ const cell = row2?.cells[cellToken.index];
64472
+ if (!row2 || !cell) return null;
64473
+ const updatedChildren = joinNumberedParagraphFromBlocks(cell.children, childTokens, direction);
64474
+ if (!updatedChildren) return null;
64475
+ const nextCells = [
64476
+ ...row2.cells.slice(0, cellToken.index),
64477
+ { ...cell, children: updatedChildren.blocks },
64478
+ ...row2.cells.slice(cellToken.index + 1)
64479
+ ];
64480
+ const nextRows = [
64481
+ ...table.rows.slice(0, rowToken.index),
64482
+ { ...row2, cells: nextCells },
64483
+ ...table.rows.slice(rowToken.index + 1)
64484
+ ];
64485
+ return { ...table, rows: nextRows };
64486
+ }
64487
+ function joinNumberedParagraphInTextBoxInline(paragraph, tokens, direction) {
64488
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
64489
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
64490
+ return null;
64491
+ }
64492
+ const inline = paragraph.children[inlineToken.index];
64493
+ if (!inline) return null;
64494
+ const updatedInline = joinNumberedParagraphInInlineTextBox(inline, childTokens, direction);
64495
+ if (!updatedInline) return null;
64496
+ return {
64497
+ ...paragraph,
64498
+ children: [
64499
+ ...paragraph.children.slice(0, inlineToken.index),
64500
+ updatedInline,
64501
+ ...paragraph.children.slice(inlineToken.index + 1)
64502
+ ]
64503
+ };
64504
+ }
64505
+ function joinNumberedParagraphInInlineTextBox(inline, tokens, direction) {
64506
+ if (inline.type === "shape" && inline.txbxBlocks) {
64507
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.txbxBlocks, tokens, direction);
64508
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
64509
+ }
64510
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
64511
+ const updatedBlocks = joinNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens, direction);
64512
+ return updatedBlocks ? {
64513
+ ...inline,
64514
+ content: {
64515
+ ...inline.content,
64516
+ txbxBlocks: updatedBlocks.blocks
64517
+ }
64518
+ } : null;
64519
+ }
64520
+ return null;
64521
+ }
63813
64522
  function removeNumberedParagraphFromBlocks(blocks, tokens) {
63814
64523
  const [token, ...rest] = tokens;
63815
64524
  if (!token || token.kind !== "block") return null;
@@ -63852,6 +64561,52 @@ function removeNumberedParagraphFromBlocks(blocks, tokens) {
63852
64561
  ]
63853
64562
  };
63854
64563
  }
64564
+ if (block.type === "paragraph" && next?.kind === "inline") {
64565
+ const updatedParagraph = removeNumberedParagraphFromTextBoxInline(block, rest);
64566
+ if (!updatedParagraph) return null;
64567
+ return {
64568
+ blocks: [
64569
+ ...blocks.slice(0, token.index),
64570
+ updatedParagraph,
64571
+ ...blocks.slice(token.index + 1)
64572
+ ]
64573
+ };
64574
+ }
64575
+ return null;
64576
+ }
64577
+ function removeNumberedParagraphFromTextBoxInline(paragraph, tokens) {
64578
+ const [inlineToken, textBoxToken, ...childTokens] = tokens;
64579
+ if (inlineToken?.kind !== "inline" || textBoxToken?.kind !== "txbx" || childTokens[0]?.kind !== "block") {
64580
+ return null;
64581
+ }
64582
+ const inline = paragraph.children[inlineToken.index];
64583
+ if (!inline) return null;
64584
+ const updatedInline = removeNumberedParagraphFromInlineTextBox(inline, childTokens);
64585
+ if (!updatedInline) return null;
64586
+ return {
64587
+ ...paragraph,
64588
+ children: [
64589
+ ...paragraph.children.slice(0, inlineToken.index),
64590
+ updatedInline,
64591
+ ...paragraph.children.slice(inlineToken.index + 1)
64592
+ ]
64593
+ };
64594
+ }
64595
+ function removeNumberedParagraphFromInlineTextBox(inline, tokens) {
64596
+ if (inline.type === "shape" && inline.txbxBlocks) {
64597
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.txbxBlocks, tokens);
64598
+ return updatedBlocks ? { ...inline, txbxBlocks: updatedBlocks.blocks } : null;
64599
+ }
64600
+ if (inline.type === "drawing_frame" && inline.content.type === "shape" && inline.content.txbxBlocks) {
64601
+ const updatedBlocks = removeNumberedParagraphFromBlocks(inline.content.txbxBlocks, tokens);
64602
+ return updatedBlocks ? {
64603
+ ...inline,
64604
+ content: {
64605
+ ...inline.content,
64606
+ txbxBlocks: updatedBlocks.blocks
64607
+ }
64608
+ } : null;
64609
+ }
63855
64610
  return null;
63856
64611
  }
63857
64612
  function removeNumberedParagraphFromTable(table, tokens) {
@@ -63892,15 +64647,79 @@ function createSelectedListItemDeleteReplayCommand(input) {
63892
64647
  target: editableTarget,
63893
64648
  activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
63894
64649
  });
64650
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
64651
+ document: document2,
64652
+ target: editableTarget,
64653
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
64654
+ commandFamilies: ["text-leaf"]
64655
+ }) : null;
64656
+ const selectedRange = {
64657
+ from: Math.min(selection.anchor, selection.head),
64658
+ to: Math.max(selection.anchor, selection.head)
64659
+ };
63895
64660
  const replacement = createSelectedListItemDeleteReplacement({
63896
64661
  command,
63897
64662
  document: document2,
63898
- editableTarget,
64663
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
63899
64664
  selection,
63900
- targetResolution,
64665
+ storyTarget,
64666
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
64667
+ kind: "accepted",
64668
+ range: selectedRange
64669
+ } : targetResolution,
64670
+ timestamp
64671
+ });
64672
+ if (!replacement) {
64673
+ return null;
64674
+ }
64675
+ return {
64676
+ type: "document.replace",
64677
+ document: replacement.document,
64678
+ selection: replacement.selection,
64679
+ mapping: replacement.mapping,
64680
+ protectionSelection: selection,
64681
+ origin: command.origin
64682
+ };
64683
+ }
64684
+ function createListItemBoundaryJoinReplayCommand(input) {
64685
+ const { command, document: document2, selection, surface, storyTarget, timestamp } = input;
64686
+ if (command.type !== "text.delete-backward" && command.type !== "text.delete-forward") {
64687
+ return null;
64688
+ }
64689
+ const editableTarget = command.editableTarget;
64690
+ if (!editableTarget) {
64691
+ return null;
64692
+ }
64693
+ const targetResolution = resolveEditableTextTarget({
64694
+ document: document2,
64695
+ selection,
64696
+ surface,
64697
+ target: editableTarget,
64698
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget)
64699
+ });
64700
+ const resolvedEditableTarget = targetResolution.kind === "accepted" ? editableTarget : storyTarget.kind !== "main" && blockPathBelongsToStoryTarget(editableTarget.blockPath, storyTarget) ? resolveEditableCommandTarget({
64701
+ document: document2,
64702
+ target: editableTarget,
64703
+ activeStoryKey: canonicalEditableTargetStoryKey(storyTarget),
64704
+ commandFamilies: ["text-leaf"]
64705
+ }) : null;
64706
+ const selectedRange = {
64707
+ from: Math.min(selection.anchor, selection.head),
64708
+ to: Math.max(selection.anchor, selection.head)
64709
+ };
64710
+ const replacement = createListItemBoundaryJoinReplacement({
64711
+ command,
64712
+ document: document2,
64713
+ editableTarget: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? resolvedEditableTarget.target : editableTarget,
64714
+ selection,
64715
+ storyTarget,
64716
+ targetResolution: resolvedEditableTarget && resolvedEditableTarget.kind === "accepted" ? {
64717
+ kind: "accepted",
64718
+ range: selectedRange
64719
+ } : targetResolution,
63901
64720
  timestamp
63902
64721
  });
63903
- if (!replacement || storyTarget.kind !== "main") {
64722
+ if (!replacement) {
63904
64723
  return null;
63905
64724
  }
63906
64725
  return {
@@ -63912,22 +64731,49 @@ function createSelectedListItemDeleteReplayCommand(input) {
63912
64731
  origin: command.origin
63913
64732
  };
63914
64733
  }
63915
- function parseMainStoryBlockPathTokens(blockPath) {
63916
- const parts = blockPath?.split("/") ?? [];
63917
- if (parts[0] !== "main" || parts.length < 2) {
64734
+ function parseStoryBlockPathTokens(blockPath, storyTarget) {
64735
+ if (!blockPath) {
64736
+ return null;
64737
+ }
64738
+ const firstTokenMatch = /\/(?:block|row|cell)\[\d+\]/u.exec(blockPath);
64739
+ if (!firstTokenMatch?.index) {
64740
+ return null;
64741
+ }
64742
+ const storyPrefix = blockPath.slice(0, firstTokenMatch.index);
64743
+ if (!blockPathBelongsToStoryTarget(storyPrefix, storyTarget)) {
63918
64744
  return null;
63919
64745
  }
64746
+ const parts = blockPath.slice(firstTokenMatch.index + 1).split("/");
63920
64747
  const tokens = [];
63921
- for (const part of parts.slice(1)) {
63922
- const match = /^(block|row|cell)\[(\d+)\]$/u.exec(part);
64748
+ for (const part of parts) {
64749
+ if (part === "txbx") {
64750
+ tokens.push({ kind: "txbx" });
64751
+ continue;
64752
+ }
64753
+ const match = /^(block|row|cell|inline)\[(\d+)\]$/u.exec(part);
63923
64754
  if (!match) return null;
64755
+ const kind = match[1];
63924
64756
  tokens.push({
63925
- kind: match[1],
64757
+ kind,
63926
64758
  index: Number.parseInt(match[2], 10)
63927
64759
  });
63928
64760
  }
63929
64761
  return tokens;
63930
64762
  }
64763
+ function blockPathBelongsToStoryTarget(storyPrefix, storyTarget) {
64764
+ switch (storyTarget.kind) {
64765
+ case "main":
64766
+ return storyPrefix === "main" || storyPrefix.startsWith("main/");
64767
+ case "header":
64768
+ return storyPrefix.startsWith("header:");
64769
+ case "footer":
64770
+ return storyPrefix.startsWith("footer:");
64771
+ case "footnote":
64772
+ return storyPrefix === `footnote:${storyTarget.noteId}` || storyPrefix.startsWith(`footnote:${storyTarget.noteId}/`);
64773
+ case "endnote":
64774
+ return storyPrefix === `endnote:${storyTarget.noteId}` || storyPrefix.startsWith(`endnote:${storyTarget.noteId}/`);
64775
+ }
64776
+ }
63931
64777
  function toInternalSelectionSnapshot2(selection) {
63932
64778
  return {
63933
64779
  anchor: selection.anchor,