superdoc 2.28.0-next.8 → 2.28.0

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 (64) hide show
  1. package/dist/chunks/{FindReplaceSurface-8V8AjgR4.cjs → FindReplaceSurface-BRs3JrCq.cjs} +1 -1
  2. package/dist/chunks/{FindReplaceSurface-RUiTFDt3.es.js → FindReplaceSurface-Dm043CZP.es.js} +1 -1
  3. package/dist/chunks/{PasswordPromptSurface-B5DHV6qr.cjs → PasswordPromptSurface-BpqP4pUa.cjs} +1 -1
  4. package/dist/chunks/{PasswordPromptSurface-BDpxqdzp.es.js → PasswordPromptSurface-DGjmN7A-.es.js} +1 -1
  5. package/dist/chunks/{PdfViewer-omriDChK.cjs → PdfViewer-Cg072l5d.cjs} +1 -1
  6. package/dist/chunks/{PdfViewer-DjdsIh6n.es.js → PdfViewer-JHXZQZ9x.es.js} +1 -1
  7. package/dist/chunks/{_plugin-vue_export-helper-BUdjGKyl.cjs → _plugin-vue_export-helper-6MBoygIY.cjs} +9 -0
  8. package/dist/chunks/{_plugin-vue_export-helper-7ZiLY07t.es.js → _plugin-vue_export-helper-CsJQtMvr.es.js} +4 -1
  9. package/dist/chunks/{create-super-doc-ui-C4Ka5Ph3.es.js → create-super-doc-ui-BbjHD1ul.es.js} +184 -28
  10. package/dist/chunks/{create-super-doc-ui-B4c55pFy.cjs → create-super-doc-ui-BfgYblyI.cjs} +195 -27
  11. package/dist/collaboration-upgrade-engine.cjs +1 -1
  12. package/dist/collaboration-upgrade-engine.es.js +1 -1
  13. package/dist/document-api/src/contract/operation-definitions.d.ts +2 -2
  14. package/dist/document-api/src/lists/lists.types.d.ts +1 -0
  15. package/dist/document-api/src/sections/sections.types.d.ts +5 -1
  16. package/dist/document-api/src/types/clipboard.d.ts +5 -1
  17. package/dist/document-api/src/types/receipt.d.ts +2 -1
  18. package/dist/layout-engine/contracts/src/index.d.ts +5 -1
  19. package/dist/layout-engine/contracts/src/run-helpers.d.ts +1 -0
  20. package/dist/layout-engine/layout-bridge/src/index.d.ts +1 -0
  21. package/dist/layout-engine/layout-bridge/src/place-inline-drawings.d.ts +9 -0
  22. package/dist/layout-engine/layout-engine/src/layout-drawing.d.ts +2 -1
  23. package/dist/layout-engine/layout-engine/src/paginator.d.ts +1 -0
  24. package/dist/layout-engine/style-engine/src/ooxml/index.d.ts +1 -1
  25. package/dist/public/ui-react.cjs +1 -1
  26. package/dist/public/ui-react.es.js +1 -1
  27. package/dist/public/ui-vue.cjs +1 -1
  28. package/dist/public/ui-vue.es.js +1 -1
  29. package/dist/public/ui.cjs +3 -2
  30. package/dist/public/ui.es.js +3 -2
  31. package/dist/shared/font-system/src/resolver.d.ts +3 -3
  32. package/dist/style.css +1 -1
  33. package/dist/style.layered.css +1 -1
  34. package/dist/superdoc/src/components/CommentsLayer/FloatingComments.vue.d.ts +11 -0
  35. package/dist/superdoc/src/components/CommentsLayer/PdfCommentsLayer.vue.d.ts +4 -0
  36. package/dist/superdoc/src/composables/use-high-contrast-mode.d.ts +8 -4
  37. package/dist/superdoc/src/composables/use-superdoc-instance.d.ts +7 -0
  38. package/dist/superdoc/src/core/SuperDoc.d.ts +1 -5
  39. package/dist/superdoc/src/core/collaboration/helpers.d.ts +0 -5
  40. package/dist/superdoc/src/core/collaboration/resolve-v2-collaboration-target.d.ts +2 -1
  41. package/dist/superdoc/src/core/create-app.d.ts +2 -6
  42. package/dist/superdoc/src/core/editor-runtime/types.d.ts +2 -0
  43. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -0
  44. package/dist/superdoc/src/core/types/index.d.ts +14 -0
  45. package/dist/superdoc/src/core/v2-integration/internal-vue-runtime.d.ts +1 -0
  46. package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +104 -84
  47. package/dist/superdoc/src/helpers/v2-review-mutation-impact.d.ts +2 -0
  48. package/dist/superdoc/src/internal/diagnostics/translate-diagnostic.d.ts +5 -0
  49. package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +0 -48
  50. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +4 -1
  51. package/dist/superdoc/src/internal/toolbar/compatibility-catalog.d.ts +16 -0
  52. package/dist/superdoc/src/public/ui/types.d.ts +39 -1
  53. package/dist/superdoc/src/public/ui.d.cts +12 -0
  54. package/dist/superdoc/src/public/ui.d.ts +1 -1
  55. package/dist/superdoc/src/stores/comments-store.d.ts +7 -97
  56. package/dist/superdoc/src/stores/superdoc-store.d.ts +21 -291
  57. package/dist/superdoc.cjs +262 -1462
  58. package/dist/superdoc.es.js +538 -12833
  59. package/dist-cdn/style.layered.css +1 -1
  60. package/dist-cdn/superdoc.min.css +1 -1
  61. package/dist-cdn/superdoc.min.js +42 -42
  62. package/package.json +4 -3
  63. package/dist/superdoc/src/core/collaboration/collaboration.d.ts +0 -18
  64. package/dist/superdoc/src/helpers/group-changes.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- const require__plugin_vue_export_helper = require("./_plugin-vue_export-helper-BUdjGKyl.cjs");
