superdoc 2.29.0 → 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 (112) hide show
  1. package/README.md +127 -25
  2. package/dist/chunks/{FindReplaceSurface-B_5ggdWg.es.js → FindReplaceSurface-BEnRLpD9.es.js} +1 -1
  3. package/dist/chunks/{FindReplaceSurface-fVHxPXtn.cjs → FindReplaceSurface-DWXgWgg7.cjs} +1 -1
  4. package/dist/chunks/{PasswordPromptSurface-CZqhDQQ1.es.js → PasswordPromptSurface-DjV1JgjD.es.js} +1 -1
  5. package/dist/chunks/{PasswordPromptSurface-x8GNmMJT.cjs → PasswordPromptSurface-VFPnQOML.cjs} +1 -1
  6. package/dist/chunks/{PdfViewer-CW09MNrB.es.js → PdfViewer-C2r-K8zC.es.js} +1 -1
  7. package/dist/chunks/{PdfViewer-CkrAHpC-.cjs → PdfViewer-DYTbPVUr.cjs} +1 -1
  8. package/dist/chunks/{_plugin-vue_export-helper-BkbCxNeT.cjs → _plugin-vue_export-helper-BzM2_tVU.cjs} +9 -0
  9. package/dist/chunks/{_plugin-vue_export-helper-DRPRMkeA.es.js → _plugin-vue_export-helper-CmkaJDnr.es.js} +4 -1
  10. package/dist/chunks/{create-super-doc-ui-L60GhVAX.cjs → create-super-doc-ui--kQBNTyt.cjs} +2733 -2574
  11. package/dist/chunks/{create-super-doc-ui-Dc8dQAMc.es.js → create-super-doc-ui-CbEDXtpm.es.js} +2734 -2581
  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-tracked-change-thread.d.ts +6 -4
  54. package/dist/superdoc/src/components/CommentsLayer/comment-params.d.ts +84 -0
  55. package/dist/superdoc/src/components/CommentsLayer/use-comment.d.ts +15 -95
  56. package/dist/superdoc/src/components/Whiteboard/use-whiteboard.d.ts +30 -9
  57. package/dist/superdoc/src/composables/use-document.d.ts +51 -99
  58. package/dist/superdoc/src/core/SuperDoc.d.ts +12 -3
  59. package/dist/superdoc/src/core/collaboration/cdn-collaboration-comment-map.d.ts +1 -0
  60. package/dist/superdoc/src/core/collaboration/collaboration-comment-map.d.ts +2 -0
  61. package/dist/superdoc/src/core/collaboration/helpers.d.ts +1 -1
  62. package/dist/superdoc/src/core/document-open-telemetry.d.ts +1 -1
  63. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +1 -0
  64. package/dist/superdoc/src/core/types/index.d.ts +71 -39
  65. package/dist/superdoc/src/helpers/deprecation.d.ts +12 -3
  66. package/dist/superdoc/src/helpers/object-guards.d.ts +1 -0
  67. package/dist/superdoc/src/helpers/v2-review-geometry-delivery.d.ts +22 -0
  68. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButton.vue.d.ts +1 -0
  69. package/dist/superdoc/src/public/content-control-ref.d.ts +12 -0
  70. package/dist/superdoc/src/public/index.d.cts +16 -0
  71. package/dist/superdoc/src/public/index.d.ts +3 -0
  72. package/dist/superdoc/src/public/ui/async-read-cache.d.ts +32 -0
  73. package/dist/superdoc/src/public/ui/block-commands.d.ts +39 -0
  74. package/dist/superdoc/src/public/ui/command-results.d.ts +39 -0
  75. package/dist/superdoc/src/public/ui/create-super-doc-ui.d.ts +1 -17
  76. package/dist/superdoc/src/public/ui/document-change-records.d.ts +7 -0
  77. package/dist/superdoc/src/public/ui/entity-rows.d.ts +14 -0
  78. package/dist/superdoc/src/public/ui/font-options.d.ts +7 -0
  79. package/dist/superdoc/src/public/ui/format-painter-state.d.ts +33 -0
  80. package/dist/superdoc/src/public/ui/heavy-read-policy.d.ts +11 -0
  81. package/dist/superdoc/src/public/ui/host-events.d.ts +3 -0
  82. package/dist/superdoc/src/public/ui/inline-values.d.ts +79 -0
  83. package/dist/superdoc/src/public/ui/loose-record.d.ts +4 -0
  84. package/dist/superdoc/src/public/ui/selection-targets.d.ts +45 -0
  85. package/dist/superdoc/src/public/ui/shared-tracked-changes-catalog.d.ts +16 -0
  86. package/dist/superdoc/src/public/ui/tracked-change-ids.d.ts +51 -0
  87. package/dist/superdoc/src/public/ui/types.d.ts +12 -2
  88. package/dist/superdoc/src/public/ui/ui-bench-timing.d.ts +9 -0
  89. package/dist/superdoc/src/public/ui.d.cts +14 -0
  90. package/dist/superdoc/src/public/ui.d.ts +1 -1
  91. package/dist/superdoc/src/stores/comments-store.d.ts +23000 -536
  92. package/dist/superdoc/src/stores/helpers/comment-grouping.d.ts +1 -1
  93. package/dist/superdoc/src/stores/helpers/comment-identity.d.ts +10 -10
  94. package/dist/superdoc/src/stores/helpers/review-presentation.d.ts +90 -0
  95. package/dist/superdoc/src/stores/helpers/tracked-change-identity.d.ts +4 -2
  96. package/dist/superdoc/src/stores/helpers/tracked-change-row-values.d.ts +1 -8
  97. package/dist/superdoc/src/stores/helpers/tracked-change-thread-index.d.ts +1 -1
  98. package/dist/superdoc/src/stores/helpers/v2-review-adapters.d.ts +147 -0
  99. package/dist/superdoc/src/stores/superdoc-store.d.ts +12 -2895
  100. package/dist/superdoc.cjs +604 -388
  101. package/dist/superdoc.es.js +604 -388
  102. package/dist/word-layout/src/marker-utils.d.ts +0 -5
  103. package/dist/word-layout/src/unit-conversions.d.ts +0 -1
  104. package/dist-cdn/style.layered.css +1 -1
  105. package/dist-cdn/superdoc.min.css +1 -1
  106. package/dist-cdn/superdoc.min.js +38 -42
  107. package/package.json +12 -3
  108. package/dist/document-api/src/diff/index.d.ts +0 -3
  109. package/dist/document-api/src/write/locator.d.ts +0 -24
  110. package/dist/layout-engine/painters/dom/src/features/feature-registry.d.ts +0 -41
  111. package/dist/superdoc/src/internal/toolbar/built-in/format-negation.d.ts +0 -11
  112. package/dist/word-layout/src/tab-layout.d.ts +0 -193
package/dist/superdoc.cjs CHANGED
@@ -1,8 +1,8 @@
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-BkbCxNeT.cjs");
3
+ const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-BzM2_tVU.cjs");
4
4
  const require_blank_docx = require("./chunks/blank-docx-BuFAbRjs.cjs");
5
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-L60GhVAX.cjs");
5
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui--kQBNTyt.cjs");
6
6
  const require_eventemitter3 = require("./chunks/eventemitter3-C_TAnXOl.cjs");
7
7
  const require_uuid = require("./chunks/uuid-BhG0ngwk.cjs");
8
8
  const require_jszip = require("./chunks/jszip-D8mAFF-r.cjs");
@@ -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";
262
+ return "2.30.0-next.4";
263
263
  } catch {
264
264
  return "unknown";
265
265
  }
