superdoc 2.29.0-next.9 → 2.30.0-next.4

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 (158) hide show
  1. package/README.md +127 -25
  2. package/dist/chunks/{FindReplaceSurface-BKVHzhQ4.es.js → FindReplaceSurface-BEnRLpD9.es.js} +1 -1
  3. package/dist/chunks/{FindReplaceSurface-BNDrJ6VS.cjs → FindReplaceSurface-DWXgWgg7.cjs} +1 -1
  4. package/dist/chunks/{PasswordPromptSurface-6mF6Azda.es.js → PasswordPromptSurface-DjV1JgjD.es.js} +1 -1
  5. package/dist/chunks/{PasswordPromptSurface-BNkaztaP.cjs → PasswordPromptSurface-VFPnQOML.cjs} +1 -1
  6. package/dist/chunks/{PdfViewer-aOWhUVI7.es.js → PdfViewer-C2r-K8zC.es.js} +4 -10
  7. package/dist/chunks/{PdfViewer-DmSkZehl.cjs → PdfViewer-DYTbPVUr.cjs} +4 -10
  8. package/dist/chunks/{_plugin-vue_export-helper-6MBoygIY.cjs → _plugin-vue_export-helper-BzM2_tVU.cjs} +40 -7
  9. package/dist/chunks/{_plugin-vue_export-helper-CsJQtMvr.es.js → _plugin-vue_export-helper-CmkaJDnr.es.js} +23 -8
  10. package/dist/chunks/{create-super-doc-ui-DN70aatf.cjs → create-super-doc-ui--kQBNTyt.cjs} +2424 -2302
  11. package/dist/chunks/{create-super-doc-ui-Bm5kmx0W.es.js → create-super-doc-ui-CbEDXtpm.es.js} +2350 -2228
  12. package/dist/collaboration-upgrade-engine.cjs +1 -1
  13. package/dist/collaboration-upgrade-engine.es.js +1 -1
  14. package/dist/document-api/src/changes/changes.d.ts +26 -0
  15. package/dist/document-api/src/changes/changes.types.d.ts +156 -0
  16. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  17. package/dist/document-api/src/contract/operation-definitions.d.ts +51 -1
  18. package/dist/document-api/src/create/create.d.ts +0 -4
  19. package/dist/document-api/src/diff/diff.types.d.ts +6 -6
  20. package/dist/document-api/src/header-footers/header-footers.d.ts +1 -3
  21. package/dist/document-api/src/index.d.ts +6 -0
  22. package/dist/document-api/src/inline-semantics/token-sets.d.ts +0 -2
  23. package/dist/document-api/src/insert/insert.d.ts +0 -1
  24. package/dist/layout-engine/contracts/src/index.d.ts +3 -1
  25. package/dist/layout-engine/dom-contract/src/data-attrs.d.ts +4 -0
  26. package/dist/layout-engine/layout-bridge/src/coupled-footnote-pagination.d.ts +1 -0
  27. package/dist/layout-engine/layout-bridge/src/footnote-page-certificate.d.ts +1 -0
  28. package/dist/layout-engine/layout-bridge/src/footnote-page-planner.d.ts +5 -0
  29. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +1 -0
  30. package/dist/layout-engine/layout-engine/src/footnote-page-flow.d.ts +3 -0
  31. package/dist/layout-engine/layout-engine/src/index.d.ts +7 -0
  32. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +5 -0
  33. package/dist/layout-engine/layout-engine/src/layout-table.d.ts +3 -1
  34. package/dist/layout-engine/layout-engine/src/layout-utils.d.ts +0 -4
  35. package/dist/layout-engine/layout-engine/src/paginator.d.ts +4 -0
  36. package/dist/layout-engine/painters/dom/src/paragraph/list-marker.d.ts +1 -1
  37. package/dist/layout-engine/painters/dom/src/paragraph/renderParagraphContent.d.ts +1 -1
  38. package/dist/layout-engine/painters/dom/src/styles.d.ts +0 -10
  39. package/dist/layout-engine/painters/dom/src/svg-utils.d.ts +1 -13
  40. package/dist/public/ui-react.cjs +1 -1
  41. package/dist/public/ui-react.es.js +1 -1
  42. package/dist/public/ui-vue.cjs +1 -1
  43. package/dist/public/ui-vue.es.js +1 -1
  44. package/dist/public/ui.cjs +1 -1
  45. package/dist/public/ui.es.js +1 -1
  46. package/dist/shared/common/Telemetry.d.ts +50 -0
  47. package/dist/shared/common/event-types.d.ts +13 -0
  48. package/dist/shared/font-system/src/bundled-face-names.d.ts +1 -0
  49. package/dist/shared/font-system/src/resolver.d.ts +1 -0
  50. package/dist/style.css +1 -1
  51. package/dist/style.layered.css +1 -1
  52. package/dist/superdoc/src/components/CommentsLayer/CommentDialog.vue.d.ts +17 -33
  53. package/dist/superdoc/src/components/CommentsLayer/collect-removed-comment-ids.d.ts +11 -1
  54. package/dist/superdoc/src/components/CommentsLayer/collect-tracked-change-thread.d.ts +25 -6
  55. package/dist/superdoc/src/components/CommentsLayer/comment-params.d.ts +84 -0
  56. package/dist/superdoc/src/components/CommentsLayer/comment-urls.d.ts +1 -1
  57. package/dist/superdoc/src/components/CommentsLayer/commentsList/super-comments-list.d.ts +23 -20
  58. package/dist/superdoc/src/components/CommentsLayer/helpers.d.ts +1 -4
  59. package/dist/superdoc/src/components/CommentsLayer/tracked-change-threading.d.ts +16 -1
  60. package/dist/superdoc/src/components/CommentsLayer/use-comment.d.ts +15 -95
  61. package/dist/superdoc/src/components/Whiteboard/WhiteboardLayer.vue.d.ts +4 -5
  62. package/dist/superdoc/src/components/Whiteboard/WhiteboardPage.vue.d.ts +3 -4
  63. package/dist/superdoc/src/components/Whiteboard/use-whiteboard.d.ts +30 -9
  64. package/dist/superdoc/src/components/Whiteboard/whiteboard-types.d.ts +2 -0
  65. package/dist/superdoc/src/components/surfaces/watermark-surface-runtime.d.ts +7 -7
  66. package/dist/superdoc/src/composables/use-comment-small-screen.d.ts +11 -7
  67. package/dist/superdoc/src/composables/use-compact-comment-popover.d.ts +44 -18
  68. package/dist/superdoc/src/composables/use-document.d.ts +51 -99
  69. package/dist/superdoc/src/composables/use-find-replace.d.ts +13 -3
  70. package/dist/superdoc/src/composables/use-password-prompt.d.ts +1 -1
  71. package/dist/superdoc/src/composables/use-viewport-fit.d.ts +62 -26
  72. package/dist/superdoc/src/core/SuperDoc.d.ts +15 -6
  73. package/dist/superdoc/src/core/collaboration/cdn-collaboration-comment-map.d.ts +1 -0
  74. package/dist/superdoc/src/core/collaboration/collaboration-comment-map.d.ts +2 -0
  75. package/dist/superdoc/src/core/collaboration/helpers.d.ts +1 -1
  76. package/dist/superdoc/src/core/document-open-telemetry.d.ts +1 -1
  77. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +1 -0
  78. package/dist/superdoc/src/core/pdf/pdf-adapter.d.ts +6 -2
  79. package/dist/superdoc/src/core/types/index.d.ts +108 -43
  80. package/dist/superdoc/src/core/v2-integration/browser-peer-runtime.d.ts +5 -3
  81. package/dist/superdoc/src/core/v2-integration/cdn-engine-loader.d.ts +3 -13
  82. package/dist/superdoc/src/core/v2-integration/internal-vue-runtime.d.ts +64 -59
  83. package/dist/superdoc/src/helpers/deprecation.d.ts +12 -3
  84. package/dist/superdoc/src/helpers/object-guards.d.ts +2 -0
  85. package/dist/superdoc/src/helpers/v2-author-required-rejection.d.ts +8 -11
  86. package/dist/superdoc/src/helpers/v2-bulk-decision-event.d.ts +9 -7
  87. package/dist/superdoc/src/helpers/v2-keyboard-edit-rejection.d.ts +8 -7
  88. package/dist/superdoc/src/helpers/v2-mutation-exception.d.ts +12 -8
  89. package/dist/superdoc/src/helpers/v2-review-geometry-delivery.d.ts +22 -0
  90. package/dist/superdoc/src/helpers/v2-review-target.d.ts +11 -1
  91. package/dist/superdoc/src/helpers/v2-selection-sync.d.ts +40 -14
  92. package/dist/superdoc/src/helpers/v2-typing-mutation-event.d.ts +14 -5
  93. package/dist/superdoc/src/icons.d.ts +11 -19
  94. package/dist/superdoc/src/internal/diagnostics/translate-diagnostic.d.ts +6 -4
  95. package/dist/superdoc/src/internal/toolbar/built-in/PageNumberMenu.vue.d.ts +25 -15
  96. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButton.vue.d.ts +1 -0
  97. package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +3 -1
  98. package/dist/superdoc/src/internal/toolbar/built-in/font-options.d.ts +15 -1
  99. package/dist/superdoc/src/internal/toolbar/built-in/font-typeahead.d.ts +37 -7
  100. package/dist/superdoc/src/internal/toolbar/built-in/general.d.ts +12 -1
  101. package/dist/superdoc/src/internal/toolbar/built-in/helpers.d.ts +9 -4
  102. package/dist/superdoc/src/internal/toolbar/built-in/list-style-buttons.d.ts +2 -2
  103. package/dist/superdoc/src/internal/toolbar/built-in/page-number-feedback.d.ts +4 -5
  104. package/dist/superdoc/src/internal/toolbar/built-in/scroll-helpers.d.ts +3 -4
  105. package/dist/superdoc/src/internal/toolbar/built-in/toolbarIcons.d.ts +78 -145
  106. package/dist/superdoc/src/internal/toolbar/built-in/url-safety.d.ts +11 -3
  107. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +4 -3
  108. package/dist/superdoc/src/internal/toolbar/image-upload.d.ts +29 -39
  109. package/dist/superdoc/src/public/content-control-ref.d.ts +12 -0
  110. package/dist/superdoc/src/public/index.d.cts +16 -0
  111. package/dist/superdoc/src/public/index.d.ts +3 -0
  112. package/dist/superdoc/src/public/ui/async-read-cache.d.ts +32 -0
  113. package/dist/superdoc/src/public/ui/block-commands.d.ts +39 -0
  114. package/dist/superdoc/src/public/ui/command-results.d.ts +39 -0
  115. package/dist/superdoc/src/public/ui/create-super-doc-ui.d.ts +1 -17
  116. package/dist/superdoc/src/public/ui/document-change-records.d.ts +7 -0
  117. package/dist/superdoc/src/public/ui/entity-rows.d.ts +14 -0
  118. package/dist/superdoc/src/public/ui/font-options.d.ts +7 -0
  119. package/dist/superdoc/src/public/ui/format-painter-helpers.d.ts +2 -8
  120. package/dist/superdoc/src/public/ui/format-painter-state.d.ts +33 -0
  121. package/dist/superdoc/src/public/ui/heavy-read-policy.d.ts +11 -0
  122. package/dist/superdoc/src/public/ui/host-events.d.ts +3 -0
  123. package/dist/superdoc/src/public/ui/inline-values.d.ts +79 -0
  124. package/dist/superdoc/src/public/ui/loose-record.d.ts +4 -0
  125. package/dist/superdoc/src/public/ui/selection-targets.d.ts +45 -0
  126. package/dist/superdoc/src/public/ui/shared-tracked-changes-catalog.d.ts +16 -0
  127. package/dist/superdoc/src/public/ui/tracked-change-ids.d.ts +51 -0
  128. package/dist/superdoc/src/public/ui/types.d.ts +12 -2
  129. package/dist/superdoc/src/public/ui/ui-bench-timing.d.ts +9 -0
  130. package/dist/superdoc/src/public/ui.d.cts +14 -0
  131. package/dist/superdoc/src/public/ui.d.ts +1 -1
  132. package/dist/superdoc/src/stores/comments-store.d.ts +23006 -542
  133. package/dist/superdoc/src/stores/helpers/comment-document-scope.d.ts +22 -0
  134. package/dist/superdoc/src/stores/helpers/comment-grouping.d.ts +1 -1
  135. package/dist/superdoc/src/stores/helpers/comment-identity.d.ts +10 -10
  136. package/dist/superdoc/src/stores/helpers/pending-selection-snapshot.d.ts +17 -0
  137. package/dist/superdoc/src/stores/helpers/review-presentation.d.ts +90 -0
  138. package/dist/superdoc/src/stores/helpers/tracked-change-compaction.d.ts +16 -0
  139. package/dist/superdoc/src/stores/helpers/tracked-change-decision.d.ts +45 -0
  140. package/dist/superdoc/src/stores/helpers/tracked-change-identity.d.ts +4 -2
  141. package/dist/superdoc/src/stores/helpers/tracked-change-row-values.d.ts +1 -8
  142. package/dist/superdoc/src/stores/helpers/tracked-change-thread-index.d.ts +1 -1
  143. package/dist/superdoc/src/stores/helpers/v2-review-adapters.d.ts +147 -0
  144. package/dist/superdoc/src/stores/superdoc-store.d.ts +12 -2895
  145. package/dist/superdoc.cjs +1019 -844
  146. package/dist/superdoc.es.js +931 -756
  147. package/dist/word-layout/src/marker-utils.d.ts +0 -5
  148. package/dist/word-layout/src/unit-conversions.d.ts +0 -1
  149. package/dist-cdn/style.layered.css +1 -1
  150. package/dist-cdn/superdoc.min.css +1 -1
  151. package/dist-cdn/superdoc.min.js +38 -42
  152. package/package.json +13 -3
  153. package/dist/document-api/src/diff/index.d.ts +0 -3
  154. package/dist/document-api/src/write/locator.d.ts +0 -24
  155. package/dist/layout-engine/painters/dom/src/features/feature-registry.d.ts +0 -41
  156. package/dist/superdoc/src/internal/toolbar/built-in/format-negation.d.ts +0 -5
  157. package/dist/superdoc/src/main.d.ts +0 -1
  158. package/dist/word-layout/src/tab-layout.d.ts +0 -193
package/dist/superdoc.cjs CHANGED
@@ -1,21 +1,21 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./chunks/rolldown-runtime-74VwNCz7.cjs");
3
+ const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-BzM2_tVU.cjs");
3
4
  const require_blank_docx = require("./chunks/blank-docx-BuFAbRjs.cjs");
4
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-DN70aatf.cjs");
5
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui--kQBNTyt.cjs");
5
6
  const require_eventemitter3 = require("./chunks/eventemitter3-C_TAnXOl.cjs");
6
7
  const require_uuid = require("./chunks/uuid-BhG0ngwk.cjs");
7
- const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-6MBoygIY.cjs");
8
8
  const require_jszip = require("./chunks/jszip-D8mAFF-r.cjs");
9
9
  const require_is_finite_number = require("./chunks/is-finite-number-BEXgTRgc.cjs");
10
10
  const require_constants = require("./chunks/constants-BeeNZoQp.cjs");
11
11
  let superdoc_entry_vue = require("vue");
12
12
  superdoc_entry_vue = require_rolldown_runtime.__toESM(superdoc_entry_vue, 1);
13
13
  let yjs = require("yjs");
14
- //#region src/core/v2-integration/browser-peer-runtime.js
14
+ //#region src/core/v2-integration/browser-peer-runtime.ts
15
15
  var SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY = "__SUPERDOC_V2_BROWSER_RUNTIME__";
16
16
  function readInstalledRuntime(globalObject = globalThis) {
17
- const installed = globalObject[SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY];
18
- return installed && typeof installed === "object" ? installed : null;
17
+ const installed = Reflect.get(globalObject, SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY);
18
+ return require__plugin_vue_export_helper.isPlainObject(installed) ? installed : null;
19
19
  }
20
20
  function installSuperDocV2BrowserRuntime(runtime = {}, globalObject = globalThis) {
21
21
  const installed = readInstalledRuntime(globalObject) ?? {};
@@ -24,7 +24,7 @@ function installSuperDocV2BrowserRuntime(runtime = {}, globalObject = globalThis
24
24
  ...runtime,
25
25
  vue: runtime.vue ?? installed.vue ?? superdoc_entry_vue
26
26
  };
27
- globalObject[SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY] = nextRuntime;
27
+ Reflect.set(globalObject, SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY, nextRuntime);
28
28
  return nextRuntime;
29
29
  }
30
30
  installSuperDocV2BrowserRuntime();
@@ -259,7 +259,7 @@ var v_click_outside_default = {
259
259
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
260
260
  function getSuperdocVersion() {
261
261
  try {
262
- return "2.29.0-next.9";
262
+ return "2.30.0-next.4";
263
263
  } catch {
264
264
  return "unknown";
265
265
  }
@@ -5839,22 +5839,27 @@ function useCheckboxField(field) {
5839
5839
  }) : itemoptions) };
5840
5840
  }
5841
5841
  //#endregion
5842
+ //#region src/core/collaboration/collaboration-comment-map.ts
5843
+ function createCollaborationCommentMap(entries) {
5844
+ return new yjs.Map(entries);
5845
+ }
5846
+ //#endregion
5842
5847
  //#region src/core/collaboration/collaboration-comments.ts
5843
5848
  var readComment = (event) => {
5844
5849
  const { comment } = event;
5845
- if (!require_create_super_doc_ui.isPlainObject(comment)) throw new TypeError("Collaboration comment events require a comment object");
5850
+ if (!require__plugin_vue_export_helper.isPlainObject(comment)) throw new TypeError("Collaboration comment events require a comment object");
5846
5851
  return comment;
5847
5852
  };
5848
5853
  var addYComment = (yArray, ydoc, event, user) => {
5849
5854
  const comment = readComment(event);
5850
- const yComment = new yjs.Map(Object.entries(comment));
5855
+ const yComment = createCollaborationCommentMap(Object.entries(comment));
5851
5856
  ydoc.transact(() => {
5852
5857
  yArray.push([yComment]);
5853
5858
  }, { user });
5854
5859
  };