1
+ const require__plugin_vue_export_helper = require("./_plugin-vue_export-helper-6MBoygIY.cjs");
2
2
  //#region src/internal/diagnostics/workflow-recording.ts
3
3
  var fields$1 = /* @__PURE__ */ new Set([
4
4
  "documentId",
@@ -1087,6 +1087,15 @@ function isSyntheticTrackedChangeCommentLaneItem(item) {
1087
1087
  return typeof itemId === "string" && itemId.startsWith(TRACKED_CHANGE_COMMENT_LANE_ID_PREFIX);
1088
1088
  }
1089
1089
  //#endregion
1090
+ //#region src/helpers/object-guards.js
1091
+ /**
1092
+ * @param {unknown} value
1093
+ * @returns {value is Record<string, unknown>}
1094
+ */
1095
+ function isPlainObject(value) {
1096
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1097
+ }
1098
+ //#endregion
1090
1099
  //#region src/public/ui/viewport-batch.ts
1091
1100
  /** No rendering or scrolling: read only geometry already acknowledged by the host. */
1092
1101
  async function readViewportBatch(input, read, generation, disposed) {
@@ -2641,16 +2650,17 @@ function selectionKey(selection) {
2641
2650
  }
2642
2651
  }
2643
2652
  //#endregion
2644
- //#region src/helpers/object-guards.js
2645
- /**
2646
- * @param {unknown} value
2647
- * @returns {value is Record<string, unknown>}
2648
- */
2649
- function isPlainObject(value) {
2650
- return typeof value === "object" && value !== null && !Array.isArray(value);
2651
- }
2652
- //#endregion
2653
2653
  //#region src/helpers/v2-review-mutation-impact.ts
2654
+ function mutationCommittedEventChangedVisibleContent(event) {
2655
+ if (event.dryRun === true) return false;
2656
+ if (isPlainObject(event.result) && event.result.noop === true) return false;
2657
+ const receipt = isPlainObject(event.receipt) ? event.receipt : null;
2658
+ if (receipt?.changed === false || receipt?.noop === true || receipt?.status === "NO_OP") return false;
2659
+ return true;
2660
+ }
2661
+ function mutationCommittedEventChangedDocument(event) {
2662
+ return event.cause !== "preview" && mutationCommittedEventChangedVisibleContent(event);
2663
+ }
2654
2664
  /**
2655
2665
  * Classify the tracked-change identities carried by a v2 mutation event.
2656
2666
  *
@@ -5763,17 +5773,42 @@ function commandResultFromOperationResult(result) {
5763
5773
  function isSuccessfulReceipt(result) {
5764
5774
  return Boolean(result) && typeof result === "object" && result.success === true;
5765
5775
  }
5766
- /**
5767
- * The host also emits `mutation:committed` for previews and no-op receipts;
5768
- * those events must not mark the document as having unsaved edits.
5769
- */
5770
- function mutationCommittedEventChangedDocument(event) {
5771
- if (event.dryRun === true) return false;
5772
- const receipt = event.receipt;
5773
- if (receipt && typeof receipt === "object" && receipt.changed === false) return false;
5774
- if (receipt && typeof receipt === "object" && receipt.noop === true) return false;
5775
- if (receipt && typeof receipt === "object" && receipt.status === "NO_OP") return false;
5776
- return true;
5776
+ function readTxId(value) {
5777
+ return typeof value === "string" && value.length > 0 ? value : null;
5778
+ }
5779
+ function documentChangeScope(stories) {
5780
+ return Array.isArray(stories) && stories.length > 0 ? {
5781
+ kind: "known",
5782
+ stories
5783
+ } : { kind: "unknown" };
5784
+ }
5785
+ function documentChangeFromHostEvent(event) {
5786
+ if (event.type === "collaboration:remote-changed") return {
5787
+ cause: "remote",
5788
+ changeTag: null,
5789
+ txId: null,
5790
+ scope: { kind: "unknown" }
5791
+ };
5792
+ if (event.type !== "mutation:committed") return null;
5793
+ if (event.origin === "history") {
5794
+ const result = isPlainObject(event.result) ? event.result : null;
5795
+ if (!result || result.noop === true) return null;
5796
+ const history = isPlainObject(result.history) ? result.history : null;
5797
+ return {
5798
+ cause: event.direction === "redo" ? "redo" : "undo",
5799
+ changeTag: null,
5800
+ txId: readTxId(history?.txId),
5801
+ scope: documentChangeScope(result.affectedStories)
5802
+ };
5803
+ }
5804
+ if (!mutationCommittedEventChangedDocument(event)) return null;
5805
+ const receipt = isPlainObject(event.receipt) ? event.receipt : {};
5806
+ return {
5807
+ cause: event.cause === "user" ? "user" : "api",
5808
+ changeTag: typeof receipt.changeTag === "string" ? receipt.changeTag : null,
5809
+ txId: readTxId(receipt.txId),
5810
+ scope: documentChangeScope(receipt.affectedStories)
5811
+ };
5777
5812
  }
5778
5813
  function commandResultSucceeded(result) {
5779
5814
  if (result === false) return false;
@@ -6682,9 +6717,19 @@ function createSuperDocUI(options) {
6682
6717
  if (seeded > 0) dirtyHosts.add(host);
6683
6718
  else if (revision === 0) dirtyHosts.delete(host);
6684
6719
  };
6685
- const hasLocalDocumentMutation = () => {
6720
+ const savedPoint = () => {
6686
6721
  const host = getHost();
6722
+ return {
6723
+ host,
6724
+ isDirty: hostMethod(host, "isDirty"),
6725
+ getDocumentVersion: hostMethod(host, "getDocumentVersion"),
6726
+ markSaved: hostMethod(host, "markSaved")
6727
+ };
6728
+ };
6729
+ const hasLocalDocumentMutation = () => {
6730
+ const { host, isDirty } = savedPoint();
6687
6731
  if (!host) return false;
6732
+ if (isDirty) return Boolean(safeCall(() => isDirty(), false));
6688
6733
  seedLocalDocumentMutation(host);
6689
6734
  return dirtyHosts.has(host);
6690
6735
  };
@@ -8095,6 +8140,33 @@ function createSuperDocUI(options) {
8095
8140
  sizeOptions: DEFAULT_FONT_SIZE_OPTIONS
8096
8141
  };
8097
8142
  };
8143
+ const EMPTY_HISTORY = {
8144
+ canUndo: false,
8145
+ canRedo: false,
8146
+ undoDepth: 0,
8147
+ redoDepth: 0
8148
+ };
8149
+ let historySlice = EMPTY_HISTORY;
8150
+ let historySource = null;
8151
+ const computeHistory = () => {
8152
+ const source = getEditCommands();
8153
+ if (source !== historySource) {
8154
+ historySource = source;
8155
+ historySlice = EMPTY_HISTORY;
8156
+ }
8157
+ const getSnapshot = hostMethod(source, "getSnapshot");
8158
+ const snapshot = getSnapshot ? safeCall(() => getSnapshot(), null) : null;
8159
+ const { undoDepth, redoDepth } = (isPlainObject(snapshot) && isPlainObject(snapshot.history) ? snapshot.history : null) ?? {};
8160
+ if (typeof undoDepth !== "number" || typeof redoDepth !== "number") return historySlice;
8161
+ const next = {
8162
+ canUndo: undoDepth > 0,
8163
+ canRedo: redoDepth > 0,
8164
+ undoDepth,
8165
+ redoDepth
8166
+ };
8167
+ if (!shallowEqual(next, historySlice)) historySlice = next;
8168
+ return historySlice;
8169
+ };
8098
8170
  let zoomFitWidth;
8099
8171
  const computeZoom = () => {
8100
8172
  const getZoomState = hostMethod(superdoc, "getZoomState");
@@ -9907,6 +9979,7 @@ function createSuperDocUI(options) {
9907
9979
  trackChanges: measure("trackChanges", () => computeTrackChanges(selection)),
9908
9980
  contentControls: measure("contentControls", () => computeContentControls(selection)),
9909
9981
  zoom: measure("zoom", computeZoom),
9982
+ history: measure("history", computeHistory),
9910
9983
  fonts: measure("fonts", computeFonts),
9911
9984
  styles: measure("styles", () => computeStyles(selection))
9912
9985
  };
@@ -10196,6 +10269,41 @@ function createSuperDocUI(options) {
10196
10269
  state = computeState("initial");
10197
10270
  lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
10198
10271
  let scheduleActiveSearchRefresh = () => {};
10272
+ const documentChangeListeners = /* @__PURE__ */ new Set();
10273
+ const documentChangeCounters = /* @__PURE__ */ new WeakMap();
10274
+ let documentEpochCount = 0;
10275
+ const readDocumentReplacement = (host) => safeCall(() => hostMethod(host, "getDocumentReplacementVersion")?.(), null);
10276
+ const startDocumentChangeEpoch = (host) => {
10277
+ documentEpochCount += 1;
10278
+ const counter = {
10279
+ epoch: `document-${documentEpochCount}`,
10280
+ seq: 0,
10281
+ replacement: readDocumentReplacement(host)
10282
+ };
10283
+ documentChangeCounters.set(host, counter);
10284
+ return counter;
10285
+ };
10286
+ const currentDocumentChangeCounter = (host) => {
10287
+ const counter = documentChangeCounters.get(host);
10288
+ return counter && counter.replacement === readDocumentReplacement(host) ? counter : startDocumentChangeEpoch(host);
10289
+ };
10290
+ const publishDocumentChange = (host, event) => {
10291
+ if (event.type === "collaboration:document-replaced" || event.documentReplaced === true) {
10292
+ startDocumentChangeEpoch(host);
10293
+ return;
10294
+ }
10295
+ if (documentChangeListeners.size === 0) return;
10296
+ const facts = documentChangeFromHostEvent(event);
10297
+ if (!facts) return;
10298
+ const counter = currentDocumentChangeCounter(host);
10299
+ counter.seq += 1;
10300
+ const change = {
10301
+ documentEpoch: counter.epoch,
10302
+ seq: counter.seq,
10303
+ ...facts
10304
+ };
10305
+ for (const listener of Array.from(documentChangeListeners)) safeCall(() => listener(change), void 0);
10306
+ };
10199
10307
  const syncHostEventsSubscription = () => {
10200
10308
  const host = getEditor()?.host;
10201
10309
  const events = host?.events;
@@ -10214,15 +10322,19 @@ function createSuperDocUI(options) {
10214
10322
  try {
10215
10323
  const off = hostMethod(next, "subscribe")?.((event) => {
10216
10324
  const type = event?.type;
10325
+ if (host) publishDocumentChange(host, event);
10217
10326
  const isStandaloneDocumentMutation = type === "document:mutated" && event.hasCommitEvent !== true;
10218
- if (type === "collaboration:document-replaced" || isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedDocument(event) || type === "collaboration:remote-changed") {
10327
+ if (type === "collaboration:document-replaced" || isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedVisibleContent(event) || type === "collaboration:remote-changed") {
10219
10328
  for (const [commandId, optimistic] of optimisticInlineToggles) if (optimistic.settled || type === "collaboration:document-replaced") optimisticInlineToggles.delete(commandId);
10220
10329
  }
10221
- if (isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedDocument(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0) scheduleActiveSearchRefresh();
10222
- if ((type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event)) && host && !dirtyHosts.has(host)) {
10330
+ if (isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedVisibleContent(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0) scheduleActiveSearchRefresh();
10331
+ const documentEdited = type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event);
10332
+ if (documentEdited && host && hostMethod(host, "isDirty")) recompute("document-dirty");
10333
+ else if (documentEdited && host && !dirtyHosts.has(host)) {
10223
10334
  dirtyHosts.add(host);
10224
10335
  recompute("document-dirty");
10225
10336
  }
10337
+ if (type === "document:saved-point-changed") recompute("document-dirty");
10226
10338
  if (type === "collaboration:document-replaced" && host) {
10227
10339
  dirtyHosts.delete(host);
10228
10340
  hostSeededMutationRevision.delete(host);
@@ -10254,6 +10366,7 @@ function createSuperDocUI(options) {
10254
10366
  if (impact?.allResolved) {
10255
10367
  replaceTrackedChangeItemsInCache([]);
10256
10368
  publishAllTrackedChangesResolved(event.receipt);
10369
+ if (event.cause === "preview") invalidateDocumentContent();
10257
10370
  return;
10258
10371
  }
10259
10372
  if (impact?.removedIds.size) markPostDecisionTrackChanges(new Set(impact.removedIds), event.receipt);
@@ -10263,7 +10376,10 @@ function createSuperDocUI(options) {
10263
10376
  scheduleTypingDocumentContentInvalidation();
10264
10377
  return;
10265
10378
  }
10266
- if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
10379
+ if (impact?.removedIds.size && impact.upsertIds.size === 0) {
10380
+ if (event.cause === "preview") invalidateDocumentContent();
10381
+ return;
10382
+ }
10267
10383
  if (isStandaloneDocumentMutation || type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
10268
10384
  const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
10269
10385
  const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
@@ -12161,6 +12277,12 @@ function createSuperDocUI(options) {
12161
12277
  keys: [...EFFECTIVE_INLINE_UNIFORMITY_KEYS, "highlight"],
12162
12278
  includeCaret: true
12163
12279
  } : null);
12280
+ if (effective?.fontFamily?.state === "mixed") {
12281
+ delete inlinePatch.fontFamily;
12282
+ delete inlinePatch.rFonts;
12283
+ mixedInlineKeys.add("fontFamily");
12284
+ mixedInlineKeys.add("rFonts");
12285
+ }
12164
12286
  for (const [markName, patchKey] of Object.entries(MARK_TO_PATCH)) {
12165
12287
  const entry = effective?.[markName];
12166
12288
  if (!entry) continue;
@@ -12354,7 +12476,11 @@ function createSuperDocUI(options) {
12354
12476
  const node = (await readBlockNode(paragraphTarget(segment.blockId, targetStory)))?.node;
12355
12477
  const para = node ? getParagraphLikeData(node) : null;
12356
12478
  const runs = Array.isArray(para?.inlines) ? para.inlines : [];
12357
- for (const props of sliceRunProps(runs, segment.range)) for (const key of Object.keys(sdRunPropsToInlineRunPatch(props))) if (!(key in inline) && !snap.mixedInlineKeys.includes(key)) inline[key] = FORMAT_PAINTER_BOOLEAN_KEYS.has(key) ? false : null;
12479
+ for (const props of sliceRunProps(runs, segment.range)) for (const key of Object.keys(sdRunPropsToInlineRunPatch(props))) {
12480
+ const fontAlias = key === "rFonts" ? "fontFamily" : key === "fontFamily" ? "rFonts" : null;
12481
+ const capturedFontAlias = fontAlias && (fontAlias in inline || snap.mixedInlineKeys.includes(fontAlias));
12482
+ if (!(key in inline) && !snap.mixedInlineKeys.includes(key) && !capturedFontAlias) inline[key] = FORMAT_PAINTER_BOOLEAN_KEYS.has(key) ? false : null;
12483
+ }
12358
12484
  }
12359
12485
  if (disposed || painter.snapshot !== snap || getEditor() !== ownerEditor || ownerEditor?.doc !== ownerDoc || readDocumentMode() !== ownerMode) return;
12360
12486
  }
@@ -13695,6 +13821,7 @@ function createSuperDocUI(options) {
13695
13821
  getFamilyOptions: () => state.fonts.options,
13696
13822
  getSizeOptions: () => state.fonts.sizeOptions
13697
13823
  };
13824
+ const history = snapshotHandle(sliceHandle((s) => s.history));
13698
13825
  const zoomSnap = snapshotHandle(sliceHandle((s) => s.zoom));
13699
13826
  const zoom = {
13700
13827
  get: zoomSnap.get,
@@ -13755,6 +13882,28 @@ function createSuperDocUI(options) {
13755
13882
  } catch {
13756
13883
  return;
13757
13884
  }
13885
+ },
13886
+ onChange: (listener) => {
13887
+ if (disposed) return () => {};
13888
+ documentChangeListeners.add(listener);
13889
+ return () => documentChangeListeners.delete(listener);
13890
+ },
13891
+ getVersion: () => {
13892
+ const { getDocumentVersion } = savedPoint();
13893
+ const version = getDocumentVersion ? safeCall(() => getDocumentVersion(), null) : null;
13894
+ return typeof version === "string" ? version : null;
13895
+ },
13896
+ markClean: (version) => {
13897
+ const { markSaved } = savedPoint();
13898
+ if (!markSaved) return {
13899
+ ok: false,
13900
+ reason: "unavailable"
13901
+ };
13902
+ const result = safeCall(() => markSaved(version), null);
13903
+ return isPlainObject(result) && result.ok === true ? { ok: true } : {
13904
+ ok: false,
13905
+ reason: isPlainObject(result) && result.reason === "document-changed" ? "document-changed" : "unavailable"
13906
+ };
13758
13907
  }
13759
13908
  };
13760
13909
  const resolveVisibleHost = () => {
@@ -15237,6 +15386,11 @@ function createSuperDocUI(options) {
15237
15386
  const scopeUnsubs = [];
15238
15387
  return {
15239
15388
  decorations: createDecorationsHandle((handle) => scopeUnsubs.push(() => handle.dispose())),
15389
+ document: { onChange: (listener) => {
15390
+ const unsub = documentHandle.onChange(listener);
15391
+ scopeUnsubs.push(unsub);
15392
+ return unsub;
15393
+ } },
15240
15394
  select: (selector, equality) => {
15241
15395
  const sub = select(selector, equality);
15242
15396
  return {
@@ -15323,6 +15477,7 @@ function createSuperDocUI(options) {
15323
15477
  painterCaptureEpoch += 1;
15324
15478
  painterCommandDoc = null;
15325
15479
  painterModeListeners.clear();
15480
+ documentChangeListeners.clear();
15326
15481
  searchRequestGeneration += 1;
15327
15482
  customCommands.clear();
15328
15483
  };
@@ -15340,6 +15495,7 @@ function createSuperDocUI(options) {
15340
15495
  bookmarks,
15341
15496
  fonts,
15342
15497
  zoom,
15498
+ history,
15343
15499
  document: documentHandle,
15344
15500
  viewport,
15345
15501
  decorations,
@@ -15615,6 +15771,12 @@ Object.defineProperty(exports, "executeFirstPartyShortcutAsync", {
15615
15771
  return executeFirstPartyShortcutAsync;
15616
15772
  }
15617
15773
  });
15774
+ Object.defineProperty(exports, "getCommandDescriptor", {
15775
+ enumerable: true,
15776
+ get: function() {
15777
+ return getCommandDescriptor;
15778
+ }
15779
+ });
15618
15780
  Object.defineProperty(exports, "getV2TrackedChangeMutationImpact", {
15619
15781
  enumerable: true,
15620
15782
  get: function() {
@@ -15651,6 +15813,12 @@ Object.defineProperty(exports, "isWorkflowRecordingEnabled", {
15651
15813
  return isWorkflowRecordingEnabled;
15652
15814
  }
15653
15815
  });
15816
+ Object.defineProperty(exports, "mutationCommittedEventChangedDocument", {
15817
+ enumerable: true,
15818
+ get: function() {
15819
+ return mutationCommittedEventChangedDocument;
15820
+ }
15821
+ });
15654
15822
  Object.defineProperty(exports, "readFirstPartyPageNumbers", {
15655
15823
  enumerable: true,
15656
15824
  get: function() {
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
19
19
  var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
20
20
  var ENGINE_INFO = Object.freeze({
21
21
  ...PRIVATE_ENGINE_INFO,
22
- superdocVersion: "2.28.0-next.8",
22
+ superdocVersion: "2.28.0",
23
23
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
24
24
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
25
25
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
18
18
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
19
19
  var ENGINE_INFO = Object.freeze({
20
20
  ...PRIVATE_ENGINE_INFO,
21
- superdocVersion: "2.28.0-next.8",
21
+ superdocVersion: "2.28.0",
22
22
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
23
23
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
24
24
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -2829,7 +2829,7 @@ export declare const OPERATION_DEFINITIONS: {
2829
2829
  readonly 'footnotes.insert': {
2830
2830
  readonly memberPath: "footnotes.insert";
2831
2831
  readonly description: "Insert a new footnote or endnote at a target location or the current selection.";
2832
- readonly expectedResult: "Returns a FootnoteMutationResult indicating success with the footnote address or a failure.";
2832
+ readonly expectedResult: string;
2833
2833
  readonly requiresDocumentContext: true;
2834
2834
  readonly metadata: CommandStaticMetadata;
2835
2835
  readonly referenceDocPath: "footnotes/insert.mdx";
@@ -3726,7 +3726,7 @@ export declare const OPERATION_DEFINITIONS: {
3726
3726
  readonly find: {
3727
3727
  readonly memberPath: "find";
3728
3728
  readonly description: "Search the document for text or node matches using SDM/1 selectors. Returns discovery-grade results: for mutation targeting, use query.match instead.";
3729
- readonly expectedResult: "Returns an SDFindResult envelope ({ total, limit, offset, items }). Each item is an SDNodeResult ({ node, address }). Text hits contain only the matched text; use getNode or getNodeById for the full containing node. Node selectors return full node projections.";
3729
+ readonly expectedResult: "Returns an SDFindResult envelope ({ total, limit, offset, items }). Each item is an SDNodeResult ({ node, address }). Text hits contain only the matched text; use getNode or getNodeById for the full containing node. Node selectors return full node projections. Bookmark selectors return the bookmarks of the searched story in document order: each address is an inline bookmark address whose anchor spans the bookmark range, and each node is an ext.bookmark node whose bookmark.address resolves through bookmarks.get.";
3730
3730
  readonly requiresDocumentContext: true;
3731
3731
  readonly metadata: CommandStaticMetadata;
3732
3732
  readonly referenceDocPath: "find.mdx";
@@ -214,6 +214,7 @@ export interface ListLevelTemplate {
214
214
  customFormat?: string;
215
215
  lvlText?: string;
216
216
  start?: number;
217
+ lvlRestart?: number;
217
218
  alignment?: LevelAlignment;
218
219
  indents?: {
219
220
  left?: number;
@@ -1,4 +1,4 @@
1
- import { BlockNodeAddress, ChangeMode, ReceiptFailure } from '../types/index.js';
1
+ import { BlockNodeAddress, ChangeMode, ReceiptFailure, TrackedChangeAddress } from '../types/index.js';
2
2
  import { DiscoveryOutput } from '../types/discovery.js';
3
3
  export type SectionAddress = {
4
4
  kind: 'section';
@@ -111,6 +111,7 @@ export interface SectionsGetInput {
111
111
  export type SectionsListResult = DiscoveryOutput<SectionDomain>;
112
112
  export interface SectionMutationSuccessResult {
113
113
  success: true;
114
+ dryRun?: boolean;
114
115
  section: SectionAddress;
115
116
  /** Committed review-aware content mode; omitted for dry runs, no-ops and non-reviewable settings. */
116
117
  appliedChangeMode?: ChangeMode;
@@ -126,11 +127,14 @@ export type SectionMutationResult = SectionMutationSuccessResult | SectionMutati
126
127
  */
127
128
  export interface DocumentMutationSuccessResult {
128
129
  success: true;
130
+ dryRun?: boolean;
131
+ changed?: boolean;
129
132
  }
130
133
  export type DocumentMutationResult = DocumentMutationSuccessResult | SectionMutationFailureResult;
131
134
  export interface CreateSectionBreakSuccessResult {
132
135
  success: true;
133
136
  appliedChangeMode?: 'direct' | 'tracked';
137
+ trackedChangeRefs?: TrackedChangeAddress[];
134
138
  section: SectionAddress;
135
139
  /**
136
140
  * Present only when the break is represented as a dedicated paragraph.
@@ -138,7 +138,11 @@ export interface SDPasteBlockSdt {
138
138
  lockMode?: 'unlocked' | 'sdtLocked' | 'contentLocked' | 'sdtContentLocked';
139
139
  multiline?: boolean;
140
140
  }
141
- export type SDPasteInline = SDPasteLeafInline | SDPasteSdtInline | {
141
+ export type SDPasteInline = {
142
+ kind: 'math';
143
+ omml: string;
144
+ sourcePath?: readonly (string | number)[];
145
+ } | SDPasteLeafInline | SDPasteSdtInline | {
142
146
  kind: 'hyperlink';
143
147
  target: {
144
148
  kind: 'external';
@@ -15,7 +15,7 @@ export type ReceiptFailureCode = 'NO_OP' | 'INVALID_TARGET' | 'TARGET_NOT_FOUND'
15
15
  export type TextRangeRejectionReason = 'text-range-in-sdt' | 'text-range-in-field' | 'text-range-in-unsupported-tracked-wrapper';
16
16
  /** Content-control creation keeps its existing top-level failure code. */
17
17
  export type ContentControlCreationRejectionReason = 'content-control-unsupported-inline-structure' | 'content-control-shared-run-boundary';
18
- export type DocumentApiRejectionReason = TextRangeRejectionReason | ContentControlCreationRejectionReason;
18
+ export type DocumentApiRejectionReason = TextRangeRejectionReason | ContentControlCreationRejectionReason | 'paragraph-mark-already-deleted';
19
19
  export interface DocumentApiRejectionDetails extends Record<string, unknown> {
20
20
  reason: DocumentApiRejectionReason;
21
21
  }
@@ -145,6 +145,7 @@ export type ReceiptSuccess = {
145
145
  /** Temporary-preview lifecycle and caller tag, also delivered through mutation events. */
146
146
  temporary?: import('./temporary-mutation.js').TemporaryMutationMetadata;
147
147
  success: true;
148
+ status?: 'NO_OP';
148
149
  /** Whether a successful request changed the document; false represents a no-op commit. */
149
150
  changed?: boolean;
150
151
  /** Tracked changes authored by this mutation. */
@@ -564,6 +564,7 @@ export type RenderPlaceholder = {
564
564
  */
565
565
  export type ImageRun = {
566
566
  kind: 'image';
567
+ inlineDrawingId?: string;
567
568
  /** Image source URL (data URI or external URL). */
568
569
  src: string;
569
570
  /** Image width in pixels. */
@@ -1525,6 +1526,7 @@ export type SectionPageBorderSide = {
1525
1526
  };
1526
1527
  export type SectionPageBorders = {
1527
1528
  offsetFrom: 'page';
1529
+ display?: 'allPages' | 'firstPage';
1528
1530
  top?: SectionPageBorderSide;
1529
1531
  right?: SectionPageBorderSide;
1530
1532
  bottom?: SectionPageBorderSide;
@@ -1894,6 +1896,7 @@ export type WordLayoutMarker = {
1894
1896
  */
1895
1897
  trackedChange?: MarkerTrackedChange;
1896
1898
  };
1899
+ export declare const markerRunSignature: (run: WordLayoutMarker["run"] | undefined) => string;
1897
1900
  /**
1898
1901
  * Word layout configuration for list items created via input rules.
1899
1902
  *
@@ -2404,6 +2407,7 @@ export type ImageMeasure = {
2404
2407
  };
2405
2408
  export type DrawingMeasure = {
2406
2409
  kind: 'drawing';
2410
+ inlineDrawing?: boolean;
2407
2411
  drawingKind: DrawingKind;
2408
2412
  width: number;
2409
2413
  height: number;
@@ -2971,7 +2975,7 @@ export declare const extractHeaderFooterSpace: (margins?: PageMargins | null) =>
2971
2975
  };
2972
2976
  export type { ResolvedLayout, ResolvedPage, ResolvedPaintItem, ResolvedGroupItem, ResolvedFragmentItem, ResolvedParagraphContent, ResolvedTextLineItem, ResolvedDropCapItem, ResolvedListMarkerItem, ResolvedTableItem, ResolvedImageItem, ResolvedDrawingItem, ResolvedHeaderFooterPage, ResolvedHeaderFooterLayout, } from './resolved-layout.js';
2973
2977
  export { isResolvedTableItem, isResolvedImageItem, isResolvedDrawingItem } from './resolved-layout.js';
2974
- export { PAGE_BREAK_DELETION_ANCHOR_ATTR, DELETED_PAGE_BREAK_LABEL, isPageBreakDeletionAnchorRun, expandRunsForInlineNewlines, isBodyNoteReferenceRun, isZeroWidthMarkerRun, hasZeroWidthMarkerSpan, isNoteLabelRun, isNumberedNoteMarkerRun, isEmptyInlineSdtPlaceholderRun, isEmptySdtPlaceholderRun, NOTE_LABEL_MARKER_ATTR, NOTE_REFERENCE_MARKER_ATTR, sliceRunsForLine, usesPositionedTextGeometry, } from './run-helpers.js';
2978
+ export { PAGE_BREAK_DELETION_ANCHOR_ATTR, DELETED_PAGE_BREAK_LABEL, isPageBreakDeletionAnchorRun, expandRunsForInlineNewlines, isBodyNoteReferenceRun, isZeroWidthMarkerRun, isGeneratedFieldResultRun, hasZeroWidthMarkerSpan, isNoteLabelRun, isNumberedNoteMarkerRun, isEmptyInlineSdtPlaceholderRun, isEmptySdtPlaceholderRun, NOTE_LABEL_MARKER_ATTR, NOTE_REFERENCE_MARKER_ATTR, sliceRunsForLine, usesPositionedTextGeometry, } from './run-helpers.js';
2975
2979
  export { INLINE_OBJECT_REPLACEMENT_CHARACTER, flattenParagraphVisibleText, mapVisibleRangeToRunSlices, type ParagraphVisibleRunSlice, } from './paragraph-visible-text.js';
2976
2980
  export { inlineBoxStyleSignature, isFiniteNonNegativeInteger, normalizeInlineBoxLogicalSides, type InlineBoxLogicalSides, type ResolvedInlineBoxLogicalSides, } from './inline-box.js';
2977
2981
  export { INCREMENTAL_DEPENDENCY_CERTIFICATE_CLASSES, PAGE_CHECKPOINT_DEPENDENCY_CLASSES, areValidPageCheckpointDependencyClasses, isValidIncrementalDependencyOwnerVersion, isValidNonFlowingPageRelativeAnchorDependencyProof, isValidPageCheckpointDependencyCertificate, type IncrementalDependencyCertificateClass, type IncrementalDependencyOwnerVersion, type NonFlowingPageRelativeAnchorDependencyProof, type PageCheckpointDependencyCertificate, type PageCheckpointDependencyClass, } from './incremental-dependency.js';
@@ -12,6 +12,7 @@ export declare const NOTE_LABEL_MARKER_ATTR = "data-v2-note-label";
12
12
  export declare function isBodyNoteReferenceRun(run: Run): boolean;
13
13
  export declare function isZeroWidthMarkerRun(run: Run): boolean;
14
14
  export declare function hasZeroWidthMarkerSpan(run: Run): boolean;
15
+ export declare function isGeneratedFieldResultRun(run: Run): boolean;
15
16
  /** Synthetic note-band or appended-endnote label keyed to its source note. */
16
17
  export declare function isNoteLabelRun(run: Run): boolean;
17
18
  /** Numbered marker text whose measurement identity can use digit capabilities. */
@@ -213,3 +213,4 @@ export declare function pmPosToCharOffset(block: FlowBlock, line: Line, pmPos: n
213
213
  export declare function pmPosToVisualCharOffset(block: FlowBlock, line: Line, pmPos: number): number;
214
214
  export { measureVisualBidiFragment, type MeasuredVisualBidiFragment } from './neutral-segment-geometry.js';
215
215
  export { measuredVisualBidiCaretX, measuredVisualBidiOffsetAtX, measuredVisualBidiRangeBands, isMeasuredVisualBidiLineCurrent, type MeasuredVisualBidiLine, } from './visual-bidi-geometry.js';
216
+ export { placeInlineDrawings } from './place-inline-drawings.js';
@@ -0,0 +1,9 @@
1
+ import { FlowBlock, Layout, Measure } from '../../contracts/src/index.js';
2
+ export declare function placeInlineDrawings(layout: Layout, blocks: FlowBlock[], measures: Measure[], blockIndexById?: ReadonlyMap<string, number>, retainedPages?: {
3
+ prefixEndPageIndex?: number;
4
+ tail?: {
5
+ startPageIndex: number;
6
+ endPageIndexExclusive: number;
7
+ blockIdRewrites?: ReadonlyMap<string, string> | null;
8
+ };
9
+ }): Layout;
@@ -9,6 +9,7 @@ import { PageState } from './paginator.js';
9
9
  * callbacks for positioning the drawing fragment on the current page/column.
10
10
  */
11
11
  export type DrawingLayoutContext = {
12
+ inlineParagraphBound?: boolean;
12
13
  /** The drawing block to layout */
13
14
  block: DrawingBlock;
14
15
  /** Measured dimensions and geometry data for the drawing */
@@ -57,4 +58,4 @@ export type DrawingLayoutContext = {
57
58
  * - Anchored drawings (`block.anchor?.isAnchored === true`) are skipped
58
59
  * - They are positioned via the paragraph anchoring pre-pass
59
60
  */
60
- export declare function layoutDrawingBlock({ block, measure, columns, ensurePage, advanceColumn, columnX, textboxContentMeasures, }: DrawingLayoutContext): void;
61
+ export declare function layoutDrawingBlock({ block, measure, columns, ensurePage, advanceColumn, columnX, textboxContentMeasures, inlineParagraphBound, }: DrawingLayoutContext): void;
@@ -99,6 +99,7 @@ export type PaginatorOptions = {
99
99
  }): Page;
100
100
  onNewPage?: (state: PageState | undefined, options?: {
101
101
  applyPendingSection: boolean;
102
+ replaceCurrentPage: boolean;
102
103
  }) => void;
103
104
  shouldStopBeforeNewPage?: (input: {
104
105
  completedPageIndex: number;
@@ -46,7 +46,7 @@ export interface TableInfo {
46
46
  * Word applies these flags when a table has no explicit w:tblLook element.
47
47
  */
48
48
  export declare const DEFAULT_TBL_LOOK: TableLookProperties;
49
- export declare function resolveRunProperties(params: OoxmlResolverParams, inlineRpr: RunProperties | null | undefined, resolvedPpr: ParagraphProperties | null | undefined, tableInfo?: TableInfo | null | undefined, isListNumber?: boolean, numberingDefinedInline?: boolean): RunProperties;
49
+ export declare function resolveRunProperties(params: OoxmlResolverParams, inlineRpr: RunProperties | null | undefined, resolvedPpr: ParagraphProperties | null | undefined, tableInfo?: TableInfo | null | undefined, isListNumber?: boolean): RunProperties;
50
50
  export declare function resolveParagraphProperties(params: OoxmlResolverParams, inlineProps: ParagraphProperties | null | undefined, tableInfo: TableInfo | null | undefined): ParagraphProperties;
51
51
  export declare function resolveStyleChain<T extends PropertyObject>(propertyType: 'paragraphProperties' | 'runProperties' | 'tableProperties', params: OoxmlResolverParams, styleId: string | undefined, followBasedOnChain?: boolean): T;
52
52
  export declare function getNumberingProperties<T extends ParagraphProperties | RunProperties>(propertyType: 'paragraphProperties' | 'runProperties', params: OoxmlResolverParams, ilvl: number, numId: number, tries?: number): T;
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-B4c55pFy.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-BfgYblyI.cjs");
3
3
  const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
4
4
  let react = require("react");
5
5
  let use_sync_external_store_shim = require("use-sync-external-store/shim");
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-C4Ka5Ph3.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BbjHD1ul.es.js";
2
2
  import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
3
3
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
4
4
  import { useSyncExternalStore } from "use-sync-external-store/shim";
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-B4c55pFy.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-BfgYblyI.cjs");
3
3
  const require_slice_source = require("../chunks/slice-source-CFaqq0Vo.cjs");
4
4
  let superdoc_entry_vue = require("vue");
5
5
  //#region src/public/ui/vue.ts
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-C4Ka5Ph3.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BbjHD1ul.es.js";
2
2
  import { t as toSliceSource } from "../chunks/slice-source-gfOhG2MW.es.js";
3
3
  import { computed, inject, onScopeDispose, provide, shallowRef, toRaw, toValue, watch } from "vue";
4
4
  //#region src/public/ui/vue.ts
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-B4c55pFy.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-BfgYblyI.cjs");
3
3
  //#region ../document-api/src/types/receipt.ts
4
4
  /** Read a known failure.details.reason without assuming every failure has one. */
5
5
  function getDocumentApiRejectionReason(details) {
@@ -9,7 +9,8 @@ function getDocumentApiRejectionReason(details) {
9
9
  case "text-range-in-field":
10
10
  case "text-range-in-unsupported-tracked-wrapper":
11
11
  case "content-control-unsupported-inline-structure":
12
- case "content-control-shared-run-boundary": return details.reason;
12
+ case "content-control-shared-run-boundary":
13
+ case "paragraph-mark-already-deleted": return details.reason;
13
14
  default: return;
14
15
  }
15
16
  }
@@ -1,4 +1,4 @@
1
- import { p as shallowEqual, s as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-C4Ka5Ph3.es.js";
1
+ import { m as shallowEqual, s as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BbjHD1ul.es.js";
2
2
  //#region ../document-api/src/types/receipt.ts
3
3
  /** Read a known failure.details.reason without assuming every failure has one. */
4
4
  function getDocumentApiRejectionReason(details) {
@@ -8,7 +8,8 @@ function getDocumentApiRejectionReason(details) {
8
8
  case "text-range-in-field":
9
9
  case "text-range-in-unsupported-tracked-wrapper":
10
10
  case "content-control-unsupported-inline-structure":
11
- case "content-control-shared-run-boundary": return details.reason;
11
+ case "content-control-shared-run-boundary":
12
+ case "paragraph-mark-already-deleted": return details.reason;
12
13
  default: return;
13
14
  }
14
15
  }