@@ -5839,6 +5839,11 @@ 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;
@@ -5847,14 +5852,14 @@ var readComment = (event) => {
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(() => {
@@ -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) => {
@@ -7112,6 +7235,7 @@ var groupCommittedComments = (comments, presentations, isVisible) => {
7112
7235
  });
7113
7236
  const grouped = groupComments(comments.filter((row) => !presentations[String(row.fileId)]), isVisible);
7114
7237
  for (const [documentId, presentation] of Object.entries(presentations)) {
7238
+ if (!presentation) continue;
7115
7239
  grouped.parentComments.push(...visibleRowsInOrder(documentId, presentation.groupOrder.open));
7116
7240
  grouped.resolvedComments.push(...visibleRowsInOrder(documentId, presentation.groupOrder.resolved));
7117
7241
  }
@@ -7807,9 +7931,55 @@ var createDroppedCommentIdMap = (duplicates) => {
7807
7931
  return droppedCommentIds;
7808
7932
  };
7809
7933
  //#endregion
7810
- //#region src/stores/comments-store.js
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);
7811
7980
  var useCommentsStore = defineStore("comments", () => {
7812
7981
  const superdocStore = useSuperdocStore();
7982
+ const findDocument = (documentId) => typeof documentId === "string" ? superdocStore.getDocument(documentId) : void 0;
7813
7983
  const commentsConfig = require__plugin_vue_export_helper.reactive({
7814
7984
  name: "comments",
7815
7985
  readOnly: false,
@@ -7876,7 +8046,7 @@ var useCommentsStore = defineStore("comments", () => {
7876
8046
  });
7877
8047
  const getTrackedChangeThread = (parentComment) => {
7878
8048
  const id = parentComment?.commentId ?? null;
7879
- return (id != null ? trackedChangeThreadIndex.value.get(id) : null) ?? [parentComment].filter(Boolean);
8049
+ return (id != null ? trackedChangeThreadIndex.value.get(id) : null) ?? (parentComment ? [parentComment] : []);
7880
8050
  };
7881
8051
  let priorTrackedChangeDecisionLinkIndex = /* @__PURE__ */ new Map();
7882
8052
  const trackedChangeDecisionLinkIndex = require__plugin_vue_export_helper.computed(() => {
@@ -7908,29 +8078,27 @@ var useCommentsStore = defineStore("comments", () => {
7908
8078
  });
7909
8079
  const v2CommentsAdapter = require__plugin_vue_export_helper.shallowRef(null);
7910
8080
  const setV2CommentsAdapter = (adapter) => {
7911
- if (v2CommentsAdapter.value !== (adapter ?? null)) pendingCommentRequest += 1;
7912
- v2CommentsAdapter.value = adapter ?? null;
8081
+ const next = isV2CommentsAdapter(adapter) ? adapter : null;
8082
+ if (v2CommentsAdapter.value !== next) pendingCommentRequest += 1;
8083
+ v2CommentsAdapter.value = next;
7913
8084
  };
7914
8085
  const getV2CommentsAdapter = (superdoc) => {
7915
- const fromFacade = superdoc?.activeEditor?.v2Comments ?? null;
7916
- if (fromFacade) return fromFacade;
8086
+ const fromFacade = superdoc?.activeEditor?.v2Comments;
8087
+ if (isV2CommentsAdapter(fromFacade)) return fromFacade;
7917
8088
  return v2CommentsAdapter.value;
7918
8089
  };
7919
8090
  const isV2EditorActive = (superdoc) => superdoc?.activeEditor?.editorVersion === 2 || v2CommentsAdapter.value !== null;
7920
8091
  const v2TrackedChangesAdapter = require__plugin_vue_export_helper.shallowRef(null);
7921
8092
  const setV2TrackedChangesAdapter = (adapter) => {
7922
- v2TrackedChangesAdapter.value = adapter ?? null;
8093
+ v2TrackedChangesAdapter.value = isV2TrackedChangesAdapter(adapter) ? adapter : null;
7923
8094
  };
7924
8095
  const getV2TrackedChangesAdapter = (superdoc) => {
7925
- const fromFacade = superdoc?.activeEditor?.v2TrackedChanges ?? null;
7926
- if (fromFacade) return fromFacade;
8096
+ const fromFacade = superdoc?.activeEditor?.v2TrackedChanges;
8097
+ if (isV2TrackedChangesAdapter(fromFacade)) return fromFacade;
7927
8098
  return v2TrackedChangesAdapter.value;
7928
8099
  };
7929
8100
  /**
7930
8101
  * Initialize the store
7931
- *
7932
- * @param {Object} config The comments module config from SuperDoc
7933
- * @returns {void}
7934
8102
  */
7935
8103
  const init = (config = {}) => {
7936
8104
  const updatedConfig = {
@@ -7962,12 +8130,17 @@ var useCommentsStore = defineStore("comments", () => {
7962
8130
  comment.trackedChangeDecision = null;
7963
8131
  };
7964
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
+ };
7965
8141
  /**
7966
8142
  * Check if a comment originated from the document editor (or has no explicit source).
7967
8143
  * Comments without a source are assumed to be editor-backed for backward compatibility.
7968
- *
7969
- * @param {Object} comment - The comment to check
7970
- * @returns {boolean} True if the comment is editor-backed
7971
8144
  */
7972
8145
  const isEditorBackedComment = (comment) => {
7973
8146
  const source = comment?.selection?.source;
@@ -8001,9 +8174,6 @@ var useCommentsStore = defineStore("comments", () => {
8001
8174
  }, { deep: false });
8002
8175
  /**
8003
8176
  * Get the editor position data for a comment.
8004
- *
8005
- * @param {Object | string} commentOrId The comment object or comment ID
8006
- * @returns {Object | null} The position data from editorCommentPositions
8007
8177
  */
8008
8178
  const getCommentPosition = (commentOrId) => {
8009
8179
  return resolveCommentPositionEntry(commentOrId).entry ?? null;
@@ -8016,10 +8186,6 @@ var useCommentsStore = defineStore("comments", () => {
8016
8186
  };
8017
8187
  /**
8018
8188
  * Set the active comment or clear all active comments
8019
- *
8020
- * @param {Object | undefined | null} superdoc The SuperDoc instance holding the active editor
8021
- * @param {string | undefined | null} id The comment ID
8022
- * @returns {void}
8023
8189
  */
8024
8190
  const setActiveComment = (superdoc, id) => {
8025
8191
  const activeEditor = superdoc?.activeEditor;
@@ -8030,7 +8196,7 @@ var useCommentsStore = defineStore("comments", () => {
8030
8196
  v2Adapter.setActiveComment(null);
8031
8197
  return;
8032
8198
  }
8033
- activeEditor?.commands?.setActiveComment({ commentId: null });
8199
+ activeEditor?.commands?.setActiveComment?.({ commentId: null });
8034
8200
  return;
8035
8201
  }
8036
8202
  const comment = getComment(id);
@@ -8041,16 +8207,11 @@ var useCommentsStore = defineStore("comments", () => {
8041
8207
  v2Adapter.setActiveComment(comment.commentId);
8042
8208
  return;
8043
8209
  }
8044
- activeEditor?.commands?.setActiveComment({ commentId: activeComment.value });
8210
+ activeEditor?.commands?.setActiveComment?.({ commentId: activeComment.value });
8045
8211
  };
8046
8212
  /**
8047
8213
  * Called when a tracked change is updated. Creates a new comment if necessary,
8048
8214
  * or updates an existing tracked-change comment.
8049
- *
8050
- * @param {Object} param0
8051
- * @param {Object} param0.superdoc The SuperDoc instance
8052
- * @param {Object} param0.params The tracked change params
8053
- * @returns {void}
8054
8215
  */
8055
8216
  const handleTrackedChangeUpdate = ({ superdoc, params, broadcastChanges = true, trackedChangeIdentityIndex = null }) => {
8056
8217
  const span = startInteractionSpan("store.trackedChanges.handleUpdate", "store-reconciliation", {
@@ -8079,7 +8240,7 @@ var useCommentsStore = defineStore("comments", () => {
8079
8240
  const normalizedTrackedChangeImagePreview = normalizeTrackedChangeImagePreview(trackedChangeImagePreview);
8080
8241
  const comment = getPendingComment({
8081
8242
  documentId,
8082
- commentId: changeId,
8243
+ commentId: normalizedChangeId ?? void 0,
8083
8244
  trackedChange: true,
8084
8245
  trackedChangeText,
8085
8246
  trackedChangeType,
@@ -8131,7 +8292,7 @@ var useCommentsStore = defineStore("comments", () => {
8131
8292
  commentCanonicalId,
8132
8293
  commentAnchorKey,
8133
8294
  ...commentAliasIds
8134
- ].filter(Boolean).some((id) => incomingAliasIds.has(id))) return true;
8295
+ ].some((id) => id != null && incomingAliasIds.has(id))) return true;
8135
8296
  const hasSyntheticSideIdentity = normalizedTrackedChangeCanonicalId && normalizedTrackedChangeCanonicalId !== normalizedChangeId || commentCanonicalId && commentCanonicalId !== commentId;
8136
8297
  if (hasCompatibleStory && commentId === normalizedChangeId) return true;
8137
8298
  if (hasCompatibleStory && !hasSyntheticSideIdentity && (importedId === normalizedChangeId || normalizedImportedId !== void 0 && normalizedImportedId != null && importedId === normalizedImportedId)) return true;
@@ -8155,7 +8316,7 @@ var useCommentsStore = defineStore("comments", () => {
8155
8316
  };
8156
8317
  const emitTrackedChangeEvent = (event) => {
8157
8318
  if (!broadcastChanges) return;
8158
- syncCommentsToClients(superdoc, event);
8319
+ syncCommentsToClients(requireHost(superdoc, "handleTrackedChangeUpdate"), event);
8159
8320
  debounceEmit(changeId, event, superdoc);
8160
8321
  };
8161
8322
  const setIfChanged = (target, key, value) => {
@@ -8198,8 +8359,9 @@ var useCommentsStore = defineStore("comments", () => {
8198
8359
  target?.trackedChangeCanonicalId,
8199
8360
  target?.trackedChangeAnchorKey,
8200
8361
  ...getCommentAliasIds(target)
8201
- ].map((id) => normalizeCommentId(id)).filter(Boolean));
8202
- 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;
8203
8365
  }
8204
8366
  let didChange = false;
8205
8367
  for (const [key, value] of Object.entries(fields)) didChange = setIfChanged(target, key, value) || didChange;
@@ -8208,7 +8370,7 @@ var useCommentsStore = defineStore("comments", () => {
8208
8370
  didChange = true;
8209
8371
  }
8210
8372
  if (hasCustomAttributes && target && !trackedChangeCustomAttributesEqual(target.customAttributes, normalizedCustomAttributes)) {
8211
- target.customAttributes = normalizedCustomAttributes;
8373
+ target.customAttributes = normalizedCustomAttributes ?? null;
8212
8374
  didChange = true;
8213
8375
  }
8214
8376
  return applyStoryMetadata(target) || didChange;
@@ -8230,7 +8392,7 @@ var useCommentsStore = defineStore("comments", () => {
8230
8392
  return;
8231
8393
  }
8232
8394
  addHydratedComment({
8233
- superdoc,
8395
+ superdoc: requireHost(superdoc, "handleTrackedChangeUpdate"),
8234
8396
  comment,
8235
8397
  broadcastChanges
8236
8398
  });
@@ -8250,11 +8412,12 @@ var useCommentsStore = defineStore("comments", () => {
8250
8412
  id: params.resolvedById ?? superdoc?.user?.id ?? null,
8251
8413
  email: params.resolvedByEmail ?? superdoc?.user?.email ?? null,
8252
8414
  name: params.resolvedByName ?? superdoc?.user?.name ?? null,
8253
- decision: params.decision ?? null,
8415
+ decision: params.decision ?? void 0,
8254
8416
  superdoc
8255
8417
  };
8256
8418
  if (existingTrackedChange && !existingTrackedChange.resolvedTime) existingTrackedChange.resolveComment({
8257
8419
  ...resolveArgs,
8420
+ superdoc: requireHost(superdoc, "handleTrackedChangeUpdate"),
8258
8421
  reconciliationToken: COMMENT_RECONCILIATION_TOKEN
8259
8422
  });
8260
8423
  }
@@ -8279,10 +8442,11 @@ var useCommentsStore = defineStore("comments", () => {
8279
8442
  instantSidebarAlignmentInstanceId.value = null;
8280
8443
  };
8281
8444
  const debounceEmit = (commentId, event, superdoc, delay = 1e3) => {
8282
- if (debounceTimers[commentId]) clearTimeout(debounceTimers[commentId]);
8283
- debounceTimers[commentId] = setTimeout(() => {
8445
+ const timerKey = String(commentId);
8446
+ if (debounceTimers[timerKey]) clearTimeout(debounceTimers[timerKey]);
8447
+ debounceTimers[timerKey] = setTimeout(() => {
8284
8448
  if (superdoc) superdoc.emit("comments-update", event);
8285
- delete debounceTimers[commentId];
8449
+ delete debounceTimers[timerKey];
8286
8450
  }, delay);
8287
8451
  };
8288
8452
  const showAddComment = (superdoc, targetClientY = null) => {
@@ -8294,7 +8458,7 @@ var useCommentsStore = defineStore("comments", () => {
8294
8458
  if (!ownsRequest()) return;
8295
8459
  superdoc.emit("comments-update", {
8296
8460
  type: COMMENT_EVENTS.PENDING,
8297
- pendingSelection: superdoc?.activeEditor === editor ? snapshot : null
8461
+ pendingSelection: superdoc?.activeEditor === editor && require__plugin_vue_export_helper.isPlainObject(snapshot) ? snapshot : null
8298
8462
  });
8299
8463
  };
8300
8464
  if (v2Adapter) {
@@ -8339,12 +8503,11 @@ var useCommentsStore = defineStore("comments", () => {
8339
8503
  }).catch((err) => ({
8340
8504
  ok: false,
8341
8505
  reason: "selection-capture-failed",
8342
- detail: err?.message ?? String(err)
8506
+ detail: errorDetail(err)
8343
8507
  }));
8344
8508
  }
8345
8509
  const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8346
- const asyncSnapshot = typeof pendingSelection?.then === "function";
8347
- if (!asyncSnapshot) emitPending(pendingSelection);
8510
+ if (!require__plugin_vue_export_helper.isThenable(pendingSelection)) emitPending(pendingSelection);
8348
8511
  const showLegacyPending = (selection) => {
8349
8512
  selection.selectionBounds = { ...selection.selectionBounds };
8350
8513
  if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
@@ -8354,7 +8517,7 @@ var useCommentsStore = defineStore("comments", () => {
8354
8517
  parentCommentId: null
8355
8518
  });
8356
8519
  if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8357
- if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8520
+ if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment?.({
8358
8521
  ...pendingComment.value.getValues(),
8359
8522
  commentId: "pending",
8360
8523
  skipEmit: true
@@ -8365,10 +8528,10 @@ var useCommentsStore = defineStore("comments", () => {
8365
8528
  activeComment.value = pendingComment.value.commentId;
8366
8529
  return { ok: true };
8367
8530
  };
8368
- if (asyncSnapshot) {
8531
+ if (require__plugin_vue_export_helper.isThenable(pendingSelection)) {
8369
8532
  const selection = { ...superdocStore.activeSelection };
8370
8533
  selection.selectionBounds = { ...selection.selectionBounds };
8371
- return pendingSelection.then((snapshot) => {
8534
+ return Promise.resolve(pendingSelection).then((snapshot) => {
8372
8535
  if (!ownsRequest()) return {
8373
8536
  ok: false,
8374
8537
  reason: "pending-comment-superseded"
@@ -8400,12 +8563,6 @@ var useCommentsStore = defineStore("comments", () => {
8400
8563
  });
8401
8564
  /**
8402
8565
  * Get a new pending comment
8403
- *
8404
- * @param {Object} param0
8405
- * @param {Object} [param0.selection] The selection object
8406
- * @param {string | null} [param0.documentId] The document ID
8407
- * @param {string | null} [param0.parentCommentId] The parent comment
8408
- * @returns {ReturnType<typeof useComment>} The new comment object
8409
8566
  */
8410
8567
  const getPendingComment = ({ selection, documentId, parentCommentId, ...options }) => {
8411
8568
  return _getNewcomment({
@@ -8417,17 +8574,11 @@ var useCommentsStore = defineStore("comments", () => {
8417
8574
  };
8418
8575
  /**
8419
8576
  * Get the new comment object
8420
- *
8421
- * @param {Object} param0
8422
- * @param {Object} param0.selection The selection object
8423
- * @param {String} param0.documentId The document ID
8424
- * @param {String} param0.parentCommentId The parent comment ID
8425
- * @returns {Object} The new comment object
8426
8577
  */
8427
8578
  const _getNewcomment = ({ selection, documentId, parentCommentId, ...options }) => {
8428
8579
  let activeDocument;
8429
- if (documentId) activeDocument = superdocStore.getDocument(documentId);
8430
- else if (selection) activeDocument = superdocStore.getDocument(selection.documentId);
8580
+ if (documentId) activeDocument = findDocument(documentId);
8581
+ else if (selection) activeDocument = findDocument(selection.documentId);
8431
8582
  if (!activeDocument) activeDocument = superdocStore.documents[0];
8432
8583
  return useComment({
8433
8584
  fileId: activeDocument.id,
@@ -8444,8 +8595,6 @@ var useCommentsStore = defineStore("comments", () => {
8444
8595
  };
8445
8596
  /**
8446
8597
  * Remove the pending comment
8447
- *
8448
- * @returns {void}
8449
8598
  */
8450
8599
  const resetPendingCommentState = (superdoc, clearViewingSelection = true) => {
8451
8600
  const hadPending = !!pendingComment.value;
@@ -8461,7 +8610,7 @@ var useCommentsStore = defineStore("comments", () => {
8461
8610
  } catch {}
8462
8611
  return;
8463
8612
  }
8464
- superdoc?.activeEditor?.commands?.removeComment({ commentId: "pending" });
8613
+ superdoc?.activeEditor?.commands?.removeComment?.({ commentId: "pending" });
8465
8614
  };
8466
8615
  const removePendingComment = (superdoc) => {
8467
8616
  pendingCommentRequest += 1;
@@ -8474,14 +8623,6 @@ var useCommentsStore = defineStore("comments", () => {
8474
8623
  };
8475
8624
  /**
8476
8625
  * Add a new comment to the document
8477
- *
8478
- * @param {Object} param0
8479
- * @param {Object} param0.superdoc The SuperDoc instance
8480
- * @param {ReturnType<typeof useComment>} param0.comment The comment to add
8481
- * @param {boolean} [param0.skipEditorUpdate] Skip writing the comment into the editor
8482
- * @param {boolean} [param0.broadcastChanges] Emit and sync the change
8483
- * @param {boolean} [param0.isHydration] The comment comes from import or collaboration
8484
- * @returns {{ ok: boolean, reason?: string, detail?: string, code?: string } | Promise<{ ok: boolean, reason?: string, detail?: string, code?: string }>} The mutation outcome
8485
8626
  */
8486
8627
  const addCommentInternal = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true, isHydration = false }) => {
8487
8628
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
@@ -8511,7 +8652,7 @@ var useCommentsStore = defineStore("comments", () => {
8511
8652
  return {
8512
8653
  ok: false,
8513
8654
  reason: "adapter-threw",
8514
- detail: err?.message ?? String(err)
8655
+ detail: errorDetail(err)
8515
8656
  };
8516
8657
  }
8517
8658
  })().then((outcome) => {
@@ -8583,7 +8724,7 @@ var useCommentsStore = defineStore("comments", () => {
8583
8724
  activeComment.value = newComment.commentId;
8584
8725
  setActiveFloatingCommentInstance(newComment.commentId);
8585
8726
  }
8586
- 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?.({
8587
8728
  ...newComment.getValues(),
8588
8729
  skipEmit: true
8589
8730
  });
@@ -8631,7 +8772,7 @@ var useCommentsStore = defineStore("comments", () => {
8631
8772
  return {
8632
8773
  ok: false,
8633
8774
  reason: "adapter-threw",
8634
- detail: err?.message ?? String(err)
8775
+ detail: errorDetail(err)
8635
8776
  };
8636
8777
  }
8637
8778
  })().then((outcome) => {
@@ -8651,16 +8792,16 @@ var useCommentsStore = defineStore("comments", () => {
8651
8792
  });
8652
8793
  return outcome;
8653
8794
  }
8654
- const removedIds = new Set((Array.isArray(outcome.removedCommentIds) ? outcome.removedCommentIds : []).map(normalizeCommentId).filter(Boolean));
8655
- if (removedIds.has(normalizeCommentId(commentId))) {
8656
- 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));
8657
8798
  let addedChild = true;
8658
8799
  while (addedChild) {
8659
8800
  addedChild = false;
8660
8801
  for (const row of commentsList.value) {
8661
8802
  const parentId = normalizeCommentId(row?.parentCommentId);
8662
8803
  if (!parentId || !removedIds.has(parentId)) continue;
8663
- 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)) {
8664
8805
  if (removedIds.has(alias)) continue;
8665
8806
  removedIds.add(alias);
8666
8807
  addedChild = true;
@@ -8668,9 +8809,9 @@ var useCommentsStore = defineStore("comments", () => {
8668
8809
  }
8669
8810
  }
8670
8811
  commentsList.value = commentsList.value.filter((row) => {
8671
- 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));
8672
8813
  });
8673
- if (removedIds.has(normalizeCommentId(activeComment.value))) clearActiveCommentSelection();
8814
+ if (removedIds.has(normalizeCommentId(activeComment.value) ?? "")) clearActiveCommentSelection();
8674
8815
  } else reconcileCommentsFromV2({
8675
8816
  superdoc,
8676
8817
  adapter: v2Adapter,
@@ -8678,18 +8819,18 @@ var useCommentsStore = defineStore("comments", () => {
8678
8819
  items: outcome.items ?? [],
8679
8820
  pruneStale: outcome.complete !== false
8680
8821
  });
8822
+ const payload = comment.getValues();
8681
8823
  superdoc.emit("comments-update", {
8682
8824
  type: COMMENT_EVENTS.DELETED,
8683
- comment: comment.getValues(),
8684
- changes: [{
8685
- key: "deleted",
8825
+ comment: payload,
8826
+ changes: getDeletedCommentChanges([{
8686
8827
  commentId,
8687
- fileId
8688
- }]
8828
+ importedId
8829
+ }, payload], fileId)
8689
8830
  });
8690
8831
  return { ok: true };
8691
8832
  });
8692
- superdoc.activeEditor?.commands?.removeComment({
8833
+ superdoc.activeEditor?.commands?.removeComment?.({
8693
8834
  commentId,
8694
8835
  importedId
8695
8836
  });
@@ -8697,14 +8838,14 @@ var useCommentsStore = defineStore("comments", () => {
8697
8838
  const childCommentIds = commentsList.value.filter((c) => c.parentCommentId === commentId).map((c) => c.commentId || c.importedId);
8698
8839
  commentsList.value = commentsList.value.filter((c) => !childCommentIds.includes(c.commentId));
8699
8840
  if (activeComment.value === commentId || childCommentIds.includes(activeComment.value)) clearActiveCommentSelection();
8841
+ const payload = comment.getValues();
8700
8842
  const event = {
8701
8843
  type: COMMENT_EVENTS.DELETED,
8702
- comment: comment.getValues(),
8703
- changes: [{
8704
- key: "deleted",
8844
+ comment: payload,
8845
+ changes: getDeletedCommentChanges([{
8705
8846
  commentId,
8706
- fileId
8707
- }]
8847
+ importedId
8848
+ }, payload], fileId)
8708
8849
  };
8709
8850
  superdoc.emit("comments-update", event);
8710
8851
  syncCommentsToClients(superdoc, event);
@@ -8716,7 +8857,7 @@ var useCommentsStore = defineStore("comments", () => {
8716
8857
  * otherwise keep the source bubble after the document comment is gone.
8717
8858
  */
8718
8859
  const dropCommentsFromMutationImpact = ({ superdoc, documentId, removedIds } = {}) => {
8719
- 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));
8720
8861
  if (!seedIds.size) return {
8721
8862
  ok: true,
8722
8863
  removedIds: []
@@ -8740,7 +8881,7 @@ var useCommentsStore = defineStore("comments", () => {
8740
8881
  if (!isDroppableCommentRow(row)) continue;
8741
8882
  const aliases = getCommentAliasIds(row);
8742
8883
  const alreadyDropped = aliases.some((alias) => droppedIds.has(alias));
8743
- 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) ?? "");
8744
8885
  if (!alreadyDropped && !parentDropped) continue;
8745
8886
  for (const alias of aliases) {
8746
8887
  if (droppedIds.has(alias)) continue;
@@ -8768,11 +8909,7 @@ var useCommentsStore = defineStore("comments", () => {
8768
8909
  const event = {
8769
8910
  type: COMMENT_EVENTS.DELETED,
8770
8911
  comment: payload,
8771
- changes: [{
8772
- key: "deleted",
8773
- commentId: payload?.commentId,
8774
- fileId: payload?.fileId
8775
- }]
8912
+ changes: getDeletedCommentChanges([payload, comment], payload?.fileId)
8776
8913
  };
8777
8914
  superdoc?.emit?.("comments-update", event);
8778
8915
  });
@@ -8794,7 +8931,7 @@ var useCommentsStore = defineStore("comments", () => {
8794
8931
  const byAlias = /* @__PURE__ */ new Map();
8795
8932
  const childrenByParentAlias = /* @__PURE__ */ new Map();
8796
8933
  for (const row of rows) {
8797
- 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);
8798
8935
  const parentId = normalizeCommentId(row.parentCommentId);
8799
8936
  if (parentId) {
8800
8937
  const children = childrenByParentAlias.get(parentId) ?? [];
@@ -8821,7 +8958,7 @@ var useCommentsStore = defineStore("comments", () => {
8821
8958
  if (!row || visited.has(row)) continue;
8822
8959
  visited.add(row);
8823
8960
  family.push(row);
8824
- 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) ?? []);
8825
8962
  }
8826
8963
  const isResolved = status === "resolved";
8827
8964
  const resolvedAt = Date.now();
@@ -8844,7 +8981,7 @@ var useCommentsStore = defineStore("comments", () => {
8844
8981
  outcome = {
8845
8982
  ok: false,
8846
8983
  reason: "adapter-threw",
8847
- detail: err?.message ?? String(err)
8984
+ detail: errorDetail(err)
8848
8985
  };
8849
8986
  }
8850
8987
  if (!isCurrentV2CommentsAdapter(adapter)) return {
@@ -8916,14 +9053,14 @@ var useCommentsStore = defineStore("comments", () => {
8916
9053
  return (outcome.items ?? []).map((item) => adapter.mapV2CommentToUseCommentInput(item, {
8917
9054
  fileId,
8918
9055
  fileType: null
8919
- })).filter(Boolean);
9056
+ })).filter(isPresent);
8920
9057
  };
8921
9058
  const isBlankDirectoryCommentText = (value) => typeof value !== "string" || value.replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").trim().length === 0;
8922
9059
  const trackedChangeDirectoryComment = (params) => {
8923
9060
  if (!params || params.event === "omit" || params.changeId == null) return null;
8924
9061
  return getPendingComment({
8925
9062
  documentId: params.documentId,
8926
- commentId: params.changeId,
9063
+ commentId: String(params.changeId),
8927
9064
  trackedChange: true,
8928
9065
  trackedChangeText: params.trackedChangeText,
8929
9066
  trackedChangeType: params.trackedChangeType,
@@ -8970,7 +9107,7 @@ var useCommentsStore = defineStore("comments", () => {
8970
9107
  const mappedCommentInputs = commentItems.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => commentsAdapter.mapV2CommentToUseCommentInput(item, {
8971
9108
  fileId: documentId,
8972
9109
  fileType: document?.type ?? null
8973
- })).filter(Boolean);
9110
+ })).filter(isPresent);
8974
9111
  const trackedParentBySidecarId = /* @__PURE__ */ new Map();
8975
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));
8976
9113
  const commentRows = mappedCommentInputs.filter((input) => !trackedParentBySidecarId.has(String(input.commentId))).map((input) => {
@@ -8981,7 +9118,7 @@ var useCommentsStore = defineStore("comments", () => {
8981
9118
  }
8982
9119
  return useComment(input);
8983
9120
  });
8984
- 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);
8985
9122
  reviewDirectoryList.value = [...commentRows, ...trackedRows];
8986
9123
  return {
8987
9124
  ok: true,
@@ -9062,13 +9199,6 @@ var useCommentsStore = defineStore("comments", () => {
9062
9199
  * - successful mutation refreshes from v2 list and reconciles
9063
9200
  * - rejection preserves rows and emits a rejected `comments-update` event
9064
9201
  * - committed-but-refresh-failed surfaces honestly (no reconcile with `[]`)
9065
- *
9066
- * @param {Object} [param0]
9067
- * @param {Object} [param0.superdoc] The SuperDoc instance.
9068
- * @param {string | null} [param0.parentCommentId] The comment or tracked-change row being replied to.
9069
- * @param {string} [param0.text] The reply text.
9070
- * @param {Array<{ name?: string | null, email?: string | null }>} [param0.mentions] Users mentioned in the reply.
9071
- * @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.
9072
9202
  */
9073
9203
  const replyCommentV2 = async ({ superdoc, parentCommentId, text, mentions = [], trackedChangeTarget } = {}) => {
9074
9204
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
@@ -9343,7 +9473,7 @@ var useCommentsStore = defineStore("comments", () => {
9343
9473
  row?.threadingParentCommentId,
9344
9474
  row?.trackedChangeParentId,
9345
9475
  row?.trackedChangeThreadParentId
9346
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9476
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9347
9477
  /** Keep one mounted review window plus rows whose interaction is still live. */
9348
9478
  const boundReviewPresentationRows = ({ documentId, visibleIds }) => {
9349
9479
  const currentRows = commentsList.value;
@@ -9364,7 +9494,7 @@ var useCommentsStore = defineStore("comments", () => {
9364
9494
  pendingComment.value?.commentId,
9365
9495
  instantSidebarAlignmentThreadId.value,
9366
9496
  instantSidebarAlignmentInstanceId.value
9367
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9497
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9368
9498
  let changed = true;
9369
9499
  while (changed) {
9370
9500
  changed = false;
@@ -9432,7 +9562,8 @@ var useCommentsStore = defineStore("comments", () => {
9432
9562
  if (preparedReview?.reuseCatalog === true && committedReviewPresentations.value[normalizedDocumentId]) {
9433
9563
  const previous = committedReviewPresentations.value[normalizedDocumentId];
9434
9564
  const next = preparedReview.presentation;
9435
- 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 {
9436
9567
  ok: false,
9437
9568
  reason: "review-catalog-stale"
9438
9569
  };
@@ -9478,8 +9609,8 @@ var useCommentsStore = defineStore("comments", () => {
9478
9609
  previousPresentation.updateContext = presentation.updateContext;
9479
9610
  return {
9480
9611
  ok: true,
9481
- commentItems: preparedReview.comments.length,
9482
- trackedItems: preparedReview.trackedChanges.length
9612
+ commentItems: preparedReview?.comments.length,
9613
+ trackedItems: preparedReview?.trackedChanges.length
9483
9614
  };
9484
9615
  }
9485
9616
  let effectiveCommentItems = commentItems;
@@ -9493,7 +9624,7 @@ var useCommentsStore = defineStore("comments", () => {
9493
9624
  reason: seeded?.reason ?? "comment-catalog-seed-failed"
9494
9625
  };
9495
9626
  const selected = commentsAdapter.selectVisibleReviewComments?.();
9496
- 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;
9497
9628
  }
9498
9629
  const fileType = (normalizedDocumentId ? superdocStore.getDocument(normalizedDocumentId) : null)?.type ?? null;
9499
9630
  let preparedInputs;
@@ -9510,16 +9641,16 @@ var useCommentsStore = defineStore("comments", () => {
9510
9641
  })) : effectiveCommentItems.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => commentsAdapter.mapV2CommentToUseCommentInput(item, {
9511
9642
  fileId: normalizedDocumentId,
9512
9643
  fileType
9513
- })).filter(Boolean);
9644
+ })).filter(isPresent);
9514
9645
  preparedParams = preparedReview ? preparedReview.trackedChanges.map((params) => ({
9515
9646
  ...params,
9516
9647
  documentId: normalizedDocumentId
9517
- })) : trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).filter(Boolean);
9648
+ })) : trackedChangeItems.map((item) => trackedChangesAdapter.mapV2TrackedChangeToCommentParams(item)).filter(isPresent);
9518
9649
  } catch (error) {
9519
9650
  return {
9520
9651
  ok: false,
9521
9652
  reason: "mapper-failed",
9522
- detail: error?.message ?? String(error)
9653
+ detail: errorDetail(error)
9523
9654
  };
9524
9655
  }
9525
9656
  if (typeof patch !== "function") return {
@@ -9547,7 +9678,7 @@ var useCommentsStore = defineStore("comments", () => {
9547
9678
  params?.trackedChangeCanonicalId,
9548
9679
  params?.trackedChangeAnchorKey
9549
9680
  ])
9550
- ].map((value) => normalizeCommentId(value)).filter(Boolean));
9681
+ ].map((value) => normalizeCommentId(value)).filter(isPresent));
9551
9682
  patch(() => {
9552
9683
  const previousPreparedPresentation = committedReviewPresentations.value[normalizedDocumentId] ?? null;
9553
9684
  if (preparedReview?.presentation) committedReviewPresentations.value = {
@@ -9595,7 +9726,7 @@ var useCommentsStore = defineStore("comments", () => {
9595
9726
  };
9596
9727
  const effectiveDocumentId = documentId ?? adapter.documentId ?? null;
9597
9728
  const normalizedEffectiveDocumentId = effectiveDocumentId != null ? String(effectiveDocumentId) : null;
9598
- const fileType = (effectiveDocumentId ? superdocStore.getDocument(effectiveDocumentId) : null)?.type ?? null;
9729
+ const fileType = (effectiveDocumentId ? findDocument(effectiveDocumentId) : null)?.type ?? null;
9599
9730
  const isBlankV2CommentText = (value) => {
9600
9731
  if (typeof value !== "string") return true;
9601
9732
  return value.replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").trim().length === 0;
@@ -9615,7 +9746,7 @@ var useCommentsStore = defineStore("comments", () => {
9615
9746
  const candidateInputs = Array.isArray(preparedInputs) ? preparedInputs : items.filter((item) => !require_create_super_doc_ui.isSyntheticTrackedChangeCommentLaneItem(item)).map((item) => adapter.mapV2CommentToUseCommentInput(item, {
9616
9747
  fileId: effectiveDocumentId,
9617
9748
  fileType
9618
- })).filter(Boolean);
9749
+ })).filter(isPresent);
9619
9750
  for (const input of candidateInputs) {
9620
9751
  if (isV2TrackedChangeSidecarCommentInput(input)) {
9621
9752
  trackedChangeSidecarParentByCommentId.set(String(input.commentId), String(input.trackedChangeThreadParentId));
@@ -9668,7 +9799,7 @@ var useCommentsStore = defineStore("comments", () => {
9668
9799
  existing.mentions = Array.isArray(input.mentions) ? input.mentions : [];
9669
9800
  existing.isInternal = typeof input.isInternal === "boolean" ? input.isInternal : existing.isInternal;
9670
9801
  if (typeof input.resolvedTime === "number") {
9671
- 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;
9672
9803
  existing.resolvedByEmail = input.resolvedByEmail ?? null;
9673
9804
  existing.resolvedByName = input.resolvedByName ?? null;
9674
9805
  } else {
@@ -9742,7 +9873,7 @@ var useCommentsStore = defineStore("comments", () => {
9742
9873
  return {
9743
9874
  ok: false,
9744
9875
  reason: "comment-read-failed",
9745
- detail: err?.message ?? String(err)
9876
+ detail: errorDetail(err)
9746
9877
  };
9747
9878
  }
9748
9879
  if (!isCurrentV2CommentsAdapter(adapter)) return {
@@ -9768,8 +9899,6 @@ var useCommentsStore = defineStore("comments", () => {
9768
9899
  };
9769
9900
  /**
9770
9901
  * Cancel the pending comment
9771
- *
9772
- * @returns {void}
9773
9902
  */
9774
9903
  const cancelComment = (superdoc) => {
9775
9904
  removePendingComment(superdoc);
@@ -9779,9 +9908,6 @@ var useCommentsStore = defineStore("comments", () => {
9779
9908
  *
9780
9909
  * Replace-file swaps call this before hydrating the replacement so stale
9781
9910
  * comments never survive long enough to render beside the new content.
9782
- *
9783
- * @param {string | null | undefined} documentId
9784
- * @returns {void}
9785
9911
  */
9786
9912
  function removeCommentsForDocument(documentId) {
9787
9913
  const activeDocumentId = documentId != null ? String(documentId) : null;
@@ -9812,20 +9938,16 @@ var useCommentsStore = defineStore("comments", () => {
9812
9938
  const remapTrackedChangeReferences = (droppedCommentIds, activeDocumentId) => {
9813
9939
  const remapSelection = (selection) => {
9814
9940
  const selectedId = normalizeCommentId(selection.value);
9815
- 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;
9816
9943
  };
9817
9944
  remapSelection(activeComment);
9818
9945
  remapSelection(activeFloatingCommentInstanceId);
9819
9946
  commentsList.value.forEach((row) => {
9820
9947
  if (!belongsToTrackedChangeSyncDocument(row, activeDocumentId)) return;
9821
9948
  const rowIdentityUpdates = {};
9822
- for (const field of [
9823
- "trackedChangeThreadParentId",
9824
- "trackedChangeParentId",
9825
- "threadingParentCommentId",
9826
- "parentCommentId"
9827
- ]) {
9828
- const replacementId = droppedCommentIds.get(normalizeCommentId(row?.[field]));
9949
+ for (const field of PARENT_LINK_FIELDS) {
9950
+ const replacementId = droppedCommentIds.get(normalizeCommentId(row?.[field]) ?? "");
9829
9951
  if (!replacementId) continue;
9830
9952
  row[field] = replacementId;
9831
9953
  rowIdentityUpdates[field] = replacementId;
@@ -9846,10 +9968,6 @@ var useCommentsStore = defineStore("comments", () => {
9846
9968
  *
9847
9969
  * Pruning is scoped to the active editor document so replay in one document does not
9848
9970
  * delete tracked-change comments from other open documents.
9849
- *
9850
- * @param {Set<string>} liveTrackedChangeIds IDs currently present in editor marks.
9851
- * @param {string | null} activeDocumentId Document currently being synced.
9852
- * @returns {void}
9853
9971
  */
9854
9972
  const pruneStaleTrackedChangeComments = (liveTrackedChangeIds, liveTrackedChangeAnchorKeys, activeDocumentId, superdoc = null, { broadcastChanges = true } = {}) => withInteractionSpan("store.trackedChanges.pruneStaleComments", "store-reconciliation", {
9855
9973
  activeDocumentId: activeDocumentId ?? null,
@@ -9894,7 +10012,7 @@ var useCommentsStore = defineStore("comments", () => {
9894
10012
  comment: payload
9895
10013
  };
9896
10014
  if (broadcastChanges) {
9897
- syncCommentsToClients(superdoc, event);
10015
+ syncCommentsToClients(requireHost(superdoc, "pruneStaleTrackedChangeComments"), event);
9898
10016
  superdoc?.emit?.("comments-update", event);
9899
10017
  }
9900
10018
  });
@@ -9926,14 +10044,10 @@ var useCommentsStore = defineStore("comments", () => {
9926
10044
  const event = {
9927
10045
  type: COMMENT_EVENTS.DELETED,
9928
10046
  comment: payload,
9929
- changes: [{
9930
- key: "deleted",
9931
- commentId: payload.commentId,
9932
- fileId: payload.fileId
9933
- }]
10047
+ changes: getDeletedCommentChanges([payload, comment], payload.fileId)
9934
10048
  };
9935
10049
  if (broadcastChanges) {
9936
- syncCommentsToClients(superdoc, event);
10050
+ syncCommentsToClients(requireHost(superdoc, "pruneStaleTrackedChangeComments"), event);
9937
10051
  superdoc?.emit?.("comments-update", event);
9938
10052
  }
9939
10053
  });
@@ -9956,7 +10070,6 @@ var useCommentsStore = defineStore("comments", () => {
9956
10070
  const resolveArgs = {
9957
10071
  email: superdoc?.user?.email ?? null,
9958
10072
  name: superdoc?.user?.name ?? null,
9959
- superdoc,
9960
10073
  reconciliationToken: COMMENT_RECONCILIATION_TOKEN
9961
10074
  };
9962
10075
  let resolvedCount = 0;
@@ -9967,9 +10080,12 @@ var useCommentsStore = defineStore("comments", () => {
9967
10080
  trackedChangeThreadParentIdForComment(linkedComment),
9968
10081
  linkedComment.threadingParentCommentId,
9969
10082
  linkedComment.parentCommentId
9970
- ].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;
9971
10084
  if (typeof linkedComment.resolveComment === "function") {
9972
- linkedComment.resolveComment(resolveArgs);
10085
+ linkedComment.resolveComment({
10086
+ ...resolveArgs,
10087
+ superdoc: requireHost(superdoc, "resolveLinkedCommentsForTrackedChangeDecision")
10088
+ });
9973
10089
  resolvedCount += 1;
9974
10090
  }
9975
10091
  });
@@ -10066,7 +10182,7 @@ var useCommentsStore = defineStore("comments", () => {
10066
10182
  if (previousCommentId) anchorSourceIds.add(previousCommentId);
10067
10183
  if (previousCanonicalId) anchorSourceIds.add(previousCanonicalId);
10068
10184
  }
10069
- if (comment.trackedChangeAnchorKey == null || anchorSourceIds.has(currentAnchorParts?.rawId)) comment.trackedChangeAnchorKey = toAnchor;
10185
+ if (comment.trackedChangeAnchorKey == null || anchorSourceIds.has(currentAnchorParts?.rawId ?? "")) comment.trackedChangeAnchorKey = toAnchor;
10070
10186
  comment.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...Array.isArray(comment.trackedChangePositionAliases) ? comment.trackedChangePositionAliases : [], fromId]);
10071
10187
  const identitySourceIds = /* @__PURE__ */ new Set([fromId]);
10072
10188
  if (advancesRemapLineage) {
@@ -10077,33 +10193,28 @@ var useCommentsStore = defineStore("comments", () => {
10077
10193
  if (row === comment) return;
10078
10194
  if (!belongsToTrackedChangeSyncDocument(row, normalizedDocumentId)) return;
10079
10195
  const rowIdentityUpdates = {};
10080
- for (const field of [
10081
- "trackedChangeThreadParentId",
10082
- "trackedChangeParentId",
10083
- "threadingParentCommentId",
10084
- "parentCommentId"
10085
- ]) {
10086
- if (!identitySourceIds.has(normalizeCommentId(row?.[field]))) continue;
10196
+ for (const field of PARENT_LINK_FIELDS) {
10197
+ if (!identitySourceIds.has(normalizeCommentId(row?.[field]) ?? "")) continue;
10087
10198
  row[field] = toId;
10088
10199
  rowIdentityUpdates[field] = toId;
10089
10200
  }
10090
10201
  if (Object.keys(rowIdentityUpdates).length && typeof row.updateIdentityValues === "function") row.updateIdentityValues(rowIdentityUpdates);
10091
10202
  });
10092
10203
  if (Object.keys(commentIdentityUpdates).length && typeof comment.updateIdentityValues === "function") comment.updateIdentityValues(commentIdentityUpdates);
10093
- 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));
10094
10205
  if (previousEntry) {
10095
- for (const key of [toId, toAnchor]) if (positions[key] === void 0) {
10206
+ for (const key of [toId, String(toAnchor)]) if (positions[key] === void 0) {
10096
10207
  positions[key] = previousEntry;
10097
10208
  positionsChanged = true;
10098
10209
  }
10099
10210
  }
10100
- if (identitySourceIds.has(normalizeCommentId(activeComment.value))) activeComment.value = toId;
10101
- 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;
10102
10213
  }
10103
10214
  if (positionsChanged) editorCommentPositions.value = { ...positions };
10104
10215
  };
10105
10216
  const pruneDecidedTrackedChangeRow = ({ superdoc, comment: targetComment, decidedId, decidedIds, documentId } = {}) => {
10106
- 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));
10107
10218
  const normalizedDocumentId = normalizeCommentId(documentId);
10108
10219
  if (!normalizedDecidedIds.size || !normalizedDocumentId) return {
10109
10220
  removed: false,
@@ -10163,12 +10274,6 @@ var useCommentsStore = defineStore("comments", () => {
10163
10274
  };
10164
10275
  /**
10165
10276
  * Accept or reject the tracked change behind a sidebar row.
10166
- *
10167
- * @param {Object} param0
10168
- * @param {Object} param0.superdoc The SuperDoc instance.
10169
- * @param {Object} param0.comment The tracked-change row.
10170
- * @param {string} param0.decision `'accept'` or `'reject'`.
10171
- * @returns {{ ok: boolean, success?: boolean, reason?: string } | Promise<{ ok: boolean, success?: boolean, reason?: string }>} The decision outcome.
10172
10277
  */
10173
10278
  const decideTrackedChangeFromSidebar = ({ superdoc, comment, decision }) => {
10174
10279
  const disabledReason = trackedChangeDecisionDisabledReason(superdoc);
@@ -10196,7 +10301,7 @@ var useCommentsStore = defineStore("comments", () => {
10196
10301
  return {
10197
10302
  ok: false,
10198
10303
  reason: "adapter-threw",
10199
- detail: err?.message ?? String(err)
10304
+ detail: errorDetail(err)
10200
10305
  };
10201
10306
  }
10202
10307
  })().then(async (outcome) => {
@@ -10249,9 +10354,11 @@ var useCommentsStore = defineStore("comments", () => {
10249
10354
  if (!activeEditor) return { ok: false };
10250
10355
  const id = comment.commentId ?? comment.importedId;
10251
10356
  if (!id) return { ok: false };
10252
- 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;
10253
10359
  const documentApi = typeof activeEditor.doc === "object" ? activeEditor.doc : null;
10254
10360
  if (documentApi?.trackChanges?.decide) try {
10361
+ if (rawStory && !story) throw new TypeError("trackedChangeStory must be a valid StoryLocator");
10255
10362
  const target = story ? {
10256
10363
  id,
10257
10364
  story
@@ -10264,7 +10371,7 @@ var useCommentsStore = defineStore("comments", () => {
10264
10371
  success: Boolean(receipt?.success)
10265
10372
  }));
10266
10373
  } catch (error) {
10267
- if (story) return {
10374
+ if (rawStory) return {
10268
10375
  ok: false,
10269
10376
  error
10270
10377
  };
@@ -10311,9 +10418,9 @@ var useCommentsStore = defineStore("comments", () => {
10311
10418
  documentId: effectiveDocumentId
10312
10419
  })).removed
10313
10420
  };
10314
- const normalizedRemovedIds = new Set(Array.from(removedIds ?? []).map((id) => normalizeCommentId(id)).filter(Boolean));
10315
- const normalizedUpsertIds = [...new Set(Array.from(upsertIds ?? []).map((id) => normalizeCommentId(id)).filter(Boolean))];
10316
- 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));
10317
10424
  const locallyRemovedIds = new Set([...normalizedRemovedIds].filter((id) => !remappedSourceIds.has(id)));
10318
10425
  if (locallyRemovedIds.size > 0 && effectiveDocumentId != null) pruneDecidedTrackedChangeRow({
10319
10426
  superdoc,
@@ -10423,23 +10530,24 @@ var useCommentsStore = defineStore("comments", () => {
10423
10530
  for (const params of paramsList) {
10424
10531
  if (!params) continue;
10425
10532
  let retainUnchangedRow = false;
10533
+ const anchorParts = parseTrackedChangeAnchorKey(params.trackedChangeAnchorKey);
10534
+ const anchorStoryKey = anchorParts ? normalizeTrackedChangeStoryKey(anchorParts.storyKey) : void 0;
10426
10535
  if (preparedPresentation) {
10427
10536
  if (preparedPresentation !== committedReviewPresentations.value[String(effectiveDocumentId)]) continue;
10428
10537
  if (params.documentId != null && String(params.documentId) !== String(effectiveDocumentId)) continue;
10429
10538
  const id = normalizeCommentId(params.changeId);
10430
- const version = preparedPresentation.rowVersions?.[id];
10539
+ const version = preparedPresentation.rowVersions?.[String(id)] ?? NaN;
10431
10540
  if (!id || !Number.isSafeInteger(version) || version < 1) continue;
10432
10541
  const existing = [...trackedChangeIdentityIndex.candidates({ changeId: id })].filter((row) => String(row.fileId) === String(effectiveDocumentId) && String(row.commentId) === id);
10433
10542
  if (existing.length > 1) continue;
10434
10543
  const row = existing[0];
10435
10544
  if (row && row.trackedChangeCanonicalId !== params.trackedChangeCanonicalId) {
10436
- const previousVersion = previousPreparedPresentation?.rowVersions?.[id];
10437
- 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;
10438
10547
  row.trackedChangeCanonicalId = params.trackedChangeCanonicalId;
10439
- row.updateIdentityValues?.({ trackedChangeCanonicalId: params.trackedChangeCanonicalId });
10440
10548
  trackedChangeIdentityIndex.add(row);
10441
10549
  }
10442
- 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;
10443
10551
  }
10444
10552
  if (params.event === "omit") {
10445
10553
  if (params.changeId != null) liveIds.add(String(params.changeId));
@@ -10480,22 +10588,18 @@ var useCommentsStore = defineStore("comments", () => {
10480
10588
  return commentsList.value.filter((comment) => {
10481
10589
  if (comment?.trackedChange !== true) return false;
10482
10590
  if (normalizedDocumentId == null) return true;
10483
- const rowDocumentId = comment?.documentId ?? comment?.fileId ?? null;
10591
+ const rowDocumentId = Reflect.get(comment, "documentId") ?? comment?.fileId ?? null;
10484
10592
  return rowDocumentId != null && String(rowDocumentId) === normalizedDocumentId;
10485
10593
  }).length;
10486
10594
  };
10487
10595
  /**
10488
10596
  * Triggered when the editor locations are updated
10489
10597
  * Updates floating comment locations from the editor
10490
- *
10491
- * @param {Object} allCommentPositions The collected geometry keyed by comment / tracked-change id
10492
- * @param {{ retainMissingTrackedChangeGeometry?: boolean, retainedTrackedChangeIds?: Iterable<string> }} options Geometry reconciliation options
10493
- * @returns {void}
10494
10598
  */
10495
10599
  const handleEditorLocationsUpdate = (allCommentPositions, options = {}) => {
10496
10600
  if (allCommentPositions == null) return;
10497
10601
  const retainMissingTrackedChangeGeometry = options?.retainMissingTrackedChangeGeometry === true;
10498
- 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;
10499
10603
  const previousPositions = editorCommentPositions.value || {};
10500
10604
  const normalizedPositions = {};
10501
10605
  Object.entries(allCommentPositions).forEach(([key, entry]) => {
@@ -10522,7 +10626,7 @@ var useCommentsStore = defineStore("comments", () => {
10522
10626
  return null;
10523
10627
  };
10524
10628
  const writeTrackedChangeAliases = (entry, comment, extraKeys = []) => {
10525
- const keys = [...aliasesFor(comment), ...extraKeys.map((id) => normalizeCommentId(id)).filter(Boolean)];
10629
+ const keys = [...aliasesFor(comment), ...extraKeys.map((id) => normalizeCommentId(id)).filter(isPresent)];
10526
10630
  for (const key of new Set(keys)) if (normalizedPositions[key] === void 0) normalizedPositions[key] = entry;
10527
10631
  };
10528
10632
  commentsList.value.forEach((comment) => {
@@ -11833,8 +11937,8 @@ var _hoisted_11$3 = {
11833
11937
  key: 0,
11834
11938
  class: "card-section comment-body"
11835
11939
  };
11836
- var _hoisted_12$2 = ["data-track-change-semantic-color-key"];
11837
- var _hoisted_13$2 = { key: 0 };
11940
+ var _hoisted_12$3 = ["data-track-change-semantic-color-key"];
11941
+ var _hoisted_13$3 = { key: 0 };
11838
11942
  var _hoisted_14$2 = { class: "change-type tracked-change-label" };
11839
11943
  var _hoisted_15$2 = {
11840
11944
  key: 0,
@@ -13006,7 +13110,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13006
13110
  "data-track-change-semantic-color-key": comment.semanticColorKey ?? void 0,
13007
13111
  ref_for: true,
13008
13112
  ref: index === 0 ? setParentBodyRef : void 0
13009
- }, [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) => {
13010
13114
  return require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
13011
13115
  key: lineIndex,
13012
13116
  class: "tracked-change-detail-line"
@@ -13031,7 +13135,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13031
13135
  style: require__plugin_vue_export_helper.normalizeStyle(trackedChangeImagePreviewStyle(comment.trackedChangeImagePreview)),
13032
13136
  loading: "lazy",
13033
13137
  decoding: "async"
13034
- }, 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),
13035
13139
  shouldTruncate.value && isTextOverflowing.value && index === 0 ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
13036
13140
  key: 0,
13037
13141
  class: "show-more-toggle",
@@ -13128,7 +13232,7 @@ var CommentDialog_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
13128
13232
  });
13129
13233
  //#endregion
13130
13234
  //#region src/components/CommentsLayer/CommentDialog.vue
13131
- 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"]]);
13132
13236
  //#endregion
13133
13237
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue?vue&type=script&setup=true&lang.ts
13134
13238
  var _hoisted_1$25 = [
@@ -13897,124 +14001,6 @@ var composeAuthorColorResolver = (config) => {
13897
14001
  };
13898
14002
  };
13899
14003
  //#endregion
13900
- //#region ../document-api/src/errors.ts
13901
- /**
13902
- * Structured validation error thrown by document-api execute* functions.
13903
- *
13904
- * Consumers should prefer checking `error.code` over `instanceof` for resilience
13905
- * across package boundaries and bundling scenarios.
13906
- */
13907
- var DocumentApiValidationError = class DocumentApiValidationError extends Error {
13908
- constructor(code, message, details) {
13909
- super(message);
13910
- this.name = "DocumentApiValidationError";
13911
- this.code = code;
13912
- this.details = details;
13913
- Object.setPrototypeOf(this, DocumentApiValidationError.prototype);
13914
- }
13915
- };
13916
- //#endregion
13917
- //#region ../document-api/src/export/export.types.ts
13918
- /** Canonical tracked-change export modes accepted by every public export surface. */
13919
- var SD_EXPORT_MODES = [
13920
- "review-preserving",
13921
- "final",
13922
- "original"
13923
- ];
13924
- /** Default mode for modeful DOCX export. */
13925
- var DEFAULT_SD_EXPORT_MODE = "review-preserving";
13926
- var SD_COMMENT_EXPORT_POLICIES = [
13927
- "preserve",
13928
- "resolve",
13929
- "remove"
13930
- ];
13931
- var SD_CONTENT_CONTROL_EXPORT_POLICIES = ["preserve", "flatten"];
13932
- //#endregion
13933
- //#region ../document-api/src/export/export.ts
13934
- /**
13935
- * Export namespace: engine-agnostic public API and adapter contract.
13936
- *
13937
- * Validates the requested mode at the public boundary so an invalid mode fails
13938
- * closed with `INVALID_INPUT` before any document work happens, then delegates
13939
- * byte production and degradation reporting to the engine adapter.
13940
- */
13941
- function resolveMode$1(input) {
13942
- if (input != null && !require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "export.toDocx input must be an object.");
13943
- const raw = input?.mode;
13944
- if (raw === void 0) return DEFAULT_SD_EXPORT_MODE;
13945
- 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(", ")}.`, {
13946
- mode: raw,
13947
- allowedModes: [...SD_EXPORT_MODES]
13948
- });
13949
- return raw;
13950
- }
13951
- function resolveDocxExportPolicies(input = {}) {
13952
- if (!require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export input must be an object.");
13953
- const mode = resolveMode$1(input);
13954
- const policies = input.policies;
13955
- if (policies !== void 0 && !require_create_super_doc_ui.isRecord(policies)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export policies must be an object.");
13956
- const allowed = {
13957
- trackedChanges: SD_EXPORT_MODES,
13958
- comments: SD_COMMENT_EXPORT_POLICIES,
13959
- contentControls: SD_CONTENT_CONTROL_EXPORT_POLICIES
13960
- };
13961
- 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}.`, {
13962
- policy: key,
13963
- value
13964
- });
13965
- const requested = policies;
13966
- if (input.mode !== void 0 && requested?.trackedChanges !== void 0 && mode !== requested.trackedChanges) throw new DocumentApiValidationError("INVALID_INPUT", "mode conflicts with policies.trackedChanges.");
13967
- return {
13968
- trackedChanges: requested?.trackedChanges ?? mode,
13969
- comments: requested?.comments ?? "preserve",
13970
- contentControls: requested?.contentControls ?? "preserve"
13971
- };
13972
- }
13973
- //#endregion
13974
- //#region ../document-api/src/permission-ranges/permission-ranges.ts
13975
- function editorKey(editor) {
13976
- return editor.id?.trim() ? editor.id : editor.email?.trim() || void 0;
13977
- }
13978
- function editorMatches(editor, id) {
13979
- return Boolean(id.trim()) && (editor.id === id || Boolean(editor.email?.trim() && editor.email.trim().toLowerCase() === id.toLowerCase()));
13980
- }
13981
- /**
13982
- * Resolve a host ID or imported Word email against an explicitly supplied roster.
13983
- * Word receives the email when available; opaque IDs remain host-specific.
13984
- * Duplicate IDs/emails are ambiguous. This does not authenticate a user.
13985
- */
13986
- function resolvePermissionRangeEditor(editors, id) {
13987
- const matches = editors.filter((editor) => editorMatches(editor, id));
13988
- if (matches.length === 0) return {
13989
- status: "unknown",
13990
- id
13991
- };
13992
- if (matches.length !== 1) return {
13993
- status: "ambiguous",
13994
- id
13995
- };
13996
- const editor = matches[0];
13997
- const wordId = editor.email?.trim() || editor.id;
13998
- if (editors.filter((candidate) => editorMatches(candidate, wordId)).length !== 1) return {
13999
- status: "ambiguous",
14000
- id
14001
- };
14002
- return {
14003
- status: "resolved",
14004
- id,
14005
- editor: { ...editor },
14006
- principal: {
14007
- kind: "editor",
14008
- id: wordId
14009
- }
14010
- };
14011
- }
14012
- /** Enumerate the host roster for an editor picker, including ambiguous entries. */
14013
- function listPermissionRangeEditors(editors) {
14014
- const ids = new Set(editors.map(editorKey).filter((id) => id !== void 0));
14015
- return Array.from(ids, (id) => resolvePermissionRangeEditor(editors, id));
14016
- }
14017
- //#endregion
14018
14004
  //#region src/core/superdoc-ui-owner.ts
14019
14005
  var ownerIds = /* @__PURE__ */ new WeakMap();
14020
14006
  function getSuperDocUiOwnerId(superdoc) {
@@ -15076,7 +15062,7 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15076
15062
  });
15077
15063
  //#endregion
15078
15064
  //#region src/components/CommentsLayer/FloatingComments.vue
15079
- 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"]]);
15080
15066
  //#endregion
15081
15067
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue?vue&type=script&setup=true&lang.ts
15082
15068
  var _hoisted_1$22 = {
@@ -15210,7 +15196,7 @@ var PdfCommentsLayer_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15210
15196
  });
15211
15197
  //#endregion
15212
15198
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue
15213
- 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"]]);
15214
15200
  //#endregion
15215
15201
  //#region src/components/Whiteboard/use-whiteboard.ts
15216
15202
  var useWhiteboard = ({ proxy, layers, documents, modules }) => {
@@ -16184,6 +16170,116 @@ function resolveV2ReviewTargetCommentId(target, getComment) {
16184
16170
  return commentId != null ? String(commentId) : null;
16185
16171
  }
16186
16172
  //#endregion
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
16187
16283
  //#region src/helpers/v2-mutation-exception.ts
16188
16284
  var FAILURE_SOURCES = /* @__PURE__ */ new Set(["shell", "receipt"]);
16189
16285
  var DIAGNOSTIC_CODE = /^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/;
@@ -16553,7 +16649,7 @@ function usePasswordPrompt({ getSurfaceManager, getPasswordPromptConfig, onUnhan
16553
16649
  })
16554
16650
  });
16555
16651
  } else {
16556
- const mod = await Promise.resolve().then(() => require("./chunks/PasswordPromptSurface-x8GNmMJT.cjs"));
16652
+ const mod = await Promise.resolve().then(() => require("./chunks/PasswordPromptSurface-VFPnQOML.cjs"));
16557
16653
  const surfaceId = `password-prompt-${doc.id}`;
16558
16654
  handle = manager.open({
16559
16655
  id: surfaceId,
@@ -17213,7 +17309,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
17213
17309
  } else {
17214
17310
  let FindReplaceSurface;
17215
17311
  try {
17216
- FindReplaceSurface = (await Promise.resolve().then(() => require("./chunks/FindReplaceSurface-fVHxPXtn.cjs"))).default;
17312
+ FindReplaceSurface = (await Promise.resolve().then(() => require("./chunks/FindReplaceSurface-DWXgWgg7.cjs"))).default;
17217
17313
  } catch {
17218
17314
  opening = false;
17219
17315
  return;
@@ -17587,11 +17683,11 @@ var _hoisted_8$3 = { class: "input-row url-input-row" };
17587
17683
  var _hoisted_9$2 = ["innerHTML"];
17588
17684
  var _hoisted_10$2 = ["readonly", "onKeydown"];
17589
17685
  var _hoisted_11$2 = ["innerHTML"];
17590
- var _hoisted_12$1 = {
17686
+ var _hoisted_12$2 = {
17591
17687
  key: 0,
17592
17688
  class: "input-row link-buttons"
17593
17689
  };
17594
- var _hoisted_13$1 = ["disabled"];
17690
+ var _hoisted_13$2 = ["disabled"];
17595
17691
  var _hoisted_14$1 = ["innerHTML"];
17596
17692
  var _hoisted_15$1 = ["disabled"];
17597
17693
  var _hoisted_16$1 = {
@@ -17864,7 +17960,7 @@ var LinkInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
17864
17960
  "data-item": "btn-link-open"
17865
17961
  }, null, 10, _hoisted_11$2)
17866
17962
  ]),
17867
- !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", {
17868
17964
  key: 0,
17869
17965
  class: "remove-btn",
17870
17966
  onClick: handleRemove,
@@ -17873,7 +17969,7 @@ var LinkInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
17873
17969
  }, [require__plugin_vue_export_helper.createElementVNode("div", {
17874
17970
  class: "remove-btn__icon",
17875
17971
  innerHTML: require__plugin_vue_export_helper.unref(toolbarIcons).removeLink
17876
- }, 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", {
17877
17973
  class: require__plugin_vue_export_helper.normalizeClass(["sd-submit-btn", { "disable-btn": isDisabled.value }]),
17878
17974
  onClick: handleSubmit,
17879
17975
  disabled: isSubmitting.value,
@@ -18786,6 +18882,7 @@ function createV2EditorRuntimeAdapter(options) {
18786
18882
  const { id, documentId, root, host, getLegacyEditorProjection, onUnregister } = options;
18787
18883
  let snapshot = host.getSnapshot();
18788
18884
  let didDispose = false;
18885
+ let detached = false;
18789
18886
  let unregistered = false;
18790
18887
  let mountedFocusHandle = null;
18791
18888
  let tokenRevision = 0;
@@ -19082,7 +19179,17 @@ function createV2EditorRuntimeAdapter(options) {
19082
19179
  };
19083
19180
  }
19084
19181
  }
19182
+ function releaseHostSubscriptions() {
19183
+ hostUnsubscribe?.();
19184
+ hostUnsubscribe = null;
19185
+ pageMetricsUnsubscribe?.();
19186
+ pageMetricsUnsubscribe = null;
19187
+ selectionUnsubscribe?.();
19188
+ selectionUnsubscribe = null;
19189
+ activeSelectionController = null;
19190
+ }
19085
19191
  function handleHostSnapshot(next) {
19192
+ if (detached || didDispose) return;
19086
19193
  snapshot = next;
19087
19194
  invalidatePositionTokens();
19088
19195
  syncSelectionSubscription();
@@ -19096,10 +19203,7 @@ function createV2EditorRuntimeAdapter(options) {
19096
19203
  });
19097
19204
  if (next.state === "disposed" && !didDispose) {
19098
19205
  didDispose = true;
19099
- hostUnsubscribe?.();
19100
- pageMetricsUnsubscribe?.();
19101
- selectionUnsubscribe?.();
19102
- selectionUnsubscribe = null;
19206
+ releaseHostSubscriptions();
19103
19207
  emit({ type: "disposed" });
19104
19208
  listeners.clear();
19105
19209
  if (!unregistered) {
@@ -19246,10 +19350,7 @@ function createV2EditorRuntimeAdapter(options) {
19246
19350
  await host.dispose();
19247
19351
  if (!didDispose) {
19248
19352
  didDispose = true;
19249
- hostUnsubscribe?.();
19250
- pageMetricsUnsubscribe?.();
19251
- selectionUnsubscribe?.();
19252
- selectionUnsubscribe = null;
19353
+ releaseHostSubscriptions();
19253
19354
  emit({ type: "disposed" });
19254
19355
  listeners.clear();
19255
19356
  if (!unregistered) {
@@ -19328,8 +19429,17 @@ function createV2EditorRuntimeAdapter(options) {
19328
19429
  }
19329
19430
  },
19330
19431
  attachMountHandle(handle) {
19432
+ if (detached || didDispose) return;
19331
19433
  mountedFocusHandle = handle;
19332
19434
  syncSelectionSubscription();
19435
+ },
19436
+ detach() {
19437
+ if (detached) return;
19438
+ detached = true;
19439
+ unregistered = true;
19440
+ releaseHostSubscriptions();
19441
+ mountedFocusHandle = null;
19442
+ listeners.clear();
19333
19443
  }
19334
19444
  };
19335
19445
  }
@@ -20498,7 +20608,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20498
20608
  __name: "SuperDoc",
20499
20609
  emits: ["selection-update"],
20500
20610
  setup(__props, { emit: __emit }) {
20501
- const PdfViewer = require__plugin_vue_export_helper.defineAsyncComponent(() => Promise.resolve().then(() => require("./chunks/PdfViewer-CkrAHpC-.cjs")));
20611
+ const PdfViewer = require__plugin_vue_export_helper.defineAsyncComponent(() => Promise.resolve().then(() => require("./chunks/PdfViewer-DYTbPVUr.cjs")));
20502
20612
  const getDocumentLoadPassword = (doc) => doc.password ?? proxy.$superdoc.config.password;
20503
20613
  const resolveDocumentV2Collaboration = (doc) => {
20504
20614
  const rawConfig = doc?.v2Collaboration;
@@ -20612,6 +20722,8 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20612
20722
  const v2ReviewSidebarUnlocked = require__plugin_vue_export_helper.ref(false);
20613
20723
  const v2GeometryEpoch = require__plugin_vue_export_helper.ref(null);
20614
20724
  let v2GeometryRafHandle = 0;
20725
+ let v2GeometryReplayRafHandle = 0;
20726
+ let v2GeometryReplayGeneration = 0;
20615
20727
  let v2TrackedChangeRestampRetainPaints = 0;
20616
20728
  let v2TrackedChangeRestampRetentionReason = null;
20617
20729
  const activeEditorRef = require__plugin_vue_export_helper.computed(() => proxy.$superdoc.activeEditor);
@@ -20795,6 +20907,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20795
20907
  if (document && provider?.sendStateless) document.provider = null;
20796
20908
  const entry = v2Runtimes.get(documentId);
20797
20909
  if (!entry) return;
20910
+ entry.adapter.detach();
20798
20911
  proxy.$superdoc["unregisterEditorRuntime"](entry.runtimeId);
20799
20912
  v2Runtimes.delete(documentId);
20800
20913
  const hostRoot = subDocumentRoots.get(documentId);
@@ -21564,6 +21677,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21564
21677
  pending: entry
21565
21678
  });
21566
21679
  };
21680
+ let scheduleV2GeometryReplay = () => {};
21567
21681
  const v2GeometryPublisher = resolvedEditorIntegration.createGeometryPublisher({
21568
21682
  getLayersContainer: () => layers.value ?? null,
21569
21683
  isCommentsEnabled: () => Boolean(commentsModuleConfig.value) && shouldRenderCommentsInViewing.value,
@@ -21579,7 +21693,8 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21579
21693
  v2ReviewSidebarUnlocked.value = true;
21580
21694
  v2GeometryEpoch.value = v2GeometryPublisher.getLastEpoch();
21581
21695
  }
21582
- }
21696
+ },
21697
+ onCommittedPagePaint: ({ payload }) => scheduleV2GeometryReplay(payload)
21583
21698
  });
21584
21699
  const armV2TrackedChangeRestampGeometryRetention = (reason = "tracked-change-restamp") => {
21585
21700
  v2TrackedChangeRestampRetainPaints = Math.max(v2TrackedChangeRestampRetainPaints, 3);
@@ -21599,20 +21714,53 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21599
21714
  v2TrackedChangeRestampRetentionReason = null;
21600
21715
  };
21601
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
+ };
21602
21728
  const scheduleV2GeometryPublish = (payload, options = void 0) => {
21603
21729
  v2GeometryRender.value = payload;
21604
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
+ };
21605
21737
  if (typeof requestAnimationFrame !== "function") {
21606
- v2GeometryPublisher.publish(v2GeometryRender.value, resolveV2GeometryPublishOptions(options));
21738
+ publish();
21607
21739
  return;
21608
21740
  }
21609
21741
  v2GeometryRafHandle = requestAnimationFrame(() => {
21610
21742
  v2GeometryRafHandle = 0;
21611
- v2GeometryPublisher.publish(v2GeometryRender.value, resolveV2GeometryPublishOptions(options));
21743
+ publish();
21612
21744
  });
21613
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
+ };
21614
21761
  const onV2Render = (payload) => {
21615
21762
  if (!payload) return;
21763
+ v2ReviewGeometryDelivery.observe(payload);
21616
21764
  scheduleV2GeometryPublish(payload, () => takeV2TrackedChangeRestampGeometryRetention());
21617
21765
  if (v2HasRangeSelection.value) scheduleV2SelectionToolbarStateSync();
21618
21766
  };
@@ -21645,7 +21793,11 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21645
21793
  cancelScheduledV2SelectionToolbarSync();
21646
21794
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21647
21795
  v2GeometryRafHandle = 0;
21796
+ if (v2GeometryReplayRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryReplayRafHandle);
21797
+ v2GeometryReplayRafHandle = 0;
21798
+ v2GeometryReplayGeneration++;
21648
21799
  v2GeometryRender.value = null;
21800
+ v2ReviewGeometryDelivery.reset();
21649
21801
  v2GeometryEpoch.value = null;
21650
21802
  v2GeometryAvailable.value = false;
21651
21803
  v2ReviewSidebarUnlocked.value = false;
@@ -21793,14 +21945,15 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21793
21945
  if (!isV2Mode.value) return;
21794
21946
  if (!v2GeometryPublisher.getLastPayload()) return;
21795
21947
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21796
- if (typeof requestAnimationFrame !== "function") {
21797
- v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21798
- return;
21799
- }
21800
- v2GeometryRafHandle = requestAnimationFrame(() => {
21948
+ const recollect = () => {
21801
21949
  v2GeometryRafHandle = 0;
21802
- v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21803
- });
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);
21804
21957
  };
21805
21958
  const handleV2DocumentModeChange = () => {
21806
21959
  if (!isV2Mode.value) return;
@@ -22028,13 +22181,17 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
22028
22181
  ...payload,
22029
22182
  documentId: doc.id
22030
22183
  });
22031
- 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);
22032
22188
  },
22033
22189
  fontAssets: proxy.$superdoc.config.fonts,
22034
22190
  workerUrls: proxy.$superdoc.config.workerUrls,
22035
22191
  fieldContext: doc.fieldContext,
22036
22192
  fieldUpdatePolicy: proxy.$superdoc.config.fieldUpdatePolicy,
22037
22193
  workerStartupTimeoutMs: proxy.$superdoc.config.workerStartupTimeoutMs,
22194
+ ...proxy.$superdoc.config.changes ? { changes: proxy.$superdoc.config.changes } : {},
22038
22195
  proofing: resolvedProofingConfig.value,
22039
22196
  isNewFile,
22040
22197
  password: getDocumentLoadPassword(doc),
@@ -23120,7 +23277,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
23120
23277
  });
23121
23278
  //#endregion
23122
23279
  //#region src/SuperDoc.vue
23123
- 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-d2540ad3"]]);
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"]]);
23124
23281
  //#endregion
23125
23282
  //#region src/core/create-app.ts
23126
23283
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -35697,6 +35854,16 @@ var SurfaceManager = class {
35697
35854
  };
35698
35855
  //#endregion
35699
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
+ */
35700
35867
  var MIGRATION_URL = "https://docs.superdoc.dev/guides/migration/document-api";
35701
35868
  var _warned = /* @__PURE__ */ new Set();
35702
35869
  /**
@@ -37087,26 +37254,39 @@ var ToolbarButtonIcon_default = /* @__PURE__ */ require__plugin_vue_export_helpe
37087
37254
  var _hoisted_1$15 = [
37088
37255
  "role",
37089
37256
  "aria-label",
37090
- "aria-disabled"
37257
+ "aria-disabled",
37258
+ "aria-busy"
37091
37259
  ];
37092
37260
  var _hoisted_2$11 = ["data-item"];
37093
37261
  var _hoisted_3$10 = ["data-item"];
37094
37262
  var _hoisted_4$8 = {
37095
- 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,
37096
37270
  class: "sd-button-label"
37097
37271
  };
37098
- var _hoisted_5$6 = ["data-item", "aria-label"];
37099
- var _hoisted_6$4 = ["innerHTML"];
37100
- var _hoisted_7$2 = { key: 2 };
37101
- var _hoisted_8$2 = ["onKeydown", "id"];
37102
- 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 = [
37103
37283
  "placeholder",
37104
37284
  "onKeydown",
37105
37285
  "id",
37106
37286
  "data-item"
37107
37287
  ];
37108
- var _hoisted_10$1 = ["data-item", "innerHTML"];
37109
- var _hoisted_11$1 = {
37288
+ var _hoisted_12$1 = ["data-item", "innerHTML"];
37289
+ var _hoisted_13$1 = {
37110
37290
  "aria-live": "polite",
37111
37291
  class: "sd-visually-hidden"
37112
37292
  };
@@ -37277,6 +37457,7 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37277
37457
  role: __props.isOverflowItem ? "menuitem" : "button",
37278
37458
  "aria-label": require__plugin_vue_export_helper.unref(attributes).ariaLabel,
37279
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,
37280
37461
  "data-sd-part": "toolbar-item",
37281
37462
  onClick: handleOuterClick,
37282
37463
  onKeydown: _cache[9] || (_cache[9] = require__plugin_vue_export_helper.withKeys(($event) => onEnterKeydown($event), ["enter"])),
@@ -37298,17 +37479,21 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37298
37479
  class: "sd-toolbar-button__main",
37299
37480
  "data-item": `btn-${require__plugin_vue_export_helper.unref(name) || ""}-main`,
37300
37481
  onClick: _cache[0] || (_cache[0] = ($event) => handleSplitMainClick($event))
37301
- }, [require__plugin_vue_export_helper.unref(icon) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(ToolbarButtonIcon_default, {
37302
- key: 0,
37303
- color: require__plugin_vue_export_helper.unref(iconColor),
37304
- class: "sd-toolbar-icon",
37305
- icon: require__plugin_vue_export_helper.unref(icon),
37306
- name: require__plugin_vue_export_helper.unref(name)
37307
- }, null, 8, [
37308
- "color",
37309
- "icon",
37310
- "name"
37311
- ])) : 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),
37312
37497
  isSplit.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
37313
37498
  key: 1,
37314
37499
  class: "sd-toolbar-button__caret",
@@ -37319,9 +37504,10 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37319
37504
  class: "sd-dropdown-caret",
37320
37505
  innerHTML: caretIcon.value,
37321
37506
  style: require__plugin_vue_export_helper.normalizeStyle({ opacity: require__plugin_vue_export_helper.unref(disabled) ? .6 : 1 })
37322
- }, 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),
37323
37509
  require__plugin_vue_export_helper.unref(icon) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(ToolbarButtonIcon_default, {
37324
- key: 0,
37510
+ key: 1,
37325
37511
  color: require__plugin_vue_export_helper.unref(iconColor),
37326
37512
  class: "sd-toolbar-icon",
37327
37513
  icon: require__plugin_vue_export_helper.unref(icon),
@@ -37332,10 +37518,10 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37332
37518
  "name"
37333
37519
  ])) : require__plugin_vue_export_helper.createCommentVNode("", true),
37334
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", {
37335
- key: 1,
37521
+ key: 2,
37336
37522
  class: require__plugin_vue_export_helper.normalizeClass(["sd-button-label", { "sd-visually-hidden": require__plugin_vue_export_helper.unref(inlineTextInputVisible) && itemName.value === "fontFamily" }])
37337
37523
  }, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(label)), 3)) : require__plugin_vue_export_helper.createCommentVNode("", true),
37338
- 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", {
37339
37525
  key: 0,
37340
37526
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => inlineTextInput.value = $event),
37341
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"]))],
@@ -37347,7 +37533,7 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37347
37533
  autocomplete: "off",
37348
37534
  ref_key: "inlineInput",
37349
37535
  ref: inlineInput
37350
- }, 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", {
37351
37537
  key: 1,
37352
37538
  "onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => inlineTextInput.value = $event),
37353
37539
  placeholder: require__plugin_vue_export_helper.unref(label),
@@ -37364,23 +37550,23 @@ var ToolbarButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ re
37364
37550
  autocomplete: "off",
37365
37551
  ref_key: "inlineInput",
37366
37552
  ref: inlineInput
37367
- }, 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),
37368
37554
  require__plugin_vue_export_helper.unref(hasCaret) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
37369
- key: 3,
37555
+ key: 4,
37370
37556
  class: "sd-dropdown-caret",
37371
37557
  "data-item": `btn-${require__plugin_vue_export_helper.unref(name) || ""}-toggle`,
37372
37558
  innerHTML: caretIcon.value,
37373
37559
  style: require__plugin_vue_export_helper.normalizeStyle({ opacity: require__plugin_vue_export_helper.unref(disabled) ? .6 : 1 })
37374
- }, 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)
37375
37561
  ], 64)),
37376
- 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)
37377
37563
  ], 10, _hoisted_2$11)], 46, _hoisted_1$15);
37378
37564
  };
37379
37565
  }
37380
37566
  });
37381
37567
  //#endregion
37382
37568
  //#region src/internal/toolbar/built-in/ToolbarButton.vue
37383
- 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"]]);
37384
37570
  //#endregion
37385
37571
  //#region src/internal/toolbar/built-in/ToolbarSeparator.vue?vue&type=script&setup=true&lang.ts
37386
37572
  var _hoisted_1$14 = {
@@ -38676,7 +38862,7 @@ var SdTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
38676
38862
  ]);
38677
38863
  const contentStyle = require__plugin_vue_export_helper.computed(() => ({
38678
38864
  ...props.contentStyle,
38679
- ...attrs.style || {},
38865
+ ...attrs.style,
38680
38866
  position: "fixed",
38681
38867
  top: position.value.top,
38682
38868
  left: position.value.left,
@@ -38848,7 +39034,7 @@ var SdTooltip_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ requir
38848
39034
  });
38849
39035
  //#endregion
38850
39036
  //#region src/internal/toolbar/built-in/SdTooltip.vue
38851
- 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"]]);
38852
39038
  //#endregion
38853
39039
  //#region src/internal/toolbar/built-in/ButtonGroup.vue?vue&type=script&setup=true&lang.ts
38854
39040
  var _hoisted_1$11 = [
@@ -41698,6 +41884,8 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41698
41884
  attributes: { ariaLabel: "Bold" }
41699
41885
  });
41700
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);
41701
41889
  const fontButton = useToolbarItem({
41702
41890
  type: "dropdown",
41703
41891
  name: "fontFamily",
@@ -41724,8 +41912,9 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41724
41912
  if (typeof fontFamily !== "string" || !fontFamily) return;
41725
41913
  const family = fontFamily.split(",")[0];
41726
41914
  const optionValue = (option) => option.value ?? option.label;
41727
- const defaultFont = fontOptions.find((option) => optionValue(option) === fontButton.defaultLabel.value);
41728
- 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);
41729
41918
  if (foundFont) {
41730
41919
  fontButton.label.value = foundFont.label;
41731
41920
  fontButton.selectedValue.value = foundFont.key;
@@ -41738,7 +41927,7 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
41738
41927
  }
41739
41928
  },
41740
41929
  onDeactivate: () => {
41741
- 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);
41742
41931
  fontButton.label.value = defaultFont?.label ?? fontButton.defaultLabel.value;
41743
41932
  fontButton.selectedValue.value = defaultFont?.key ?? "";
41744
41933
  }
@@ -42950,7 +43139,7 @@ var V1_ENABLED_ON_SELECTION_REASON = /* @__PURE__ */ new Set([
42950
43139
  ]);
42951
43140
  var V1_ENABLED_ON_EMPTY_REASON = /* @__PURE__ */ new Set(["list", "numberedlist"]);
42952
43141
  function shouldKeepEnabledForV1ToolbarParity(name, commandState) {
42953
- if (name === "fontFamily" || name === "fontSize") return true;
43142
+ if (name === "fontFamily" || name === "fontSize") return commandState?.reason !== "document-readonly";
42954
43143
  if (V1_ENABLED_ON_EMPTY_REASON.has(name) && commandState?.disabled && commandState?.supported !== false && commandState?.reason == null) return true;
42955
43144
  if (!V1_ENABLED_ON_SELECTION_REASON.has(name)) return false;
42956
43145
  const reason = commandState?.reason;
@@ -43141,7 +43330,7 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43141
43330
  const signature = this.#fontOptionsSignature();
43142
43331
  if (signature !== this._lastFontOptionsSignature) {
43143
43332
  this._lastFontOptionsSignature = signature;
43144
- this.#rebuildToolbarItems();
43333
+ if (!this.#refreshFontFamilyOptions()) this.#rebuildToolbarItems();
43145
43334
  }
43146
43335
  this.updateToolbarState();
43147
43336
  };
@@ -43289,6 +43478,13 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43289
43478
  this.#makeToolbarItems();
43290
43479
  this.emit("toolbar-items-changed");
43291
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
+ }
43292
43488
  #fontOptionsSignature() {
43293
43489
  if (this.config.fonts) return "custom-fonts";
43294
43490
  const options = this.superdoc?.fonts?.getFontFamilyOptions?.() ?? [];
@@ -43468,6 +43664,10 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43468
43664
  const commandId = resolveBuiltInItemCommandId(name);
43469
43665
  if (!commandId) return false;
43470
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
+ };
43471
43671
  if (shouldKeepEnabledForV1ToolbarParity(name, commandState)) item.setDisabled(false);
43472
43672
  else item.setDisabled(Boolean(commandState?.disabled));
43473
43673
  const handlers = {
@@ -44012,6 +44212,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44012
44212
  #v2ConnectionUnsub;
44013
44213
  /** Latest `collaboration-connection-change` payload, for late readers. */
44014
44214
  #v2ConnectionState;
44215
+ #v2ConnectionFailureReported;
44015
44216
  /** Whether the current collaboration room has completed a sync at least once. */
44016
44217
  #v2ConnectionHasSynced;
44017
44218
  /** Lock state captured before a local → v2 collaboration promotion remount. */
@@ -44114,6 +44315,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44114
44315
  this.#v2LockUnsub = null;
44115
44316
  this.#v2ConnectionUnsub = null;
44116
44317
  this.#v2ConnectionState = null;
44318
+ this.#v2ConnectionFailureReported = false;
44117
44319
  this.#v2ConnectionHasSynced = false;
44118
44320
  this.#pendingV2LockSeed = null;
44119
44321
  this.#mountWrapper = null;
@@ -44316,7 +44518,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44316
44518
  }
44317
44519
  this.userColorMap = /* @__PURE__ */ new Map();
44318
44520
  this.colorIndex = 0;
44319
- this.version = "2.29.0";
44521
+ this.version = "2.30.0-next.4";
44320
44522
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
44321
44523
  this.superdocId = config.superdocId || require_uuid.v4();
44322
44524
  this.colors = this.config.colors ?? [];
@@ -44735,6 +44937,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44735
44937
  if (this.#v2ConnectionState?.documentId !== documentId) {
44736
44938
  this.#v2ConnectionState = null;
44737
44939
  this.#v2ConnectionHasSynced = false;
44940
+ this.#v2ConnectionFailureReported = false;
44738
44941
  }
44739
44942
  const publish = (snapshot) => {
44740
44943
  if (this.#destroyed) return;
@@ -44749,8 +44952,21 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44749
44952
  superdoc: this
44750
44953
  };
44751
44954
  this.#v2ConnectionState = payload;
44752
- if (snapshot.state === "synced") this.#v2ConnectionHasSynced = true;
44753
- 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
+ }
44754
44970
  };
44755
44971
  try {
44756
44972
  const initialSnapshot = connection.getSnapshot?.();