5855
5860
  var updateYComment = (yArray, ydoc, event, user) => {
5856
5861
  const comment = readComment(event);
5857
- const yComment = new yjs.Map(Object.entries(comment));
5862
+ const yComment = createCollaborationCommentMap(Object.entries(comment));
5858
5863
  const commentIndex = getCommentIndex(yArray, comment);
5859
5864
  if (commentIndex === -1) return;
5860
5865
  ydoc.transact(() => {
@@ -5870,12 +5875,12 @@ var deleteYComment = (yArray, ydoc, event, user) => {
5870
5875
  }, { user });
5871
5876
  };
5872
5877
  var getCommentIndex = (yArray, comment) => {
5873
- return yArray.toJSON().findIndex((c) => require_create_super_doc_ui.isPlainObject(c) && c.commentId === comment.commentId);
5878
+ return yArray.toJSON().findIndex((c) => require__plugin_vue_export_helper.isPlainObject(c) && c.commentId === comment.commentId);
5874
5879
  };
5875
5880
  //#endregion
5876
5881
  //#region src/core/collaboration/helpers.ts
5877
5882
  var isPropertyBag = (value) => typeof value === "object" && value !== null || typeof value === "function";
5878
- var readCommentsStore = (superdoc) => superdoc["commentsStore"];
5883
+ var readCommentsStore$1 = (superdoc) => superdoc["commentsStore"];
5879
5884
  var isV2ReviewRuntimeActive = (superdoc) => superdoc.activeEditor?.editorVersion === 2 || superdoc.editorVersion === 2;
5880
5885
  var commentKey = (comment) => {
5881
5886
  const key = comment.commentId ?? comment.importedId;
@@ -5894,7 +5899,7 @@ var preserveLocalV2TrackedChangeRows = (superdoc, commentsStore, incomingComment
5894
5899
  };
5895
5900
  var loadCommentsFromYdoc = (superdoc) => {
5896
5901
  if (!superdoc?.ydoc) return false;
5897
- const commentsStore = readCommentsStore(superdoc);
5902
+ const commentsStore = readCommentsStore$1(superdoc);
5898
5903
  if (!commentsStore) return false;
5899
5904
  const comments = superdoc.ydoc.getArray("comments").toJSON();
5900
5905
  const seenCommentIdByKey = /* @__PURE__ */ new Map();
@@ -5940,7 +5945,7 @@ var initCollaborationComments = (superdoc) => {
5940
5945
  const updateCommentsStore = () => loadCommentsFromYdoc(superdoc);
5941
5946
  const onSuperDocYdocSynced = () => {
5942
5947
  if (!updateCommentsStore()) setTimeout(updateCommentsStore, 0);
5943
- const commentsStore = readCommentsStore(superdoc);
5948
+ const commentsStore = readCommentsStore$1(superdoc);
5944
5949
  if (commentsStore) commentsStore.hasSyncedCollaborationComments = true;
5945
5950
  const currentProvider = superdoc.provider;
5946
5951
  if (!currentProvider) throw new TypeError("initCollaborationComments requires superdoc.provider");
@@ -5952,7 +5957,7 @@ var initCollaborationComments = (superdoc) => {
5952
5957
  provider.on("synced", onSuperDocYdocSynced);
5953
5958
  if (!updateCommentsStore()) setTimeout(updateCommentsStore, 0);
5954
5959
  commentsArray.observe((event) => {
5955
- if (!readCommentsStore(superdoc)) return;
5960
+ if (!readCommentsStore$1(superdoc)) return;
5956
5961
  const currentUser = superdoc.config.user;
5957
5962
  const origin = event?.transaction?.origin;
5958
5963
  const originUser = isPropertyBag(origin) ? origin.user : null;
@@ -6751,6 +6756,124 @@ var useSuperdocStore = defineStore("superdoc", () => {
6751
6756
  };
6752
6757
  });
6753
6758
  //#endregion
6759
+ //#region ../document-api/src/errors.ts
6760
+ /**
6761
+ * Structured validation error thrown by document-api execute* functions.
6762
+ *
6763
+ * Consumers should prefer checking `error.code` over `instanceof` for resilience
6764
+ * across package boundaries and bundling scenarios.
6765
+ */
6766
+ var DocumentApiValidationError = class DocumentApiValidationError extends Error {
6767
+ constructor(code, message, details) {
6768
+ super(message);
6769
+ this.name = "DocumentApiValidationError";
6770
+ this.code = code;
6771
+ this.details = details;
6772
+ Object.setPrototypeOf(this, DocumentApiValidationError.prototype);
6773
+ }
6774
+ };
6775
+ //#endregion
6776
+ //#region ../document-api/src/export/export.types.ts
6777
+ /** Canonical tracked-change export modes accepted by every public export surface. */
6778
+ var SD_EXPORT_MODES = [
6779
+ "review-preserving",
6780
+ "final",
6781
+ "original"
6782
+ ];
6783
+ /** Default mode for modeful DOCX export. */
6784
+ var DEFAULT_SD_EXPORT_MODE = "review-preserving";
6785
+ var SD_COMMENT_EXPORT_POLICIES = [
6786
+ "preserve",
6787
+ "resolve",
6788
+ "remove"
6789
+ ];
6790
+ var SD_CONTENT_CONTROL_EXPORT_POLICIES = ["preserve", "flatten"];
6791
+ //#endregion
6792
+ //#region ../document-api/src/export/export.ts
6793
+ /**
6794
+ * Export namespace: engine-agnostic public API and adapter contract.
6795
+ *
6796
+ * Validates the requested mode at the public boundary so an invalid mode fails
6797
+ * closed with `INVALID_INPUT` before any document work happens, then delegates
6798
+ * byte production and degradation reporting to the engine adapter.
6799
+ */
6800
+ function resolveMode$1(input) {
6801
+ if (input != null && !require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "export.toDocx input must be an object.");
6802
+ const raw = input?.mode;
6803
+ if (raw === void 0) return DEFAULT_SD_EXPORT_MODE;
6804
+ if (typeof raw !== "string" || !SD_EXPORT_MODES.includes(raw)) throw new DocumentApiValidationError("INVALID_INPUT", `export.toDocx mode must be one of: ${SD_EXPORT_MODES.join(", ")}.`, {
6805
+ mode: raw,
6806
+ allowedModes: [...SD_EXPORT_MODES]
6807
+ });
6808
+ return raw;
6809
+ }
6810
+ function resolveDocxExportPolicies(input = {}) {
6811
+ if (!require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export input must be an object.");
6812
+ const mode = resolveMode$1(input);
6813
+ const policies = input.policies;
6814
+ if (policies !== void 0 && !require_create_super_doc_ui.isRecord(policies)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export policies must be an object.");
6815
+ const allowed = {
6816
+ trackedChanges: SD_EXPORT_MODES,
6817
+ comments: SD_COMMENT_EXPORT_POLICIES,
6818
+ contentControls: SD_CONTENT_CONTROL_EXPORT_POLICIES
6819
+ };
6820
+ for (const [key, value] of Object.entries(policies ?? {})) if (!Object.prototype.hasOwnProperty.call(allowed, key) || value !== void 0 && !allowed[key].includes(value)) throw new DocumentApiValidationError("INVALID_INPUT", `Unsupported DOCX export policy: ${key}.`, {
6821
+ policy: key,
6822
+ value
6823
+ });
6824
+ const requested = policies;
6825
+ if (input.mode !== void 0 && requested?.trackedChanges !== void 0 && mode !== requested.trackedChanges) throw new DocumentApiValidationError("INVALID_INPUT", "mode conflicts with policies.trackedChanges.");
6826
+ return {
6827
+ trackedChanges: requested?.trackedChanges ?? mode,
6828
+ comments: requested?.comments ?? "preserve",
6829
+ contentControls: requested?.contentControls ?? "preserve"
6830
+ };
6831
+ }
6832
+ //#endregion
6833
+ //#region ../document-api/src/permission-ranges/permission-ranges.ts
6834
+ function editorKey(editor) {
6835
+ return editor.id?.trim() ? editor.id : editor.email?.trim() || void 0;
6836
+ }
6837
+ function editorMatches(editor, id) {
6838
+ return Boolean(id.trim()) && (editor.id === id || Boolean(editor.email?.trim() && editor.email.trim().toLowerCase() === id.toLowerCase()));
6839
+ }
6840
+ /**
6841
+ * Resolve a host ID or imported Word email against an explicitly supplied roster.
6842
+ * Word receives the email when available; opaque IDs remain host-specific.
6843
+ * Duplicate IDs/emails are ambiguous. This does not authenticate a user.
6844
+ */
6845
+ function resolvePermissionRangeEditor(editors, id) {
6846
+ const matches = editors.filter((editor) => editorMatches(editor, id));
6847
+ if (matches.length === 0) return {
6848
+ status: "unknown",
6849
+ id
6850
+ };
6851
+ if (matches.length !== 1) return {
6852
+ status: "ambiguous",
6853
+ id
6854
+ };
6855
+ const editor = matches[0];
6856
+ const wordId = editor.email?.trim() || editor.id;
6857
+ if (editors.filter((candidate) => editorMatches(candidate, wordId)).length !== 1) return {
6858
+ status: "ambiguous",
6859
+ id
6860
+ };
6861
+ return {
6862
+ status: "resolved",
6863
+ id,
6864
+ editor: { ...editor },
6865
+ principal: {
6866
+ kind: "editor",
6867
+ id: wordId
6868
+ }
6869
+ };
6870
+ }
6871
+ /** Enumerate the host roster for an editor picker, including ambiguous entries. */
6872
+ function listPermissionRangeEditors(editors) {
6873
+ const ids = new Set(editors.map(editorKey).filter((id) => id !== void 0));
6874
+ return Array.from(ids, (id) => resolvePermissionRangeEditor(editors, id));
6875
+ }
6876
+ //#endregion
6754
6877
  //#region src/stores/helpers/floating-comment-instances.ts
6755
6878
  var HEADER_FOOTER_TRACKED_CHANGE_STORY_TYPE = "headerFooterPart";
6756
6879
  var toFinitePageIndex = (value) => {
@@ -6810,7 +6933,7 @@ var groupRectsByPage = (rects) => {
6810
6933
  }));
6811
6934
  };
6812
6935
  var readStoryType = (story) => {
6813
- return require_create_super_doc_ui.isPlainObject(story) ? story.storyType : void 0;
6936
+ return require__plugin_vue_export_helper.isPlainObject(story) ? story.storyType : void 0;
6814
6937
  };
6815
6938
  var isRepeatedHeaderFooterTrackedChange = (comment, positionEntry) => {
6816
6939
  if (!comment?.trackedChange) return false;
@@ -6891,23 +7014,76 @@ var buildFloatingCommentInstances = ({ comment, positionKey, positionEntry, fall
6891
7014
  })];
6892
7015
  };
6893
7016
  //#endregion
6894
- //#region src/components/CommentsLayer/tracked-change-threading.js
7017
+ //#region src/stores/helpers/comment-document-scope.ts
7018
+ var getCommentDocumentId = (comment) => {
7019
+ if (!comment) return null;
7020
+ if (comment.fileId != null) return String(comment.fileId);
7021
+ if (comment.documentId != null) return String(comment.documentId);
7022
+ if (comment.selection?.documentId != null) return String(comment.selection.documentId);
7023
+ return null;
7024
+ };
7025
+ var createCommentDocumentScope = (readOpenDocuments) => {
7026
+ const getOpenDocuments = () => {
7027
+ const source = readOpenDocuments();
7028
+ const docs = Array.isArray(source) ? source : source?.value;
7029
+ return Array.isArray(docs) ? docs : [];
7030
+ };
7031
+ const getSingleOpenDocumentId = () => {
7032
+ const docs = getOpenDocuments();
7033
+ if (docs.length !== 1) return null;
7034
+ return docs[0]?.id != null ? String(docs[0].id) : null;
7035
+ };
7036
+ const belongsToDocument = (comment, activeDocumentId, options = {}) => {
7037
+ const { allowSingleDocumentMismatch = false } = options;
7038
+ if (!activeDocumentId) return false;
7039
+ const commentDocumentId = getCommentDocumentId(comment);
7040
+ if (commentDocumentId) {
7041
+ if (commentDocumentId === activeDocumentId) return true;
7042
+ const singleOpenDocumentId = getSingleOpenDocumentId();
7043
+ return allowSingleDocumentMismatch && singleOpenDocumentId === activeDocumentId;
7044
+ }
7045
+ return getSingleOpenDocumentId() === activeDocumentId;
7046
+ };
7047
+ const belongsToTrackedChangeSyncDocument = (comment, activeDocumentId) => belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true });
7048
+ return {
7049
+ belongsToDocument,
7050
+ belongsToTrackedChangeSyncDocument
7051
+ };
7052
+ };
7053
+ //#endregion
7054
+ //#region src/stores/helpers/pending-selection-snapshot.ts
7055
+ var isThenable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
7056
+ var getPendingSelectionSnapshot = (superdoc, activeSelection) => {
7057
+ if (activeSelection?.source !== "document-editor") return null;
7058
+ const selectionDocumentId = activeSelection?.documentId ?? null;
7059
+ const editorDocumentId = superdoc?.activeEditor?.options?.documentId ?? null;
7060
+ if (!selectionDocumentId || !editorDocumentId || selectionDocumentId !== editorDocumentId) return null;
7061
+ let currentSelection;
7062
+ try {
7063
+ currentSelection = superdoc?.activeEditor?.doc?.selection?.current;
7064
+ } catch {
7065
+ return null;
7066
+ }
7067
+ if (typeof currentSelection !== "function") return null;
7068
+ try {
7069
+ const snapshot = currentSelection();
7070
+ return isThenable(snapshot) ? Promise.resolve(snapshot).catch(() => null) : snapshot;
7071
+ } catch {
7072
+ return null;
7073
+ }
7074
+ };
7075
+ //#endregion
7076
+ //#region src/components/CommentsLayer/tracked-change-threading.ts
6895
7077
  /**
6896
7078
  * Legacy comment payloads predate explicit tracked-change thread provenance.
6897
7079
  * These fields distinguish a true legacy review child from a v2 comment whose
6898
7080
  * anchor merely overlaps tracked content.
6899
- *
6900
- * @param {Record<string, any> | null | undefined} comment
6901
- * @returns {boolean}
6902
7081
  */
6903
7082
  var hasLegacyTrackedChangeThreadSignal = (comment) => Boolean(comment?.trackedChangeLink) || Boolean(comment?.trackedChangeType) || Boolean(comment?.trackedChangeDisplayType) || Boolean(comment?.trackedChangeText) || Boolean(comment?.deletedText) || comment?.trackedChange === true;
6904
7083
  /**
6905
7084
  * Resolve explicit thread provenance first, then the guarded legacy fallback.
6906
7085
  * Spatial-only v2 comments carry neither the explicit field nor a legacy
6907
7086
  * review signal and therefore remain standalone.
6908
- *
6909
- * @param {Record<string, any> | null | undefined} comment
6910
- * @returns {string | number | null}
6911
7087
  */
6912
7088
  var trackedChangeThreadParentIdForComment$1 = (comment) => {
6913
7089
  if (comment?.trackedChangeThreadParentId != null) return comment.trackedChangeThreadParentId;
@@ -7059,6 +7235,7 @@ var groupCommittedComments = (comments, presentations, isVisible) => {
7059
7235
  });
7060
7236
  const grouped = groupComments(comments.filter((row) => !presentations[String(row.fileId)]), isVisible);
7061
7237
  for (const [documentId, presentation] of Object.entries(presentations)) {
7238
+ if (!presentation) continue;
7062
7239
  grouped.parentComments.push(...visibleRowsInOrder(documentId, presentation.groupOrder.open));
7063
7240
  grouped.resolvedComments.push(...visibleRowsInOrder(documentId, presentation.groupOrder.resolved));
7064
7241
  }
@@ -7096,7 +7273,7 @@ async function loadDefaultV2IntegrationOrFallback() {
7096
7273
  }
7097
7274
  var V2_BODY_TRACKED_CHANGE_ANCHOR_PREFIX = "tc::body::";
7098
7275
  function isV2SyntheticTrackedChangeRow(row) {
7099
- if (!require_create_super_doc_ui.isPlainObject(row) || row.trackedChange !== true) return false;
7276
+ if (!require__plugin_vue_export_helper.isPlainObject(row) || row.trackedChange !== true) return false;
7100
7277
  const anchorKey = row.trackedChangeAnchorKey;
7101
7278
  return typeof anchorKey === "string" && anchorKey.startsWith(V2_BODY_TRACKED_CHANGE_ANCHOR_PREFIX);
7102
7279
  }
@@ -7160,7 +7337,7 @@ function createStubV2Integration() {
7160
7337
  }
7161
7338
  function adoptEngineIntegration(engineIntegration) {
7162
7339
  const stub = createStubV2Integration();
7163
- if (!require_create_super_doc_ui.isPlainObject(engineIntegration) || !engineIntegration.EditorComponent) return stub;
7340
+ if (!require__plugin_vue_export_helper.isPlainObject(engineIntegration) || !engineIntegration.EditorComponent) return stub;
7164
7341
  const engine = engineIntegration;
7165
7342
  return {
7166
7343
  version: typeof engine.version === "number" ? engine.version : stub.version,
@@ -7186,7 +7363,6 @@ function createDefaultV2Integration() {
7186
7363
  //#region src/helpers/interaction-trace.ts
7187
7364
  var isStartSpan = (value) => typeof value === "function";
7188
7365
  var isEndSpan = (value) => typeof value === "function";
7189
- var isThenable$3 = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
7190
7366
  function safeTraceCollector() {
7191
7367
  try {
7192
7368
  const collector = Reflect.get(globalThis, "__superdocInteractionTrace");
@@ -7217,7 +7393,7 @@ function withInteractionSpan(stage, branch, meta, fn) {
7217
7393
  if (!span) return fn();
7218
7394
  try {
7219
7395
  const result = fn();
7220
- if (isThenable$3(result)) return result.then((value) => {
7396
+ if (require__plugin_vue_export_helper.isThenable(result)) return result.then((value) => {
7221
7397
  endInteractionSpan(span);
7222
7398
  return value;
7223
7399
  }, (error) => {
@@ -7232,6 +7408,81 @@ function withInteractionSpan(stage, branch, meta, fn) {
7232
7408
  }
7233
7409
  }
7234
7410
  //#endregion
7411
+ //#region src/stores/helpers/tracked-change-decision.ts
7412
+ var normalizeTrackedChangeDecisionType = (value) => {
7413
+ const lower = typeof value === "string" ? value.toLowerCase() : "";
7414
+ if (!lower) return null;
7415
+ if (lower === "insert" || lower === "insertion" || lower === "trackinsert" || lower === "tableinsert" || lower === "paragraphsplit") return "insertion";
7416
+ if (lower === "delete" || lower === "deletion" || lower === "trackdelete" || lower === "tabledelete") return "deletion";
7417
+ return lower;
7418
+ };
7419
+ var trackedChangeDecisionKeepsCommentAnchor = ({ comment, decision } = {}) => {
7420
+ const normalizedDecision = decision === "accept" || decision === "reject" ? decision : null;
7421
+ if (!normalizedDecision) return false;
7422
+ const type = normalizeTrackedChangeDecisionType(comment?.trackedChangeDisplayType) ?? normalizeTrackedChangeDecisionType(comment?.trackedChangeType);
7423
+ return normalizedDecision === "accept" && type === "insertion" || normalizedDecision === "reject" && type === "deletion";
7424
+ };
7425
+ var collectTrackedChangeDecisionIdsWithAliases = (comment, aliasIds) => {
7426
+ const trackedChangeIds = new Set(aliasIds);
7427
+ if (comment?.trackedChangeCanonicalId != null) trackedChangeIds.add(String(comment.trackedChangeCanonicalId));
7428
+ const anchorKey = comment?.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
7429
+ if (anchorKey) {
7430
+ trackedChangeIds.add(anchorKey);
7431
+ if (anchorKey.startsWith("tc::")) {
7432
+ const rawId = anchorKey.slice(anchorKey.lastIndexOf("::") + 2);
7433
+ if (rawId) trackedChangeIds.add(rawId);
7434
+ }
7435
+ }
7436
+ return trackedChangeIds;
7437
+ };
7438
+ var collectTrackedChangeEntityIdsFromReceipt = (receipt) => {
7439
+ const record = receipt && typeof receipt === "object" ? receipt : null;
7440
+ if (!record?.success) return /* @__PURE__ */ new Set();
7441
+ const ids = /* @__PURE__ */ new Set();
7442
+ const collect = (entry) => {
7443
+ const ref = entry && typeof entry === "object" ? entry : null;
7444
+ if (ref?.kind !== "entity" || ref.entityType !== "trackedChange") return;
7445
+ if (ref.entityId != null && String(ref.entityId).length > 0) ids.add(String(ref.entityId));
7446
+ };
7447
+ if (Array.isArray(record.removed)) record.removed.forEach(collect);
7448
+ if (Array.isArray(record.invalidatedRefs)) record.invalidatedRefs.forEach(collect);
7449
+ return ids;
7450
+ };
7451
+ var collectReliableDecidedTrackedChangeIds = (outcome) => {
7452
+ const ids = /* @__PURE__ */ new Set();
7453
+ if (outcome?.decidedId != null && String(outcome.decidedId).length > 0) ids.add(String(outcome.decidedId));
7454
+ if (Array.isArray(outcome?.decidedIds)) outcome.decidedIds.forEach((id) => {
7455
+ if (id != null && String(id).length > 0) ids.add(String(id));
7456
+ });
7457
+ collectTrackedChangeEntityIdsFromReceipt(outcome?.receipt).forEach((id) => ids.add(id));
7458
+ return ids;
7459
+ };
7460
+ var clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
7461
+ if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
7462
+ try {
7463
+ adapter.clearActiveTrackedChangeTargetIfMatches(decidedId);
7464
+ } catch {}
7465
+ };
7466
+ var waitForTrackedDecisionCanonicalPaint = async ({ superdoc, receipt } = {}) => {
7467
+ const readiness = superdoc?.activeEditor?.documentMutationReadiness;
7468
+ if (receipt?.success !== true || typeof receipt?.txId !== "string" || !receipt.txId || typeof readiness?.whenPainted !== "function") return;
7469
+ try {
7470
+ await readiness.whenPainted(receipt);
7471
+ const requestFrame = globalThis.requestAnimationFrame;
7472
+ if (typeof requestFrame === "function") await new Promise((resolve) => {
7473
+ let settled = false;
7474
+ const finish = () => {
7475
+ if (settled) return;
7476
+ settled = true;
7477
+ clearTimeout(fallback);
7478
+ resolve();
7479
+ };
7480
+ const fallback = setTimeout(finish, 250);
7481
+ requestFrame(() => requestFrame(() => setTimeout(finish, 0)));
7482
+ });
7483
+ } catch {}
7484
+ };
7485
+ //#endregion
7235
7486
  //#region src/stores/helpers/comment-draft-text.ts
7236
7487
  var COMMENT_DRAFT_BR_TAG = /<br(?:\s[^>]*)?\s*\/?>/gi;
7237
7488
  var COMMENT_DRAFT_BLOCK_BOUNDARY = /(?:<\/(?:p|div|li|blockquote|pre|h[1-6])\s*>\s*)+(?:<(?:p|div|li|blockquote|pre|h[1-6])(?:\s[^>]*)?\s*\/?>)+/gi;
@@ -7276,12 +7527,12 @@ var BODY_TRACKED_CHANGE_STORY = {
7276
7527
  };
7277
7528
  var normalizeCommentId = (id) => id === void 0 || id === null ? null : String(id);
7278
7529
  var isNonEmptyString$2 = (value) => Boolean(value);
7279
- var trackedChangeFields = (comment) => require_create_super_doc_ui.isPlainObject(comment) && comment.trackedChange ? comment : null;
7530
+ var trackedChangeFields = (comment) => require__plugin_vue_export_helper.isPlainObject(comment) && comment.trackedChange ? comment : null;
7280
7531
  var makeTrackedChangeAnchorKey = ({ storyKey, rawId }) => `tc::${storyKey}::${rawId}`;
7281
7532
  var isBodyTrackedChangeComment = (comment) => {
7282
7533
  const fields = trackedChangeFields(comment);
7283
7534
  if (!fields) return false;
7284
- const storyType = require_create_super_doc_ui.isPlainObject(fields.trackedChangeStory) ? fields.trackedChangeStory.storyType : void 0;
7535
+ const storyType = require__plugin_vue_export_helper.isPlainObject(fields.trackedChangeStory) ? fields.trackedChangeStory.storyType : void 0;
7285
7536
  if (storyType == null || storyType === "body") return true;
7286
7537
  const anchorKey = fields.trackedChangeAnchorKey;
7287
7538
  return typeof anchorKey === "string" && anchorKey.startsWith("tc::body::");
@@ -7324,7 +7575,7 @@ var getTrackedChangeStoryKey = (comment) => {
7324
7575
  const anchorParts = parseTrackedChangeAnchorKey(fields.trackedChangeAnchorKey);
7325
7576
  if (anchorParts) return anchorParts.storyKey;
7326
7577
  const story = fields.trackedChangeStory;
7327
- if (!require_create_super_doc_ui.isPlainObject(story)) return null;
7578
+ if (!require__plugin_vue_export_helper.isPlainObject(story)) return null;
7328
7579
  switch (story.storyType) {
7329
7580
  case "body": return "body";
7330
7581
  case "headerFooterPart": return storyIdKey("hf", story.refId);
@@ -7345,7 +7596,7 @@ var trackedChangeStoryKeysAreCompatible = (leftStoryKey, rightStoryKey) => {
7345
7596
  return !left || !right || left === right;
7346
7597
  };
7347
7598
  var positionEntryMatchesTrackedChangeStory = (entry, comment) => {
7348
- return trackedChangeStoryKeysAreCompatible(normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(comment)), normalizeTrackedChangeStoryKey(normalizeCommentId(require_create_super_doc_ui.isPlainObject(entry) ? entry.storyKey : null)));
7599
+ return trackedChangeStoryKeysAreCompatible(normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(comment)), normalizeTrackedChangeStoryKey(normalizeCommentId(require__plugin_vue_export_helper.isPlainObject(entry) ? entry.storyKey : null)));
7349
7600
  };
7350
7601
  var buildTrackedChangeImportedPositionId = (id) => {
7351
7602
  const normalizedId = normalizeCommentId(id);
@@ -7542,7 +7793,7 @@ var createCommentIdentity = ({ getComments, getReviewDirectory, getPositions })
7542
7793
  };
7543
7794
  //#endregion
7544
7795
  //#region src/stores/helpers/tracked-change-row-values.ts
7545
- var isObjectOrArray = (value) => require_create_super_doc_ui.isPlainObject(value) || Array.isArray(value);
7796
+ var isObjectOrArray = (value) => require__plugin_vue_export_helper.isPlainObject(value) || Array.isArray(value);
7546
7797
  var stringOrEmpty = (value) => typeof value === "string" ? value : "";
7547
7798
  var shallowEqual = (a, b) => {
7548
7799
  if (Object.is(a, b)) return true;
@@ -7604,9 +7855,131 @@ var cloneV2TrackedChangeStory = (story) => {
7604
7855
  };
7605
7856
  };
7606
7857
  //#endregion
7607
- //#region src/stores/comments-store.js
7858
+ //#region src/stores/helpers/tracked-change-compaction.ts
7859
+ var isPresentId = (id) => Boolean(id);
7860
+ var getBodyTrackedChangeIdentityIds = (comment) => {
7861
+ return [normalizeCommentId(comment.commentId), ...!normalizeCommentId(comment.trackedChangeCanonicalId) ? [
7862
+ comment.importedId,
7863
+ comment.trackedChangeAnchorKey,
7864
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
7865
+ ] : []].map((id) => normalizeCommentId(id)).filter(isPresentId);
7866
+ };
7867
+ var groupBodyTrackedChangeCommentsByIdentity = (comments) => {
7868
+ const parents = comments.map((_, index) => index);
7869
+ const findRoot = (index) => {
7870
+ let root = index;
7871
+ while (parents[root] !== root) root = parents[root];
7872
+ while (parents[index] !== index) {
7873
+ const next = parents[index];
7874
+ parents[index] = root;
7875
+ index = next;
7876
+ }
7877
+ return root;
7878
+ };
7879
+ const join = (left, right) => {
7880
+ const leftRoot = findRoot(left);
7881
+ const rightRoot = findRoot(right);
7882
+ if (leftRoot === rightRoot) return;
7883
+ parents[Math.max(leftRoot, rightRoot)] = Math.min(leftRoot, rightRoot);
7884
+ };
7885
+ const identityOwner = /* @__PURE__ */ new Map();
7886
+ comments.forEach((comment, index) => {
7887
+ getBodyTrackedChangeIdentityIds(comment).forEach((identityId) => {
7888
+ const owner = identityOwner.get(identityId);
7889
+ if (owner === void 0) identityOwner.set(identityId, index);
7890
+ else join(index, owner);
7891
+ });
7892
+ });
7893
+ const groups = /* @__PURE__ */ new Map();
7894
+ comments.forEach((comment, index) => {
7895
+ const root = findRoot(index);
7896
+ const group = groups.get(root) ?? [];
7897
+ group.push(comment);
7898
+ groups.set(root, group);
7899
+ });
7900
+ return groups;
7901
+ };
7902
+ var mergeDuplicateBodyTrackedChangeComments = (groups) => {
7903
+ const duplicates = /* @__PURE__ */ new Map();
7904
+ groups.forEach(([survivor, ...duplicateRows]) => {
7905
+ if (!survivor || duplicateRows.length === 0) return;
7906
+ const resolvedDuplicate = duplicateRows.find((comment) => comment.resolvedTime != null);
7907
+ if (survivor.resolvedTime == null && resolvedDuplicate) {
7908
+ survivor.resolvedTime = resolvedDuplicate.resolvedTime;
7909
+ survivor.resolvedById = resolvedDuplicate.resolvedById;
7910
+ survivor.resolvedByEmail = resolvedDuplicate.resolvedByEmail;
7911
+ survivor.resolvedByName = resolvedDuplicate.resolvedByName;
7912
+ survivor.trackedChangeDecision = resolvedDuplicate.trackedChangeDecision;
7913
+ }
7914
+ survivor.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...normalizeTrackedChangePositionAliases(survivor.trackedChangePositionAliases), ...duplicateRows.flatMap((comment) => [
7915
+ comment.commentId,
7916
+ comment.importedId,
7917
+ comment.trackedChangeCanonicalId,
7918
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
7919
+ ])]);
7920
+ duplicateRows.forEach((comment) => duplicates.set(comment, survivor));
7921
+ });
7922
+ return duplicates;
7923
+ };
7924
+ var createDroppedCommentIdMap = (duplicates) => {
7925
+ const droppedCommentIds = /* @__PURE__ */ new Map();
7926
+ duplicates.forEach((survivor, duplicate) => {
7927
+ const fromId = normalizeCommentId(duplicate.commentId);
7928
+ const toId = normalizeCommentId(survivor.commentId);
7929
+ if (fromId && toId) droppedCommentIds.set(fromId, toId);
7930
+ });
7931
+ return droppedCommentIds;
7932
+ };
7933
+ //#endregion
7934
+ //#region src/stores/helpers/v2-review-adapters.ts
7935
+ var COMMENTS_ADAPTER_METHODS = [
7936
+ "setActiveComment",
7937
+ "commitPendingComment",
7938
+ "reply",
7939
+ "edit",
7940
+ "resolve",
7941
+ "reopen",
7942
+ "delete",
7943
+ "mapV2CommentToUseCommentInput"
7944
+ ];
7945
+ var COMMENTS_ADAPTER_OPTIONAL_METHODS = [
7946
+ "getCapabilityState",
7947
+ "captureCurrentSelection",
7948
+ "isPendingCommentCreation",
7949
+ "seedReviewCatalog",
7950
+ "selectVisibleReviewComments"
7951
+ ];
7952
+ var TRACKED_CHANGES_ADAPTER_METHODS = [
7953
+ "accept",
7954
+ "reject",
7955
+ "mapV2TrackedChangeToCommentParams"
7956
+ ];
7957
+ var TRACKED_CHANGES_ADAPTER_OPTIONAL_METHODS = ["clearActiveTrackedChangeTargetIfMatches"];
7958
+ var isAdapterDocumentId = (value) => value === void 0 || value === null || typeof value === "string" || typeof value === "number";
7959
+ var hasAdapterShape = (value, required, optional) => require__plugin_vue_export_helper.isPlainObject(value) && isAdapterDocumentId(value.documentId) && required.every((member) => typeof value[member] === "function") && optional.every((member) => value[member] === void 0 || typeof value[member] === "function");
7960
+ function isV2CommentsAdapter(value) {
7961
+ return hasAdapterShape(value, COMMENTS_ADAPTER_METHODS, COMMENTS_ADAPTER_OPTIONAL_METHODS);
7962
+ }
7963
+ function isV2TrackedChangesAdapter(value) {
7964
+ return hasAdapterShape(value, TRACKED_CHANGES_ADAPTER_METHODS, TRACKED_CHANGES_ADAPTER_OPTIONAL_METHODS);
7965
+ }
7966
+ //#endregion
7967
+ //#region src/stores/comments-store.ts
7968
+ var requireHost = (superdoc, action) => {
7969
+ if (!superdoc) throw new TypeError(`${action} requires superdoc`);
7970
+ return superdoc;
7971
+ };
7972
+ var PARENT_LINK_FIELDS = [
7973
+ "trackedChangeThreadParentId",
7974
+ "trackedChangeParentId",
7975
+ "threadingParentCommentId",
7976
+ "parentCommentId"
7977
+ ];
7978
+ var isPresent = (value) => Boolean(value);
7979
+ var errorDetail = (error) => (error == null ? void 0 : Reflect.get(Object(error), "message")) ?? String(error);
7608
7980
  var useCommentsStore = defineStore("comments", () => {
7609
7981
  const superdocStore = useSuperdocStore();
7982
+ const findDocument = (documentId) => typeof documentId === "string" ? superdocStore.getDocument(documentId) : void 0;
7610
7983
  const commentsConfig = require__plugin_vue_export_helper.reactive({
7611
7984
  name: "comments",
7612
7985
  readOnly: false,
@@ -7673,7 +8046,7 @@ var useCommentsStore = defineStore("comments", () => {
7673
8046
  });
7674
8047
  const getTrackedChangeThread = (parentComment) => {
7675
8048
  const id = parentComment?.commentId ?? null;
7676
- return (id != null ? trackedChangeThreadIndex.value.get(id) : null) ?? [parentComment].filter(Boolean);
8049
+ return (id != null ? trackedChangeThreadIndex.value.get(id) : null) ?? (parentComment ? [parentComment] : []);
7677
8050
  };
7678
8051
  let priorTrackedChangeDecisionLinkIndex = /* @__PURE__ */ new Map();
7679
8052
  const trackedChangeDecisionLinkIndex = require__plugin_vue_export_helper.computed(() => {
@@ -7705,29 +8078,27 @@ var useCommentsStore = defineStore("comments", () => {
7705
8078
  });
7706
8079
  const v2CommentsAdapter = require__plugin_vue_export_helper.shallowRef(null);
7707
8080
  const setV2CommentsAdapter = (adapter) => {
7708
- if (v2CommentsAdapter.value !== (adapter ?? null)) pendingCommentRequest += 1;
7709
- v2CommentsAdapter.value = adapter ?? null;
8081
+ const next = isV2CommentsAdapter(adapter) ? adapter : null;
8082
+ if (v2CommentsAdapter.value !== next) pendingCommentRequest += 1;
8083
+ v2CommentsAdapter.value = next;
7710
8084
  };
7711
8085
  const getV2CommentsAdapter = (superdoc) => {
7712
- const fromFacade = superdoc?.activeEditor?.v2Comments ?? null;
7713
- if (fromFacade) return fromFacade;
8086
+ const fromFacade = superdoc?.activeEditor?.v2Comments;
8087
+ if (isV2CommentsAdapter(fromFacade)) return fromFacade;
7714
8088
  return v2CommentsAdapter.value;
7715
8089
  };
7716
8090
  const isV2EditorActive = (superdoc) => superdoc?.activeEditor?.editorVersion === 2 || v2CommentsAdapter.value !== null;
7717
8091
  const v2TrackedChangesAdapter = require__plugin_vue_export_helper.shallowRef(null);
7718
8092
  const setV2TrackedChangesAdapter = (adapter) => {
7719
- v2TrackedChangesAdapter.value = adapter ?? null;
8093
+ v2TrackedChangesAdapter.value = isV2TrackedChangesAdapter(adapter) ? adapter : null;
7720
8094
  };
7721
8095
  const getV2TrackedChangesAdapter = (superdoc) => {
7722
- const fromFacade = superdoc?.activeEditor?.v2TrackedChanges ?? null;
7723
- if (fromFacade) return fromFacade;
8096
+ const fromFacade = superdoc?.activeEditor?.v2TrackedChanges;
8097
+ if (isV2TrackedChangesAdapter(fromFacade)) return fromFacade;
7724
8098
  return v2TrackedChangesAdapter.value;
7725
8099
  };
7726
8100
  /**
7727
8101
  * Initialize the store
7728
- *
7729
- * @param {Object} config The comments module config from SuperDoc
7730
- * @returns {void}
7731
8102
  */
7732
8103
  const init = (config = {}) => {
7733
8104
  const updatedConfig = {
@@ -7759,12 +8130,17 @@ var useCommentsStore = defineStore("comments", () => {
7759
8130
  comment.trackedChangeDecision = null;
7760
8131
  };
7761
8132
  const getCommentEventPayload = (comment) => typeof comment?.getValues === "function" ? comment.getValues() : { ...comment };
8133
+ const getDeletedCommentChanges = (sources, fileId) => {
8134
+ const commentId = [...sources.map((source) => source?.commentId), ...sources.map((source) => source?.importedId)].map(normalizeCommentId).find(Boolean);
8135
+ return commentId ? [{
8136
+ key: "deleted",
8137
+ commentId,
8138
+ fileId
8139
+ }] : [];
8140
+ };
7762
8141
  /**
7763
8142
  * Check if a comment originated from the document editor (or has no explicit source).
7764
8143
  * Comments without a source are assumed to be editor-backed for backward compatibility.
7765
- *
7766
- * @param {Object} comment - The comment to check
7767
- * @returns {boolean} True if the comment is editor-backed
7768
8144
  */
7769
8145
  const isEditorBackedComment = (comment) => {
7770
8146
  const source = comment?.selection?.source;
@@ -7798,9 +8174,6 @@ var useCommentsStore = defineStore("comments", () => {
7798
8174
  }, { deep: false });
7799
8175
  /**
7800
8176
  * Get the editor position data for a comment.
7801
- *
7802
- * @param {Object | string} commentOrId The comment object or comment ID
7803
- * @returns {Object | null} The position data from editorCommentPositions
7804
8177
  */
7805
8178
  const getCommentPosition = (commentOrId) => {
7806
8179
  return resolveCommentPositionEntry(commentOrId).entry ?? null;
@@ -7813,10 +8186,6 @@ var useCommentsStore = defineStore("comments", () => {
7813
8186
  };
7814
8187
  /**
7815
8188
  * Set the active comment or clear all active comments
7816
- *
7817
- * @param {Object | undefined | null} superdoc The SuperDoc instance holding the active editor
7818
- * @param {string | undefined | null} id The comment ID
7819
- * @returns {void}
7820
8189
  */
7821
8190
  const setActiveComment = (superdoc, id) => {
7822
8191
  const activeEditor = superdoc?.activeEditor;
@@ -7827,7 +8196,7 @@ var useCommentsStore = defineStore("comments", () => {
7827
8196
  v2Adapter.setActiveComment(null);
7828
8197
  return;
7829
8198
  }
7830
- activeEditor?.commands?.setActiveComment({ commentId: null });
8199
+ activeEditor?.commands?.setActiveComment?.({ commentId: null });
7831
8200
  return;
7832
8201
  }
7833
8202
  const comment = getComment(id);
@@ -7838,16 +8207,11 @@ var useCommentsStore = defineStore("comments", () => {
7838
8207
  v2Adapter.setActiveComment(comment.commentId);
7839
8208
  return;
7840
8209
  }
7841
- activeEditor?.commands?.setActiveComment({ commentId: activeComment.value });
8210
+ activeEditor?.commands?.setActiveComment?.({ commentId: activeComment.value });
7842
8211
  };
7843
8212
  /**
7844
8213
  * Called when a tracked change is updated. Creates a new comment if necessary,
7845
8214
  * or updates an existing tracked-change comment.
7846
- *
7847
- * @param {Object} param0
7848
- * @param {Object} param0.superdoc The SuperDoc instance
7849
- * @param {Object} param0.params The tracked change params
7850
- * @returns {void}
7851
8215
  */
7852
8216
  const handleTrackedChangeUpdate = ({ superdoc, params, broadcastChanges = true, trackedChangeIdentityIndex = null }) => {
7853
8217
  const span = startInteractionSpan("store.trackedChanges.handleUpdate", "store-reconciliation", {
@@ -7876,7 +8240,7 @@ var useCommentsStore = defineStore("comments", () => {
7876
8240
  const normalizedTrackedChangeImagePreview = normalizeTrackedChangeImagePreview(trackedChangeImagePreview);
7877
8241
  const comment = getPendingComment({
7878
8242
  documentId,
7879
- commentId: changeId,
8243
+ commentId: normalizedChangeId ?? void 0,
7880
8244
  trackedChange: true,
7881
8245
  trackedChangeText,
7882
8246
  trackedChangeType,
@@ -7928,7 +8292,7 @@ var useCommentsStore = defineStore("comments", () => {
7928
8292
  commentCanonicalId,
7929
8293
  commentAnchorKey,
7930
8294
  ...commentAliasIds
7931
- ].filter(Boolean).some((id) => incomingAliasIds.has(id))) return true;
8295
+ ].some((id) => id != null && incomingAliasIds.has(id))) return true;
7932
8296
  const hasSyntheticSideIdentity = normalizedTrackedChangeCanonicalId && normalizedTrackedChangeCanonicalId !== normalizedChangeId || commentCanonicalId && commentCanonicalId !== commentId;
7933
8297
  if (hasCompatibleStory && commentId === normalizedChangeId) return true;
7934
8298
  if (hasCompatibleStory && !hasSyntheticSideIdentity && (importedId === normalizedChangeId || normalizedImportedId !== void 0 && normalizedImportedId != null && importedId === normalizedImportedId)) return true;
@@ -7952,7 +8316,7 @@ var useCommentsStore = defineStore("comments", () => {
7952
8316
  };
7953
8317
  const emitTrackedChangeEvent = (event) => {
7954
8318
  if (!broadcastChanges) return;
7955
- syncCommentsToClients(superdoc, event);
8319
+ syncCommentsToClients(requireHost(superdoc, "handleTrackedChangeUpdate"), event);
7956
8320
  debounceEmit(changeId, event, superdoc);
7957
8321
  };
7958
8322
  const setIfChanged = (target, key, value) => {
@@ -7995,8 +8359,9 @@ var useCommentsStore = defineStore("comments", () => {
7995
8359
  target?.trackedChangeCanonicalId,
7996
8360
  target?.trackedChangeAnchorKey,
7997
8361
  ...getCommentAliasIds(target)
7998
- ].map((id) => normalizeCommentId(id)).filter(Boolean));
7999
- fields.trackedChangePositionAliases = normalizedTrackedChangePositionAliases.some((alias) => targetIdentityIds.has(alias)) ? normalizeTrackedChangePositionAliases([...Array.isArray(target?.trackedChangePositionAliases) ? target.trackedChangePositionAliases : [], ...normalizedTrackedChangePositionAliases]) : normalizedTrackedChangePositionAliases;
8362
+ ].map((id) => normalizeCommentId(id)).filter(isPresent));
8363
+ const incomingAliases = normalizedTrackedChangePositionAliases ?? [];
8364
+ fields.trackedChangePositionAliases = incomingAliases.some((alias) => targetIdentityIds.has(alias)) ? normalizeTrackedChangePositionAliases([...Array.isArray(target?.trackedChangePositionAliases) ? target.trackedChangePositionAliases : [], ...incomingAliases]) : incomingAliases;
8000
8365
  }
8001
8366
  let didChange = false;
8002
8367
  for (const [key, value] of Object.entries(fields)) didChange = setIfChanged(target, key, value) || didChange;
@@ -8005,7 +8370,7 @@ var useCommentsStore = defineStore("comments", () => {
8005
8370
  didChange = true;
8006
8371
  }
8007
8372
  if (hasCustomAttributes && target && !trackedChangeCustomAttributesEqual(target.customAttributes, normalizedCustomAttributes)) {
8008
- target.customAttributes = normalizedCustomAttributes;
8373
+ target.customAttributes = normalizedCustomAttributes ?? null;
8009
8374
  didChange = true;
8010
8375
  }
8011
8376
  return applyStoryMetadata(target) || didChange;
@@ -8027,7 +8392,7 @@ var useCommentsStore = defineStore("comments", () => {
8027
8392
  return;
8028
8393
  }
8029
8394
  addHydratedComment({
8030
- superdoc,
8395
+ superdoc: requireHost(superdoc, "handleTrackedChangeUpdate"),
8031
8396
  comment,
8032
8397
  broadcastChanges
8033
8398
  });
@@ -8047,11 +8412,12 @@ var useCommentsStore = defineStore("comments", () => {
8047
8412
  id: params.resolvedById ?? superdoc?.user?.id ?? null,
8048
8413
  email: params.resolvedByEmail ?? superdoc?.user?.email ?? null,
8049
8414
  name: params.resolvedByName ?? superdoc?.user?.name ?? null,
8050
- decision: params.decision ?? null,
8415
+ decision: params.decision ?? void 0,
8051
8416
  superdoc
8052
8417
  };
8053
8418
  if (existingTrackedChange && !existingTrackedChange.resolvedTime) existingTrackedChange.resolveComment({
8054
8419
  ...resolveArgs,
8420
+ superdoc: requireHost(superdoc, "handleTrackedChangeUpdate"),
8055
8421
  reconciliationToken: COMMENT_RECONCILIATION_TOKEN
8056
8422
  });
8057
8423
  }
@@ -8076,31 +8442,13 @@ var useCommentsStore = defineStore("comments", () => {
8076
8442
  instantSidebarAlignmentInstanceId.value = null;
8077
8443
  };
8078
8444
  const debounceEmit = (commentId, event, superdoc, delay = 1e3) => {
8079
- if (debounceTimers[commentId]) clearTimeout(debounceTimers[commentId]);
8080
- debounceTimers[commentId] = setTimeout(() => {
8445
+ const timerKey = String(commentId);
8446
+ if (debounceTimers[timerKey]) clearTimeout(debounceTimers[timerKey]);
8447
+ debounceTimers[timerKey] = setTimeout(() => {
8081
8448
  if (superdoc) superdoc.emit("comments-update", event);
8082
- delete debounceTimers[commentId];
8449
+ delete debounceTimers[timerKey];
8083
8450
  }, delay);
8084
8451
  };
8085
- const getPendingSelectionSnapshot = (superdoc, activeSelection) => {
8086
- if (activeSelection?.source !== "document-editor") return null;
8087
- const selectionDocumentId = activeSelection?.documentId ?? null;
8088
- const editorDocumentId = superdoc?.activeEditor?.options?.documentId ?? null;
8089
- if (!selectionDocumentId || !editorDocumentId || selectionDocumentId !== editorDocumentId) return null;
8090
- let currentSelection;
8091
- try {
8092
- currentSelection = superdoc?.activeEditor?.doc?.selection?.current;
8093
- } catch {
8094
- return null;
8095
- }
8096
- if (typeof currentSelection !== "function") return null;
8097
- try {
8098
- const snapshot = currentSelection();
8099
- return typeof snapshot?.then === "function" ? Promise.resolve(snapshot).catch(() => null) : snapshot;
8100
- } catch {
8101
- return null;
8102
- }
8103
- };
8104
8452
  const showAddComment = (superdoc, targetClientY = null) => {
8105
8453
  const request = ++pendingCommentRequest;
8106
8454
  const editor = superdoc?.activeEditor;
@@ -8110,7 +8458,7 @@ var useCommentsStore = defineStore("comments", () => {
8110
8458
  if (!ownsRequest()) return;
8111
8459
  superdoc.emit("comments-update", {
8112
8460
  type: COMMENT_EVENTS.PENDING,
8113
- pendingSelection: superdoc?.activeEditor === editor ? snapshot : null
8461
+ pendingSelection: superdoc?.activeEditor === editor && require__plugin_vue_export_helper.isPlainObject(snapshot) ? snapshot : null
8114
8462
  });
8115
8463
  };
8116
8464
  if (v2Adapter) {
@@ -8155,12 +8503,11 @@ var useCommentsStore = defineStore("comments", () => {
8155
8503
  }).catch((err) => ({
8156
8504
  ok: false,
8157
8505
  reason: "selection-capture-failed",
8158
- detail: err?.message ?? String(err)
8506
+ detail: errorDetail(err)
8159
8507
  }));
8160
8508
  }
8161
8509
  const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8162
- const asyncSnapshot = typeof pendingSelection?.then === "function";
8163
- if (!asyncSnapshot) emitPending(pendingSelection);
8510
+ if (!require__plugin_vue_export_helper.isThenable(pendingSelection)) emitPending(pendingSelection);
8164
8511
  const showLegacyPending = (selection) => {
8165
8512
  selection.selectionBounds = { ...selection.selectionBounds };
8166
8513
  if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
@@ -8170,7 +8517,7 @@ var useCommentsStore = defineStore("comments", () => {
8170
8517
  parentCommentId: null
8171
8518
  });
8172
8519
  if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8173
- if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8520
+ if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment?.({
8174
8521
  ...pendingComment.value.getValues(),
8175
8522
  commentId: "pending",
8176
8523
  skipEmit: true
@@ -8181,10 +8528,10 @@ var useCommentsStore = defineStore("comments", () => {
8181
8528
  activeComment.value = pendingComment.value.commentId;
8182
8529
  return { ok: true };
8183
8530
  };
8184
- if (asyncSnapshot) {
8531
+ if (require__plugin_vue_export_helper.isThenable(pendingSelection)) {
8185
8532
  const selection = { ...superdocStore.activeSelection };
8186
8533
  selection.selectionBounds = { ...selection.selectionBounds };
8187
- return pendingSelection.then((snapshot) => {
8534
+ return Promise.resolve(pendingSelection).then((snapshot) => {
8188
8535
  if (!ownsRequest()) return {
8189
8536
  ok: false,
8190
8537
  reason: "pending-comment-superseded"
@@ -8216,12 +8563,6 @@ var useCommentsStore = defineStore("comments", () => {
8216
8563
  });
8217
8564
  /**
8218
8565
  * Get a new pending comment
8219
- *
8220
- * @param {Object} param0
8221
- * @param {Object} [param0.selection] The selection object
8222
- * @param {string | null} [param0.documentId] The document ID
8223
- * @param {string | null} [param0.parentCommentId] The parent comment
8224
- * @returns {ReturnType<typeof useComment>} The new comment object
8225
8566
  */
8226
8567
  const getPendingComment = ({ selection, documentId, parentCommentId, ...options }) => {
8227
8568
  return _getNewcomment({
@@ -8233,17 +8574,11 @@ var useCommentsStore = defineStore("comments", () => {
8233
8574
  };
8234
8575
  /**
8235
8576
  * Get the new comment object
8236
- *
8237
- * @param {Object} param0
8238
- * @param {Object} param0.selection The selection object
8239
- * @param {String} param0.documentId The document ID
8240
- * @param {String} param0.parentCommentId The parent comment ID
8241
- * @returns {Object} The new comment object
8242
8577
  */
8243
8578
  const _getNewcomment = ({ selection, documentId, parentCommentId, ...options }) => {
8244
8579
  let activeDocument;
8245
- if (documentId) activeDocument = superdocStore.getDocument(documentId);
8246
- else if (selection) activeDocument = superdocStore.getDocument(selection.documentId);
8580
+ if (documentId) activeDocument = findDocument(documentId);
8581
+ else if (selection) activeDocument = findDocument(selection.documentId);
8247
8582
  if (!activeDocument) activeDocument = superdocStore.documents[0];
8248
8583
  return useComment({
8249
8584
  fileId: activeDocument.id,
@@ -8260,8 +8595,6 @@ var useCommentsStore = defineStore("comments", () => {
8260
8595
  };
8261
8596
  /**
8262
8597
  * Remove the pending comment
8263
- *
8264
- * @returns {void}
8265
8598
  */
8266
8599
  const resetPendingCommentState = (superdoc, clearViewingSelection = true) => {
8267
8600
  const hadPending = !!pendingComment.value;
@@ -8277,7 +8610,7 @@ var useCommentsStore = defineStore("comments", () => {
8277
8610
  } catch {}
8278
8611
  return;
8279
8612
  }
8280
- superdoc?.activeEditor?.commands?.removeComment({ commentId: "pending" });
8613
+ superdoc?.activeEditor?.commands?.removeComment?.({ commentId: "pending" });
8281
8614
  };
8282
8615
  const removePendingComment = (superdoc) => {
8283
8616
  pendingCommentRequest += 1;
@@ -8290,14 +8623,6 @@ var useCommentsStore = defineStore("comments", () => {
8290
8623
  };
8291
8624
  /**
8292
8625
  * Add a new comment to the document
8293
- *
8294
- * @param {Object} param0
8295
- * @param {Object} param0.superdoc The SuperDoc instance
8296
- * @param {ReturnType<typeof useComment>} param0.comment The comment to add
8297
- * @param {boolean} [param0.skipEditorUpdate] Skip writing the comment into the editor
8298
- * @param {boolean} [param0.broadcastChanges] Emit and sync the change
8299
- * @param {boolean} [param0.isHydration] The comment comes from import or collaboration
8300
- * @returns {{ ok: boolean, reason?: string, detail?: string, code?: string } | Promise<{ ok: boolean, reason?: string, detail?: string, code?: string }>} The mutation outcome
8301
8626
  */
8302
8627
  const addCommentInternal = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true, isHydration = false }) => {
8303
8628
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
@@ -8327,7 +8652,7 @@ var useCommentsStore = defineStore("comments", () => {
8327
8652
  return {
8328
8653
  ok: false,
8329
8654
  reason: "adapter-threw",
8330
- detail: err?.message ?? String(err)
8655
+ detail: errorDetail(err)
8331
8656
  };
8332
8657
  }
8333
8658
  })().then((outcome) => {
@@ -8399,7 +8724,7 @@ var useCommentsStore = defineStore("comments", () => {
8399
8724
  activeComment.value = newComment.commentId;
8400
8725
  setActiveFloatingCommentInstance(newComment.commentId);
8401
8726
  }
8402
- if (!skipEditorUpdate && !comment.trackedChange && superdoc.activeEditor?.commands && !comment.parentCommentId) superdoc.activeEditor.commands.insertComment({
8727
+ if (!skipEditorUpdate && !comment.trackedChange && superdoc.activeEditor?.commands && !comment.parentCommentId) superdoc.activeEditor.commands.insertComment?.({
8403
8728
  ...newComment.getValues(),
8404
8729
  skipEmit: true
8405
8730
  });
@@ -8447,7 +8772,7 @@ var useCommentsStore = defineStore("comments", () => {
8447
8772
  return {
8448
8773
  ok: false,
8449
8774
  reason: "adapter-threw",
8450
- detail: err?.message ?? String(err)
8775
+ detail: errorDetail(err)
8451
8776
  };
8452
8777
  }
8453
8778
  })().then((outcome) => {
@@ -8467,16 +8792,16 @@ var useCommentsStore = defineStore("comments", () => {
8467
8792
  });
8468
8793
  return outcome;
8469
8794
  }
8470
- const removedIds = new Set((Array.isArray(outcome.removedCommentIds) ? outcome.removedCommentIds : []).map(normalizeCommentId).filter(Boolean));
8471
- if (removedIds.has(normalizeCommentId(commentId))) {
8472
- if (importedId != null) removedIds.add(normalizeCommentId(importedId));
8795
+ const removedIds = new Set((Array.isArray(outcome.removedCommentIds) ? outcome.removedCommentIds : []).map(normalizeCommentId).filter(isPresent));
8796
+ if (removedIds.has(normalizeCommentId(commentId) ?? "")) {
8797
+ if (importedId != null) removedIds.add(String(importedId));
8473
8798
  let addedChild = true;
8474
8799
  while (addedChild) {
8475
8800
  addedChild = false;
8476
8801
  for (const row of commentsList.value) {
8477
8802
  const parentId = normalizeCommentId(row?.parentCommentId);
8478
8803
  if (!parentId || !removedIds.has(parentId)) continue;
8479
- for (const alias of [row?.commentId, row?.importedId].map(normalizeCommentId).filter(Boolean)) {
8804
+ for (const alias of [row?.commentId, row?.importedId].map(normalizeCommentId).filter(isPresent)) {
8480
8805
  if (removedIds.has(alias)) continue;
8481
8806
  removedIds.add(alias);
8482
8807
  addedChild = true;
@@ -8484,9 +8809,9 @@ var useCommentsStore = defineStore("comments", () => {
8484
8809
  }
8485
8810
  }
8486
8811
  commentsList.value = commentsList.value.filter((row) => {
8487
- return ![row?.commentId, row?.importedId].map(normalizeCommentId).filter(Boolean).some((alias) => removedIds.has(alias));
8812
+ return ![row?.commentId, row?.importedId].map(normalizeCommentId).filter(isPresent).some((alias) => removedIds.has(alias));
8488
8813
  });
8489
- if (removedIds.has(normalizeCommentId(activeComment.value))) clearActiveCommentSelection();
8814
+ if (removedIds.has(normalizeCommentId(activeComment.value) ?? "")) clearActiveCommentSelection();
8490
8815
  } else reconcileCommentsFromV2({
8491
8816
  superdoc,
8492
8817
  adapter: v2Adapter,
@@ -8494,18 +8819,18 @@ var useCommentsStore = defineStore("comments", () => {
8494
8819
  items: outcome.items ?? [],
8495
8820
  pruneStale: outcome.complete !== false
8496
8821
  });
8822
+ const payload = comment.getValues();
8497
8823
  superdoc.emit("comments-update", {
8498
8824
  type: COMMENT_EVENTS.DELETED,
8499
- comment: comment.getValues(),
8500
- changes: [{
8501
- key: "deleted",
8825
+ comment: payload,
8826
+ changes: getDeletedCommentChanges([{
8502
8827
  commentId,
8503
- fileId
8504
- }]
8828
+ importedId
8829
+ }, payload], fileId)
8505
8830
  });
8506
8831
  return { ok: true };
8507
8832
  });
8508
- superdoc.activeEditor?.commands?.removeComment({
8833
+ superdoc.activeEditor?.commands?.removeComment?.({
8509
8834
  commentId,
8510
8835
  importedId
8511
8836
  });
@@ -8513,14 +8838,14 @@ var useCommentsStore = defineStore("comments", () => {
8513
8838
  const childCommentIds = commentsList.value.filter((c) => c.parentCommentId === commentId).map((c) => c.commentId || c.importedId);
8514
8839
  commentsList.value = commentsList.value.filter((c) => !childCommentIds.includes(c.commentId));
8515
8840
  if (activeComment.value === commentId || childCommentIds.includes(activeComment.value)) clearActiveCommentSelection();
8841
+ const payload = comment.getValues();
8516
8842
  const event = {
8517
8843
  type: COMMENT_EVENTS.DELETED,
8518
- comment: comment.getValues(),
8519
- changes: [{
8520
- key: "deleted",
8844
+ comment: payload,
8845
+ changes: getDeletedCommentChanges([{
8521
8846
  commentId,
8522
- fileId
8523
- }]
8847
+ importedId
8848
+ }, payload], fileId)
8524
8849
  };
8525
8850
  superdoc.emit("comments-update", event);
8526
8851
  syncCommentsToClients(superdoc, event);
@@ -8532,7 +8857,7 @@ var useCommentsStore = defineStore("comments", () => {
8532
8857
  * otherwise keep the source bubble after the document comment is gone.
8533
8858
  */
8534
8859
  const dropCommentsFromMutationImpact = ({ superdoc, documentId, removedIds } = {}) => {
8535
- const seedIds = new Set([...removedIds instanceof Set ? removedIds : removedIds ?? []].map((id) => normalizeCommentId(id)).filter(Boolean));
8860
+ const seedIds = new Set([...removedIds instanceof Set ? removedIds : removedIds ?? []].map((id) => normalizeCommentId(id)).filter(isPresent));
8536
8861
  if (!seedIds.size) return {
8537
8862
  ok: true,
8538
8863
  removedIds: []
@@ -8556,7 +8881,7 @@ var useCommentsStore = defineStore("comments", () => {
8556
8881
  if (!isDroppableCommentRow(row)) continue;
8557
8882
  const aliases = getCommentAliasIds(row);
8558
8883
  const alreadyDropped = aliases.some((alias) => droppedIds.has(alias));
8559
- const parentDropped = droppedIds.has(normalizeCommentId(row?.parentCommentId)) || droppedIds.has(normalizeCommentId(row?.threadingParentCommentId));
8884
+ const parentDropped = droppedIds.has(normalizeCommentId(row?.parentCommentId) ?? "") || droppedIds.has(normalizeCommentId(row?.threadingParentCommentId) ?? "");
8560
8885
  if (!alreadyDropped && !parentDropped) continue;
8561
8886
  for (const alias of aliases) {
8562
8887
  if (droppedIds.has(alias)) continue;
@@ -8584,11 +8909,7 @@ var useCommentsStore = defineStore("comments", () => {
8584
8909
  const event = {
8585
8910
  type: COMMENT_EVENTS.DELETED,
8586
8911
  comment: payload,
8587
- changes: [{
8588
- key: "deleted",
8589
- commentId: payload?.commentId,
8590
- fileId: payload?.fileId
8591
- }]
8912
+ changes: getDeletedCommentChanges([payload, comment], payload?.fileId)
8592
8913
  };
8593
8914
  superdoc?.emit?.("comments-update", event);
8594
8915
  });
@@ -8610,7 +8931,7 @@ var useCommentsStore = defineStore("comments", () => {
8610
8931
  const byAlias = /* @__PURE__ */ new Map();
8611
8932
  const childrenByParentAlias = /* @__PURE__ */ new Map();
8612
8933
  for (const row of rows) {
8613
- for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(Boolean)) if (!byAlias.has(alias)) byAlias.set(alias, row);
8934
+ for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(isPresent)) if (!byAlias.has(alias)) byAlias.set(alias, row);
8614
8935
  const parentId = normalizeCommentId(row.parentCommentId);
8615
8936
  if (parentId) {
8616
8937
  const children = childrenByParentAlias.get(parentId) ?? [];
@@ -8637,7 +8958,7 @@ var useCommentsStore = defineStore("comments", () => {
8637
8958
  if (!row || visited.has(row)) continue;
8638
8959
  visited.add(row);
8639
8960
  family.push(row);
8640
- for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(Boolean)) queue.push(...childrenByParentAlias.get(alias) ?? []);
8961
+ for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(isPresent)) queue.push(...childrenByParentAlias.get(alias) ?? []);
8641
8962
  }
8642
8963
  const isResolved = status === "resolved";
8643
8964
  const resolvedAt = Date.now();
@@ -8660,7 +8981,7 @@ var useCommentsStore = defineStore("comments", () => {
8660
8981
  outcome = {
8661
8982
  ok: false,
8662
8983
  reason: "adapter-threw",
8663
- detail: err?.message ?? String(err)
8984
+ detail: errorDetail(err)
8664
8985
  };
8665
8986
  }
8666
8987
  if (!isCurrentV2CommentsAdapter(adapter)) return {
@@ -8732,14 +9053,14 @@ var useCommentsStore = defineStore("comments", () => {
8732
9053
  return (outcome.items ?? []).map((item) => adapter.mapV2CommentToUseCommentInput(item, {
8733
9054
  fileId,
8734
9055
  fileType: null
8735
- })).filter(Boolean);
9056
+ })).filter(isPresent);
8736
9057
  };
8737
9058
  const isBlankDirectoryCommentText = (value) => typeof value !== "string" || value.replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").trim().length === 0;
8738
9059
  const trackedChangeDirectoryComment = (params) => {
8739
9060
  if (!params || params.event === "omit" || params.changeId == null) return null;
8740
9061
  return getPendingComment({
8741
9062
  documentId: params.documentId,
8742
- commentId: params.changeId,
9063
+ commentId: String(params.changeId),
8743
9064
  trackedChange: true,
8744
9065
  trackedChangeText: params.trackedChangeText,
8745
9066
  trackedChangeType: params.trackedChangeType,
@@ -8786,7 +9107,7 @@ var useCommentsStore = defineStore("comments", () => {
8786
9107
  const mappedCommentInputs = commentItems.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => commentsAdapter.mapV2CommentToUseCommentInput(item, {
8787
9108
  fileId: documentId,
8788
9109
  fileType: document?.type ?? null
8789
- })).filter(Boolean);
9110
+ })).filter(isPresent);
8790
9111
  const trackedParentBySidecarId = /* @__PURE__ */ new Map();
8791
9112
  for (const input of mappedCommentInputs) if (input.trackedChange !== true && input.trackedChangeThreadParentId && !input.parentCommentId && isBlankDirectoryCommentText(input.commentText)) trackedParentBySidecarId.set(String(input.commentId), String(input.trackedChangeThreadParentId));
8792
9113
  const commentRows = mappedCommentInputs.filter((input) => !trackedParentBySidecarId.has(String(input.commentId))).map((input) => {
@@ -8797,7 +9118,7 @@ var useCommentsStore = defineStore("comments", () => {
8797
9118
  }
8798
9119
  return useComment(input);
8799
9120
  });
8800
- const trackedRows = trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).map((params) => trackedChangeDirectoryComment(params)).filter(Boolean);
9121
+ const trackedRows = trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).map((params) => trackedChangeDirectoryComment(params)).filter(isPresent);
8801
9122
  reviewDirectoryList.value = [...commentRows, ...trackedRows];
8802
9123
  return {
8803
9124
  ok: true,
@@ -8878,13 +9199,6 @@ var useCommentsStore = defineStore("comments", () => {
8878
9199
  * - successful mutation refreshes from v2 list and reconciles
8879
9200
  * - rejection preserves rows and emits a rejected `comments-update` event
8880
9201
  * - committed-but-refresh-failed surfaces honestly (no reconcile with `[]`)
8881
- *
8882
- * @param {Object} [param0]
8883
- * @param {Object} [param0.superdoc] The SuperDoc instance.
8884
- * @param {string | null} [param0.parentCommentId] The comment or tracked-change row being replied to.
8885
- * @param {string} [param0.text] The reply text.
8886
- * @param {Array<{ name?: string | null, email?: string | null }>} [param0.mentions] Users mentioned in the reply.
8887
- * @param {{ kind: 'trackedChange', trackedChangeId: string, story?: unknown, side?: import('./helpers/tracked-change-thread-index.js').TrackedChangeSideGroup }} [param0.trackedChangeTarget] The tracked change a first reply anchors to.
8888
9202
  */
8889
9203
  const replyCommentV2 = async ({ superdoc, parentCommentId, text, mentions = [], trackedChangeTarget } = {}) => {
8890
9204
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
@@ -9159,7 +9473,7 @@ var useCommentsStore = defineStore("comments", () => {
9159
9473
  row?.threadingParentCommentId,
9160
9474
  row?.trackedChangeParentId,
9161
9475
  row?.trackedChangeThreadParentId
9162
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9476
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9163
9477
  /** Keep one mounted review window plus rows whose interaction is still live. */
9164
9478
  const boundReviewPresentationRows = ({ documentId, visibleIds }) => {
9165
9479
  const currentRows = commentsList.value;
@@ -9180,7 +9494,7 @@ var useCommentsStore = defineStore("comments", () => {
9180
9494
  pendingComment.value?.commentId,
9181
9495
  instantSidebarAlignmentThreadId.value,
9182
9496
  instantSidebarAlignmentInstanceId.value
9183
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9497
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9184
9498
  let changed = true;
9185
9499
  while (changed) {
9186
9500
  changed = false;
@@ -9248,7 +9562,8 @@ var useCommentsStore = defineStore("comments", () => {
9248
9562
  if (preparedReview?.reuseCatalog === true && committedReviewPresentations.value[normalizedDocumentId]) {
9249
9563
  const previous = committedReviewPresentations.value[normalizedDocumentId];
9250
9564
  const next = preparedReview.presentation;
9251
- if (!next || !Number.isSafeInteger(preparedReview.catalogVersion) || preparedReview.catalogVersion < 1 || previous.catalogVersion > preparedReview.catalogVersion || next.catalogVersion !== preparedReview.catalogVersion || previous.coordinate?.documentEpoch !== next.coordinate?.documentEpoch || previous.coordinate?.mountId !== next.coordinate?.mountId || next.coordinate?.reviewVersion <= previous.coordinate?.reviewVersion || next.coordinate?.commitSequence < previous.coordinate?.commitSequence) return {
9565
+ const catalogVersion = preparedReview.catalogVersion ?? NaN;
9566
+ if (!next || !Number.isSafeInteger(catalogVersion) || catalogVersion < 1 || (previous.catalogVersion ?? 0) > catalogVersion || next.catalogVersion !== preparedReview.catalogVersion || previous.coordinate?.documentEpoch !== next.coordinate?.documentEpoch || previous.coordinate?.mountId !== next.coordinate?.mountId || next.coordinate?.reviewVersion <= previous.coordinate?.reviewVersion || next.coordinate?.commitSequence < previous.coordinate?.commitSequence) return {
9252
9567
  ok: false,
9253
9568
  reason: "review-catalog-stale"
9254
9569
  };
@@ -9294,8 +9609,8 @@ var useCommentsStore = defineStore("comments", () => {
9294
9609
  previousPresentation.updateContext = presentation.updateContext;
9295
9610
  return {
9296
9611
  ok: true,
9297
- commentItems: preparedReview.comments.length,
9298
- trackedItems: preparedReview.trackedChanges.length
9612
+ commentItems: preparedReview?.comments.length,
9613
+ trackedItems: preparedReview?.trackedChanges.length
9299
9614
  };
9300
9615
  }
9301
9616
  let effectiveCommentItems = commentItems;
@@ -9309,7 +9624,7 @@ var useCommentsStore = defineStore("comments", () => {
9309
9624
  reason: seeded?.reason ?? "comment-catalog-seed-failed"
9310
9625
  };
9311
9626
  const selected = commentsAdapter.selectVisibleReviewComments?.();
9312
- if (selected?.ok === true && Array.isArray(selected.items) && (!Array.isArray(selected.unresolvedIds) || selected.unresolvedIds.length === 0)) effectiveCommentItems = selected.items;
9627
+ if (!require__plugin_vue_export_helper.isThenable(selected) && selected?.ok === true && Array.isArray(selected.items) && (!Array.isArray(selected.unresolvedIds) || selected.unresolvedIds.length === 0)) effectiveCommentItems = selected.items;
9313
9628
  }
9314
9629
  const fileType = (normalizedDocumentId ? superdocStore.getDocument(normalizedDocumentId) : null)?.type ?? null;
9315
9630
  let preparedInputs;
@@ -9326,16 +9641,16 @@ var useCommentsStore = defineStore("comments", () => {
9326
9641
  })) : effectiveCommentItems.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => commentsAdapter.mapV2CommentToUseCommentInput(item, {
9327
9642
  fileId: normalizedDocumentId,
9328
9643
  fileType
9329
- })).filter(Boolean);
9644
+ })).filter(isPresent);
9330
9645
  preparedParams = preparedReview ? preparedReview.trackedChanges.map((params) => ({
9331
9646
  ...params,
9332
9647
  documentId: normalizedDocumentId
9333
- })) : trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).filter(Boolean);
9648
+ })) : trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).filter(isPresent);
9334
9649
  } catch (error) {
9335
9650
  return {
9336
9651
  ok: false,
9337
9652
  reason: "mapper-failed",
9338
- detail: error?.message ?? String(error)
9653
+ detail: errorDetail(error)
9339
9654
  };
9340
9655
  }
9341
9656
  if (typeof patch !== "function") return {
@@ -9363,7 +9678,7 @@ var useCommentsStore = defineStore("comments", () => {
9363
9678
  params?.trackedChangeCanonicalId,
9364
9679
  params?.trackedChangeAnchorKey
9365
9680
  ])
9366
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9681
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9367
9682
  patch(() => {
9368
9683
  const previousPreparedPresentation = committedReviewPresentations.value[normalizedDocumentId] ?? null;
9369
9684
  if (preparedReview?.presentation) committedReviewPresentations.value = {
@@ -9411,7 +9726,7 @@ var useCommentsStore = defineStore("comments", () => {
9411
9726
  };
9412
9727
  const effectiveDocumentId = documentId ?? adapter.documentId ?? null;
9413
9728
  const normalizedEffectiveDocumentId = effectiveDocumentId != null ? String(effectiveDocumentId) : null;
9414
- const fileType = (effectiveDocumentId ? superdocStore.getDocument(effectiveDocumentId) : null)?.type ?? null;
9729
+ const fileType = (effectiveDocumentId ? findDocument(effectiveDocumentId) : null)?.type ?? null;
9415
9730
  const isBlankV2CommentText = (value) => {
9416
9731
  if (typeof value !== "string") return true;
9417
9732
  return value.replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").trim().length === 0;
@@ -9431,7 +9746,7 @@ var useCommentsStore = defineStore("comments", () => {
9431
9746
  const candidateInputs = Array.isArray(preparedInputs) ? preparedInputs : items.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => adapter.mapV2CommentToUseCommentInput(item, {
9432
9747
  fileId: effectiveDocumentId,
9433
9748
  fileType
9434
- })).filter(Boolean);
9749
+ })).filter(isPresent);
9435
9750
  for (const input of candidateInputs) {
9436
9751
  if (isV2TrackedChangeSidecarCommentInput(input)) {
9437
9752
  trackedChangeSidecarParentByCommentId.set(String(input.commentId), String(input.trackedChangeThreadParentId));
@@ -9484,7 +9799,7 @@ var useCommentsStore = defineStore("comments", () => {
9484
9799
  existing.mentions = Array.isArray(input.mentions) ? input.mentions : [];
9485
9800
  existing.isInternal = typeof input.isInternal === "boolean" ? input.isInternal : existing.isInternal;
9486
9801
  if (typeof input.resolvedTime === "number") {
9487
- existing.resolvedTime = input.resolvedTimeWasSynthesized === true && typeof existing.resolvedTime === "number" ? existing.resolvedTime : input.resolvedTime;
9802
+ existing.resolvedTime = input.resolvedTimeWasSynthesized === true && typeof existing.resolvedTime === "number" ? existing.resolvedTime : input.resolvedTime ?? null;
9488
9803
  existing.resolvedByEmail = input.resolvedByEmail ?? null;
9489
9804
  existing.resolvedByName = input.resolvedByName ?? null;
9490
9805
  } else {
@@ -9558,7 +9873,7 @@ var useCommentsStore = defineStore("comments", () => {
9558
9873
  return {
9559
9874
  ok: false,
9560
9875
  reason: "comment-read-failed",
9561
- detail: err?.message ?? String(err)
9876
+ detail: errorDetail(err)
9562
9877
  };
9563
9878
  }
9564
9879
  if (!isCurrentV2CommentsAdapter(adapter)) return {
@@ -9584,8 +9899,6 @@ var useCommentsStore = defineStore("comments", () => {
9584
9899
  };
9585
9900
  /**
9586
9901
  * Cancel the pending comment
9587
- *
9588
- * @returns {void}
9589
9902
  */
9590
9903
  const cancelComment = (superdoc) => {
9591
9904
  removePendingComment(superdoc);
@@ -9595,9 +9908,6 @@ var useCommentsStore = defineStore("comments", () => {
9595
9908
  *
9596
9909
  * Replace-file swaps call this before hydrating the replacement so stale
9597
9910
  * comments never survive long enough to render beside the new content.
9598
- *
9599
- * @param {string | null | undefined} documentId
9600
- * @returns {void}
9601
9911
  */
9602
9912
  function removeCommentsForDocument(documentId) {
9603
9913
  const activeDocumentId = documentId != null ? String(documentId) : null;
@@ -9624,139 +9934,20 @@ var useCommentsStore = defineStore("comments", () => {
9624
9934
  const activeCommentId = activeComment.value != null ? String(activeComment.value) : null;
9625
9935
  if (activeCommentId && removedAliasIds.has(activeCommentId)) clearActiveCommentSelection();
9626
9936
  }
9627
- const getCommentDocumentId = (comment) => {
9628
- if (!comment) return null;
9629
- if (comment.fileId != null) return String(comment.fileId);
9630
- if (comment.documentId != null) return String(comment.documentId);
9631
- if (comment.selection?.documentId != null) return String(comment.selection.documentId);
9632
- return null;
9633
- };
9634
- const getOpenDocuments = () => {
9635
- const docs = Array.isArray(superdocStore.documents) ? superdocStore.documents : superdocStore.documents?.value;
9636
- return Array.isArray(docs) ? docs : [];
9637
- };
9638
- const getSingleOpenDocumentId = () => {
9639
- const docs = getOpenDocuments();
9640
- if (docs.length !== 1) return null;
9641
- return docs[0]?.id != null ? String(docs[0].id) : null;
9642
- };
9643
- const belongsToDocument = (comment, activeDocumentId, options = {}) => {
9644
- const { allowSingleDocumentMismatch = false } = options;
9645
- if (!activeDocumentId) return false;
9646
- const commentDocumentId = getCommentDocumentId(comment);
9647
- if (commentDocumentId) {
9648
- if (commentDocumentId === activeDocumentId) return true;
9649
- const singleOpenDocumentId = getSingleOpenDocumentId();
9650
- return allowSingleDocumentMismatch && singleOpenDocumentId === activeDocumentId;
9651
- }
9652
- return getSingleOpenDocumentId() === activeDocumentId;
9653
- };
9654
- const belongsToTrackedChangeSyncDocument = (comment, activeDocumentId) => {
9655
- return belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true });
9656
- };
9657
- const normalizeTrackedChangeDecisionType = (value) => {
9658
- const lower = typeof value === "string" ? value.toLowerCase() : "";
9659
- if (!lower) return null;
9660
- if (lower === "insert" || lower === "insertion" || lower === "trackinsert" || lower === "tableinsert" || lower === "paragraphsplit") return "insertion";
9661
- if (lower === "delete" || lower === "deletion" || lower === "trackdelete" || lower === "tabledelete") return "deletion";
9662
- return lower;
9663
- };
9664
- const trackedChangeDecisionKeepsCommentAnchor = ({ comment, decision } = {}) => {
9665
- const normalizedDecision = decision === "accept" || decision === "reject" ? decision : null;
9666
- if (!normalizedDecision) return false;
9667
- const type = normalizeTrackedChangeDecisionType(comment?.trackedChangeDisplayType) ?? normalizeTrackedChangeDecisionType(comment?.trackedChangeType);
9668
- return normalizedDecision === "accept" && type === "insertion" || normalizedDecision === "reject" && type === "deletion";
9669
- };
9670
- const getBodyTrackedChangeIdentityIds = (comment) => {
9671
- return [normalizeCommentId(comment.commentId), ...!normalizeCommentId(comment.trackedChangeCanonicalId) ? [
9672
- comment.importedId,
9673
- comment.trackedChangeAnchorKey,
9674
- ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
9675
- ] : []].map((id) => normalizeCommentId(id)).filter(Boolean);
9676
- };
9677
- const groupBodyTrackedChangeCommentsByIdentity = (comments) => {
9678
- const parents = comments.map((_, index) => index);
9679
- const findRoot = (index) => {
9680
- let root = index;
9681
- while (parents[root] !== root) root = parents[root];
9682
- while (parents[index] !== index) {
9683
- const next = parents[index];
9684
- parents[index] = root;
9685
- index = next;
9686
- }
9687
- return root;
9688
- };
9689
- const join = (left, right) => {
9690
- const leftRoot = findRoot(left);
9691
- const rightRoot = findRoot(right);
9692
- if (leftRoot === rightRoot) return;
9693
- parents[Math.max(leftRoot, rightRoot)] = Math.min(leftRoot, rightRoot);
9694
- };
9695
- const identityOwner = /* @__PURE__ */ new Map();
9696
- comments.forEach((comment, index) => {
9697
- getBodyTrackedChangeIdentityIds(comment).forEach((identityId) => {
9698
- const owner = identityOwner.get(identityId);
9699
- if (owner === void 0) identityOwner.set(identityId, index);
9700
- else join(index, owner);
9701
- });
9702
- });
9703
- const groups = /* @__PURE__ */ new Map();
9704
- comments.forEach((comment, index) => {
9705
- const root = findRoot(index);
9706
- const group = groups.get(root) ?? [];
9707
- group.push(comment);
9708
- groups.set(root, group);
9709
- });
9710
- return groups;
9711
- };
9712
- const mergeDuplicateBodyTrackedChangeComments = (groups) => {
9713
- const duplicates = /* @__PURE__ */ new Map();
9714
- groups.forEach(([survivor, ...duplicateRows]) => {
9715
- if (!survivor || duplicateRows.length === 0) return;
9716
- const resolvedDuplicate = duplicateRows.find((comment) => comment.resolvedTime != null);
9717
- if (survivor.resolvedTime == null && resolvedDuplicate) {
9718
- survivor.resolvedTime = resolvedDuplicate.resolvedTime;
9719
- survivor.resolvedById = resolvedDuplicate.resolvedById;
9720
- survivor.resolvedByEmail = resolvedDuplicate.resolvedByEmail;
9721
- survivor.resolvedByName = resolvedDuplicate.resolvedByName;
9722
- survivor.trackedChangeDecision = resolvedDuplicate.trackedChangeDecision;
9723
- }
9724
- survivor.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...normalizeTrackedChangePositionAliases(survivor.trackedChangePositionAliases), ...duplicateRows.flatMap((comment) => [
9725
- comment.commentId,
9726
- comment.importedId,
9727
- comment.trackedChangeCanonicalId,
9728
- ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
9729
- ])]);
9730
- duplicateRows.forEach((comment) => duplicates.set(comment, survivor));
9731
- });
9732
- return duplicates;
9733
- };
9734
- const createDroppedCommentIdMap = (duplicates) => {
9735
- const droppedCommentIds = /* @__PURE__ */ new Map();
9736
- duplicates.forEach((survivor, duplicate) => {
9737
- const fromId = normalizeCommentId(duplicate.commentId);
9738
- const toId = normalizeCommentId(survivor.commentId);
9739
- if (fromId && toId) droppedCommentIds.set(fromId, toId);
9740
- });
9741
- return droppedCommentIds;
9742
- };
9937
+ const { belongsToDocument, belongsToTrackedChangeSyncDocument } = createCommentDocumentScope(() => superdocStore.documents);
9743
9938
  const remapTrackedChangeReferences = (droppedCommentIds, activeDocumentId) => {
9744
9939
  const remapSelection = (selection) => {
9745
9940
  const selectedId = normalizeCommentId(selection.value);
9746
- if (selectedId && droppedCommentIds.has(selectedId)) selection.value = droppedCommentIds.get(selectedId);
9941
+ const replacementId = selectedId ? droppedCommentIds.get(selectedId) : void 0;
9942
+ if (replacementId) selection.value = replacementId;
9747
9943
  };
9748
9944
  remapSelection(activeComment);
9749
9945
  remapSelection(activeFloatingCommentInstanceId);
9750
9946
  commentsList.value.forEach((row) => {
9751
9947
  if (!belongsToTrackedChangeSyncDocument(row, activeDocumentId)) return;
9752
9948
  const rowIdentityUpdates = {};
9753
- for (const field of [
9754
- "trackedChangeThreadParentId",
9755
- "trackedChangeParentId",
9756
- "threadingParentCommentId",
9757
- "parentCommentId"
9758
- ]) {
9759
- const replacementId = droppedCommentIds.get(normalizeCommentId(row?.[field]));
9949
+ for (const field of PARENT_LINK_FIELDS) {
9950
+ const replacementId = droppedCommentIds.get(normalizeCommentId(row?.[field]) ?? "");
9760
9951
  if (!replacementId) continue;
9761
9952
  row[field] = replacementId;
9762
9953
  rowIdentityUpdates[field] = replacementId;
@@ -9765,9 +9956,7 @@ var useCommentsStore = defineStore("comments", () => {
9765
9956
  });
9766
9957
  };
9767
9958
  const compactDuplicateBodyTrackedChangeComments = (activeDocumentId) => {
9768
- const candidates = commentsList.value.filter((comment) => isBodyTrackedChangeComment(comment) && belongsToTrackedChangeSyncDocument(comment, activeDocumentId));
9769
- const groups = groupBodyTrackedChangeCommentsByIdentity(candidates);
9770
- const duplicates = mergeDuplicateBodyTrackedChangeComments(groups);
9959
+ const duplicates = mergeDuplicateBodyTrackedChangeComments(groupBodyTrackedChangeCommentsByIdentity(commentsList.value.filter((comment) => isBodyTrackedChangeComment(comment) && belongsToTrackedChangeSyncDocument(comment, activeDocumentId))));
9771
9960
  if (!duplicates.size) return 0;
9772
9961
  commentsList.value = commentsList.value.filter((comment) => !duplicates.has(comment));
9773
9962
  remapTrackedChangeReferences(createDroppedCommentIdMap(duplicates), activeDocumentId);
@@ -9779,10 +9968,6 @@ var useCommentsStore = defineStore("comments", () => {
9779
9968
  *
9780
9969
  * Pruning is scoped to the active editor document so replay in one document does not
9781
9970
  * delete tracked-change comments from other open documents.
9782
- *
9783
- * @param {Set<string>} liveTrackedChangeIds IDs currently present in editor marks.
9784
- * @param {string | null} activeDocumentId Document currently being synced.
9785
- * @returns {void}
9786
9971
  */
9787
9972
  const pruneStaleTrackedChangeComments = (liveTrackedChangeIds, liveTrackedChangeAnchorKeys, activeDocumentId, superdoc = null, { broadcastChanges = true } = {}) => withInteractionSpan("store.trackedChanges.pruneStaleComments", "store-reconciliation", {
9788
9973
  activeDocumentId: activeDocumentId ?? null,
@@ -9827,7 +10012,7 @@ var useCommentsStore = defineStore("comments", () => {
9827
10012
  comment: payload
9828
10013
  };
9829
10014
  if (broadcastChanges) {
9830
- syncCommentsToClients(superdoc, event);
10015
+ syncCommentsToClients(requireHost(superdoc, "pruneStaleTrackedChangeComments"), event);
9831
10016
  superdoc?.emit?.("comments-update", event);
9832
10017
  }
9833
10018
  });
@@ -9859,14 +10044,10 @@ var useCommentsStore = defineStore("comments", () => {
9859
10044
  const event = {
9860
10045
  type: COMMENT_EVENTS.DELETED,
9861
10046
  comment: payload,
9862
- changes: [{
9863
- key: "deleted",
9864
- commentId: payload.commentId,
9865
- fileId: payload.fileId
9866
- }]
10047
+ changes: getDeletedCommentChanges([payload, comment], payload.fileId)
9867
10048
  };
9868
10049
  if (broadcastChanges) {
9869
- syncCommentsToClients(superdoc, event);
10050
+ syncCommentsToClients(requireHost(superdoc, "pruneStaleTrackedChangeComments"), event);
9870
10051
  superdoc?.emit?.("comments-update", event);
9871
10052
  }
9872
10053
  });
@@ -9889,7 +10070,6 @@ var useCommentsStore = defineStore("comments", () => {
9889
10070
  const resolveArgs = {
9890
10071
  email: superdoc?.user?.email ?? null,
9891
10072
  name: superdoc?.user?.name ?? null,
9892
- superdoc,
9893
10073
  reconciliationToken: COMMENT_RECONCILIATION_TOKEN
9894
10074
  };
9895
10075
  let resolvedCount = 0;
@@ -9900,27 +10080,18 @@ var useCommentsStore = defineStore("comments", () => {
9900
10080
  trackedChangeThreadParentIdForComment(linkedComment),
9901
10081
  linkedComment.threadingParentCommentId,
9902
10082
  linkedComment.parentCommentId
9903
- ].map((id) => normalizeCommentId(id)).filter(Boolean).some((id) => trackedChangeIds.has(id))) return;
10083
+ ].map((id) => normalizeCommentId(id)).filter(isPresent).some((id) => trackedChangeIds.has(id))) return;
9904
10084
  if (typeof linkedComment.resolveComment === "function") {
9905
- linkedComment.resolveComment(resolveArgs);
10085
+ linkedComment.resolveComment({
10086
+ ...resolveArgs,
10087
+ superdoc: requireHost(superdoc, "resolveLinkedCommentsForTrackedChangeDecision")
10088
+ });
9906
10089
  resolvedCount += 1;
9907
10090
  }
9908
10091
  });
9909
10092
  return resolvedCount;
9910
10093
  };
9911
- const collectTrackedChangeDecisionIds = (comment) => {
9912
- const trackedChangeIds = new Set(getCommentAliasIds(comment));
9913
- if (comment?.trackedChangeCanonicalId != null) trackedChangeIds.add(String(comment.trackedChangeCanonicalId));
9914
- const anchorKey = comment?.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
9915
- if (anchorKey) {
9916
- trackedChangeIds.add(anchorKey);
9917
- if (anchorKey.startsWith("tc::")) {
9918
- const rawId = anchorKey.slice(anchorKey.lastIndexOf("::") + 2);
9919
- if (rawId) trackedChangeIds.add(rawId);
9920
- }
9921
- }
9922
- return trackedChangeIds;
9923
- };
10094
+ const collectTrackedChangeDecisionIds = (comment) => collectTrackedChangeDecisionIdsWithAliases(comment, getCommentAliasIds(comment));
9924
10095
  const getTrackedChangeDecisionLinks = (comment) => {
9925
10096
  const linked = [];
9926
10097
  const seen = /* @__PURE__ */ new Set();
@@ -9931,28 +10102,6 @@ var useCommentsStore = defineStore("comments", () => {
9931
10102
  }
9932
10103
  return linked;
9933
10104
  };
9934
- const collectTrackedChangeEntityIdsFromReceipt = (receipt) => {
9935
- const record = receipt && typeof receipt === "object" ? receipt : null;
9936
- if (!record?.success) return /* @__PURE__ */ new Set();
9937
- const ids = /* @__PURE__ */ new Set();
9938
- const collect = (entry) => {
9939
- const ref = entry && typeof entry === "object" ? entry : null;
9940
- if (ref?.kind !== "entity" || ref.entityType !== "trackedChange") return;
9941
- if (ref.entityId != null && String(ref.entityId).length > 0) ids.add(String(ref.entityId));
9942
- };
9943
- if (Array.isArray(record.removed)) record.removed.forEach(collect);
9944
- if (Array.isArray(record.invalidatedRefs)) record.invalidatedRefs.forEach(collect);
9945
- return ids;
9946
- };
9947
- const collectReliableDecidedTrackedChangeIds = (outcome) => {
9948
- const ids = /* @__PURE__ */ new Set();
9949
- if (outcome?.decidedId != null && String(outcome.decidedId).length > 0) ids.add(String(outcome.decidedId));
9950
- if (Array.isArray(outcome?.decidedIds)) outcome.decidedIds.forEach((id) => {
9951
- if (id != null && String(id).length > 0) ids.add(String(id));
9952
- });
9953
- collectTrackedChangeEntityIdsFromReceipt(outcome?.receipt).forEach((id) => ids.add(id));
9954
- return ids;
9955
- };
9956
10105
  const detachLinkedCommentsForTrackedChangeDecision = ({ comment, decision } = {}) => {
9957
10106
  if (!comment?.trackedChange) return 0;
9958
10107
  if (!trackedChangeDecisionKeepsCommentAnchor({
@@ -10033,7 +10182,7 @@ var useCommentsStore = defineStore("comments", () => {
10033
10182
  if (previousCommentId) anchorSourceIds.add(previousCommentId);
10034
10183
  if (previousCanonicalId) anchorSourceIds.add(previousCanonicalId);
10035
10184
  }
10036
- if (comment.trackedChangeAnchorKey == null || anchorSourceIds.has(currentAnchorParts?.rawId)) comment.trackedChangeAnchorKey = toAnchor;
10185
+ if (comment.trackedChangeAnchorKey == null || anchorSourceIds.has(currentAnchorParts?.rawId ?? "")) comment.trackedChangeAnchorKey = toAnchor;
10037
10186
  comment.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...Array.isArray(comment.trackedChangePositionAliases) ? comment.trackedChangePositionAliases : [], fromId]);
10038
10187
  const identitySourceIds = /* @__PURE__ */ new Set([fromId]);
10039
10188
  if (advancesRemapLineage) {
@@ -10044,33 +10193,28 @@ var useCommentsStore = defineStore("comments", () => {
10044
10193
  if (row === comment) return;
10045
10194
  if (!belongsToTrackedChangeSyncDocument(row, normalizedDocumentId)) return;
10046
10195
  const rowIdentityUpdates = {};
10047
- for (const field of [
10048
- "trackedChangeThreadParentId",
10049
- "trackedChangeParentId",
10050
- "threadingParentCommentId",
10051
- "parentCommentId"
10052
- ]) {
10053
- if (!identitySourceIds.has(normalizeCommentId(row?.[field]))) continue;
10196
+ for (const field of PARENT_LINK_FIELDS) {
10197
+ if (!identitySourceIds.has(normalizeCommentId(row?.[field]) ?? "")) continue;
10054
10198
  row[field] = toId;
10055
10199
  rowIdentityUpdates[field] = toId;
10056
10200
  }
10057
10201
  if (Object.keys(rowIdentityUpdates).length && typeof row.updateIdentityValues === "function") row.updateIdentityValues(rowIdentityUpdates);
10058
10202
  });
10059
10203
  if (Object.keys(commentIdentityUpdates).length && typeof comment.updateIdentityValues === "function") comment.updateIdentityValues(commentIdentityUpdates);
10060
- const previousEntry = previousPositionEntry ?? [positions[fromId], positions[buildBodyTrackedChangeAnchorKey(fromId)]].find((entry) => entry && positionEntryMatchesTrackedChangeStory(entry, comment));
10204
+ const previousEntry = previousPositionEntry ?? [positions[fromId], positions[String(buildBodyTrackedChangeAnchorKey(fromId))]].find((entry) => entry && positionEntryMatchesTrackedChangeStory(entry, comment));
10061
10205
  if (previousEntry) {
10062
- for (const key of [toId, toAnchor]) if (positions[key] === void 0) {
10206
+ for (const key of [toId, String(toAnchor)]) if (positions[key] === void 0) {
10063
10207
  positions[key] = previousEntry;
10064
10208
  positionsChanged = true;
10065
10209
  }
10066
10210
  }
10067
- if (identitySourceIds.has(normalizeCommentId(activeComment.value))) activeComment.value = toId;
10068
- if (identitySourceIds.has(normalizeCommentId(activeFloatingCommentInstanceId.value))) activeFloatingCommentInstanceId.value = toId;
10211
+ if (identitySourceIds.has(normalizeCommentId(activeComment.value) ?? "")) activeComment.value = toId;
10212
+ if (identitySourceIds.has(normalizeCommentId(activeFloatingCommentInstanceId.value) ?? "")) activeFloatingCommentInstanceId.value = toId;
10069
10213
  }
10070
10214
  if (positionsChanged) editorCommentPositions.value = { ...positions };
10071
10215
  };
10072
10216
  const pruneDecidedTrackedChangeRow = ({ superdoc, comment: targetComment, decidedId, decidedIds, documentId } = {}) => {
10073
- const normalizedDecidedIds = new Set((Array.isArray(decidedIds) || decidedIds instanceof Set ? Array.from(decidedIds) : [decidedId]).map((id) => normalizeCommentId(id)).filter(Boolean));
10217
+ const normalizedDecidedIds = new Set((Array.isArray(decidedIds) || decidedIds instanceof Set ? Array.from(decidedIds) : [decidedId]).map((id) => normalizeCommentId(id)).filter(isPresent));
10074
10218
  const normalizedDocumentId = normalizeCommentId(documentId);
10075
10219
  if (!normalizedDecidedIds.size || !normalizedDocumentId) return {
10076
10220
  removed: false,
@@ -10128,39 +10272,8 @@ var useCommentsStore = defineStore("comments", () => {
10128
10272
  removedIds
10129
10273
  };
10130
10274
  };
10131
- const clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
10132
- if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
10133
- try {
10134
- adapter.clearActiveTrackedChangeTargetIfMatches(decidedId);
10135
- } catch {}
10136
- };
10137
- const waitForTrackedDecisionCanonicalPaint = async ({ superdoc, receipt } = {}) => {
10138
- const readiness = superdoc?.activeEditor?.documentMutationReadiness;
10139
- if (receipt?.success !== true || typeof receipt?.txId !== "string" || !receipt.txId || typeof readiness?.whenPainted !== "function") return;
10140
- try {
10141
- await readiness.whenPainted(receipt);
10142
- const requestFrame = globalThis.requestAnimationFrame;
10143
- if (typeof requestFrame === "function") await new Promise((resolve) => {
10144
- let settled = false;
10145
- const finish = () => {
10146
- if (settled) return;
10147
- settled = true;
10148
- clearTimeout(fallback);
10149
- resolve();
10150
- };
10151
- const fallback = setTimeout(finish, 250);
10152
- requestFrame(() => requestFrame(() => setTimeout(finish, 0)));
10153
- });
10154
- } catch {}
10155
- };
10156
10275
  /**
10157
10276
  * Accept or reject the tracked change behind a sidebar row.
10158
- *
10159
- * @param {Object} param0
10160
- * @param {Object} param0.superdoc The SuperDoc instance.
10161
- * @param {Object} param0.comment The tracked-change row.
10162
- * @param {string} param0.decision `'accept'` or `'reject'`.
10163
- * @returns {{ ok: boolean, success?: boolean, reason?: string } | Promise<{ ok: boolean, success?: boolean, reason?: string }>} The decision outcome.
10164
10277
  */
10165
10278
  const decideTrackedChangeFromSidebar = ({ superdoc, comment, decision }) => {
10166
10279
  const disabledReason = trackedChangeDecisionDisabledReason(superdoc);
@@ -10188,7 +10301,7 @@ var useCommentsStore = defineStore("comments", () => {
10188
10301
  return {
10189
10302
  ok: false,
10190
10303
  reason: "adapter-threw",
10191
- detail: err?.message ?? String(err)
10304
+ detail: errorDetail(err)
10192
10305
  };
10193
10306
  }
10194
10307
  })().then(async (outcome) => {
@@ -10241,9 +10354,11 @@ var useCommentsStore = defineStore("comments", () => {
10241
10354
  if (!activeEditor) return { ok: false };
10242
10355
  const id = comment.commentId ?? comment.importedId;
10243
10356
  if (!id) return { ok: false };
10244
- const story = comment.trackedChangeStory ?? void 0;
10357
+ const rawStory = comment.trackedChangeStory ?? void 0;
10358
+ const story = require_create_super_doc_ui.isStoryLocator(rawStory) ? rawStory : void 0;
10245
10359
  const documentApi = typeof activeEditor.doc === "object" ? activeEditor.doc : null;
10246
10360
  if (documentApi?.trackChanges?.decide) try {
10361
+ if (rawStory && !story) throw new TypeError("trackedChangeStory must be a valid StoryLocator");
10247
10362
  const target = story ? {
10248
10363
  id,
10249
10364
  story
@@ -10256,7 +10371,7 @@ var useCommentsStore = defineStore("comments", () => {
10256
10371
  success: Boolean(receipt?.success)
10257
10372
  }));
10258
10373
  } catch (error) {
10259
- if (story) return {
10374
+ if (rawStory) return {
10260
10375
  ok: false,
10261
10376
  error
10262
10377
  };
@@ -10303,9 +10418,9 @@ var useCommentsStore = defineStore("comments", () => {
10303
10418
  documentId: effectiveDocumentId
10304
10419
  })).removed
10305
10420
  };
10306
- const normalizedRemovedIds = new Set(Array.from(removedIds ?? []).map((id) => normalizeCommentId(id)).filter(Boolean));
10307
- const normalizedUpsertIds = [...new Set(Array.from(upsertIds ?? []).map((id) => normalizeCommentId(id)).filter(Boolean))];
10308
- const remappedSourceIds = new Set((Array.isArray(remappedPairs) ? remappedPairs : []).map((pair) => normalizeCommentId(pair?.from)).filter(Boolean));
10421
+ const normalizedRemovedIds = new Set(Array.from(removedIds ?? []).map((id) => normalizeCommentId(id)).filter(isPresent));
10422
+ const normalizedUpsertIds = [...new Set(Array.from(upsertIds ?? []).map((id) => normalizeCommentId(id)).filter(isPresent))];
10423
+ const remappedSourceIds = new Set((Array.isArray(remappedPairs) ? remappedPairs : []).map((pair) => normalizeCommentId(pair?.from)).filter(isPresent));
10309
10424
  const locallyRemovedIds = new Set([...normalizedRemovedIds].filter((id) => !remappedSourceIds.has(id)));
10310
10425
  if (locallyRemovedIds.size > 0 && effectiveDocumentId != null) pruneDecidedTrackedChangeRow({
10311
10426
  superdoc,
@@ -10415,23 +10530,24 @@ var useCommentsStore = defineStore("comments", () => {
10415
10530
  for (const params of paramsList) {
10416
10531
  if (!params) continue;
10417
10532
  let retainUnchangedRow = false;
10533
+ const anchorParts = parseTrackedChangeAnchorKey(params.trackedChangeAnchorKey);
10534
+ const anchorStoryKey = anchorParts ? normalizeTrackedChangeStoryKey(anchorParts.storyKey) : void 0;
10418
10535
  if (preparedPresentation) {
10419
10536
  if (preparedPresentation !== committedReviewPresentations.value[String(effectiveDocumentId)]) continue;
10420
10537
  if (params.documentId != null && String(params.documentId) !== String(effectiveDocumentId)) continue;
10421
10538
  const id = normalizeCommentId(params.changeId);
10422
- const version = preparedPresentation.rowVersions?.[id];
10539
+ const version = preparedPresentation.rowVersions?.[String(id)] ?? NaN;
10423
10540
  if (!id || !Number.isSafeInteger(version) || version < 1) continue;
10424
10541
  const existing = [...trackedChangeIdentityIndex.candidates({ changeId: id })].filter((row) => String(row.fileId) === String(effectiveDocumentId) && String(row.commentId) === id);
10425
10542
  if (existing.length > 1) continue;
10426
10543
  const row = existing[0];
10427
10544
  if (row && row.trackedChangeCanonicalId !== params.trackedChangeCanonicalId) {
10428
- const previousVersion = previousPreparedPresentation?.rowVersions?.[id];
10429
- if (!row.trackedChange || params.event !== "add" || typeof params.trackedChangeCanonicalId !== "string" || !params.trackedChangeCanonicalId || !Number.isSafeInteger(previousVersion) || previousVersion < 1 || version <= previousVersion || normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(row)) !== normalizeTrackedChangeStoryKey(parseTrackedChangeAnchorKey(params.trackedChangeAnchorKey)?.storyKey) || row.trackedChangeType !== params.trackedChangeType || row.trackedChangeDisplayType !== params.trackedChangeDisplayType) continue;
10545
+ const previousVersion = previousPreparedPresentation?.rowVersions?.[id] ?? NaN;
10546
+ if (!row.trackedChange || params.event !== "add" || typeof params.trackedChangeCanonicalId !== "string" || !params.trackedChangeCanonicalId || !Number.isSafeInteger(previousVersion) || previousVersion < 1 || version <= previousVersion || normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(row)) !== anchorStoryKey || row.trackedChangeType !== params.trackedChangeType || row.trackedChangeDisplayType !== params.trackedChangeDisplayType) continue;
10430
10547
  row.trackedChangeCanonicalId = params.trackedChangeCanonicalId;
10431
- row.updateIdentityValues?.({ trackedChangeCanonicalId: params.trackedChangeCanonicalId });
10432
10548
  trackedChangeIdentityIndex.add(row);
10433
10549
  }
10434
- retainUnchangedRow = retainUnchangedRows && row?.trackedChange === true && previousPreparedPresentation.rowVersions?.[id] === version && row.trackedChangeCanonicalId === params.trackedChangeCanonicalId && row.trackedChangeType === params.trackedChangeType && row.trackedChangeDisplayType === params.trackedChangeDisplayType && normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(row)) === normalizeTrackedChangeStoryKey(parseTrackedChangeAnchorKey(params.trackedChangeAnchorKey)?.storyKey) && !row.resolvedTime && !row.resolvedById && !row.resolvedByEmail && !row.resolvedByName;
10550
+ retainUnchangedRow = retainUnchangedRows === true && row?.trackedChange === true && previousPreparedPresentation.rowVersions?.[id] === version && row.trackedChangeCanonicalId === params.trackedChangeCanonicalId && row.trackedChangeType === params.trackedChangeType && row.trackedChangeDisplayType === params.trackedChangeDisplayType && normalizeTrackedChangeStoryKey(getTrackedChangeStoryKey(row)) === anchorStoryKey && !row.resolvedTime && !row.resolvedById && !row.resolvedByEmail && !row.resolvedByName;
10435
10551
  }
10436
10552
  if (params.event === "omit") {
10437
10553
  if (params.changeId != null) liveIds.add(String(params.changeId));
@@ -10472,22 +10588,18 @@ var useCommentsStore = defineStore("comments", () => {
10472
10588
  return commentsList.value.filter((comment) => {
10473
10589
  if (comment?.trackedChange !== true) return false;
10474
10590
  if (normalizedDocumentId == null) return true;
10475
- const rowDocumentId = comment?.documentId ?? comment?.fileId ?? null;
10591
+ const rowDocumentId = Reflect.get(comment, "documentId") ?? comment?.fileId ?? null;
10476
10592
  return rowDocumentId != null && String(rowDocumentId) === normalizedDocumentId;
10477
10593
  }).length;
10478
10594
  };
10479
10595
  /**
10480
10596
  * Triggered when the editor locations are updated
10481
10597
  * Updates floating comment locations from the editor
10482
- *
10483
- * @param {Object} allCommentPositions The collected geometry keyed by comment / tracked-change id
10484
- * @param {{ retainMissingTrackedChangeGeometry?: boolean, retainedTrackedChangeIds?: Iterable<string> }} options Geometry reconciliation options
10485
- * @returns {void}
10486
10598
  */
10487
10599
  const handleEditorLocationsUpdate = (allCommentPositions, options = {}) => {
10488
10600
  if (allCommentPositions == null) return;
10489
10601
  const retainMissingTrackedChangeGeometry = options?.retainMissingTrackedChangeGeometry === true;
10490
- const retainedTrackedChangeIds = retainMissingTrackedChangeGeometry && options?.retainedTrackedChangeIds != null ? new Set(Array.from(options.retainedTrackedChangeIds, (id) => normalizeCommentId(id)).filter(Boolean)) : null;
10602
+ const retainedTrackedChangeIds = retainMissingTrackedChangeGeometry && options?.retainedTrackedChangeIds != null ? new Set(Array.from(options.retainedTrackedChangeIds, (id) => normalizeCommentId(id)).filter(isPresent)) : null;
10491
10603
  const previousPositions = editorCommentPositions.value || {};
10492
10604
  const normalizedPositions = {};
10493
10605
  Object.entries(allCommentPositions).forEach(([key, entry]) => {
@@ -10514,7 +10626,7 @@ var useCommentsStore = defineStore("comments", () => {
10514
10626
  return null;
10515
10627
  };
10516
10628
  const writeTrackedChangeAliases = (entry, comment, extraKeys = []) => {
10517
- const keys = [...aliasesFor(comment), ...extraKeys.map((id) => normalizeCommentId(id)).filter(Boolean)];
10629
+ const keys = [...aliasesFor(comment), ...extraKeys.map((id) => normalizeCommentId(id)).filter(isPresent)];
10518
10630
  for (const key of new Set(keys)) if (normalizedPositions[key] === void 0) normalizedPositions[key] = entry;
10519
10631
  };
10520
10632
  commentsList.value.forEach((comment) => {
@@ -10713,7 +10825,7 @@ var ellipsis_vertical_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\"
10713
10825
  //#region ../../shared/common/icons/rotate-left-solid.svg?raw
10714
10826
  var rotate_left_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d=\"M48.5 224L40 224c-13.3 0-24-10.7-24-24L16 72c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2L98.6 96.6c87.6-86.5 228.7-86.2 315.8 1c87.5 87.5 87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3c-62.2-62.2-162.7-62.5-225.3-1L185 183c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8L48.5 224z\"/></svg>";
10715
10827
  //#endregion
10716
- //#region src/icons.js
10828
+ //#region src/icons.ts
10717
10829
  var superdocIcons = {
10718
10830
  comment: comment_solid_default,
10719
10831
  caretDown: caret_down_solid_default,
@@ -10798,8 +10910,8 @@ var scrollThreadAnchorToFocusTarget = (presentation, primaryThreadId, fallbackTh
10798
10910
  var DEFAULT_UI_FONT_FAMILY$1 = "Arial, Helvetica, sans-serif";
10799
10911
  function configuredUiFontFamily(proxy) {
10800
10912
  const superdoc = proxy ? Reflect.get(proxy, "$superdoc") : void 0;
10801
- const config = require_create_super_doc_ui.isPlainObject(superdoc) ? superdoc.config : void 0;
10802
- return require_create_super_doc_ui.isPlainObject(config) ? config.uiDisplayFallbackFont : void 0;
10913
+ const config = require__plugin_vue_export_helper.isPlainObject(superdoc) ? superdoc.config : void 0;
10914
+ return require__plugin_vue_export_helper.isPlainObject(config) ? config.uiDisplayFallbackFont : void 0;
10803
10915
  }
10804
10916
  /**
10805
10917
  * Vue composable that returns the computed UI font-family for SuperDoc surfaces.
@@ -11077,12 +11189,9 @@ var InternalDropdown_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
11077
11189
  //#region src/components/CommentsLayer/InternalDropdown.vue
11078
11190
  var InternalDropdown_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(InternalDropdown_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-026f5d66"]]);
11079
11191
  //#endregion
11080
- //#region src/components/CommentsLayer/helpers.js
11192
+ //#region src/components/CommentsLayer/helpers.ts
11081
11193
  /**
11082
11194
  * Comments helper to format dates from timestamp
11083
- *
11084
- * @param {Number} timestamp The timestamp to format
11085
- * @returns {String} The formatted date
11086
11195
  */
11087
11196
  function formatDate(timestamp) {
11088
11197
  const date = new Date(timestamp);
@@ -11683,7 +11792,7 @@ var CommentInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ req
11683
11792
  //#region src/components/CommentsLayer/CommentInput.vue
11684
11793
  var CommentInput_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(CommentInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-aa97de44"]]);
11685
11794
  //#endregion
11686
- //#region src/internal/toolbar/built-in/url-safety.js
11795
+ //#region src/internal/toolbar/built-in/url-safety.ts
11687
11796
  /**
11688
11797
  * Minimal href sanitizer for the built-in link popover.
11689
11798
  *
@@ -11699,8 +11808,6 @@ var DANGEROUS_SCHEME = /^(javascript|data|vbscript):/i;
11699
11808
  var HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
11700
11809
  /**
11701
11810
  * Validate and normalize an href. Returns `{ href }` for safe values, or `null`.
11702
- * @param {string} value
11703
- * @returns {{ href: string }|null}
11704
11811
  */
11705
11812
  function sanitizeHref(value) {
11706
11813
  if (typeof value !== "string") return null;
@@ -11712,7 +11819,7 @@ function sanitizeHref(value) {
11712
11819
  return { href: trimmed };
11713
11820
  }
11714
11821
  //#endregion
11715
- //#region src/components/CommentsLayer/comment-urls.js
11822
+ //#region src/components/CommentsLayer/comment-urls.ts
11716
11823
  function isAbsoluteWebUrl(value) {
11717
11824
  if (!/^https?:\/\/[^\s/?#\\]+/i.test(value) || /[\s\\]/u.test(value)) return false;
11718
11825
  try {
@@ -11736,7 +11843,7 @@ function trimUrlPunctuation(value) {
11736
11843
  for (const character of value) {
11737
11844
  const close = closingDelimiter[character];
11738
11845
  if (close) balance[close] += 1;
11739
- else if (Object.hasOwn(balance, character)) balance[character] -= 1;
11846
+ else if (Object.prototype.hasOwnProperty.call(balance, character)) balance[character] -= 1;
11740
11847
  }
11741
11848
  let end = value.length;
11742
11849
  while (end > 0) {
@@ -11760,17 +11867,18 @@ function renderCommentHtml(value) {
11760
11867
  if (typeof document === "undefined") return value;
11761
11868
  const template = document.createElement("template");
11762
11869
  template.innerHTML = value;
11763
- for (const link of template.content.querySelectorAll("a")) {
11764
- const safe = sanitizeHref(link.getAttribute("href"));
11870
+ for (const link of Array.from(template.content.querySelectorAll("a"))) {
11871
+ const rawHref = link.getAttribute("href");
11872
+ const safe = rawHref === null ? null : sanitizeHref(rawHref);
11765
11873
  if (safe && (isAbsoluteWebUrl(safe.href) || /^(mailto|tel):\S+$/i.test(safe.href))) configureLink(link, safe.href);
11766
- else link.replaceWith(...link.childNodes);
11874
+ else link.replaceWith(...Array.from(link.childNodes));
11767
11875
  }
11768
11876
  const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
11769
11877
  const textNodes = [];
11770
- while (walker.nextNode()) textNodes.push(walker.currentNode);
11878
+ while (walker.nextNode()) if (walker.currentNode instanceof Text) textNodes.push(walker.currentNode);
11771
11879
  for (const node of textNodes) {
11772
11880
  if (node.parentElement?.closest("a, script, style, textarea, code, pre")) continue;
11773
- const text = node.textContent;
11881
+ const text = node.data;
11774
11882
  const fragment = document.createDocumentFragment();
11775
11883
  let end = 0;
11776
11884
  for (const match of text.matchAll(/(^|[\s([{])(https?:\/\/[^\s<>"']+)/gi)) {
@@ -11829,8 +11937,8 @@ var _hoisted_11$3 = {
11829
11937
  key: 0,
11830
11938
  class: "card-section comment-body"
11831
11939
  };
11832
- var _hoisted_12$2 = ["data-track-change-semantic-color-key"];
11833
- var _hoisted_13$2 = { key: 0 };
11940
+ var _hoisted_12$3 = ["data-track-change-semantic-color-key"];
11941
+ var _hoisted_13$3 = { key: 0 };
11834
11942
  var _hoisted_14$2 = { class: "change-type tracked-change-label" };
11835
11943
  var _hoisted_15$2 = {
11836
11944
  key: 0,
@@ -13002,7 +13110,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13002
13110
  "data-track-change-semantic-color-key": comment.semanticColorKey ?? void 0,
13003
13111
  ref_for: true,
13004
13112
  ref: index === 0 ? setParentBodyRef : void 0
13005
- }, [comment.trackedChangeLabel ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_13$2, [require__plugin_vue_export_helper.createElementVNode("span", _hoisted_14$2, require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeLabel), 1), comment.trackedChangeDetailLines && comment.trackedChangeDetailLines.length ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_15$2, [(require__plugin_vue_export_helper.openBlock(true), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, null, require__plugin_vue_export_helper.renderList(comment.trackedChangeDetailLines, (line, lineIndex) => {
13113
+ }, [comment.trackedChangeLabel ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_13$3, [require__plugin_vue_export_helper.createElementVNode("span", _hoisted_14$2, require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeLabel), 1), comment.trackedChangeDetailLines && comment.trackedChangeDetailLines.length ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_15$2, [(require__plugin_vue_export_helper.openBlock(true), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, null, require__plugin_vue_export_helper.renderList(comment.trackedChangeDetailLines, (line, lineIndex) => {
13006
13114
  return require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
13007
13115
  key: lineIndex,
13008
13116
  class: "tracked-change-detail-line"
@@ -13027,7 +13135,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13027
13135
  style: require__plugin_vue_export_helper.normalizeStyle(trackedChangeImagePreviewStyle(comment.trackedChangeImagePreview)),
13028
13136
  loading: "lazy",
13029
13137
  decoding: "async"
13030
- }, null, 12, _hoisted_38)], 8, _hoisted_37)) : require__plugin_vue_export_helper.createCommentVNode("", true)], 10, _hoisted_12$2),
13138
+ }, null, 12, _hoisted_38)], 8, _hoisted_37)) : require__plugin_vue_export_helper.createCommentVNode("", true)], 10, _hoisted_12$3),
13031
13139
  shouldTruncate.value && isTextOverflowing.value && index === 0 ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
13032
13140
  key: 0,
13033
13141
  class: "show-more-toggle",
@@ -13124,7 +13232,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13124
13232
  });
13125
13233
  //#endregion
13126
13234
  //#region src/components/CommentsLayer/CommentDialog.vue
13127
- var CommentDialog_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(CommentDialog_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-4220ce17"]]);
13235
+ var CommentDialog_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(CommentDialog_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-c0cc448b"]]);
13128
13236
  //#endregion
13129
13237
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue?vue&type=script&setup=true&lang.ts
13130
13238
  var _hoisted_1$25 = [
@@ -13454,21 +13562,25 @@ var commentsList_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ req
13454
13562
  //#region src/components/CommentsLayer/commentsList/commentsList.vue
13455
13563
  var commentsList_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(commentsList_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-8eca48e1"]]);
13456
13564
  //#endregion
13457
- //#region src/components/CommentsLayer/commentsList/super-comments-list.js
13565
+ //#region src/components/CommentsLayer/commentsList/super-comments-list.ts
13566
+ var isReviewDirectoryStore = (value) => require__plugin_vue_export_helper.isPlainObject(value) && typeof value.setReviewDirectoryFromV2 === "function" && typeof value.clearReviewDirectory === "function";
13567
+ var readCommentsStore = (superdoc) => {
13568
+ const store = superdoc?.["commentsStore"];
13569
+ return isReviewDirectoryStore(store) ? store : void 0;
13570
+ };
13458
13571
  /**
13459
13572
  * Comments list renderer (not floating comments)
13460
13573
  *
13461
13574
  * This renders a list of comments into an element, connected to main SuperDoc instance
13462
13575
  */
13463
13576
  var SuperComments = class extends require_eventemitter3.import_eventemitter3.default {
13464
- element;
13465
- config = {
13466
- comments: [],
13467
- element: null,
13468
- commentsStore: null
13469
- };
13470
13577
  constructor(options, superdoc) {
13471
13578
  super();
13579
+ this.config = {
13580
+ comments: [],
13581
+ element: null,
13582
+ commentsStore: null
13583
+ };
13472
13584
  this.config = {
13473
13585
  ...this.config,
13474
13586
  ...options
@@ -13489,7 +13601,7 @@ var SuperComments = class extends require_eventemitter3.import_eventemitter3.def
13489
13601
  this.open();
13490
13602
  }
13491
13603
  syncDirectory() {
13492
- const store = this.superdoc?.commentsStore;
13604
+ const store = readCommentsStore(this.superdoc);
13493
13605
  if (!store) return;
13494
13606
  const comments = this.directorySnapshots.comments;
13495
13607
  const trackChanges = this.directorySnapshots.trackChanges;
@@ -13507,12 +13619,14 @@ var SuperComments = class extends require_eventemitter3.import_eventemitter3.def
13507
13619
  const acceptDirectorySnapshot = (snapshot) => {
13508
13620
  if (generation !== this.directoryGeneration) return;
13509
13621
  if ((snapshot?.listStatus ?? snapshot?.status) !== "ready") {
13510
- if (this.superdoc?.commentsStore) this.superdoc.commentsStore.isReviewDirectoryLoading = true;
13622
+ const store = readCommentsStore(this.superdoc);
13623
+ if (store) store.isReviewDirectoryLoading = true;
13511
13624
  return;
13512
13625
  }
13513
13626
  const items = Array.isArray(snapshot.items) ? snapshot.items : [];
13514
13627
  if (this.directoryItemRefs[family] === items) {
13515
- if (this.superdoc?.commentsStore) this.superdoc.commentsStore.isReviewDirectoryLoading = this.directorySnapshots.comments == null || this.directorySnapshots.trackChanges == null;
13628
+ const store = readCommentsStore(this.superdoc);
13629
+ if (store) store.isReviewDirectoryLoading = this.directorySnapshots.comments == null || this.directorySnapshots.trackChanges == null;
13516
13630
  return;
13517
13631
  }
13518
13632
  this.directoryItemRefs[family] = items;
@@ -13529,15 +13643,16 @@ var SuperComments = class extends require_eventemitter3.import_eventemitter3.def
13529
13643
  };
13530
13644
  const ui = this.superdoc?.ui;
13531
13645
  if (!ui) return;
13532
- if (this.superdoc?.commentsStore) {
13533
- this.superdoc.commentsStore.isReviewDirectoryActive = true;
13534
- this.superdoc.commentsStore.isReviewDirectoryLoading = true;
13646
+ const store = readCommentsStore(this.superdoc);
13647
+ if (store) {
13648
+ store.isReviewDirectoryActive = true;
13649
+ store.isReviewDirectoryLoading = true;
13535
13650
  }
13536
13651
  this.stopDirectoryObservers = [subscribe(ui.comments, "comments"), subscribe(ui.trackChanges, "trackChanges")];
13537
13652
  }
13538
13653
  createVueApp() {
13539
13654
  this.app = require__plugin_vue_export_helper.createApp(commentsList_default);
13540
- const parentProvides = this.superdoc?.app?._context?.provides;
13655
+ const parentProvides = this.superdoc?.["app"]?._context?.provides;
13541
13656
  if (parentProvides && this.app?._context?.provides) Object.setPrototypeOf(this.app._context.provides, parentProvides);
13542
13657
  if (this.superdoc?.pinia) {
13543
13658
  setActivePinia(this.superdoc.pinia);
@@ -13561,10 +13676,11 @@ var SuperComments = class extends require_eventemitter3.import_eventemitter3.def
13561
13676
  comments: null,
13562
13677
  trackChanges: null
13563
13678
  };
13564
- if (this.superdoc?.commentsStore) {
13565
- this.superdoc.commentsStore.clearReviewDirectory();
13566
- this.superdoc.commentsStore.isReviewDirectoryActive = false;
13567
- this.superdoc.commentsStore.isReviewDirectoryLoading = false;
13679
+ const store = readCommentsStore(this.superdoc);
13680
+ if (store) {
13681
+ store.clearReviewDirectory();
13682
+ store.isReviewDirectoryActive = false;
13683
+ store.isReviewDirectoryLoading = false;
13568
13684
  }
13569
13685
  if (this.app) {
13570
13686
  this.app.unmount();
@@ -13578,7 +13694,7 @@ var SuperComments = class extends require_eventemitter3.import_eventemitter3.def
13578
13694
  }
13579
13695
  };
13580
13696
  //#endregion
13581
- //#region src/composables/use-viewport-fit.js
13697
+ //#region src/composables/use-viewport-fit.ts
13582
13698
  var CSS_PX_PER_INCH = 96;
13583
13699
  var SIDEBAR_SELECTOR = ".superdoc__right-sidebar";
13584
13700
  var PDF_PAGE_SELECTOR = ".sd-pdf-viewer-page";
@@ -13683,7 +13799,7 @@ function useViewportFit({ getSuperdoc, superdocContainerWidth, isReady, activeZo
13683
13799
  const root = superdocRoot.value;
13684
13800
  if (!root?.querySelectorAll) return null;
13685
13801
  let widest = 0;
13686
- for (const page of root.querySelectorAll(PDF_PAGE_SELECTOR)) {
13802
+ for (const page of Array.from(root.querySelectorAll(PDF_PAGE_SELECTOR))) {
13687
13803
  const measured = Number(page.clientWidth) || Number(page.getBoundingClientRect?.().width) || 0;
13688
13804
  let scaleFactor = NaN;
13689
13805
  if (typeof window !== "undefined" && typeof window.getComputedStyle === "function") scaleFactor = Number.parseFloat(window.getComputedStyle(page).getPropertyValue("--scale-factor"));
@@ -13885,124 +14001,6 @@ var composeAuthorColorResolver = (config) => {
13885
14001
  };
13886
14002
  };
13887
14003
  //#endregion
13888
- //#region ../document-api/src/errors.ts
13889
- /**
13890
- * Structured validation error thrown by document-api execute* functions.
13891
- *
13892
- * Consumers should prefer checking `error.code` over `instanceof` for resilience
13893
- * across package boundaries and bundling scenarios.
13894
- */
13895
- var DocumentApiValidationError = class DocumentApiValidationError extends Error {
13896
- constructor(code, message, details) {
13897
- super(message);
13898
- this.name = "DocumentApiValidationError";
13899
- this.code = code;
13900
- this.details = details;
13901
- Object.setPrototypeOf(this, DocumentApiValidationError.prototype);
13902
- }
13903
- };
13904
- //#endregion
13905
- //#region ../document-api/src/export/export.types.ts
13906
- /** Canonical tracked-change export modes accepted by every public export surface. */
13907
- var SD_EXPORT_MODES = [
13908
- "review-preserving",
13909
- "final",
13910
- "original"
13911
- ];
13912
- /** Default mode for modeful DOCX export. */
13913
- var DEFAULT_SD_EXPORT_MODE = "review-preserving";
13914
- var SD_COMMENT_EXPORT_POLICIES = [
13915
- "preserve",
13916
- "resolve",
13917
- "remove"
13918
- ];
13919
- var SD_CONTENT_CONTROL_EXPORT_POLICIES = ["preserve", "flatten"];
13920
- //#endregion
13921
- //#region ../document-api/src/export/export.ts
13922
- /**
13923
- * Export namespace: engine-agnostic public API and adapter contract.
13924
- *
13925
- * Validates the requested mode at the public boundary so an invalid mode fails
13926
- * closed with `INVALID_INPUT` before any document work happens, then delegates
13927
- * byte production and degradation reporting to the engine adapter.
13928
- */
13929
- function resolveMode$1(input) {
13930
- if (input != null && !require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "export.toDocx input must be an object.");
13931
- const raw = input?.mode;
13932
- if (raw === void 0) return DEFAULT_SD_EXPORT_MODE;
13933
- if (typeof raw !== "string" || !SD_EXPORT_MODES.includes(raw)) throw new DocumentApiValidationError("INVALID_INPUT", `export.toDocx mode must be one of: ${SD_EXPORT_MODES.join(", ")}.`, {
13934
- mode: raw,
13935
- allowedModes: [...SD_EXPORT_MODES]
13936
- });
13937
- return raw;
13938
- }
13939
- function resolveDocxExportPolicies(input = {}) {
13940
- if (!require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export input must be an object.");
13941
- const mode = resolveMode$1(input);
13942
- const policies = input.policies;
13943
- if (policies !== void 0 && !require_create_super_doc_ui.isRecord(policies)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export policies must be an object.");
13944
- const allowed = {
13945
- trackedChanges: SD_EXPORT_MODES,
13946
- comments: SD_COMMENT_EXPORT_POLICIES,
13947
- contentControls: SD_CONTENT_CONTROL_EXPORT_POLICIES
13948
- };
13949
- for (const [key, value] of Object.entries(policies ?? {})) if (!Object.prototype.hasOwnProperty.call(allowed, key) || value !== void 0 && !allowed[key].includes(value)) throw new DocumentApiValidationError("INVALID_INPUT", `Unsupported DOCX export policy: ${key}.`, {
13950
- policy: key,
13951
- value
13952
- });
13953
- const requested = policies;
13954
- if (input.mode !== void 0 && requested?.trackedChanges !== void 0 && mode !== requested.trackedChanges) throw new DocumentApiValidationError("INVALID_INPUT", "mode conflicts with policies.trackedChanges.");
13955
- return {
13956
- trackedChanges: requested?.trackedChanges ?? mode,
13957
- comments: requested?.comments ?? "preserve",
13958
- contentControls: requested?.contentControls ?? "preserve"
13959
- };
13960
- }
13961
- //#endregion
13962
- //#region ../document-api/src/permission-ranges/permission-ranges.ts
13963
- function editorKey(editor) {
13964
- return editor.id?.trim() ? editor.id : editor.email?.trim() || void 0;
13965
- }
13966
- function editorMatches(editor, id) {
13967
- return Boolean(id.trim()) && (editor.id === id || Boolean(editor.email?.trim() && editor.email.trim().toLowerCase() === id.toLowerCase()));
13968
- }
13969
- /**
13970
- * Resolve a host ID or imported Word email against an explicitly supplied roster.
13971
- * Word receives the email when available; opaque IDs remain host-specific.
13972
- * Duplicate IDs/emails are ambiguous. This does not authenticate a user.
13973
- */
13974
- function resolvePermissionRangeEditor(editors, id) {
13975
- const matches = editors.filter((editor) => editorMatches(editor, id));
13976
- if (matches.length === 0) return {
13977
- status: "unknown",
13978
- id
13979
- };
13980
- if (matches.length !== 1) return {
13981
- status: "ambiguous",
13982
- id
13983
- };
13984
- const editor = matches[0];
13985
- const wordId = editor.email?.trim() || editor.id;
13986
- if (editors.filter((candidate) => editorMatches(candidate, wordId)).length !== 1) return {
13987
- status: "ambiguous",
13988
- id
13989
- };
13990
- return {
13991
- status: "resolved",
13992
- id,
13993
- editor: { ...editor },
13994
- principal: {
13995
- kind: "editor",
13996
- id: wordId
13997
- }
13998
- };
13999
- }
14000
- /** Enumerate the host roster for an editor picker, including ambiguous entries. */
14001
- function listPermissionRangeEditors(editors) {
14002
- const ids = new Set(editors.map(editorKey).filter((id) => id !== void 0));
14003
- return Array.from(ids, (id) => resolvePermissionRangeEditor(editors, id));
14004
- }
14005
- //#endregion
14006
14004
  //#region src/core/superdoc-ui-owner.ts
14007
14005
  var ownerIds = /* @__PURE__ */ new WeakMap();
14008
14006
  function getSuperDocUiOwnerId(superdoc) {
@@ -15064,7 +15062,7 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15064
15062
  });
15065
15063
  //#endregion
15066
15064
  //#region src/components/CommentsLayer/FloatingComments.vue
15067
- var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(FloatingComments_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-aaf2c537"]]);
15065
+ var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(FloatingComments_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-df897b8d"]]);
15068
15066
  //#endregion
15069
15067
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue?vue&type=script&setup=true&lang.ts
15070
15068
  var _hoisted_1$22 = {
@@ -15198,7 +15196,7 @@ var PdfCommentsLayer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15198
15196
  });
15199
15197
  //#endregion
15200
15198
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue
15201
- var PdfCommentsLayer_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(PdfCommentsLayer_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-86166837"]]);
15199
+ var PdfCommentsLayer_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(PdfCommentsLayer_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e3ae65fa"]]);
15202
15200
  //#endregion
15203
15201
  //#region src/components/Whiteboard/use-whiteboard.ts
15204
15202
  var useWhiteboard = ({ proxy, layers, documents, modules }) => {
@@ -15493,7 +15491,7 @@ var WhiteboardPage_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ r
15493
15491
  });
15494
15492
  //#endregion
15495
15493
  //#region src/components/Whiteboard/WhiteboardPage.vue
15496
- var WhiteboardPage_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(WhiteboardPage_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-f730b33d"]]);
15494
+ var WhiteboardPage_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(WhiteboardPage_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-fdae8749"]]);
15497
15495
  //#endregion
15498
15496
  //#region src/components/Whiteboard/WhiteboardLayer.vue?vue&type=script&setup=true&lang.ts
15499
15497
  var WhiteboardLayer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require__plugin_vue_export_helper.defineComponent({
@@ -15567,16 +15565,11 @@ var WhiteboardLayer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15567
15565
  });
15568
15566
  //#endregion
15569
15567
  //#region src/components/Whiteboard/WhiteboardLayer.vue
15570
- var WhiteboardLayer_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(WhiteboardLayer_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-980e1f94"]]);
15568
+ var WhiteboardLayer_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(WhiteboardLayer_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-800e1970"]]);
15571
15569
  //#endregion
15572
- //#region src/components/CommentsLayer/collect-removed-comment-ids.js
15570
+ //#region src/components/CommentsLayer/collect-removed-comment-ids.ts
15573
15571
  /**
15574
15572
  * Expand deleted comment ids through comment and tracked-change descendants.
15575
- *
15576
- * @param {ReadonlyArray<Record<string, any>>} comments
15577
- * @param {ReadonlyArray<string>} targetIds
15578
- * @param {(comment: Record<string, any>) => boolean} [isInScope]
15579
- * @returns {Set<string>}
15580
15573
  */
15581
15574
  var collectRemovedCommentIds = (comments, targetIds, isInScope = () => true) => {
15582
15575
  const targets = new Set(targetIds.map(String));
@@ -15638,7 +15631,7 @@ function isActiveTrackedChangeContextMenuTarget(target) {
15638
15631
  function normalizeCommentsUiConfig(commentsConfig) {
15639
15632
  if (!commentsConfig || typeof commentsConfig !== "object") return commentsConfig;
15640
15633
  const normalized = { ...commentsConfig };
15641
- const responsive = require_create_super_doc_ui.isPlainObject(commentsConfig.responsive) ? commentsConfig.responsive : {};
15634
+ const responsive = require__plugin_vue_export_helper.isPlainObject(commentsConfig.responsive) ? commentsConfig.responsive : {};
15642
15635
  const layout = firstDefined$1(commentsConfig.layout, commentsConfig.displayMode);
15643
15636
  const target = normalizeResponsiveTarget(firstDefined$1(responsive.target, commentsConfig.compactMeasurementSelector));
15644
15637
  const breakpoint = firstDefined$1(responsive.breakpoint, commentsConfig.compactBreakpointPx);
@@ -15659,7 +15652,7 @@ function normalizeCommentsUiConfig(commentsConfig) {
15659
15652
  return normalized;
15660
15653
  }
15661
15654
  //#endregion
15662
- //#region src/composables/use-comment-small-screen.js
15655
+ //#region src/composables/use-comment-small-screen.ts
15663
15656
  var SUPERDOC_DOCUMENT_SELECTOR = ".superdoc__document";
15664
15657
  var isValidCompactBreakpoint = (value) => {
15665
15658
  return require_is_finite_number.isFiniteNumber(value) && value >= 0;
@@ -15739,10 +15732,11 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
15739
15732
  }
15740
15733
  documentWidthTargets = nextTargets;
15741
15734
  if (!nextTargets.length) return;
15742
- documentWidthResizeObserver = new ResizeObserverClass(() => {
15735
+ const observer = new ResizeObserverClass(() => {
15743
15736
  recalculateCompactCommentsMode();
15744
15737
  });
15745
- nextTargets.forEach((el) => documentWidthResizeObserver.observe(el));
15738
+ documentWidthResizeObserver = observer;
15739
+ nextTargets.forEach((el) => observer.observe(el));
15746
15740
  };
15747
15741
  const getMeasuredDocumentWidth = () => {
15748
15742
  ensureDocumentWidthObserver();
@@ -15798,7 +15792,7 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
15798
15792
  };
15799
15793
  }
15800
15794
  //#endregion
15801
- //#region src/composables/use-compact-comment-popover.js
15795
+ //#region src/composables/use-compact-comment-popover.ts
15802
15796
  var POPOVER_WIDTH_PX = 320;
15803
15797
  var SAFE_MARGIN_PX = 12;
15804
15798
  var MIN_BOTTOM_SPACE_PX = 220;
@@ -15828,7 +15822,7 @@ var resolveInteractionAnchor = (lastClickAnchor) => {
15828
15822
  var resolveInlineHighlightAnchorRect = ({ rootEl, comment, pendingComment }) => {
15829
15823
  if (Boolean(pendingComment?.value && comment?.commentId === pendingComment.value?.commentId)) {
15830
15824
  const nodes = rootEl.querySelectorAll(COMMENT_HIGHLIGHT_SELECTOR);
15831
- for (const node of nodes) {
15825
+ for (const node of Array.from(nodes)) {
15832
15826
  if (!parseCommentIds(node.getAttribute(COMMENT_HIGHLIGHT_DATA_ATTR)).includes("pending")) continue;
15833
15827
  if (typeof node.getBoundingClientRect !== "function") continue;
15834
15828
  return node.getBoundingClientRect();
@@ -15838,7 +15832,7 @@ var resolveInlineHighlightAnchorRect = ({ rootEl, comment, pendingComment }) =>
15838
15832
  if (!anchorId) return null;
15839
15833
  const safeId = String(anchorId);
15840
15834
  const highlightNodes = rootEl.querySelectorAll(COMMENT_HIGHLIGHT_SELECTOR);
15841
- for (const node of highlightNodes) {
15835
+ for (const node of Array.from(highlightNodes)) {
15842
15836
  if (!parseCommentIds(node.getAttribute(COMMENT_HIGHLIGHT_DATA_ATTR)).includes(safeId)) continue;
15843
15837
  if (typeof node.getBoundingClientRect !== "function") continue;
15844
15838
  return node.getBoundingClientRect();
@@ -15923,9 +15917,10 @@ function useCompactCommentPopover({ activeComment, pendingComment, activeCompact
15923
15917
  };
15924
15918
  const trackCompactPopoverClickAnchor = (e) => {
15925
15919
  const root = superdocRoot.value;
15926
- if (!root || !layers.value?.contains(e.target)) return;
15927
- const anchorElement = (typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(e.clientX, e.clientY) : []).find((node) => node?.nodeType === 1 && root.contains(node) && node.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor"))?.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor") ?? (e.target?.nodeType === 1 ? e.target.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor") : null);
15928
- if (clearCompactPopoverIfPdfClickedOutside(root, e.target, anchorElement)) return;
15920
+ const target = e.target instanceof Node ? e.target : null;
15921
+ if (!root || !layers.value?.contains(target)) return;
15922
+ const anchorElement = (typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(e.clientX, e.clientY) : []).find((node) => node?.nodeType === 1 && root.contains(node) && node.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor"))?.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor") ?? (target instanceof Element ? target.closest("[data-track-change-id], .superdoc-comment-highlight, .sd-comment-anchor") : null);
15923
+ if (clearCompactPopoverIfPdfClickedOutside(root, target, anchorElement)) return;
15929
15924
  if (e.button !== 0 || e.pointerType !== "mouse") return;
15930
15925
  const anchorRect = anchorElement && typeof anchorElement.getBoundingClientRect === "function" ? anchorElement.getBoundingClientRect() : null;
15931
15926
  if (!anchorRect) return;
@@ -16128,10 +16123,10 @@ function mergeCommentsConfig(config, presentation) {
16128
16123
  * existing UI suppression rules keep their current behavior.
16129
16124
  */
16130
16125
  function normalizeHyperlinksConfig(config = {}) {
16131
- const canonical = require_create_super_doc_ui.isPlainObject(config.hyperlinks) ? config.hyperlinks : {};
16126
+ const canonical = require__plugin_vue_export_helper.isPlainObject(config.hyperlinks) ? config.hyperlinks : {};
16132
16127
  const hasCanonicalHandler = typeof canonical.onActivate === "function";
16133
- const ui = require_create_super_doc_ui.isPlainObject(config.ui) ? config.ui : {};
16134
- const legacyUi = require_create_super_doc_ui.isPlainObject(ui.linkPopover) ? ui.linkPopover : {};
16128
+ const ui = require__plugin_vue_export_helper.isPlainObject(config.ui) ? config.ui : {};
16129
+ const legacyUi = require__plugin_vue_export_helper.isPlainObject(ui.linkPopover) ? ui.linkPopover : {};
16135
16130
  const allActivationDisabled = config.hyperlinks === false;
16136
16131
  const builtInEditorDisabled = config.ui === false || ui.linkPopover === false;
16137
16132
  const selectedHandler = [
@@ -16159,7 +16154,7 @@ function normalizeHyperlinksConfig(config = {}) {
16159
16154
  };
16160
16155
  }
16161
16156
  //#endregion
16162
- //#region src/helpers/v2-review-target.js
16157
+ //#region src/helpers/v2-review-target.ts
16163
16158
  /**
16164
16159
  * Resolve the comments-store identity for a document-origin v2 review target.
16165
16160
  * Painted review carriers can become interactive before the asynchronous row
@@ -16175,15 +16170,126 @@ function resolveV2ReviewTargetCommentId(target, getComment) {
16175
16170
  return commentId != null ? String(commentId) : null;
16176
16171
  }
16177
16172
  //#endregion
16178
- //#region src/helpers/v2-mutation-exception.js
16173
+ //#region src/helpers/v2-review-geometry-delivery.ts
16174
+ function createReviewGeometryDelivery(deliver) {
16175
+ const packets = /* @__PURE__ */ new Map();
16176
+ let stageOwners = /* @__PURE__ */ new WeakMap();
16177
+ let active = null;
16178
+ const documentOf = (current) => current.documentId != null ? String(current.documentId) : current.mountContainer?.dataset.superdocV2DocumentId ?? null;
16179
+ const matches = (documentId, current) => current.mountContainer?.dataset.superdocV2DocumentId === documentId && (current.documentId == null || String(current.documentId) === documentId);
16180
+ const matchesPaint = (packet, current) => typeof packet.payload.paintEpoch !== "number" || packet.payload.paintEpoch === current.epoch;
16181
+ const observe = (current) => {
16182
+ const stage = current.mountContainer;
16183
+ const documentId = documentOf(current);
16184
+ if (!stage || !documentId || !matches(documentId, current)) return;
16185
+ const previousOwner = stageOwners.get(stage);
16186
+ if (previousOwner && previousOwner !== documentId) packets.delete(previousOwner);
16187
+ stageOwners.set(stage, documentId);
16188
+ const packet = packets.get(documentId);
16189
+ if (packet?.stage && packet.stage !== stage) packets.delete(documentId);
16190
+ else if (packet && (!active || active.stage !== stage || active.documentId !== documentId || active.epoch !== current.epoch)) packet.delivered = false;
16191
+ active = {
16192
+ documentId,
16193
+ stage,
16194
+ epoch: current.epoch
16195
+ };
16196
+ };
16197
+ const dispatch = (documentId, packet, current, replay = false) => {
16198
+ if (!current.mountContainer || !matches(documentId, current) || !matchesPaint(packet, current)) return false;
16199
+ if (packet.stage && packet.stage !== current.mountContainer || packet.delivering || packet.delivered && !replay) return false;
16200
+ const wasDelivered = packet.delivered;
16201
+ const previousStage = packet.stage;
16202
+ packet.stage = current.mountContainer;
16203
+ packet.delivered = true;
16204
+ packet.delivering = true;
16205
+ try {
16206
+ deliver(current, packet.payload);
16207
+ } catch (error) {
16208
+ packet.delivered = wasDelivered;
16209
+ packet.stage = previousStage;
16210
+ throw error;
16211
+ } finally {
16212
+ packet.delivering = false;
16213
+ }
16214
+ return true;
16215
+ };
16216
+ const notify = (documentId, payload, current, ready = true) => {
16217
+ if (!payload.reviewGeometry || !Array.isArray(payload.pageIndices)) return false;
16218
+ let key;
16219
+ try {
16220
+ key = JSON.stringify([
16221
+ documentId,
16222
+ payload.documentEpoch,
16223
+ payload.paintEpoch,
16224
+ payload.commitSequence,
16225
+ payload.pageIndices,
16226
+ payload.zoomScale,
16227
+ payload.reviewGeometry
16228
+ ]);
16229
+ } catch {
16230
+ return false;
16231
+ }
16232
+ const isCurrent = current != null && matches(documentId, current);
16233
+ if (isCurrent) observe(current);
16234
+ const previous = packets.get(documentId);
16235
+ if (previous && previous.payload.documentEpoch === payload.documentEpoch && typeof previous.payload.paintEpoch === "number" && typeof payload.paintEpoch === "number" && payload.paintEpoch < previous.payload.paintEpoch) return false;
16236
+ if (previous && previous.payload.documentEpoch === payload.documentEpoch && typeof previous.payload.commitSequence === "number" && typeof payload.commitSequence === "number" && payload.commitSequence < previous.payload.commitSequence) return false;
16237
+ if (previous && previous.payload.documentEpoch === payload.documentEpoch && typeof previous.payload.generation === "number" && typeof payload.generation === "number" && payload.generation < previous.payload.generation) return false;
16238
+ if (isCurrent && typeof payload.paintEpoch === "number" && typeof current.epoch === "number" && payload.paintEpoch < current.epoch) return false;
16239
+ if (previous?.key === key) {
16240
+ previous.payload = payload;
16241
+ return isCurrent && ready ? dispatch(documentId, previous, current) : false;
16242
+ }
16243
+ const packet = {
16244
+ payload,
16245
+ key,
16246
+ stage: isCurrent ? current.mountContainer : previous && previous.payload.documentEpoch === payload.documentEpoch ? previous.stage : null,
16247
+ delivered: false,
16248
+ delivering: false
16249
+ };
16250
+ packets.set(documentId, packet);
16251
+ if (!isCurrent || !ready) return false;
16252
+ try {
16253
+ return dispatch(documentId, packet, current);
16254
+ } catch (error) {
16255
+ if (previous) packets.set(documentId, previous);
16256
+ else packets.delete(documentId);
16257
+ throw error;
16258
+ }
16259
+ };
16260
+ return {
16261
+ notify,
16262
+ observe,
16263
+ flush(current) {
16264
+ observe(current);
16265
+ const documentId = documentOf(current);
16266
+ const packet = documentId == null ? null : packets.get(documentId);
16267
+ return documentId && packet ? dispatch(documentId, packet, current) : false;
16268
+ },
16269
+ replay(current) {
16270
+ observe(current);
16271
+ const documentId = documentOf(current);
16272
+ const packet = documentId == null ? null : packets.get(documentId);
16273
+ return documentId && packet ? dispatch(documentId, packet, current, true) : false;
16274
+ },
16275
+ reset() {
16276
+ packets.clear();
16277
+ stageOwners = /* @__PURE__ */ new WeakMap();
16278
+ active = null;
16279
+ }
16280
+ };
16281
+ }
16282
+ //#endregion
16283
+ //#region src/helpers/v2-mutation-exception.ts
16179
16284
  var FAILURE_SOURCES = /* @__PURE__ */ new Set(["shell", "receipt"]);
16180
16285
  var DIAGNOSTIC_CODE = /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/;
16181
16286
  var COMMAND_KIND = /^[a-z][a-z0-9-]*(?::[a-z][a-z0-9-]*)?$/;
16182
16287
  function createV2MutationRejectionCause(event) {
16183
- if (!event || typeof event !== "object") return {};
16184
- const reason = event.reason ?? (event.failureSource === "receipt" ? event.failure?.code : void 0);
16288
+ if (!require__plugin_vue_export_helper.isPlainObject(event)) return {};
16289
+ const failure = require__plugin_vue_export_helper.isPlainObject(event.failure) ? event.failure : void 0;
16290
+ const reason = event.reason ?? (event.failureSource === "receipt" ? failure?.code : void 0);
16185
16291
  return {
16186
- ...FAILURE_SOURCES.has(event.failureSource) ? { failureSource: event.failureSource } : {},
16292
+ ...typeof event.failureSource === "string" && FAILURE_SOURCES.has(event.failureSource) ? { failureSource: event.failureSource } : {},
16187
16293
  ...typeof reason === "string" && DIAGNOSTIC_CODE.test(reason) ? { reason } : {},
16188
16294
  ...typeof event.inputKind === "string" && DIAGNOSTIC_CODE.test(event.inputKind) ? { inputKind: event.inputKind } : {},
16189
16295
  ...typeof event.editableCommandKind === "string" && event.editableCommandKind.length <= 128 && COMMAND_KIND.test(event.editableCommandKind) ? { editableCommandKind: event.editableCommandKind } : {}
@@ -16211,7 +16317,7 @@ function createV2MutationRejectionNotificationGate(matches) {
16211
16317
  };
16212
16318
  }
16213
16319
  //#endregion
16214
- //#region src/helpers/v2-author-required-rejection.js
16320
+ //#region src/helpers/v2-author-required-rejection.ts
16215
16321
  var NO_AUTHOR_SIGNAL = "no-author-configured";
16216
16322
  /** Stable, non-terminal exception code surfaced to consumers. */
16217
16323
  var V2_AUTHOR_REQUIRED_CODE = "author-required";
@@ -16223,15 +16329,11 @@ var V2_AUTHOR_REQUIRED_MESSAGE = "This edit needs an author identity. Set `user.
16223
16329
  function messageHasNoAuthorSignal(message) {
16224
16330
  return typeof message === "string" && message.includes(NO_AUTHOR_SIGNAL);
16225
16331
  }
16226
- /**
16227
- * @param {any} event - a `v2-host-event` payload.
16228
- * @returns {boolean} true when the rejection means the session needs an author.
16229
- */
16230
16332
  function isV2AuthorRequiredRejection(event) {
16231
- if (!event || event.type !== "mutation:rejected") return false;
16333
+ if (!require__plugin_vue_export_helper.isPlainObject(event) || event.type !== "mutation:rejected") return false;
16232
16334
  if (event.failureSource === "receipt") {
16233
16335
  const failure = event.failure;
16234
- if (!failure) return false;
16336
+ if (!require__plugin_vue_export_helper.isPlainObject(failure)) return false;
16235
16337
  return failure.code === "PRECONDITION_FAILED" && messageHasNoAuthorSignal(failure.message);
16236
16338
  }
16237
16339
  if (event.failureSource === "shell") {
@@ -16244,7 +16346,7 @@ function createV2AuthorRequiredNotificationGate() {
16244
16346
  return createV2MutationRejectionNotificationGate(isV2AuthorRequiredRejection);
16245
16347
  }
16246
16348
  //#endregion
16247
- //#region src/helpers/v2-bulk-decision-event.js
16349
+ //#region src/helpers/v2-bulk-decision-event.ts
16248
16350
  function toV2BulkDecisionEvent(documentId, fact) {
16249
16351
  if (fact?.schemaVersion !== 1 || fact.decision !== "accept" && fact.decision !== "reject") return null;
16250
16352
  return {
@@ -16256,7 +16358,7 @@ function toV2BulkDecisionEvent(documentId, fact) {
16256
16358
  };
16257
16359
  }
16258
16360
  //#endregion
16259
- //#region src/helpers/v2-keyboard-edit-rejection.js
16361
+ //#region src/helpers/v2-keyboard-edit-rejection.ts
16260
16362
  var EDIT_INPUT_KINDS = /* @__PURE__ */ new Set([
16261
16363
  "keydown",
16262
16364
  "beforeinput",
@@ -16306,7 +16408,7 @@ var EDIT_FAILURE_SOURCES = /* @__PURE__ */ new Set(["shell", "receipt"]);
16306
16408
  var V2_EDIT_REJECTED_CODE = "edit-rejected";
16307
16409
  var V2_EDIT_REJECTED_MESSAGE = "This edit couldn’t be completed. Adjust the selection and try again.";
16308
16410
  function isV2KeyboardEditRejection(event) {
16309
- return Boolean(event && event.type === "mutation:rejected" && event.origin === "document-surface" && EDIT_FAILURE_SOURCES.has(event.failureSource) && EDIT_INPUT_KINDS.has(event.inputKind) && (EDIT_COMMAND_KINDS.has(event.editableCommandKind) || event.editableCommandKind == null && EDIT_INPUT_WITHOUT_COMMAND_KINDS.has(event.inputKind)));
16411
+ return require__plugin_vue_export_helper.isPlainObject(event) && event.type === "mutation:rejected" && event.origin === "document-surface" && EDIT_FAILURE_SOURCES.has(event.failureSource) && EDIT_INPUT_KINDS.has(event.inputKind) && (EDIT_COMMAND_KINDS.has(event.editableCommandKind) || event.editableCommandKind == null && EDIT_INPUT_WITHOUT_COMMAND_KINDS.has(event.inputKind));
16310
16412
  }
16311
16413
  function createV2KeyboardEditRejectionException(documentId, event) {
16312
16414
  return {
@@ -16320,24 +16422,17 @@ function createV2KeyboardEditRejectionNotificationGate() {
16320
16422
  return createV2MutationRejectionNotificationGate(isV2KeyboardEditRejection);
16321
16423
  }
16322
16424
  //#endregion
16323
- //#region src/helpers/v2-selection-sync.js
16425
+ //#region src/helpers/v2-selection-sync.ts
16324
16426
  /**
16325
16427
  * A logical v2 selection snapshot represents a non-empty range when its anchor
16326
16428
  * and focus point at different block positions. Mirrors the range check the v2
16327
16429
  * shell uses when it emits `v2-selection-changed`.
16328
- *
16329
- * @param {{ anchor?: { blockId?: unknown, blockOffset?: unknown }, focus?: { blockId?: unknown, blockOffset?: unknown } } | null | undefined} snapshot
16330
- * @returns {boolean}
16331
16430
  */
16332
16431
  var isV2RangeSnapshot = (snapshot) => Boolean(snapshot?.anchor && snapshot?.focus && (snapshot.anchor.blockId !== snapshot.focus.blockId || snapshot.anchor.blockOffset !== snapshot.focus.blockOffset));
16333
16432
  /**
16334
16433
  * Detect a real browser text selection whose endpoints are outside the active
16335
16434
  * v2 mount. Editable host selections can have no native DOM range, so an
16336
16435
  * absent range must not count as an outside selection.
16337
- *
16338
- * @param {Selection | null | undefined} selection
16339
- * @param {Node | null | undefined} root
16340
- * @returns {boolean}
16341
16436
  */
16342
16437
  var hasOutsideV2DomRangeSelection = (selection, root) => {
16343
16438
  if (!selection || selection.rangeCount < 1 || selection.isCollapsed || !root) return false;
@@ -16353,10 +16448,6 @@ var hasOutsideV2DomRangeSelection = (selection, root) => {
16353
16448
  * host snapshot rather than clobber the selection the host just published.
16354
16449
  * Only editable modes use the host snapshot. Viewing mode keeps native DOM
16355
16450
  * selection, and unknown modes should not preserve stale host state.
16356
- *
16357
- * @param {string | null | undefined} documentMode
16358
- * @param {unknown} hostSnapshot
16359
- * @returns {boolean}
16360
16451
  */
16361
16452
  var shouldPreserveHostV2Selection = (documentMode, hostSnapshot) => {
16362
16453
  if (documentMode !== "editing" && documentMode !== "suggesting") return false;
@@ -16367,10 +16458,6 @@ var shouldPreserveHostV2Selection = (documentMode, hostSnapshot) => {
16367
16458
  * rebuilt. Keep an already-positioned comment affordance during that gap when
16368
16459
  * the host still owns a range; otherwise the button unmounts and remounts on
16369
16460
  * consecutive paint frames, making it blink and intercepting its own click.
16370
- *
16371
- * @param {boolean} hasHostRange
16372
- * @param {{ source?: unknown } | null | undefined} selectionPosition
16373
- * @returns {boolean}
16374
16461
  */
16375
16462
  var shouldRetainV2FloatingSelection = (hasHostRange, selectionPosition) => hasHostRange === true && selectionPosition?.source === "document-editor";
16376
16463
  //#endregion
@@ -16562,7 +16649,7 @@ function usePasswordPrompt({ getSurfaceManager, getPasswordPromptConfig, onUnhan
16562
16649
  })
16563
16650
  });
16564
16651
  } else {
16565
- const mod = await Promise.resolve().then(() => require("./chunks/PasswordPromptSurface-BNkaztaP.cjs"));
16652
+ const mod = await Promise.resolve().then(() => require("./chunks/PasswordPromptSurface-VFPnQOML.cjs"));
16566
16653
  const surfaceId = `password-prompt-${doc.id}`;
16567
16654
  handle = manager.open({
16568
16655
  id: surfaceId,
@@ -16664,9 +16751,6 @@ function createReplaceContinuation(session, { getCurrentSession, applySlice, onS
16664
16751
  }
16665
16752
  //#endregion
16666
16753
  //#region src/composables/use-find-replace.ts
16667
- function isThenable$2(value) {
16668
- return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
16669
- }
16670
16754
  var DEFAULT_TEXTS = {
16671
16755
  findPlaceholder: "Find",
16672
16756
  findAriaLabel: "Find text",
@@ -16841,7 +16925,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
16841
16925
  try {
16842
16926
  result = search.replace(replaceText.value);
16843
16927
  } catch {}
16844
- if (isThenable$2(result)) Promise.resolve(result).then(finish, finish);
16928
+ if (require__plugin_vue_export_helper.isThenable(result)) Promise.resolve(result).then(finish, finish);
16845
16929
  else finish();
16846
16930
  }
16847
16931
  function replaceAll() {
@@ -16863,7 +16947,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
16863
16947
  try {
16864
16948
  result = search.replaceAll(replaceText.value);
16865
16949
  } catch {}
16866
- if (isThenable$2(result)) Promise.resolve(result).then(finish, finish);
16950
+ if (require__plugin_vue_export_helper.isThenable(result)) Promise.resolve(result).then(finish, finish);
16867
16951
  else finish();
16868
16952
  }
16869
16953
  function syncFromSearchSession() {
@@ -17225,7 +17309,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
17225
17309
  } else {
17226
17310
  let FindReplaceSurface;
17227
17311
  try {
17228
- FindReplaceSurface = (await Promise.resolve().then(() => require("./chunks/FindReplaceSurface-BNDrJ6VS.cjs"))).default;
17312
+ FindReplaceSurface = (await Promise.resolve().then(() => require("./chunks/FindReplaceSurface-DWXgWgg7.cjs"))).default;
17229
17313
  } catch {
17230
17314
  opening = false;
17231
17315
  return;
@@ -17492,7 +17576,7 @@ var plus_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0
17492
17576
  //#region ../../shared/common/icons/trash-can-solid.svg?raw
17493
17577
  var trash_can_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 448 512\"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d=\"M135.2 17.7C140.6 6.8 151.7 0 163.8 0L284.2 0c12.1 0 23.2 6.8 28.6 17.7L320 32l96 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 96C14.3 96 0 81.7 0 64S14.3 32 32 32l96 0 7.2-14.3zM32 128l384 0 0 320c0 35.3-28.7 64-64 64L96 512c-35.3 0-64-28.7-64-64l0-320zm96 64c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16z\"/></svg>";
17494
17578
  //#endregion
17495
- //#region src/internal/toolbar/built-in/toolbarIcons.js
17579
+ //#region src/internal/toolbar/built-in/toolbarIcons.ts
17496
17580
  var toolbarIcons = {
17497
17581
  undo: rotate_left_solid_default,
17498
17582
  redo: rotate_right_solid_default,
@@ -17599,11 +17683,11 @@ var _hoisted_8$3 = { class: "input-row url-input-row" };
17599
17683
  var _hoisted_9$2 = ["innerHTML"];
17600
17684
  var _hoisted_10$2 = ["readonly", "onKeydown"];
17601
17685
  var _hoisted_11$2 = ["innerHTML"];
17602
- var _hoisted_12$1 = {
17686
+ var _hoisted_12$2 = {
17603
17687
  key: 0,
17604
17688
  class: "input-row link-buttons"
17605
17689
  };
17606
- var _hoisted_13$1 = ["disabled"];
17690
+ var _hoisted_13$2 = ["disabled"];
17607
17691
  var _hoisted_14$1 = ["innerHTML"];
17608
17692
  var _hoisted_15$1 = ["disabled"];
17609
17693
  var _hoisted_16$1 = {
@@ -17876,7 +17960,7 @@ var LinkInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
17876
17960
  "data-item": "btn-link-open"
17877
17961
  }, null, 10, _hoisted_11$2)
17878
17962
  ]),
17879
- !isViewingMode.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_12$1, [isEditing.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("button", {
17963
+ !isViewingMode.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_12$2, [isEditing.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("button", {
17880
17964
  key: 0,
17881
17965
  class: "remove-btn",
17882
17966
  onClick: handleRemove,
@@ -17885,7 +17969,7 @@ var LinkInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
17885
17969
  }, [require__plugin_vue_export_helper.createElementVNode("div", {
17886
17970
  class: "remove-btn__icon",
17887
17971
  innerHTML: require__plugin_vue_export_helper.unref(toolbarIcons).removeLink
17888
- }, null, 8, _hoisted_14$1), _cache[6] || (_cache[6] = require__plugin_vue_export_helper.createTextVNode(" Remove ", -1))], 8, _hoisted_13$1)) : require__plugin_vue_export_helper.createCommentVNode("", true), require__plugin_vue_export_helper.createElementVNode("button", {
17972
+ }, null, 8, _hoisted_14$1), _cache[6] || (_cache[6] = require__plugin_vue_export_helper.createTextVNode(" Remove ", -1))], 8, _hoisted_13$2)) : require__plugin_vue_export_helper.createCommentVNode("", true), require__plugin_vue_export_helper.createElementVNode("button", {
17889
17973
  class: require__plugin_vue_export_helper.normalizeClass(["sd-submit-btn", { "disable-btn": isDisabled.value }]),
17890
17974
  onClick: handleSubmit,
17891
17975
  disabled: isSubmitting.value,
@@ -17902,7 +17986,7 @@ var LinkInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
17902
17986
  //#region src/internal/toolbar/built-in/LinkInput.vue
17903
17987
  var LinkInput_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(LinkInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-172107e4"]]);
17904
17988
  //#endregion
17905
- //#region src/internal/toolbar/built-in/scroll-helpers.js
17989
+ //#region src/internal/toolbar/built-in/scroll-helpers.ts
17906
17990
  function getScrollableParent(element) {
17907
17991
  let currentElement = element;
17908
17992
  while (currentElement) {
@@ -17935,26 +18019,25 @@ function scrollToElement(targetElement, options = {
17935
18019
  var FLOATING_SURFACE_ID = "link-popover";
17936
18020
  var RECENT_OUTSIDE_CLOSE_MS = 500;
17937
18021
  var MAX_ANCHOR_NAVIGATION_STEPS = 4;
17938
- var isThenable$1 = (value) => Boolean(value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function");
17939
18022
  function isLinkPopoverDocumentApi(value) {
17940
- return require_create_super_doc_ui.isPlainObject(value) || typeof value === "function";
18023
+ return require__plugin_vue_export_helper.isPlainObject(value) || typeof value === "function";
17941
18024
  }
17942
18025
  function linkPopoverDocumentApi(editor) {
17943
18026
  const doc = editor?.doc;
17944
18027
  return isLinkPopoverDocumentApi(doc) ? doc : null;
17945
18028
  }
17946
18029
  function isLinkNavigationHost(value) {
17947
- return require_create_super_doc_ui.isPlainObject(value) || typeof value === "function";
18030
+ return require__plugin_vue_export_helper.isPlainObject(value) || typeof value === "function";
17948
18031
  }
17949
18032
  function isHyperlinkTarget(value) {
17950
- if (!require_create_super_doc_ui.isPlainObject(value) || value.kind !== "inline" || value.nodeType !== "hyperlink") return false;
17951
- const anchor = require_create_super_doc_ui.isPlainObject(value.anchor) ? value.anchor : null;
17952
- const start = anchor && require_create_super_doc_ui.isPlainObject(anchor.start) ? anchor.start : null;
17953
- const end = anchor && require_create_super_doc_ui.isPlainObject(anchor.end) ? anchor.end : null;
18033
+ if (!require__plugin_vue_export_helper.isPlainObject(value) || value.kind !== "inline" || value.nodeType !== "hyperlink") return false;
18034
+ const anchor = require__plugin_vue_export_helper.isPlainObject(value.anchor) ? value.anchor : null;
18035
+ const start = anchor && require__plugin_vue_export_helper.isPlainObject(anchor.start) ? anchor.start : null;
18036
+ const end = anchor && require__plugin_vue_export_helper.isPlainObject(anchor.end) ? anchor.end : null;
17954
18037
  return typeof start?.blockId === "string" && typeof start.offset === "number" && typeof end?.blockId === "string" && typeof end.offset === "number";
17955
18038
  }
17956
18039
  function isValidResolution(value) {
17957
- if (!require_create_super_doc_ui.isPlainObject(value)) return false;
18040
+ if (!require__plugin_vue_export_helper.isPlainObject(value)) return false;
17958
18041
  if (value.type === "default" || value.type === "suppress" || value.type === "none") return true;
17959
18042
  if (value.type === "custom") return value.component != null;
17960
18043
  if (value.type === "external") return typeof value.render === "function";
@@ -17991,8 +18074,8 @@ function readPaintedSourceRef(element) {
17991
18074
  if (!encoded) return null;
17992
18075
  try {
17993
18076
  const parsed = JSON.parse(encoded);
17994
- const sourceRef = require_create_super_doc_ui.isPlainObject(parsed) ? parsed.sourceRef : void 0;
17995
- if (!require_create_super_doc_ui.isPlainObject(sourceRef)) return null;
18077
+ const sourceRef = require__plugin_vue_export_helper.isPlainObject(parsed) ? parsed.sourceRef : void 0;
18078
+ if (!require__plugin_vue_export_helper.isPlainObject(sourceRef)) return null;
17996
18079
  const partUri = typeof sourceRef.partUri === "string" ? sourceRef.partUri : void 0;
17997
18080
  const xpathLikePath = typeof sourceRef.xpathLikePath === "string" ? sourceRef.xpathLikePath : void 0;
17998
18081
  return partUri || xpathLikePath ? {
@@ -18580,7 +18663,7 @@ function useLinkPopover({ getSurfaceManager, getActiveEditor, getUi, getActivati
18580
18663
  const fallbackResolution = () => usesOnActivate ? { type: "suppress" } : { type: "default" };
18581
18664
  try {
18582
18665
  const resolution = handler(ctx);
18583
- if (isThenable$1(resolution)) {
18666
+ if (require__plugin_vue_export_helper.isThenable(resolution)) {
18584
18667
  Promise.resolve(resolution).catch(() => void 0);
18585
18668
  emitException({
18586
18669
  error: /* @__PURE__ */ new Error(usesOnActivate ? "hyperlinks.onActivate must return synchronously; Promises are not supported." : "The hyperlink activation handler must return synchronously."),
@@ -18799,6 +18882,7 @@ function createV2EditorRuntimeAdapter(options) {
18799
18882
  const { id, documentId, root, host, getLegacyEditorProjection, onUnregister } = options;
18800
18883
  let snapshot = host.getSnapshot();
18801
18884
  let didDispose = false;
18885
+ let detached = false;
18802
18886
  let unregistered = false;
18803
18887
  let mountedFocusHandle = null;
18804
18888
  let tokenRevision = 0;
@@ -19095,7 +19179,17 @@ function createV2EditorRuntimeAdapter(options) {
19095
19179
  };
19096
19180
  }
19097
19181
  }
19182
+ function releaseHostSubscriptions() {
19183
+ hostUnsubscribe?.();
19184
+ hostUnsubscribe = null;
19185
+ pageMetricsUnsubscribe?.();
19186
+ pageMetricsUnsubscribe = null;
19187
+ selectionUnsubscribe?.();
19188
+ selectionUnsubscribe = null;
19189
+ activeSelectionController = null;
19190
+ }
19098
19191
  function handleHostSnapshot(next) {
19192
+ if (detached || didDispose) return;
19099
19193
  snapshot = next;
19100
19194
  invalidatePositionTokens();
19101
19195
  syncSelectionSubscription();
@@ -19109,10 +19203,7 @@ function createV2EditorRuntimeAdapter(options) {
19109
19203
  });
19110
19204
  if (next.state === "disposed" && !didDispose) {
19111
19205
  didDispose = true;
19112
- hostUnsubscribe?.();
19113
- pageMetricsUnsubscribe?.();
19114
- selectionUnsubscribe?.();
19115
- selectionUnsubscribe = null;
19206
+ releaseHostSubscriptions();
19116
19207
  emit({ type: "disposed" });
19117
19208
  listeners.clear();
19118
19209
  if (!unregistered) {
@@ -19259,10 +19350,7 @@ function createV2EditorRuntimeAdapter(options) {
19259
19350
  await host.dispose();
19260
19351
  if (!didDispose) {
19261
19352
  didDispose = true;
19262
- hostUnsubscribe?.();
19263
- pageMetricsUnsubscribe?.();
19264
- selectionUnsubscribe?.();
19265
- selectionUnsubscribe = null;
19353
+ releaseHostSubscriptions();
19266
19354
  emit({ type: "disposed" });
19267
19355
  listeners.clear();
19268
19356
  if (!unregistered) {
@@ -19341,8 +19429,17 @@ function createV2EditorRuntimeAdapter(options) {
19341
19429
  }
19342
19430
  },
19343
19431
  attachMountHandle(handle) {
19432
+ if (detached || didDispose) return;
19344
19433
  mountedFocusHandle = handle;
19345
19434
  syncSelectionSubscription();
19435
+ },
19436
+ detach() {
19437
+ if (detached) return;
19438
+ detached = true;
19439
+ unregistered = true;
19440
+ releaseHostSubscriptions();
19441
+ mountedFocusHandle = null;
19442
+ listeners.clear();
19346
19443
  }
19347
19444
  };
19348
19445
  }
@@ -19373,10 +19470,10 @@ function isPromiseLike(value) {
19373
19470
  return Boolean(value && typeof value === "object" && typeof value.then === "function");
19374
19471
  }
19375
19472
  function isTextTarget(value) {
19376
- return require_create_super_doc_ui.isPlainObject(value) && value.kind === "text" && Array.isArray(value.segments) && value.segments.length > 0;
19473
+ return require__plugin_vue_export_helper.isPlainObject(value) && value.kind === "text" && Array.isArray(value.segments) && value.segments.length > 0;
19377
19474
  }
19378
19475
  function isHeaderFooterStory(story) {
19379
- return require_create_super_doc_ui.isPlainObject(story) && story.kind === "story" && (story.storyType === "headerFooterSlot" || story.storyType === "headerFooterPart");
19476
+ return require__plugin_vue_export_helper.isPlainObject(story) && story.kind === "story" && (story.storyType === "headerFooterSlot" || story.storyType === "headerFooterPart");
19380
19477
  }
19381
19478
  function resolveCurrentHeaderFooterTextTarget(doc) {
19382
19479
  if (!isFn(doc.selection?.current)) return {
@@ -19396,7 +19493,7 @@ function resolveCurrentHeaderFooterTextTarget(doc) {
19396
19493
  handled: false,
19397
19494
  reason: "page-field-selection-async"
19398
19495
  };
19399
- if (!require_create_super_doc_ui.isPlainObject(currentSelection) || !isTextTarget(currentSelection.target)) return {
19496
+ if (!require__plugin_vue_export_helper.isPlainObject(currentSelection) || !isTextTarget(currentSelection.target)) return {
19400
19497
  handled: false,
19401
19498
  reason: "page-field-selection-unavailable"
19402
19499
  };
@@ -19494,7 +19591,7 @@ function createV2SessionShortcutRoutes(deps) {
19494
19591
  mode: "raw"
19495
19592
  });
19496
19593
  if (isPromiseLike(result)) result.catch(() => {});
19497
- else if (require_create_super_doc_ui.isPlainObject(result) && result.success === false) return {
19594
+ else if (require__plugin_vue_export_helper.isPlainObject(result) && result.success === false) return {
19498
19595
  handled: false,
19499
19596
  reason: "page-field-insert-failed"
19500
19597
  };
@@ -20511,7 +20608,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20511
20608
  __name: "SuperDoc",
20512
20609
  emits: ["selection-update"],
20513
20610
  setup(__props, { emit: __emit }) {
20514
- const PdfViewer = require__plugin_vue_export_helper.defineAsyncComponent(() => Promise.resolve().then(() => require("./chunks/PdfViewer-DmSkZehl.cjs")));
20611
+ const PdfViewer = require__plugin_vue_export_helper.defineAsyncComponent(() => Promise.resolve().then(() => require("./chunks/PdfViewer-DYTbPVUr.cjs")));
20515
20612
  const getDocumentLoadPassword = (doc) => doc.password ?? proxy.$superdoc.config.password;
20516
20613
  const resolveDocumentV2Collaboration = (doc) => {
20517
20614
  const rawConfig = doc?.v2Collaboration;
@@ -20625,6 +20722,8 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20625
20722
  const v2ReviewSidebarUnlocked = require__plugin_vue_export_helper.ref(false);
20626
20723
  const v2GeometryEpoch = require__plugin_vue_export_helper.ref(null);
20627
20724
  let v2GeometryRafHandle = 0;
20725
+ let v2GeometryReplayRafHandle = 0;
20726
+ let v2GeometryReplayGeneration = 0;
20628
20727
  let v2TrackedChangeRestampRetainPaints = 0;
20629
20728
  let v2TrackedChangeRestampRetentionReason = null;
20630
20729
  const activeEditorRef = require__plugin_vue_export_helper.computed(() => proxy.$superdoc.activeEditor);
@@ -20808,6 +20907,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20808
20907
  if (document && provider?.sendStateless) document.provider = null;
20809
20908
  const entry = v2Runtimes.get(documentId);
20810
20909
  if (!entry) return;
20910
+ entry.adapter.detach();
20811
20911
  proxy.$superdoc["unregisterEditorRuntime"](entry.runtimeId);
20812
20912
  v2Runtimes.delete(documentId);
20813
20913
  const hostRoot = subDocumentRoots.get(documentId);
@@ -21314,7 +21414,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21314
21414
  let v2SelectionToolbarRafHandle = 0;
21315
21415
  let v2SelectionToolbarTimeoutHandle = 0;
21316
21416
  let v2DomSelectionRafHandle = 0;
21317
- const buildV2EditorUpdatePayload = ({ editor, sourceEditor, surface = "body", headerId = null, sectionType = null } = {}) => {
21417
+ const buildV2EditorUpdatePayload = ({ editor, sourceEditor, surface = "body", headerId = null, sectionType = null, isRemote = false } = {}) => {
21318
21418
  const activeEditor = proxy.$superdoc?.activeEditor ?? null;
21319
21419
  const effectiveEditor = editor ?? sourceEditor ?? activeEditor ?? void 0;
21320
21420
  return {
@@ -21322,7 +21422,8 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21322
21422
  sourceEditor: sourceEditor ?? effectiveEditor,
21323
21423
  surface,
21324
21424
  headerId,
21325
- sectionType
21425
+ sectionType,
21426
+ isRemote
21326
21427
  };
21327
21428
  };
21328
21429
  const emitV2EditorUpdate = (payload = {}) => {
@@ -21576,6 +21677,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21576
21677
  pending: entry
21577
21678
  });
21578
21679
  };
21680
+ let scheduleV2GeometryReplay = () => {};
21579
21681
  const v2GeometryPublisher = resolvedEditorIntegration.createGeometryPublisher({
21580
21682
  getLayersContainer: () => layers.value ?? null,
21581
21683
  isCommentsEnabled: () => Boolean(commentsModuleConfig.value) && shouldRenderCommentsInViewing.value,
@@ -21591,7 +21693,8 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21591
21693
  v2ReviewSidebarUnlocked.value = true;
21592
21694
  v2GeometryEpoch.value = v2GeometryPublisher.getLastEpoch();
21593
21695
  }
21594
- }
21696
+ },
21697
+ onCommittedPagePaint: ({ payload }) => scheduleV2GeometryReplay(payload)
21595
21698
  });
21596
21699
  const armV2TrackedChangeRestampGeometryRetention = (reason = "tracked-change-restamp") => {
21597
21700
  v2TrackedChangeRestampRetainPaints = Math.max(v2TrackedChangeRestampRetainPaints, 3);
@@ -21611,20 +21714,53 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21611
21714
  v2TrackedChangeRestampRetentionReason = null;
21612
21715
  };
21613
21716
  const resolveV2GeometryPublishOptions = (options) => typeof options === "function" ? options() : options;
21717
+ const isV2GeometryReady = (current) => {
21718
+ if (!current?.mountContainer || !commentsModuleConfig.value || !shouldRenderCommentsInViewing.value) return false;
21719
+ const mount = current.mount;
21720
+ let liveEpoch;
21721
+ try {
21722
+ liveEpoch = mount?.getRenderEpoch?.();
21723
+ } catch {
21724
+ return false;
21725
+ }
21726
+ return v2GeometryPublisher.getLastPayload() === current && v2GeometryPublisher.getLastEpoch() != null && v2GeometryPublisher.getLastEpoch() === current.epoch && (liveEpoch == null || liveEpoch === current.epoch);
21727
+ };
21614
21728
  const scheduleV2GeometryPublish = (payload, options = void 0) => {
21615
21729
  v2GeometryRender.value = payload;
21616
21730
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21731
+ const publish = () => {
21732
+ const current = v2GeometryRender.value;
21733
+ Promise.resolve(v2GeometryPublisher.publish(current, resolveV2GeometryPublishOptions(options))).then(() => {
21734
+ if (current === v2GeometryRender.value && isV2GeometryReady(current)) v2ReviewGeometryDelivery.flush(current);
21735
+ });
21736
+ };
21617
21737
  if (typeof requestAnimationFrame !== "function") {
21618
- v2GeometryPublisher.publish(v2GeometryRender.value, resolveV2GeometryPublishOptions(options));
21738
+ publish();
21619
21739
  return;
21620
21740
  }
21621
21741
  v2GeometryRafHandle = requestAnimationFrame(() => {
21622
21742
  v2GeometryRafHandle = 0;
21623
- v2GeometryPublisher.publish(v2GeometryRender.value, resolveV2GeometryPublishOptions(options));
21743
+ publish();
21624
21744
  });
21625
21745
  };
21746
+ const v2ReviewGeometryDelivery = createReviewGeometryDelivery((current, packet) => {
21747
+ v2GeometryPublisher.noteCommittedPageWindow?.(packet);
21748
+ scheduleV2GeometryPublish(current);
21749
+ });
21750
+ scheduleV2GeometryReplay = (payload) => {
21751
+ if (!payload || payload !== v2GeometryRender.value) return;
21752
+ const generation = ++v2GeometryReplayGeneration;
21753
+ if (v2GeometryReplayRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryReplayRafHandle);
21754
+ const replay = () => {
21755
+ v2GeometryReplayRafHandle = 0;
21756
+ if (generation === v2GeometryReplayGeneration && payload === v2GeometryRender.value && isV2GeometryReady(payload)) v2ReviewGeometryDelivery.replay(payload);
21757
+ };
21758
+ if (typeof requestAnimationFrame === "function") v2GeometryReplayRafHandle = requestAnimationFrame(replay);
21759
+ else queueMicrotask(replay);
21760
+ };
21626
21761
  const onV2Render = (payload) => {
21627
21762
  if (!payload) return;
21763
+ v2ReviewGeometryDelivery.observe(payload);
21628
21764
  scheduleV2GeometryPublish(payload, () => takeV2TrackedChangeRestampGeometryRetention());
21629
21765
  if (v2HasRangeSelection.value) scheduleV2SelectionToolbarStateSync();
21630
21766
  };
@@ -21657,7 +21793,11 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21657
21793
  cancelScheduledV2SelectionToolbarSync();
21658
21794
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21659
21795
  v2GeometryRafHandle = 0;
21796
+ if (v2GeometryReplayRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryReplayRafHandle);
21797
+ v2GeometryReplayRafHandle = 0;
21798
+ v2GeometryReplayGeneration++;
21660
21799
  v2GeometryRender.value = null;
21800
+ v2ReviewGeometryDelivery.reset();
21661
21801
  v2GeometryEpoch.value = null;
21662
21802
  v2GeometryAvailable.value = false;
21663
21803
  v2ReviewSidebarUnlocked.value = false;
@@ -21716,6 +21856,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21716
21856
  v2ReviewWindowController.invalidate("collaboration:remote-review-changed");
21717
21857
  v2ReviewWindowController.refreshCommittedWindow("collaboration:remote-review-changed");
21718
21858
  }
21859
+ emitV2EditorUpdate({ isRemote: true });
21719
21860
  return;
21720
21861
  }
21721
21862
  if (event.type === "source:complete") {
@@ -21804,14 +21945,15 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21804
21945
  if (!isV2Mode.value) return;
21805
21946
  if (!v2GeometryPublisher.getLastPayload()) return;
21806
21947
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21807
- if (typeof requestAnimationFrame !== "function") {
21808
- v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21809
- return;
21810
- }
21811
- v2GeometryRafHandle = requestAnimationFrame(() => {
21948
+ const recollect = () => {
21812
21949
  v2GeometryRafHandle = 0;
21813
- v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21814
- });
21950
+ const current = v2GeometryRender.value;
21951
+ Promise.resolve(v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options))).then(() => {
21952
+ if (current === v2GeometryRender.value && isV2GeometryReady(current)) v2ReviewGeometryDelivery.replay(current);
21953
+ });
21954
+ };
21955
+ if (typeof requestAnimationFrame !== "function") recollect();
21956
+ else v2GeometryRafHandle = requestAnimationFrame(recollect);
21815
21957
  };
21816
21958
  const handleV2DocumentModeChange = () => {
21817
21959
  if (!isV2Mode.value) return;
@@ -22039,13 +22181,17 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
22039
22181
  ...payload,
22040
22182
  documentId: doc.id
22041
22183
  });
22042
- v2GeometryPublisher.noteCommittedPageWindow?.(payload);
22184
+ if (payload.reviewGeometry && Array.isArray(payload.pageIndices)) {
22185
+ const current = v2GeometryRender.value;
22186
+ v2ReviewGeometryDelivery.notify(String(doc.id), payload, current, isV2GeometryReady(current));
22187
+ } else v2GeometryPublisher.noteCommittedPageWindow?.(payload);
22043
22188
  },
22044
22189
  fontAssets: proxy.$superdoc.config.fonts,
22045
22190
  workerUrls: proxy.$superdoc.config.workerUrls,
22046
22191
  fieldContext: doc.fieldContext,
22047
22192
  fieldUpdatePolicy: proxy.$superdoc.config.fieldUpdatePolicy,
22048
22193
  workerStartupTimeoutMs: proxy.$superdoc.config.workerStartupTimeoutMs,
22194
+ ...proxy.$superdoc.config.changes ? { changes: proxy.$superdoc.config.changes } : {},
22049
22195
  proofing: resolvedProofingConfig.value,
22050
22196
  isNewFile,
22051
22197
  password: getDocumentLoadPassword(doc),
@@ -23131,7 +23277,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
23131
23277
  });
23132
23278
  //#endregion
23133
23279
  //#region src/SuperDoc.vue
23134
- var SuperDoc_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SuperDoc_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-26bcc2bd"]]);
23280
+ var SuperDoc_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SuperDoc_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-7c932add"]]);
23135
23281
  //#endregion
23136
23282
  //#region src/core/create-app.ts
23137
23283
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -32546,7 +32692,7 @@ function checkDefaultFill(config) {
32546
32692
  if (!config.fillLinearGradientColorStops && !config.fillRadialGradientColorStops && !config.fillPatternImage) config.fill = config.fill || "black";
32547
32693
  return config;
32548
32694
  }
32549
- var Text = class extends Shape {
32695
+ var Text$1 = class extends Shape {
32550
32696
  constructor(config) {
32551
32697
  super(checkDefaultFill(config));
32552
32698
  this._partialTextX = 0;
@@ -32808,10 +32954,10 @@ var Text = class extends Shape {
32808
32954
  return super._useBufferCanvas();
32809
32955
  }
32810
32956
  };
32811
- Text.prototype._fillFunc = _fillFunc$1;
32812
- Text.prototype._strokeFunc = _strokeFunc$1;
32813
- Text.prototype.className = TEXT_UPPER;
32814
- Text.prototype._attrsAffectingSize = [
32957
+ Text$1.prototype._fillFunc = _fillFunc$1;
32958
+ Text$1.prototype._strokeFunc = _strokeFunc$1;
32959
+ Text$1.prototype.className = TEXT_UPPER;
32960
+ Text$1.prototype._attrsAffectingSize = [
32815
32961
  "text",
32816
32962
  "fontSize",
32817
32963
  "padding",
@@ -32819,25 +32965,25 @@ Text.prototype._attrsAffectingSize = [
32819
32965
  "lineHeight",
32820
32966
  "letterSpacing"
32821
32967
  ];
32822
- _registerNode(Text);
32823
- Factory.overWriteSetter(Text, "width", getNumberOrAutoValidator());
32824
- Factory.overWriteSetter(Text, "height", getNumberOrAutoValidator());
32825
- Factory.addGetterSetter(Text, "direction", INHERIT);
32826
- Factory.addGetterSetter(Text, "fontFamily", "Arial");
32827
- Factory.addGetterSetter(Text, "fontSize", 12, getNumberValidator());
32828
- Factory.addGetterSetter(Text, "fontStyle", NORMAL$1);
32829
- Factory.addGetterSetter(Text, "fontVariant", NORMAL$1);
32830
- Factory.addGetterSetter(Text, "padding", 0, getNumberValidator());
32831
- Factory.addGetterSetter(Text, "align", LEFT);
32832
- Factory.addGetterSetter(Text, "verticalAlign", TOP);
32833
- Factory.addGetterSetter(Text, "lineHeight", 1, getNumberValidator());
32834
- Factory.addGetterSetter(Text, "wrap", WORD);
32835
- Factory.addGetterSetter(Text, "ellipsis", false, getBooleanValidator());
32836
- Factory.addGetterSetter(Text, "letterSpacing", 0, getNumberValidator());
32837
- Factory.addGetterSetter(Text, "text", "", getStringValidator());
32838
- Factory.addGetterSetter(Text, "textDecoration", "");
32839
- Factory.addGetterSetter(Text, "underlineOffset", void 0, getNumberValidator());
32840
- Factory.addGetterSetter(Text, "charRenderFunc", void 0);
32968
+ _registerNode(Text$1);
32969
+ Factory.overWriteSetter(Text$1, "width", getNumberOrAutoValidator());
32970
+ Factory.overWriteSetter(Text$1, "height", getNumberOrAutoValidator());
32971
+ Factory.addGetterSetter(Text$1, "direction", INHERIT);
32972
+ Factory.addGetterSetter(Text$1, "fontFamily", "Arial");
32973
+ Factory.addGetterSetter(Text$1, "fontSize", 12, getNumberValidator());
32974
+ Factory.addGetterSetter(Text$1, "fontStyle", NORMAL$1);
32975
+ Factory.addGetterSetter(Text$1, "fontVariant", NORMAL$1);
32976
+ Factory.addGetterSetter(Text$1, "padding", 0, getNumberValidator());
32977
+ Factory.addGetterSetter(Text$1, "align", LEFT);
32978
+ Factory.addGetterSetter(Text$1, "verticalAlign", TOP);
32979
+ Factory.addGetterSetter(Text$1, "lineHeight", 1, getNumberValidator());
32980
+ Factory.addGetterSetter(Text$1, "wrap", WORD);
32981
+ Factory.addGetterSetter(Text$1, "ellipsis", false, getBooleanValidator());
32982
+ Factory.addGetterSetter(Text$1, "letterSpacing", 0, getNumberValidator());
32983
+ Factory.addGetterSetter(Text$1, "text", "", getStringValidator());
32984
+ Factory.addGetterSetter(Text$1, "textDecoration", "");
32985
+ Factory.addGetterSetter(Text$1, "underlineOffset", void 0, getNumberValidator());
32986
+ Factory.addGetterSetter(Text$1, "charRenderFunc", void 0);
32841
32987
  //#endregion
32842
32988
  //#region ../../node_modules/.pnpm/konva@10.2.5/node_modules/konva/lib/shapes/TextPath.js
32843
32989
  var EMPTY_STRING = "";
@@ -32943,10 +33089,10 @@ var TextPath = class extends Shape {
32943
33089
  return this.textHeight;
32944
33090
  }
32945
33091
  setText(text) {
32946
- return Text.prototype.setText.call(this, text);
33092
+ return Text$1.prototype.setText.call(this, text);
32947
33093
  }
32948
33094
  _getContextFont() {
32949
- return Text.prototype._getContextFont.call(this);
33095
+ return Text$1.prototype._getContextFont.call(this);
32950
33096
  }
32951
33097
  _getTextSize(text) {
32952
33098
  const _context = this.dummyCanvas.getContext("2d");
@@ -35486,7 +35632,7 @@ var lib_default = Konva$1.Util._assign(Konva$1, {
35486
35632
  Ring,
35487
35633
  Sprite,
35488
35634
  Star,
35489
- Text,
35635
+ Text: Text$1,
35490
35636
  TextPath,
35491
35637
  Transformer,
35492
35638
  Wedge,
@@ -35708,6 +35854,16 @@ var SurfaceManager = class {
35708
35854
  };
35709
35855
  //#endregion
35710
35856
  //#region src/helpers/deprecation.ts
35857
+ /**
35858
+ * Deprecation utilities for steering consumers toward the Document API.
35859
+ *
35860
+ * ProseMirror will be removed in a future major version. These helpers emit
35861
+ * one-time console warnings when deprecated properties are accessed on an
35862
+ * editor instance handed to consumer callbacks (onEditorCreate, etc.).
35863
+ *
35864
+ * Internal code continues to use the raw Editor — only the consumer-facing
35865
+ * boundary wraps the editor with a Proxy.
35866
+ */
35711
35867
  var MIGRATION_URL = "https://docs.superdoc.dev/guides/migration/document-api";
35712
35868
  var _warned = /* @__PURE__ */ new Set();
35713
35869
  /**
@@ -35951,7 +36107,7 @@ var TOOLBAR_ITEM_ALIASES = Object.freeze({
35951
36107
  * historical default rather than inheriting from its siblings.
35952
36108
  */
35953
36109
  var isUnknownArray = (value) => Array.isArray(value);
35954
- var isOptionsBag = (value) => require_create_super_doc_ui.isPlainObject(value);
36110
+ var isOptionsBag = (value) => require__plugin_vue_export_helper.isPlainObject(value);
35955
36111
  var hasSelectHandler = (item) => typeof item.onSelect === "function";
35956
36112
  /** Surfaces that render when the consumer says nothing at all. */
35957
36113
  var HISTORICAL_DEFAULTS = Object.freeze({
@@ -36080,7 +36236,7 @@ var SEARCH_STRING_KEYS = Object.freeze({
36080
36236
  invalidPattern: "invalidPatternLabel"
36081
36237
  });
36082
36238
  function normalizeSearchStrings(strings) {
36083
- if (!require_create_super_doc_ui.isPlainObject(strings)) return {};
36239
+ if (!require__plugin_vue_export_helper.isPlainObject(strings)) return {};
36084
36240
  return Object.fromEntries(Object.entries(strings).filter(([key, value]) => SEARCH_STRING_KEYS[key] !== void 0 && value !== void 0).map(([key, value]) => [SEARCH_STRING_KEYS[key], value]));
36085
36241
  }
36086
36242
  function normalizeSearchOptions(options) {
@@ -36174,7 +36330,7 @@ function mapToolbarKey(key, aliases) {
36174
36330
  return aliases[String(key)] ?? key;
36175
36331
  }
36176
36332
  function mapToolbarRecord(record, aliases) {
36177
- if (!require_create_super_doc_ui.isPlainObject(record)) return void 0;
36333
+ if (!require__plugin_vue_export_helper.isPlainObject(record)) return void 0;
36178
36334
  const entries = Object.entries(record);
36179
36335
  const passthroughEntries = entries.filter(([key]) => aliases[key] === void 0);
36180
36336
  const aliasedEntries = entries.filter(([key]) => aliases[key] !== void 0);
@@ -36185,14 +36341,14 @@ function mapToolbarItems(items) {
36185
36341
  return items.map((item) => mapToolbarKey(item, TOOLBAR_ITEM_ALIASES));
36186
36342
  }
36187
36343
  function mapToolbarRegions(regions) {
36188
- if (!require_create_super_doc_ui.isPlainObject(regions)) return regions;
36344
+ if (!require__plugin_vue_export_helper.isPlainObject(regions)) return regions;
36189
36345
  return Object.fromEntries(Object.entries(regions).map(([region, items]) => [region, mapToolbarItems(items)]));
36190
36346
  }
36191
36347
  function addCustomItemRegions(regions, customItems) {
36192
- if (!require_create_super_doc_ui.isPlainObject(regions) || !isUnknownArray(customItems)) return regions;
36348
+ if (!require__plugin_vue_export_helper.isPlainObject(regions) || !isUnknownArray(customItems)) return regions;
36193
36349
  const result = { ...regions };
36194
36350
  for (const item of customItems) {
36195
- if (!require_create_super_doc_ui.isPlainObject(item)) continue;
36351
+ if (!require__plugin_vue_export_helper.isPlainObject(item)) continue;
36196
36352
  const region = item.region ?? "center";
36197
36353
  if (result[region] === void 0) result[region] = [];
36198
36354
  }
@@ -36205,7 +36361,7 @@ var TOOLBAR_OPTIONAL_ITEM_REGIONS = Object.freeze({
36205
36361
  "table-of-contents": "center"
36206
36362
  });
36207
36363
  function addIncludedToolbarItems(regions, includeItems) {
36208
- if (!require_create_super_doc_ui.isPlainObject(regions) || !isUnknownArray(includeItems)) return regions;
36364
+ if (!require__plugin_vue_export_helper.isPlainObject(regions) || !isUnknownArray(includeItems)) return regions;
36209
36365
  const result = Object.fromEntries(Object.entries(regions).map(([region, items]) => [region, isUnknownArray(items) ? [...items] : items]));
36210
36366
  const configuredItems = new Set(Object.values(result).flatMap((items) => isUnknownArray(items) ? items : []).map((item) => mapToolbarKey(item, TOOLBAR_ITEM_ALIASES)));
36211
36367
  for (const item of includeItems) {
@@ -36225,7 +36381,7 @@ function extendToolbarRegions(regions, options) {
36225
36381
  function mapToolbarFontOptions(options) {
36226
36382
  if (!isUnknownArray(options)) return options;
36227
36383
  return options.map((option) => {
36228
- if (!require_create_super_doc_ui.isPlainObject(option)) return option;
36384
+ if (!require__plugin_vue_export_helper.isPlainObject(option)) return option;
36229
36385
  const { value, label, previewFamily } = option;
36230
36386
  return {
36231
36387
  key: value,
@@ -36238,7 +36394,7 @@ function mapToolbarFontOptions(options) {
36238
36394
  function mapToolbarCustomItems(items) {
36239
36395
  if (!isUnknownArray(items)) return items;
36240
36396
  return items.map((item) => {
36241
- if (!require_create_super_doc_ui.isPlainObject(item) || typeof item.id !== "string") return item;
36397
+ if (!require__plugin_vue_export_helper.isPlainObject(item) || typeof item.id !== "string") return item;
36242
36398
  const size = item.size ?? "default";
36243
36399
  const layoutWidth = item.type === "separator" ? void 0 : CUSTOM_TOOLBAR_ITEM_WIDTHS[String(size)];
36244
36400
  const style = item.style;
@@ -36266,7 +36422,7 @@ function mapToolbarCustomItems(items) {
36266
36422
  }
36267
36423
  if (item.type === "dropdown" && isUnknownArray(item.options)) {
36268
36424
  mapped.options = item.options.map((option) => {
36269
- if (!require_create_super_doc_ui.isPlainObject(option)) return option;
36425
+ if (!require__plugin_vue_export_helper.isPlainObject(option)) return option;
36270
36426
  return {
36271
36427
  ...option,
36272
36428
  key: option.value ?? option.id,
@@ -36288,14 +36444,14 @@ function mapToolbarCustomItems(items) {
36288
36444
  }
36289
36445
  function normalizeToolbarOptions(options) {
36290
36446
  const normalized = { ...options };
36291
- const configuredItems = firstDefined(options.items, require_create_super_doc_ui.isPlainObject(options.groups) ? options.groups : void 0);
36292
- const items = require_create_super_doc_ui.isPlainObject(options.items) && Object.keys(options.items).length === 0 ? { center: [] } : configuredItems;
36447
+ const configuredItems = firstDefined(options.items, require__plugin_vue_export_helper.isPlainObject(options.groups) ? options.groups : void 0);
36448
+ const items = require__plugin_vue_export_helper.isPlainObject(options.items) && Object.keys(options.items).length === 0 ? { center: [] } : configuredItems;
36293
36449
  const groupedItems = extendToolbarRegions(items, options);
36294
36450
  const groups = groupedItems === void 0 ? options.groups : mapToolbarRegions(groupedItems);
36295
36451
  const icons = mapToolbarRecord(options.icons, TOOLBAR_ICON_ALIASES);
36296
36452
  const texts = mergeDefined(mapToolbarRecord(options.texts, {}), mapToolbarRecord(options.strings, TOOLBAR_STRING_ALIASES));
36297
36453
  const includeItems = isUnknownArray(options.includeItems) ? new Set(options.includeItems) : null;
36298
- const itemIds = require_create_super_doc_ui.isPlainObject(items) ? new Set(Object.values(items).flatMap((regionItems) => isUnknownArray(regionItems) ? regionItems : [])) : /* @__PURE__ */ new Set();
36454
+ const itemIds = require__plugin_vue_export_helper.isPlainObject(items) ? new Set(Object.values(items).flatMap((regionItems) => isUnknownArray(regionItems) ? regionItems : [])) : /* @__PURE__ */ new Set();
36299
36455
  delete normalized.items;
36300
36456
  delete normalized.includeItems;
36301
36457
  delete normalized.overflow;
@@ -36324,7 +36480,7 @@ function normalizeToolbarOptions(options) {
36324
36480
  function normalizeUiConfig(config = {}) {
36325
36481
  const raw = config.ui;
36326
36482
  const allDisabled = raw === false;
36327
- const ui = require_create_super_doc_ui.isPlainObject(raw) ? raw : void 0;
36483
+ const ui = require__plugin_vue_export_helper.isPlainObject(raw) ? raw : void 0;
36328
36484
  const enabled = (key) => !allDisabled && resolveSurface(ui, key);
36329
36485
  const explicit = (key) => {
36330
36486
  if (allDisabled) return false;
@@ -36338,16 +36494,16 @@ function normalizeUiConfig(config = {}) {
36338
36494
  const legacyContentControlsChrome = config.modules?.contentControls?.chrome === "none" ? void 0 : config.modules?.contentControls?.chrome;
36339
36495
  const rawToolbarOptions = options("toolbar");
36340
36496
  const toolbarOptions = normalizeToolbarOptions(rawToolbarOptions);
36341
- const hasCanonicalToolbarItems = require_create_super_doc_ui.isPlainObject(rawToolbarOptions.items);
36497
+ const hasCanonicalToolbarItems = require__plugin_vue_export_helper.isPlainObject(rawToolbarOptions.items);
36342
36498
  const legacyToolbar = config.modules?.toolbar;
36343
- const legacyToolbarOptions = require_create_super_doc_ui.isPlainObject(legacyToolbar) ? legacyToolbar : {};
36499
+ const legacyToolbarOptions = require__plugin_vue_export_helper.isPlainObject(legacyToolbar) ? legacyToolbar : {};
36344
36500
  const legacyContextMenuRaw = config.modules?.contextMenu ?? config.modules?.slashMenu;
36345
- const legacyContextMenu = require_create_super_doc_ui.isPlainObject(legacyContextMenuRaw) ? legacyContextMenuRaw : {};
36501
+ const legacyContextMenu = require__plugin_vue_export_helper.isPlainObject(legacyContextMenuRaw) ? legacyContextMenuRaw : {};
36346
36502
  const legacySearchRaw = config.modules?.surfaces?.findReplace;
36347
- const legacySearch = normalizeSearchOptions(require_create_super_doc_ui.isPlainObject(legacySearchRaw) ? legacySearchRaw : {});
36348
- const legacyToolbarGroups = require_create_super_doc_ui.isPlainObject(legacyToolbarOptions.groups) ? mapToolbarRegions(extendToolbarRegions(legacyToolbarOptions.groups, rawToolbarOptions)) : legacyToolbarOptions.groups;
36503
+ const legacySearch = normalizeSearchOptions(require__plugin_vue_export_helper.isPlainObject(legacySearchRaw) ? legacySearchRaw : {});
36504
+ const legacyToolbarGroups = require__plugin_vue_export_helper.isPlainObject(legacyToolbarOptions.groups) ? mapToolbarRegions(extendToolbarRegions(legacyToolbarOptions.groups, rawToolbarOptions)) : legacyToolbarOptions.groups;
36349
36505
  const groupCandidates = [toolbarOptions.groups, legacyToolbarGroups];
36350
- const composedGroups = groupCandidates.find(require_create_super_doc_ui.isPlainObject);
36506
+ const composedGroups = groupCandidates.find(require__plugin_vue_export_helper.isPlainObject);
36351
36507
  const orderedGroups = groupCandidates.find(isUnknownArray);
36352
36508
  const selectedGroups = hasCanonicalToolbarItems ? Object.keys(toolbarOptions.groups ?? {}) : firstDefined(orderedGroups, legacyToolbarOptions.toolbarGroups, config.toolbarGroups);
36353
36509
  const selection = isUnknownArray(selectedGroups) ? selectedGroups.map(String) : null;
@@ -36425,10 +36581,10 @@ var isCommentInteractionLevel = (value) => value === "read" || value === "write"
36425
36581
  * resolve and reopen actions.
36426
36582
  */
36427
36583
  function normalizeInteractionConfig(config = {}) {
36428
- const interaction = require_create_super_doc_ui.isPlainObject(config.interaction) ? config.interaction : {};
36429
- const interactionComments = require_create_super_doc_ui.isPlainObject(interaction.comments) ? interaction.comments : {};
36430
- const interactionTrackedChanges = require_create_super_doc_ui.isPlainObject(interaction.trackedChanges) ? interaction.trackedChanges : {};
36431
- const legacyComments = require_create_super_doc_ui.isPlainObject(config.modules?.comments) ? config.modules.comments : {};
36584
+ const interaction = require__plugin_vue_export_helper.isPlainObject(config.interaction) ? config.interaction : {};
36585
+ const interactionComments = require__plugin_vue_export_helper.isPlainObject(interaction.comments) ? interaction.comments : {};
36586
+ const interactionTrackedChanges = require__plugin_vue_export_helper.isPlainObject(interaction.trackedChanges) ? interaction.trackedChanges : {};
36587
+ const legacyComments = require__plugin_vue_export_helper.isPlainObject(config.modules?.comments) ? config.modules.comments : {};
36432
36588
  const legacyReadOnly = (interactionComments.readOnly ?? legacyComments.readOnly ?? false) === true;
36433
36589
  const legacyAllowResolve = (interactionComments.allowResolve ?? legacyComments.allowResolve ?? true) !== false;
36434
36590
  const canonicalLevel = interactionComments.level;
@@ -36472,8 +36628,8 @@ function normalizeInteractionConfig(config = {}) {
36472
36628
  * is a function or `null` once a non-function value has been rejected.
36473
36629
  */
36474
36630
  function normalizeSurfacesConfig(config = {}) {
36475
- const next = require_create_super_doc_ui.isPlainObject(config.surfaces) ? config.surfaces : {};
36476
- const legacy = require_create_super_doc_ui.isPlainObject(config.modules?.surfaces) ? config.modules.surfaces : {};
36631
+ const next = require__plugin_vue_export_helper.isPlainObject(config.surfaces) ? config.surfaces : {};
36632
+ const legacy = require__plugin_vue_export_helper.isPlainObject(config.modules?.surfaces) ? config.modules.surfaces : {};
36477
36633
  const resolver = next.resolver === void 0 ? legacy.resolver : next.resolver;
36478
36634
  return {
36479
36635
  resolver: typeof resolver === "function" ? resolver : null,
@@ -37010,23 +37166,21 @@ function resolveBuiltInItemCommandId(name) {
37010
37166
  return resolveToolbarCommandId(name) ?? UNCATALOGED_ITEM_COMMAND_IDS[name] ?? null;
37011
37167
  }
37012
37168
  //#endregion
37013
- //#region src/internal/toolbar/built-in/helpers.js
37169
+ //#region src/internal/toolbar/built-in/helpers.ts
37014
37170
  var sanitizeNumber = (value, defaultNumber) => {
37015
- let sanitized = value.replace(/[^0-9.]/g, "");
37016
- sanitized = parseFloat(sanitized);
37017
- if (isNaN(sanitized)) sanitized = defaultNumber;
37018
- sanitized = parseFloat(sanitized);
37019
- return sanitized;
37020
- };
37021
- var throttle = (func, wait, options) => {
37022
- let timeout, args, result;
37171
+ const parsed = parseFloat(String(value ?? "").replace(/[^0-9.]/g, ""));
37172
+ return isNaN(parsed) ? defaultNumber : parsed;
37173
+ };
37174
+ var throttle = (func, wait, options = {}) => {
37175
+ let timeout;
37176
+ let args;
37177
+ let result;
37023
37178
  let previous = 0;
37024
- if (!options) options = {};
37025
37179
  const later = () => {
37026
37180
  previous = options.leading === false ? 0 : Date.now();
37027
- timeout = null;
37028
- result = func(...args);
37029
- if (!timeout) args = null;
37181
+ timeout = void 0;
37182
+ if (args) result = func(...args);
37183
+ if (!timeout) args = void 0;
37030
37184
  };
37031
37185
  const throttled = (...callArgs) => {
37032
37186
  const _now = Date.now();
@@ -37036,18 +37190,18 @@ var throttle = (func, wait, options) => {
37036
37190
  if (remaining <= 0 || remaining > wait) {
37037
37191
  if (timeout) {
37038
37192
  clearTimeout(timeout);
37039
- timeout = null;
37193
+ timeout = void 0;
37040
37194
  }
37041
37195
  previous = _now;
37042
37196
  result = func(...callArgs);
37043
- if (!timeout) args = null;
37197
+ if (!timeout) args = void 0;
37044
37198
  } else if (!timeout && options.trailing !== false) timeout = setTimeout(later, remaining);
37045
37199
  return result;
37046
37200
  };
37047
37201
  throttled.cancel = function() {
37048
37202
  clearTimeout(timeout);
37049
37203
  previous = 0;
37050
- timeout = args = null;
37204
+ timeout = args = void 0;
37051
37205
  };
37052
37206
  return throttled;
37053
37207
  };
@@ -37100,26 +37254,39 @@ var ToolbarButtonIcon_default = /* @__PURE__ */ require__plugin_vue_export_helpe
37100
37254
  var _hoisted_1$15 = [
37101
37255
  "role",
37102
37256
  "aria-label",
37103
- "aria-disabled"
37257
+ "aria-disabled",
37258
+ "aria-busy"
37104
37259
  ];
37105
37260
  var _hoisted_2$11 = ["data-item"];
37106
37261
  var _hoisted_3$10 = ["data-item"];
37107
37262
  var _hoisted_4$8 = {
37108
- key: 1,
37263
+ key: 0,
37264
+ role: "status",
37265
+ "aria-label": "Applying list",
37266
+ style: { "font-weight": "700" }
37267
+ };
37268
+ var _hoisted_5$6 = {
37269
+ key: 2,
37109
37270
  class: "sd-button-label"
37110
37271
  };
37111
- var _hoisted_5$6 = ["data-item", "aria-label"];
37112
- var _hoisted_6$4 = ["innerHTML"];
37113
- var _hoisted_7$2 = { key: 2 };
37114
- var _hoisted_8$2 = ["onKeydown", "id"];
37115
- var _hoisted_9$1 = [
37272
+ var _hoisted_6$4 = ["data-item", "aria-label"];
37273
+ var _hoisted_7$2 = ["innerHTML"];
37274
+ var _hoisted_8$2 = {
37275
+ key: 0,
37276
+ role: "status",
37277
+ "aria-label": "Applying list",
37278
+ style: { "font-weight": "700" }
37279
+ };
37280
+ var _hoisted_9$1 = { key: 3 };
37281
+ var _hoisted_10$1 = ["onKeydown", "id"];
37282
+ var _hoisted_11$1 = [
37116
37283
  "placeholder",
37117
37284
  "onKeydown",
37118
37285
  "id",
37119
37286
  "data-item"
37120
37287
  ];
37121
- var _hoisted_10$1 = ["data-item", "innerHTML"];
37122
- var _hoisted_11$1 = {
37288
+ var _hoisted_12$1 = ["data-item", "innerHTML"];
37289
+ var _hoisted_13$1 = {
37123
37290
  "aria-live": "polite",
37124
37291
  class: "sd-visually-hidden"
37125
37292
  };
@@ -37290,6 +37457,7 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37290
37457
  role: __props.isOverflowItem ? "menuitem" : "button",
37291
37458
  "aria-label": require__plugin_vue_export_helper.unref(attributes).ariaLabel,
37292
37459
  "aria-disabled": require__plugin_vue_export_helper.unref(disabled) ? "true" : void 0,
37460
+ "aria-busy": require__plugin_vue_export_helper.unref(attributes).ariaBusy || void 0,
37293
37461
  "data-sd-part": "toolbar-item",
37294
37462
  onClick: handleOuterClick,
37295
37463
  onKeydown: _cache[9] || (_cache[9] = require__plugin_vue_export_helper.withKeys(($event) => onEnterKeydown($event), ["enter"])),
@@ -37311,17 +37479,21 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37311
37479
  class: "sd-toolbar-button__main",
37312
37480
  "data-item": `btn-${require__plugin_vue_export_helper.unref(name) || ""}-main`,
37313
37481
  onClick: _cache[0] || (_cache[0] = ($event) => handleSplitMainClick($event))
37314
- }, [require__plugin_vue_export_helper.unref(icon) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(ToolbarButtonIcon_default, {
37315
- key: 0,
37316
- color: require__plugin_vue_export_helper.unref(iconColor),
37317
- class: "sd-toolbar-icon",
37318
- icon: require__plugin_vue_export_helper.unref(icon),
37319
- name: require__plugin_vue_export_helper.unref(name)
37320
- }, null, 8, [
37321
- "color",
37322
- "icon",
37323
- "name"
37324
- ])) : require__plugin_vue_export_helper.createCommentVNode("", true), require__plugin_vue_export_helper.unref(label) && !require__plugin_vue_export_helper.unref(hideLabel) && !require__plugin_vue_export_helper.unref(inlineTextInputVisible) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_4$8, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(label)), 1)) : require__plugin_vue_export_helper.createCommentVNode("", true)], 8, _hoisted_3$10)) : require__plugin_vue_export_helper.createCommentVNode("", true),
37482
+ }, [
37483
+ require__plugin_vue_export_helper.unref(attributes).ariaBusy && isSplit.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_4$8, "…")) : require__plugin_vue_export_helper.createCommentVNode("", true),
37484
+ require__plugin_vue_export_helper.unref(icon) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(ToolbarButtonIcon_default, {
37485
+ key: 1,
37486
+ color: require__plugin_vue_export_helper.unref(iconColor),
37487
+ class: "sd-toolbar-icon",
37488
+ icon: require__plugin_vue_export_helper.unref(icon),
37489
+ name: require__plugin_vue_export_helper.unref(name)
37490
+ }, null, 8, [
37491
+ "color",
37492
+ "icon",
37493
+ "name"
37494
+ ])) : require__plugin_vue_export_helper.createCommentVNode("", true),
37495
+ require__plugin_vue_export_helper.unref(label) && !require__plugin_vue_export_helper.unref(hideLabel) && !require__plugin_vue_export_helper.unref(inlineTextInputVisible) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_5$6, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(label)), 1)) : require__plugin_vue_export_helper.createCommentVNode("", true)
37496
+ ], 8, _hoisted_3$10)) : require__plugin_vue_export_helper.createCommentVNode("", true),
37325
37497
  isSplit.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
37326
37498
  key: 1,
37327
37499
  class: "sd-toolbar-button__caret",
@@ -37332,9 +37504,10 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37332
37504
  class: "sd-dropdown-caret",
37333
37505
  innerHTML: caretIcon.value,
37334
37506
  style: require__plugin_vue_export_helper.normalizeStyle({ opacity: require__plugin_vue_export_helper.unref(disabled) ? .6 : 1 })
37335
- }, null, 12, _hoisted_6$4)], 8, _hoisted_5$6)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 2 }, [
37507
+ }, null, 12, _hoisted_7$2)], 8, _hoisted_6$4)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 2 }, [
37508
+ require__plugin_vue_export_helper.unref(attributes).ariaBusy ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_8$2, "…")) : require__plugin_vue_export_helper.createCommentVNode("", true),
37336
37509
  require__plugin_vue_export_helper.unref(icon) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(ToolbarButtonIcon_default, {
37337
- key: 0,
37510
+ key: 1,
37338
37511
  color: require__plugin_vue_export_helper.unref(iconColor),
37339
37512
  class: "sd-toolbar-icon",
37340
37513
  icon: require__plugin_vue_export_helper.unref(icon),
@@ -37345,10 +37518,10 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37345
37518
  "name"
37346
37519
  ])) : require__plugin_vue_export_helper.createCommentVNode("", true),
37347
37520
  require__plugin_vue_export_helper.unref(label) && !require__plugin_vue_export_helper.unref(hideLabel) && (!require__plugin_vue_export_helper.unref(inlineTextInputVisible) || itemName.value === "fontFamily") ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
37348
- key: 1,
37521
+ key: 2,
37349
37522
  class: require__plugin_vue_export_helper.normalizeClass(["sd-button-label", { "sd-visually-hidden": require__plugin_vue_export_helper.unref(inlineTextInputVisible) && itemName.value === "fontFamily" }])
37350
37523
  }, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(label)), 3)) : require__plugin_vue_export_helper.createCommentVNode("", true),
37351
- require__plugin_vue_export_helper.unref(inlineTextInputVisible) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_7$2, [require__plugin_vue_export_helper.unref(name) === "fontSize" ? require__plugin_vue_export_helper.withDirectives((require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("input", {
37524
+ require__plugin_vue_export_helper.unref(inlineTextInputVisible) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_9$1, [require__plugin_vue_export_helper.unref(name) === "fontSize" ? require__plugin_vue_export_helper.withDirectives((require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("input", {
37352
37525
  key: 0,
37353
37526
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => inlineTextInput.value = $event),
37354
37527
  onKeydown: [require__plugin_vue_export_helper.withKeys(require__plugin_vue_export_helper.withModifiers(handleInlineInputEnter, ["stop", "prevent"]), ["enter"]), _cache[2] || (_cache[2] = require__plugin_vue_export_helper.withKeys(($event) => handleInlineInputTab($event), ["tab"]))],
@@ -37360,7 +37533,7 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37360
37533
  autocomplete: "off",
37361
37534
  ref_key: "inlineInput",
37362
37535
  ref: inlineInput
37363
- }, null, 42, _hoisted_8$2)), [[require__plugin_vue_export_helper.vModelText, inlineTextInput.value]]) : require__plugin_vue_export_helper.withDirectives((require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("input", {
37536
+ }, null, 42, _hoisted_10$1)), [[require__plugin_vue_export_helper.vModelText, inlineTextInput.value]]) : require__plugin_vue_export_helper.withDirectives((require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("input", {
37364
37537
  key: 1,
37365
37538
  "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => inlineTextInput.value = $event),
37366
37539
  placeholder: require__plugin_vue_export_helper.unref(label),
@@ -37377,23 +37550,23 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37377
37550
  autocomplete: "off",
37378
37551
  ref_key: "inlineInput",
37379
37552
  ref: inlineInput
37380
- }, null, 42, _hoisted_9$1)), [[require__plugin_vue_export_helper.vModelText, inlineTextInput.value]])])) : require__plugin_vue_export_helper.createCommentVNode("", true),
37553
+ }, null, 42, _hoisted_11$1)), [[require__plugin_vue_export_helper.vModelText, inlineTextInput.value]])])) : require__plugin_vue_export_helper.createCommentVNode("", true),
37381
37554
  require__plugin_vue_export_helper.unref(hasCaret) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
37382
- key: 3,
37555
+ key: 4,
37383
37556
  class: "sd-dropdown-caret",
37384
37557
  "data-item": `btn-${require__plugin_vue_export_helper.unref(name) || ""}-toggle`,
37385
37558
  innerHTML: caretIcon.value,
37386
37559
  style: require__plugin_vue_export_helper.normalizeStyle({ opacity: require__plugin_vue_export_helper.unref(disabled) ? .6 : 1 })
37387
- }, null, 12, _hoisted_10$1)) : require__plugin_vue_export_helper.createCommentVNode("", true)
37560
+ }, null, 12, _hoisted_12$1)) : require__plugin_vue_export_helper.createCommentVNode("", true)
37388
37561
  ], 64)),
37389
- require__plugin_vue_export_helper.createElementVNode("div", _hoisted_11$1, require__plugin_vue_export_helper.toDisplayString(`${require__plugin_vue_export_helper.unref(attributes).ariaLabel} ${require__plugin_vue_export_helper.unref(active) ? "selected" : "unset"}`), 1)
37562
+ require__plugin_vue_export_helper.createElementVNode("div", _hoisted_13$1, require__plugin_vue_export_helper.toDisplayString(`${require__plugin_vue_export_helper.unref(attributes).ariaLabel} ${require__plugin_vue_export_helper.unref(active) ? "selected" : "unset"}`), 1)
37390
37563
  ], 10, _hoisted_2$11)], 46, _hoisted_1$15);
37391
37564
  };
37392
37565
  }
37393
37566
  });
37394
37567
  //#endregion
37395
37568
  //#region src/internal/toolbar/built-in/ToolbarButton.vue
37396
- var ToolbarButton_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(ToolbarButton_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e599674c"]]);
37569
+ var ToolbarButton_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(ToolbarButton_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-b49ede12"]]);
37397
37570
  //#endregion
37398
37571
  //#region src/internal/toolbar/built-in/ToolbarSeparator.vue?vue&type=script&setup=true&lang.ts
37399
37572
  var _hoisted_1$14 = {
@@ -37953,24 +38126,11 @@ var OverflowMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ req
37953
38126
  //#region src/internal/toolbar/built-in/OverflowMenu.vue
37954
38127
  var OverflowMenu_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(OverflowMenu_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-d2e189fd"]]);
37955
38128
  //#endregion
37956
- //#region src/internal/toolbar/built-in/font-typeahead.js
37957
- /**
37958
- * Pure typeahead/autocomplete helpers for the font comboboxes (family + size).
37959
- *
37960
- * Matching is case-insensitive prefix matching on the logical font labels.
37961
- * Space is a normal query character, so the query is never split on spaces;
37962
- * only the outer whitespace is ignored when comparing.
37963
- *
37964
- * These functions hold no Vue or DOM state so CI can unit-test them in isolation.
37965
- */
38129
+ //#region src/internal/toolbar/built-in/font-typeahead.ts
37966
38130
  var normalize = (value) => String(value ?? "").trim().toLowerCase();
37967
38131
  /**
37968
38132
  * Index of the first label that starts with `query` (case-insensitive).
37969
- * An empty/whitespace query never matches.
37970
- *
37971
- * @param {string} query
37972
- * @param {ReadonlyArray<string>} labels
37973
- * @returns {number} matching index or -1
38133
+ * An empty/whitespace query never matches. Returns the matching index or -1.
37974
38134
  */
37975
38135
  var findPrefixMatchIndex = (query, labels) => {
37976
38136
  const q = normalize(query);
@@ -37984,12 +38144,7 @@ var findPrefixMatchIndex = (query, labels) => {
37984
38144
  * When `autocomplete` is true and a prefix match exists that is longer than the
37985
38145
  * typed query, the completion is shown with the suffix selected so the next
37986
38146
  * keystroke replaces it. When false (deletion) or no match exists, the raw
37987
- * query is shown with the caret at its end.
37988
- *
37989
- * @param {string} query - the user-typed portion
37990
- * @param {ReadonlyArray<string>} labels
37991
- * @param {{ autocomplete?: boolean }} [options]
37992
- * @returns {{ matchIndex: number, display: string, selectionStart: number, selectionEnd: number }}
38147
+ * query is shown with the caret at its end. `query` is the user-typed portion.
37993
38148
  */
37994
38149
  var computeTypeahead = (query, labels, { autocomplete = true } = {}) => {
37995
38150
  const typed = String(query ?? "");
@@ -38041,9 +38196,6 @@ var MAX_FONT_SIZE = 1638;
38041
38196
  * the nearest half point (DOCX/Word support half points such as 10.5), and clamps
38042
38197
  * to the supported range. Returns '' when nothing usable was typed, including
38043
38198
  * negative or sub-minimum values.
38044
- *
38045
- * @param {string} value
38046
- * @returns {string} point size (whole or half), or '' when empty/invalid
38047
38199
  */
38048
38200
  var normalizeCustomFontSize = (value) => {
38049
38201
  const cleaned = String(value ?? "").replace(/[^0-9.-]/g, "");
@@ -38710,7 +38862,7 @@ var SdTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
38710
38862
  ]);
38711
38863
  const contentStyle = require__plugin_vue_export_helper.computed(() => ({
38712
38864
  ...props.contentStyle,
38713
- ...attrs.style || {},
38865
+ ...attrs.style,
38714
38866
  position: "fixed",
38715
38867
  top: position.value.top,
38716
38868
  left: position.value.left,
@@ -38882,7 +39034,7 @@ var SdTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
38882
39034
  });
38883
39035
  //#endregion
38884
39036
  //#region src/internal/toolbar/built-in/SdTooltip.vue
38885
- var SdTooltip_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SdTooltip_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-dfd6f1d1"]]);
39037
+ var SdTooltip_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SdTooltip_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-87967ab1"]]);
38886
39038
  //#endregion
38887
39039
  //#region src/internal/toolbar/built-in/ButtonGroup.vue?vue&type=script&setup=true&lang.ts
38888
39040
  var _hoisted_1$11 = [
@@ -39738,7 +39890,7 @@ var Toolbar_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require_
39738
39890
  //#region src/internal/toolbar/built-in/Toolbar.vue
39739
39891
  var Toolbar_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(Toolbar_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-bce7c04a"]]);
39740
39892
  //#endregion
39741
- //#region src/internal/toolbar/built-in/font-options.js
39893
+ //#region src/internal/toolbar/built-in/font-options.ts
39742
39894
  /**
39743
39895
  * Normalize a font dropdown option so each row renders in its own typeface.
39744
39896
  *
@@ -40096,7 +40248,7 @@ var StyleButtonsList_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
40096
40248
  //#region src/internal/toolbar/built-in/StyleButtonsList.vue
40097
40249
  var StyleButtonsList_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(StyleButtonsList_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-539d0995"]]);
40098
40250
  //#endregion
40099
- //#region src/internal/toolbar/built-in/list-style-buttons.js
40251
+ //#region src/internal/toolbar/built-in/list-style-buttons.ts
40100
40252
  var bulletStyleButtons = [
40101
40253
  {
40102
40254
  key: "disc",
@@ -40429,13 +40581,13 @@ var AIWriter_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
40429
40581
  });
40430
40582
  function extractGeneratedText(payload) {
40431
40583
  if (typeof payload === "string") return payload;
40432
- if (!require_create_super_doc_ui.isPlainObject(payload)) return "";
40584
+ if (!require__plugin_vue_export_helper.isPlainObject(payload)) return "";
40433
40585
  const customPrompt = payload.custom_prompt;
40434
40586
  if (Array.isArray(customPrompt)) {
40435
40587
  const first = customPrompt[0];
40436
- if (require_create_super_doc_ui.isPlainObject(first) && typeof first.value === "string") return first.value;
40588
+ if (require__plugin_vue_export_helper.isPlainObject(first) && typeof first.value === "string") return first.value;
40437
40589
  }
40438
- if (require_create_super_doc_ui.isPlainObject(customPrompt) && typeof customPrompt.value === "string") return customPrompt.value;
40590
+ if (require__plugin_vue_export_helper.isPlainObject(customPrompt) && typeof customPrompt.value === "string") return customPrompt.value;
40439
40591
  if (typeof payload.value === "string") return payload.value;
40440
40592
  if (typeof payload.text === "string") return payload.text;
40441
40593
  return "";
@@ -41314,7 +41466,7 @@ var PageNumberMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ r
41314
41466
  }
41315
41467
  function failureDetails(result) {
41316
41468
  if (typeof result !== "object" || result === null || result.success) return null;
41317
- return require_create_super_doc_ui.isPlainObject(result.failure?.details) ? result.failure.details : null;
41469
+ return require__plugin_vue_export_helper.isPlainObject(result.failure?.details) ? result.failure.details : null;
41318
41470
  }
41319
41471
  function failureMessage(result, action) {
41320
41472
  const details = failureDetails(result);
@@ -41426,7 +41578,7 @@ var PageNumberMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ r
41426
41578
  onClick: ($event) => selectTile(tile),
41427
41579
  onDblclick: applyPageNumbers,
41428
41580
  onKeydown: onTileKeydown
41429
- }, [(require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("svg", _hoisted_5, [_cache[4] || (_cache[4] = require__plugin_vue_export_helper.createStaticVNode("<rect class=\"sd-page-number-menu__sheet\" x=\"0.75\" y=\"0.75\" width=\"34.5\" height=\"44.5\" rx=\"2.5\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"14\" width=\"22\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"19\" width=\"18\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"24\" width=\"22\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"29\" width=\"14\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect>", 5)), require__plugin_vue_export_helper.createElementVNode("rect", {
41581
+ }, [(require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("svg", _hoisted_5, [_cache[4] || (_cache[4] = require__plugin_vue_export_helper.createStaticVNode("<rect class=\"sd-page-number-menu__sheet\" x=\"0.75\" y=\"0.75\" width=\"34.5\" height=\"44.5\" rx=\"2.5\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"14\" width=\"22\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"19\" width=\"18\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"24\" width=\"22\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"29\" width=\"14\" height=\"2\" rx=\"1\" data-v-e3105afd></rect>", 5)), require__plugin_vue_export_helper.createElementVNode("rect", {
41430
41582
  class: "sd-page-number-menu__chip",
41431
41583
  x: CHIP_X[tile.alignment],
41432
41584
  y: CHIP_Y[tile.position],
@@ -41509,23 +41661,21 @@ var PageNumberMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ r
41509
41661
  });
41510
41662
  //#endregion
41511
41663
  //#region src/internal/toolbar/built-in/PageNumberMenu.vue
41512
- var PageNumberMenu_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(PageNumberMenu_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-a6c124c0"]]);
41664
+ var PageNumberMenu_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(PageNumberMenu_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e3105afd"]]);
41513
41665
  //#endregion
41514
- //#region src/internal/toolbar/built-in/page-number-feedback.js
41666
+ //#region src/internal/toolbar/built-in/page-number-feedback.ts
41515
41667
  var FLASH_CLASS = "sd-page-number-flash";
41516
41668
  var FLASH_MS = 1400;
41517
41669
  var nextFrame = (view) => new Promise((resolve) => {
41518
- if (typeof view?.requestAnimationFrame === "function") view.requestAnimationFrame(() => resolve());
41670
+ if (typeof view.requestAnimationFrame === "function") view.requestAnimationFrame(() => resolve());
41519
41671
  else setTimeout(resolve, 16);
41520
41672
  });
41521
41673
  /**
41522
41674
  * Briefly highlight the painted header or footer regions that are on screen,
41523
41675
  * so the user sees where page numbers landed without the caret leaving the
41524
41676
  * body. Regions are read after the repaint that follows the mutation; nothing
41525
- * happens when none is visible or the host is unavailable.
41526
- *
41527
- * @param {HTMLElement | null | undefined} host Document viewport host element.
41528
- * @param {'header' | 'footer'} kind
41677
+ * happens when none is visible or the host is unavailable. `host` is the
41678
+ * document viewport host element.
41529
41679
  */
41530
41680
  async function flashPageNumberRegions(host, kind) {
41531
41681
  const view = host?.ownerDocument?.defaultView;
@@ -41533,7 +41683,7 @@ async function flashPageNumberRegions(host, kind) {
41533
41683
  await nextFrame(view);
41534
41684
  await nextFrame(view);
41535
41685
  const viewportHeight = view.innerHeight;
41536
- const regions = [...host.querySelectorAll(`[data-sd-headerfooter-kind="${kind}"]`)].filter((region) => {
41686
+ const regions = Array.from(host.querySelectorAll(`[data-sd-headerfooter-kind="${kind}"]`)).filter((region) => {
41537
41687
  const rect = region.getBoundingClientRect();
41538
41688
  return rect.height > 0 && rect.bottom > 0 && rect.top < viewportHeight;
41539
41689
  });
@@ -41711,7 +41861,7 @@ function currentSelectionSnapshot(superToolbar) {
41711
41861
  return superToolbar.ui?.selection?.get?.() ?? superToolbar.ui?.selection?.current?.() ?? null;
41712
41862
  }
41713
41863
  function readMember(value, key) {
41714
- return require_create_super_doc_ui.isPlainObject(value) ? value[key] : void 0;
41864
+ return require__plugin_vue_export_helper.isPlainObject(value) ? value[key] : void 0;
41715
41865
  }
41716
41866
  function configuredAiModule(superToolbar) {
41717
41867
  return readMember(readMember(readMember(readMember(superToolbar.config, "superdoc"), "config"), "modules"), "ai");
@@ -41734,6 +41884,8 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41734
41884
  attributes: { ariaLabel: "Bold" }
41735
41885
  });
41736
41886
  const fontOptions = (toolbarFonts ?? TOOLBAR_FONTS).map(normalizeFontOption);
41887
+ const isFontOption = (option) => typeof option.label === "string" && typeof option.key === "string";
41888
+ const currentFontOptions = () => fontButton.nestedOptions.value.filter(isFontOption);
41737
41889
  const fontButton = useToolbarItem({
41738
41890
  type: "dropdown",
41739
41891
  name: "fontFamily",
@@ -41760,8 +41912,9 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41760
41912
  if (typeof fontFamily !== "string" || !fontFamily) return;
41761
41913
  const family = fontFamily.split(",")[0];
41762
41914
  const optionValue = (option) => option.value ?? option.label;
41763
- const defaultFont = fontOptions.find((option) => optionValue(option) === fontButton.defaultLabel.value);
41764
- const foundFont = fontOptions.find((option) => optionValue(option) === family);
41915
+ const options = currentFontOptions();
41916
+ const defaultFont = options.find((option) => optionValue(option) === fontButton.defaultLabel.value);
41917
+ const foundFont = options.find((option) => optionValue(option) === family);
41765
41918
  if (foundFont) {
41766
41919
  fontButton.label.value = foundFont.label;
41767
41920
  fontButton.selectedValue.value = foundFont.key;
@@ -41774,7 +41927,7 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41774
41927
  }
41775
41928
  },
41776
41929
  onDeactivate: () => {
41777
- const defaultFont = fontOptions.find((option) => (option.value ?? option.label) === fontButton.defaultLabel.value);
41930
+ const defaultFont = currentFontOptions().find((option) => (option.value ?? option.label) === fontButton.defaultLabel.value);
41778
41931
  fontButton.label.value = defaultFont?.label ?? fontButton.defaultLabel.value;
41779
41932
  fontButton.selectedValue.value = defaultFont?.key ?? "";
41780
41933
  }
@@ -42881,7 +43034,7 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
42881
43034
  };
42882
43035
  };
42883
43036
  //#endregion
42884
- //#region src/internal/toolbar/built-in/general.js
43037
+ //#region src/internal/toolbar/built-in/general.ts
42885
43038
  /**
42886
43039
  * Minimal DOM helpers for the built-in toolbar shell.
42887
43040
  *
@@ -42892,8 +43045,6 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
42892
43045
  */
42893
43046
  /**
42894
43047
  * Resolve a toolbar mount target from a selector string or element id.
42895
- * @param {string|HTMLElement|null|undefined} selector
42896
- * @returns {HTMLElement|null}
42897
43048
  */
42898
43049
  var findElementBySelector = (selector) => {
42899
43050
  if (!selector) return null;
@@ -42933,9 +43084,6 @@ function toSelectedValue(value) {
42933
43084
  function nonEmptyString(value) {
42934
43085
  return typeof value === "string" && value ? value : void 0;
42935
43086
  }
42936
- function isThenable(value) {
42937
- return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
42938
- }
42939
43087
  function isToolbarCommandCallback(value) {
42940
43088
  return typeof value === "function";
42941
43089
  }
@@ -42958,7 +43106,7 @@ function executeCommand(ui, commandId, argument, options = {}) {
42958
43106
  if (!options.reportUnhandled || settled !== false) return;
42959
43107
  options.onError?.(/* @__PURE__ */ new Error(`[superdoc toolbar] Command "${commandId}" did not run. Check that it is enabled and has the required input.`));
42960
43108
  };
42961
- if (isThenable(result)) Promise.resolve(result).then((settled) => {
43109
+ if (require__plugin_vue_export_helper.isThenable(result)) Promise.resolve(result).then((settled) => {
42962
43110
  reportFailure(settled);
42963
43111
  options.onSettled?.();
42964
43112
  }, (error) => {
@@ -42991,7 +43139,7 @@ var V1_ENABLED_ON_SELECTION_REASON = /* @__PURE__ */ new Set([
42991
43139
  ]);
42992
43140
  var V1_ENABLED_ON_EMPTY_REASON = /* @__PURE__ */ new Set(["list", "numberedlist"]);
42993
43141
  function shouldKeepEnabledForV1ToolbarParity(name, commandState) {
42994
- if (name === "fontFamily" || name === "fontSize") return true;
43142
+ if (name === "fontFamily" || name === "fontSize") return commandState?.reason !== "document-readonly";
42995
43143
  if (V1_ENABLED_ON_EMPTY_REASON.has(name) && commandState?.disabled && commandState?.supported !== false && commandState?.reason == null) return true;
42996
43144
  if (!V1_ENABLED_ON_SELECTION_REASON.has(name)) return false;
42997
43145
  const reason = commandState?.reason;
@@ -43182,7 +43330,7 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43182
43330
  const signature = this.#fontOptionsSignature();
43183
43331
  if (signature !== this._lastFontOptionsSignature) {
43184
43332
  this._lastFontOptionsSignature = signature;
43185
- this.#rebuildToolbarItems();
43333
+ if (!this.#refreshFontFamilyOptions()) this.#rebuildToolbarItems();
43186
43334
  }
43187
43335
  this.updateToolbarState();
43188
43336
  };
@@ -43310,7 +43458,7 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43310
43458
  argument: payload.argument,
43311
43459
  option: payload.option
43312
43460
  });
43313
- if (isThenable(result)) return Promise.resolve(result).catch((error) => {
43461
+ if (require__plugin_vue_export_helper.isThenable(result)) return Promise.resolve(result).catch((error) => {
43314
43462
  this.#emitCommandException(error, config.name);
43315
43463
  return false;
43316
43464
  });
@@ -43330,6 +43478,13 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43330
43478
  this.#makeToolbarItems();
43331
43479
  this.emit("toolbar-items-changed");
43332
43480
  }
43481
+ #refreshFontFamilyOptions() {
43482
+ const items = this.#getAllToolbarItems().filter((item) => item.name.value === "fontFamily");
43483
+ if (!items.length) return false;
43484
+ const options = (this.#resolveToolbarFonts(this.config.fonts) ?? TOOLBAR_FONTS).map(normalizeFontOption);
43485
+ for (const item of items) item.nestedOptions.value = options.map((option) => ({ ...option }));
43486
+ return true;
43487
+ }
43333
43488
  #fontOptionsSignature() {
43334
43489
  if (this.config.fonts) return "custom-fonts";
43335
43490
  const options = this.superdoc?.fonts?.getFontFamilyOptions?.() ?? [];
@@ -43509,6 +43664,10 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43509
43664
  const commandId = resolveBuiltInItemCommandId(name);
43510
43665
  if (!commandId) return false;
43511
43666
  const commandState = this.snapshot?.commands?.[commandId];
43667
+ if ((name === "list" || name === "numberedlist") && item.attributes.value.ariaBusy !== Boolean(commandState?.pending)) item.attributes.value = {
43668
+ ...item.attributes.value,
43669
+ ariaBusy: Boolean(commandState?.pending)
43670
+ };
43512
43671
  if (shouldKeepEnabledForV1ToolbarParity(name, commandState)) item.setDisabled(false);
43513
43672
  else item.setDisabled(Boolean(commandState?.disabled));
43514
43673
  const handlers = {
@@ -43787,7 +43946,7 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43787
43946
  ui: this.ui,
43788
43947
  superdoc: this.superdoc
43789
43948
  });
43790
- if (isThenable(result)) Promise.resolve(result).catch((error) => this.#emitCommandException(error, name));
43949
+ if (require__plugin_vue_export_helper.isThenable(result)) Promise.resolve(result).catch((error) => this.#emitCommandException(error, name));
43791
43950
  }
43792
43951
  this.updateToolbarState();
43793
43952
  return;
@@ -44053,6 +44212,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44053
44212
  #v2ConnectionUnsub;
44054
44213
  /** Latest `collaboration-connection-change` payload, for late readers. */
44055
44214
  #v2ConnectionState;
44215
+ #v2ConnectionFailureReported;
44056
44216
  /** Whether the current collaboration room has completed a sync at least once. */
44057
44217
  #v2ConnectionHasSynced;
44058
44218
  /** Lock state captured before a local → v2 collaboration promotion remount. */
@@ -44155,6 +44315,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44155
44315
  this.#v2LockUnsub = null;
44156
44316
  this.#v2ConnectionUnsub = null;
44157
44317
  this.#v2ConnectionState = null;
44318
+ this.#v2ConnectionFailureReported = false;
44158
44319
  this.#v2ConnectionHasSynced = false;
44159
44320
  this.#pendingV2LockSeed = null;
44160
44321
  this.#mountWrapper = null;
@@ -44357,7 +44518,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44357
44518
  }
44358
44519
  this.userColorMap = /* @__PURE__ */ new Map();
44359
44520
  this.colorIndex = 0;
44360
- this.version = "2.29.0-next.9";
44521
+ this.version = "2.30.0-next.4";
44361
44522
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
44362
44523
  this.superdocId = config.superdocId || require_uuid.v4();
44363
44524
  this.colors = this.config.colors ?? [];
@@ -44776,6 +44937,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44776
44937
  if (this.#v2ConnectionState?.documentId !== documentId) {
44777
44938
  this.#v2ConnectionState = null;
44778
44939
  this.#v2ConnectionHasSynced = false;
44940
+ this.#v2ConnectionFailureReported = false;
44779
44941
  }
44780
44942
  const publish = (snapshot) => {
44781
44943
  if (this.#destroyed) return;
@@ -44790,8 +44952,21 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44790
44952
  superdoc: this
44791
44953
  };
44792
44954
  this.#v2ConnectionState = payload;
44793
- if (snapshot.state === "synced") this.#v2ConnectionHasSynced = true;
44794
- this.emit("collaboration-connection-change", payload);
44955
+ if (snapshot.state === "synced") {
44956
+ this.#v2ConnectionHasSynced = true;
44957
+ this.#v2ConnectionFailureReported = false;
44958
+ }
44959
+ const firstFailure = snapshot.state === "failed" && !this.#v2ConnectionFailureReported;
44960
+ if (firstFailure) this.#v2ConnectionFailureReported = true;
44961
+ const reportFailure = firstFailure && snapshot.detail !== "worker-transport-failed";
44962
+ try {
44963
+ this.emit("collaboration-connection-change", payload);
44964
+ } finally {
44965
+ if (reportFailure) {
44966
+ const exception = createCollaborationException("collaboration-connection-failed", documentId);
44967
+ if (exception) this.emit("exception", exception);
44968
+ }
44969
+ }
44795
44970
  };
44796
44971
  try {
44797
44972
  const initialSnapshot = connection.getSnapshot?.();