superdoc 2.28.0-next.5 → 2.28.0-next.7

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 (45) hide show
  1. package/dist/chunks/{create-super-doc-ui-D1eOhAjv.cjs → create-super-doc-ui-B4c55pFy.cjs} +420 -84
  2. package/dist/chunks/{create-super-doc-ui-B29zw5qD.es.js → create-super-doc-ui-C4Ka5Ph3.es.js} +415 -85
  3. package/dist/collaboration-upgrade-engine.cjs +1 -1
  4. package/dist/collaboration-upgrade-engine.es.js +1 -1
  5. package/dist/document-api/src/content-controls/content-controls.types.d.ts +11 -0
  6. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  7. package/dist/document-api/src/contract/operation-definitions.d.ts +41 -41
  8. package/dist/document-api/src/contract/operation-registry.d.ts +4 -0
  9. package/dist/document-api/src/export/export.d.ts +3 -1
  10. package/dist/document-api/src/export/export.types.d.ts +8 -0
  11. package/dist/document-api/src/get-node/get-node.d.ts +10 -4
  12. package/dist/document-api/src/index.d.ts +2 -1
  13. package/dist/document-api/src/replace/replace.d.ts +4 -1
  14. package/dist/document-api/src/types/mutation-plan.types.d.ts +2 -0
  15. package/dist/document-api/src/types/track-changes.types.d.ts +10 -2
  16. package/dist/layout-engine/contracts/src/index.d.ts +1 -0
  17. package/dist/public/ui-react.cjs +1 -1
  18. package/dist/public/ui-react.es.js +1 -1
  19. package/dist/public/ui-vue.cjs +1 -1
  20. package/dist/public/ui-vue.es.js +1 -1
  21. package/dist/public/ui.cjs +1 -1
  22. package/dist/public/ui.es.js +1 -1
  23. package/dist/style.css +1 -1
  24. package/dist/style.layered.css +1 -1
  25. package/dist/superdoc/src/core/SuperDoc.d.ts +2 -6
  26. package/dist/superdoc/src/core/collaboration/resolve-v2-collaboration-target.d.ts +2 -0
  27. package/dist/superdoc/src/core/editor-runtime/types.d.ts +1 -0
  28. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -2
  29. package/dist/superdoc/src/core/helpers/resolve-docx-export.d.ts +6 -0
  30. package/dist/superdoc/src/core/types/index.d.ts +10 -0
  31. package/dist/superdoc/src/public/export-types.d.ts +3 -0
  32. package/dist/superdoc/src/public/ui/entity-at.d.ts +1 -0
  33. package/dist/superdoc/src/public/ui/types.d.ts +16 -2
  34. package/dist/superdoc/src/public/ui.d.cts +14 -0
  35. package/dist/superdoc/src/public/ui.d.ts +1 -1
  36. package/dist/superdoc/src/stores/comments-store.d.ts +3 -57
  37. package/dist/superdoc/src/stores/superdoc-store.d.ts +9 -171
  38. package/dist/superdoc.cjs +352 -135
  39. package/dist/superdoc.es.js +352 -135
  40. package/dist-cdn/style.layered.css +1 -1
  41. package/dist-cdn/superdoc.min.css +1 -1
  42. package/dist-cdn/superdoc.min.js +42 -42
  43. package/package.json +2 -2
  44. package/dist/superdoc/src/index.d.cts +0 -18
  45. package/dist/superdoc/src/index.d.ts +0 -14
package/dist/superdoc.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./chunks/rolldown-runtime-74VwNCz7.cjs");
3
3
  const require_blank_docx = require("./chunks/blank-docx-BuFAbRjs.cjs");
4
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-D1eOhAjv.cjs");
4
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-B4c55pFy.cjs");
5
5
  const require_eventemitter3 = require("./chunks/eventemitter3-C_TAnXOl.cjs");
6
6
  const require_uuid = require("./chunks/uuid-BhG0ngwk.cjs");
7
7
  const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-BUdjGKyl.cjs");
@@ -260,7 +260,7 @@ var v_click_outside_default = {
260
260
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
261
261
  function getSuperdocVersion() {
262
262
  try {
263
- return "2.28.0-next.5";
263
+ return "2.28.0-next.7";
264
264
  } catch {
265
265
  return "unknown";
266
266
  }
@@ -5464,7 +5464,8 @@ function resolveWebsocketFamily(family, candidate) {
5464
5464
  roomMode,
5465
5465
  serverUrl,
5466
5466
  ...params ? { params } : {},
5467
- ...token ? { token } : {}
5467
+ ...token ? { token } : {},
5468
+ ...family === "hocuspocus" && candidate.retry !== void 0 ? { retry: candidate.retry } : {}
5468
5469
  }
5469
5470
  };
5470
5471
  }
@@ -7755,6 +7756,7 @@ var useCommentsStore = defineStore("comments", () => {
7755
7756
  const instantSidebarAlignmentInstanceId = require__plugin_vue_export_helper.ref(null);
7756
7757
  const pendingComment = require__plugin_vue_export_helper.ref(null);
7757
7758
  const pendingV2CommentTarget = require__plugin_vue_export_helper.shallowRef(null);
7759
+ let pendingCommentRequest = 0;
7758
7760
  const isViewingMode = require__plugin_vue_export_helper.computed(() => viewingVisibility.documentMode === "viewing");
7759
7761
  const shouldRenderReviewInViewing = require__plugin_vue_export_helper.computed(() => {
7760
7762
  if (!isViewingMode.value) return true;
@@ -7762,6 +7764,7 @@ var useCommentsStore = defineStore("comments", () => {
7762
7764
  });
7763
7765
  const v2CommentsAdapter = require__plugin_vue_export_helper.shallowRef(null);
7764
7766
  const setV2CommentsAdapter = (adapter) => {
7767
+ if (v2CommentsAdapter.value !== (adapter ?? null)) pendingCommentRequest += 1;
7765
7768
  v2CommentsAdapter.value = adapter ?? null;
7766
7769
  };
7767
7770
  const getV2CommentsAdapter = (superdoc) => {
@@ -8620,26 +8623,41 @@ var useCommentsStore = defineStore("comments", () => {
8620
8623
  }
8621
8624
  if (typeof currentSelection !== "function") return null;
8622
8625
  try {
8623
- return currentSelection();
8626
+ const snapshot = currentSelection();
8627
+ return typeof snapshot?.then === "function" ? Promise.resolve(snapshot).catch(() => null) : snapshot;
8624
8628
  } catch {
8625
8629
  return null;
8626
8630
  }
8627
8631
  };
8628
8632
  const showAddComment = (superdoc, targetClientY = null) => {
8633
+ const request = ++pendingCommentRequest;
8634
+ const editor = superdoc?.activeEditor;
8629
8635
  const v2Adapter = getV2CommentsAdapter(superdoc);
8630
- const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8631
- const event = {
8632
- type: COMMENT_EVENTS.PENDING,
8633
- pendingSelection
8636
+ const ownsRequest = () => pendingCommentRequest === request;
8637
+ const emitPending = (snapshot) => {
8638
+ if (!ownsRequest()) return;
8639
+ superdoc.emit("comments-update", {
8640
+ type: COMMENT_EVENTS.PENDING,
8641
+ pendingSelection: superdoc?.activeEditor === editor ? snapshot : null
8642
+ });
8634
8643
  };
8635
- superdoc.emit("comments-update", event);
8636
8644
  if (v2Adapter) {
8637
8645
  const cap = v2Adapter.getCapabilityState?.();
8638
8646
  if (cap && cap.canWrite === false) return {
8639
8647
  ok: false,
8640
8648
  reason: cap.reason
8641
8649
  };
8642
- return Promise.resolve(v2Adapter.captureCurrentSelection?.()).then((capture) => {
8650
+ return Promise.resolve(v2Adapter.captureCurrentSelection?.({ beforeReady: (snapshot) => {
8651
+ if (superdoc?.activeEditor === editor && getV2CommentsAdapter(superdoc) === v2Adapter) emitPending(snapshot);
8652
+ } })).then((capture) => {
8653
+ if (!ownsRequest()) return {
8654
+ ok: false,
8655
+ reason: "pending-comment-superseded"
8656
+ };
8657
+ if (superdoc?.activeEditor !== editor || getV2CommentsAdapter(superdoc) !== v2Adapter) return {
8658
+ ok: false,
8659
+ reason: "document-replaced"
8660
+ };
8643
8661
  if (!capture?.ok) return {
8644
8662
  ok: false,
8645
8663
  reason: capture?.reason ?? "editing-range-required",
@@ -8668,25 +8686,52 @@ var useCommentsStore = defineStore("comments", () => {
8668
8686
  detail: err?.message ?? String(err)
8669
8687
  }));
8670
8688
  }
8671
- const selection = { ...superdocStore.activeSelection };
8672
- selection.selectionBounds = { ...selection.selectionBounds };
8673
- if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
8674
- pendingComment.value = getPendingComment({
8675
- selection,
8676
- documentId: selection.documentId,
8677
- parentCommentId: null
8678
- });
8679
- if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8680
- if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8681
- ...pendingComment.value.getValues(),
8682
- commentId: "pending",
8683
- skipEmit: true
8684
- });
8685
- if (pendingComment.value.selection.source === "document-editor" && superdocStore.selectionPosition) superdocStore.selectionPosition.source = DOCUMENT_EDITOR_SELECTION_SOURCE;
8686
- requestInstantSidebarAlignment(targetClientY, "pending");
8687
- setActiveFloatingCommentInstance(null);
8688
- activeComment.value = pendingComment.value.commentId;
8689
- return { ok: true };
8689
+ const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8690
+ const asyncSnapshot = typeof pendingSelection?.then === "function";
8691
+ if (!asyncSnapshot) emitPending(pendingSelection);
8692
+ const showLegacyPending = (selection) => {
8693
+ selection.selectionBounds = { ...selection.selectionBounds };
8694
+ if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
8695
+ pendingComment.value = getPendingComment({
8696
+ selection,
8697
+ documentId: selection.documentId,
8698
+ parentCommentId: null
8699
+ });
8700
+ if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8701
+ if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8702
+ ...pendingComment.value.getValues(),
8703
+ commentId: "pending",
8704
+ skipEmit: true
8705
+ });
8706
+ if (pendingComment.value.selection.source === "document-editor" && superdocStore.selectionPosition) superdocStore.selectionPosition.source = DOCUMENT_EDITOR_SELECTION_SOURCE;
8707
+ requestInstantSidebarAlignment(targetClientY, "pending");
8708
+ setActiveFloatingCommentInstance(null);
8709
+ activeComment.value = pendingComment.value.commentId;
8710
+ return { ok: true };
8711
+ };
8712
+ if (asyncSnapshot) {
8713
+ const selection = { ...superdocStore.activeSelection };
8714
+ selection.selectionBounds = { ...selection.selectionBounds };
8715
+ return pendingSelection.then((snapshot) => {
8716
+ if (!ownsRequest()) return {
8717
+ ok: false,
8718
+ reason: "pending-comment-superseded"
8719
+ };
8720
+ emitPending(snapshot);
8721
+ if (!ownsRequest()) return {
8722
+ ok: false,
8723
+ reason: "pending-comment-superseded"
8724
+ };
8725
+ return superdoc?.activeEditor === editor ? showLegacyPending(selection) : {
8726
+ ok: false,
8727
+ reason: "document-replaced"
8728
+ };
8729
+ });
8730
+ }
8731
+ return ownsRequest() ? showLegacyPending({ ...superdocStore.activeSelection }) : {
8732
+ ok: false,
8733
+ reason: "pending-comment-superseded"
8734
+ };
8690
8735
  };
8691
8736
  /**
8692
8737
  * Get the numeric position value for sorting a comment by document order.
@@ -8841,7 +8886,7 @@ var useCommentsStore = defineStore("comments", () => {
8841
8886
  *
8842
8887
  * @returns {void}
8843
8888
  */
8844
- const removePendingComment = (superdoc) => {
8889
+ const resetPendingCommentState = (superdoc, clearViewingSelection = true) => {
8845
8890
  const hadPending = !!pendingComment.value;
8846
8891
  currentCommentText.value = "";
8847
8892
  currentCommentMentions.value = [];
@@ -8850,13 +8895,17 @@ var useCommentsStore = defineStore("comments", () => {
8850
8895
  superdocStore.selectionPosition = null;
8851
8896
  if (hadPending) clearActiveCommentSelection();
8852
8897
  if (isV2EditorActive(superdoc)) {
8853
- if (hadPending && isViewingMode.value) try {
8898
+ if (hadPending && clearViewingSelection && isViewingMode.value) try {
8854
8899
  superdoc?.activeEditor?.host?.getHandles?.()?.selection?.clear?.();
8855
8900
  } catch {}
8856
8901
  return;
8857
8902
  }
8858
8903
  superdoc?.activeEditor?.commands?.removeComment({ commentId: "pending" });
8859
8904
  };
8905
+ const removePendingComment = (superdoc) => {
8906
+ pendingCommentRequest += 1;
8907
+ resetPendingCommentState(superdoc);
8908
+ };
8860
8909
  const getV2CreatedComment = ({ outcome, reconciled, documentId }) => {
8861
8910
  const createdId = normalizeCommentId(outcome?.createdCommentId);
8862
8911
  if (!createdId) return reconciled?.added ?? null;
@@ -8874,6 +8923,7 @@ var useCommentsStore = defineStore("comments", () => {
8874
8923
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8875
8924
  if (v2Adapter && !comment.trackedChange) {
8876
8925
  const submittedPendingComment = pendingComment.value;
8926
+ const submittedPendingRequest = pendingCommentRequest;
8877
8927
  const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8878
8928
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8879
8929
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
@@ -8922,9 +8972,11 @@ var useCommentsStore = defineStore("comments", () => {
8922
8972
  documentId: v2Adapter.documentId
8923
8973
  });
8924
8974
  const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8925
- if (hadPendingComment) removePendingComment(superdoc);
8975
+ const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8976
+ if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8977
+ else resetPendingCommentState(superdoc, false);
8926
8978
  const createdId = created?.commentId ?? null;
8927
- if (hadPendingComment && createdId) {
8979
+ if (hadPendingComment && ownsSubmittedRequest && createdId) {
8928
8980
  setActiveComment(superdoc, createdId);
8929
8981
  setActiveFloatingCommentInstance(createdId);
8930
8982
  }
@@ -9021,6 +9073,8 @@ var useCommentsStore = defineStore("comments", () => {
9021
9073
  rejected: true,
9022
9074
  comment: comment.getValues(),
9023
9075
  reason: outcome?.reason ?? "v2-delete-failed",
9076
+ ...outcome?.code !== void 0 ? { code: outcome.code } : {},
9077
+ ...outcome?.detail !== void 0 ? { detail: outcome.detail } : {},
9024
9078
  ...outcome?.committed ? { committed: true } : {}
9025
9079
  });
9026
9080
  return outcome;
@@ -13338,97 +13392,107 @@ var _hoisted_2$19 = {
13338
13392
  class: "existing-internal-input"
13339
13393
  };
13340
13394
  var _hoisted_3$16 = { class: "new-comment-input-wrapper" };
13341
- var _hoisted_4$11 = { class: "reply-actions" };
13342
- var _hoisted_5$8 = ["disabled"];
13343
- var _hoisted_6$6 = {
13395
+ var _hoisted_4$11 = {
13396
+ key: 1,
13397
+ class: "tracked-change-decision-alert",
13398
+ role: "alert"
13399
+ };
13400
+ var _hoisted_5$8 = { class: "reply-actions" };
13401
+ var _hoisted_6$6 = ["disabled"];
13402
+ var _hoisted_7$4 = {
13344
13403
  key: 0,
13345
13404
  class: "resolved-badge"
13346
13405
  };
13347
- var _hoisted_7$4 = ["innerHTML"];
13348
- var _hoisted_8$4 = {
13406
+ var _hoisted_8$4 = ["innerHTML"];
13407
+ var _hoisted_9$3 = {
13349
13408
  key: 1,
13350
13409
  class: "existing-internal-input"
13351
13410
  };
13352
- var _hoisted_9$3 = {
13411
+ var _hoisted_10$3 = {
13412
+ key: 2,
13413
+ class: "tracked-change-decision-alert",
13414
+ role: "alert"
13415
+ };
13416
+ var _hoisted_11$3 = {
13353
13417
  key: 0,
13354
13418
  class: "card-section comment-body"
13355
13419
  };
13356
- var _hoisted_10$3 = ["data-track-change-semantic-color-key"];
13357
- var _hoisted_11$3 = { key: 0 };
13358
- var _hoisted_12$2 = { class: "change-type tracked-change-label" };
13359
- var _hoisted_13$2 = {
13420
+ var _hoisted_12$2 = ["data-track-change-semantic-color-key"];
13421
+ var _hoisted_13$2 = { key: 0 };
13422
+ var _hoisted_14$2 = { class: "change-type tracked-change-label" };
13423
+ var _hoisted_15$2 = {
13360
13424
  key: 0,
13361
13425
  class: "tracked-change-detail-lines"
13362
13426
  };
13363
- var _hoisted_14$2 = {
13427
+ var _hoisted_16$2 = {
13364
13428
  key: 0,
13365
13429
  class: "tracked-change-text"
13366
13430
  };
13367
- var _hoisted_15$2 = {
13431
+ var _hoisted_17$2 = {
13368
13432
  key: 1,
13369
13433
  class: "change-type"
13370
13434
  };
13371
- var _hoisted_16$2 = { class: "change-type" };
13372
- var _hoisted_17$2 = { key: 1 };
13373
- var _hoisted_18$2 = { class: "tracked-change-text is-inserted" };
13374
- var _hoisted_19$1 = { key: 2 };
13435
+ var _hoisted_18$2 = { class: "change-type" };
13436
+ var _hoisted_19$1 = { key: 1 };
13375
13437
  var _hoisted_20$1 = { class: "tracked-change-text is-inserted" };
13376
- var _hoisted_21$1 = { key: 3 };
13377
- var _hoisted_22$1 = { key: 4 };
13378
- var _hoisted_23$1 = { key: 5 };
13379
- var _hoisted_24 = { key: 6 };
13380
- var _hoisted_25 = { class: "tracked-change-text" };
13381
- var _hoisted_26 = { key: 7 };
13382
- var _hoisted_27 = { class: "tracked-change-text is-deleted" };
13383
- var _hoisted_28 = { class: "tracked-change-text is-inserted" };
13384
- var _hoisted_29 = { key: 8 };
13385
- var _hoisted_30 = { key: 9 };
13386
- var _hoisted_31 = { key: 10 };
13387
- var _hoisted_32 = { class: "tracked-change-text is-deleted" };
13388
- var _hoisted_33 = { key: 11 };
13389
- var _hoisted_34 = { class: "tracked-change-text is-inserted" };
13390
- var _hoisted_35 = ["data-track-change-image-preview-role"];
13391
- var _hoisted_36 = ["src", "alt"];
13392
- var _hoisted_37 = {
13438
+ var _hoisted_21$1 = { key: 2 };
13439
+ var _hoisted_22$1 = { class: "tracked-change-text is-inserted" };
13440
+ var _hoisted_23$1 = { key: 3 };
13441
+ var _hoisted_24 = { key: 4 };
13442
+ var _hoisted_25 = { key: 5 };
13443
+ var _hoisted_26 = { key: 6 };
13444
+ var _hoisted_27 = { class: "tracked-change-text" };
13445
+ var _hoisted_28 = { key: 7 };
13446
+ var _hoisted_29 = { class: "tracked-change-text is-deleted" };
13447
+ var _hoisted_30 = { class: "tracked-change-text is-inserted" };
13448
+ var _hoisted_31 = { key: 8 };
13449
+ var _hoisted_32 = { key: 9 };
13450
+ var _hoisted_33 = { key: 10 };
13451
+ var _hoisted_34 = { class: "tracked-change-text is-deleted" };
13452
+ var _hoisted_35 = { key: 11 };
13453
+ var _hoisted_36 = { class: "tracked-change-text is-inserted" };
13454
+ var _hoisted_37 = ["data-track-change-image-preview-role"];
13455
+ var _hoisted_38 = ["src", "alt"];
13456
+ var _hoisted_39 = {
13393
13457
  key: 1,
13394
13458
  class: "card-section comment-body"
13395
13459
  };
13396
- var _hoisted_38 = ["innerHTML"];
13397
- var _hoisted_39 = {
13460
+ var _hoisted_40 = ["innerHTML"];
13461
+ var _hoisted_41 = {
13398
13462
  key: 1,
13399
13463
  class: "comment"
13400
13464
  };
13401
- var _hoisted_40 = {
13465
+ var _hoisted_42 = {
13402
13466
  key: 2,
13403
13467
  class: "reply-expanded"
13404
13468
  };
13405
- var _hoisted_41 = { class: "reply-input-wrapper" };
13406
- var _hoisted_42 = { class: "reply-actions" };
13407
- var _hoisted_43 = ["onClick"];
13408
- var _hoisted_44 = [
13469
+ var _hoisted_43 = { class: "reply-input-wrapper" };
13470
+ var _hoisted_44 = { class: "reply-actions" };
13471
+ var _hoisted_45 = ["onClick"];
13472
+ var _hoisted_46 = [
13409
13473
  "onClick",
13410
13474
  "disabled",
13411
13475
  "data-disabled-reason"
13412
13476
  ];
13413
- var _hoisted_45 = { class: "collapsed-avatars" };
13414
- var _hoisted_46 = {
13477
+ var _hoisted_47 = { class: "collapsed-avatars" };
13478
+ var _hoisted_48 = {
13415
13479
  key: 3,
13416
13480
  class: "comment-separator"
13417
13481
  };
13418
- var _hoisted_47 = {
13419
- key: 2,
13482
+ var _hoisted_49 = {
13483
+ key: 3,
13420
13484
  class: "tracked-change-decision-alert",
13421
13485
  role: "alert"
13422
13486
  };
13423
- var _hoisted_48 = { class: "tracked-change-decision-alert__message" };
13424
- var _hoisted_49 = ["disabled", "data-disabled-reason"];
13425
- var _hoisted_50 = {
13487
+ var _hoisted_50 = { class: "tracked-change-decision-alert__message" };
13488
+ var _hoisted_51 = ["disabled", "data-disabled-reason"];
13489
+ var _hoisted_52 = {
13426
13490
  key: 1,
13427
13491
  class: "reply-expanded"
13428
13492
  };
13429
- var _hoisted_51 = { class: "reply-input-wrapper" };
13430
- var _hoisted_52 = { class: "reply-actions" };
13431
- var _hoisted_53 = ["disabled", "data-disabled-reason"];
13493
+ var _hoisted_53 = { class: "reply-input-wrapper" };
13494
+ var _hoisted_54 = { class: "reply-actions" };
13495
+ var _hoisted_55 = ["disabled", "data-disabled-reason"];
13432
13496
  var commentEditSessions = /* @__PURE__ */ new WeakMap();
13433
13497
  var _sfc_main$33 = {
13434
13498
  __name: "CommentDialog",
@@ -13508,6 +13572,7 @@ var _sfc_main$33 = {
13508
13572
  };
13509
13573
  };
13510
13574
  const CLICK_OUTSIDE_IGNORED_SELECTORS = [
13575
+ ".superdoc__tools [data-id=\"is-tool\"]",
13511
13576
  ".comments-dropdown__option-label",
13512
13577
  ".comments-dropdown__menu",
13513
13578
  ".comments-dropdown__option",
@@ -13681,12 +13746,17 @@ var _sfc_main$33 = {
13681
13746
  const isReplying = require__plugin_vue_export_helper.ref(false);
13682
13747
  const isSubmittingReply = require__plugin_vue_export_helper.ref(false);
13683
13748
  const isSubmittingNewComment = require__plugin_vue_export_helper.ref(false);
13749
+ const commentSaveFailure = require__plugin_vue_export_helper.ref("");
13750
+ const commentSaveFailureMessage = (outcome, hasDraft = true) => {
13751
+ return `Your comment could not be saved${outcome?.detail === "document-mode-read-only" ? " because the document or connection is read-only" : outcome?.code === "PERMISSION_DENIED" ? " because you do not have permission" : ""}.${hasDraft ? " Your draft is still here. Try again or cancel." : " Try again."}`;
13752
+ };
13684
13753
  const startReply = () => {
13685
13754
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
13686
13755
  if (isV2WriteDisabled.value) return {
13687
13756
  ok: false,
13688
13757
  reason: v2WriteCapability.value?.reason ?? "v2-write-unavailable"
13689
13758
  };
13759
+ commentSaveFailure.value = "";
13690
13760
  isReplying.value = true;
13691
13761
  require__plugin_vue_export_helper.nextTick(() => {
13692
13762
  commentInput.value?.focus?.();
@@ -13936,6 +14006,7 @@ var _sfc_main$33 = {
13936
14006
  reason: "reply-submit-in-flight"
13937
14007
  };
13938
14008
  isSubmittingReply.value = true;
14009
+ commentSaveFailure.value = "";
13939
14010
  try {
13940
14011
  const parentCommentId = getV2ExistingReplyParentId(props.comment);
13941
14012
  const trackedChangeTarget = getV2TrackedChangeCommentTarget(props.comment);
@@ -13947,6 +14018,7 @@ var _sfc_main$33 = {
13947
14018
  ...trackedChangeTarget ? { trackedChangeTarget } : {}
13948
14019
  });
13949
14020
  if (!outcome?.ok) {
14021
+ commentSaveFailure.value = commentSaveFailureMessage(outcome);
13950
14022
  require__plugin_vue_export_helper.nextTick(() => emit("resize"));
13951
14023
  return outcome;
13952
14024
  }
@@ -13965,6 +14037,7 @@ var _sfc_main$33 = {
13965
14037
  reason: "comment-submit-in-flight"
13966
14038
  };
13967
14039
  isSubmittingNewComment.value = true;
14040
+ commentSaveFailure.value = "";
13968
14041
  }
13969
14042
  const options = {
13970
14043
  documentId: props.comment.fileId,
@@ -13980,7 +14053,10 @@ var _sfc_main$33 = {
13980
14053
  Promise.resolve().then(() => addComment({
13981
14054
  superdoc: proxy.$superdoc,
13982
14055
  comment
13983
- })).catch((err) => {
14056
+ })).then((outcome) => {
14057
+ if (isPendingNewComment.value && outcome?.ok === false) commentSaveFailure.value = commentSaveFailureMessage(outcome);
14058
+ }).catch((err) => {
14059
+ commentSaveFailure.value = commentSaveFailureMessage();
13984
14060
  console.error("[SuperDoc] addComment failed", err);
13985
14061
  }).finally(() => {
13986
14062
  isSubmittingNewComment.value = false;
@@ -14205,10 +14281,15 @@ var _sfc_main$33 = {
14205
14281
  });
14206
14282
  v1TrackedChangeDecisionApplied = Boolean(outcome?.ok) && outcome.success !== false;
14207
14283
  } else if (isV2Mode.value && v2CommentsAdapter.value) {
14208
- if (!(await commentsStore.resolveCommentV2({
14284
+ const outcome = await commentsStore.resolveCommentV2({
14209
14285
  superdoc: proxy.$superdoc,
14210
14286
  commentId: props.comment.commentId
14211
- }))?.ok) return;
14287
+ });
14288
+ if (!outcome?.ok) {
14289
+ commentSaveFailure.value = commentSaveFailureMessage(outcome, false);
14290
+ return outcome;
14291
+ }
14292
+ commentSaveFailure.value = "";
14212
14293
  } else props.comment.resolveComment({
14213
14294
  id: superdocStore.user.id,
14214
14295
  email: superdocStore.user.email,
@@ -14237,17 +14318,22 @@ var _sfc_main$33 = {
14237
14318
  reason: "resolve-disabled"
14238
14319
  };
14239
14320
  if (!isV2Mode.value || !v2CommentsAdapter.value) return;
14240
- if (!(await commentsStore.reopenCommentV2({
14321
+ const outcome = await commentsStore.reopenCommentV2({
14241
14322
  superdoc: proxy.$superdoc,
14242
14323
  commentId: props.comment.commentId
14243
- }))?.ok) return;
14324
+ });
14325
+ if (!outcome?.ok) {
14326
+ commentSaveFailure.value = commentSaveFailureMessage(outcome, false);
14327
+ return outcome;
14328
+ }
14329
+ commentSaveFailure.value = "";
14244
14330
  require__plugin_vue_export_helper.nextTick(() => {
14245
14331
  commentsStore.lastUpdate = /* @__PURE__ */ new Date();
14246
14332
  commentsStore.setActiveComment(proxy.$superdoc, activeComment.value);
14247
14333
  proxy.$superdoc.focus?.();
14248
14334
  });
14249
14335
  };
14250
- const handleOverflowSelect = (value, comment) => {
14336
+ const handleOverflowSelect = async (value, comment) => {
14251
14337
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
14252
14338
  switch (value) {
14253
14339
  case "edit":
@@ -14266,10 +14352,13 @@ var _sfc_main$33 = {
14266
14352
  });
14267
14353
  break;
14268
14354
  case "delete":
14269
- deleteComment({
14270
- superdoc: proxy.$superdoc,
14271
- commentId: comment.commentId
14272
- });
14355
+ {
14356
+ const outcome = await deleteComment({
14357
+ superdoc: proxy.$superdoc,
14358
+ commentId: comment.commentId
14359
+ });
14360
+ commentSaveFailure.value = outcome?.ok ? "" : commentSaveFailureMessage(outcome, false);
14361
+ }
14273
14362
  break;
14274
14363
  }
14275
14364
  };
@@ -14290,8 +14379,12 @@ var _sfc_main$33 = {
14290
14379
  commentId: comment.commentId,
14291
14380
  text: draft
14292
14381
  });
14293
- if (!outcome?.ok) return outcome;
14294
14382
  if (session?.owner !== editSessionOwner || commentEditSessions.get(commentsStore) !== session || session.submission !== submission || proxy.$superdoc.activeEditor !== editor || editor.v2Comments !== adapter || adapter.documentId !== documentId || editor.doc !== document || props.comment !== thread || editingCommentId.value !== comment.commentId || currentCommentText.value !== draft) return outcome;
14383
+ if (!outcome?.ok) {
14384
+ commentSaveFailure.value = commentSaveFailureMessage(outcome);
14385
+ return outcome;
14386
+ }
14387
+ commentSaveFailure.value = "";
14295
14388
  retireOwnEditSession();
14296
14389
  editingCommentId.value = null;
14297
14390
  removePendingComment(proxy.$superdoc);
@@ -14323,6 +14416,7 @@ var _sfc_main$33 = {
14323
14416
  return typeof timestamp === "string" ? new Date(timestamp).getTime() : timestamp;
14324
14417
  };
14325
14418
  const handleCancel = (comment) => {
14419
+ commentSaveFailure.value = "";
14326
14420
  retireOwnEditSession();
14327
14421
  editingCommentId.value = null;
14328
14422
  isReplying.value = false;
@@ -14422,26 +14516,28 @@ var _sfc_main$33 = {
14422
14516
  "config",
14423
14517
  "comment"
14424
14518
  ])]),
14425
- require__plugin_vue_export_helper.createElementVNode("div", _hoisted_4$11, [require__plugin_vue_export_helper.createElementVNode("button", {
14519
+ commentSaveFailure.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("p", _hoisted_4$11, require__plugin_vue_export_helper.toDisplayString(commentSaveFailure.value), 1)) : require__plugin_vue_export_helper.createCommentVNode("", true),
14520
+ require__plugin_vue_export_helper.createElementVNode("div", _hoisted_5$8, [require__plugin_vue_export_helper.createElementVNode("button", {
14426
14521
  class: "sd-button reply-btn-cancel",
14427
14522
  onClick: require__plugin_vue_export_helper.withModifiers(handleCancel, ["stop", "prevent"])
14428
14523
  }, "Cancel"), require__plugin_vue_export_helper.createElementVNode("button", {
14429
14524
  class: require__plugin_vue_export_helper.normalizeClass(["sd-button primary reply-btn-primary", { "sd-is-disabled": !hasTextContent.value || isSubmittingNewComment.value }]),
14430
14525
  onClick: require__plugin_vue_export_helper.withModifiers(handleAddComment, ["stop", "prevent"]),
14431
14526
  disabled: !hasTextContent.value || isSubmittingNewComment.value
14432
- }, " Comment ", 10, _hoisted_5$8)])
14527
+ }, " Comment ", 10, _hoisted_6$6)])
14433
14528
  ], 64)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 1 }, [
14434
- resolvedBadgeLabel.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_6$6, [require__plugin_vue_export_helper.createElementVNode("span", {
14529
+ resolvedBadgeLabel.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_7$4, [require__plugin_vue_export_helper.createElementVNode("span", {
14435
14530
  class: "resolved-badge__icon",
14436
14531
  innerHTML: require__plugin_vue_export_helper.unref(superdocIcons).markDone
14437
- }, null, 8, _hoisted_7$4), require__plugin_vue_export_helper.createTextVNode(" " + require__plugin_vue_export_helper.toDisplayString(resolvedBadgeLabel.value), 1)])) : require__plugin_vue_export_helper.createCommentVNode("", true),
14438
- shouldShowInternalExternal.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_8$4, [require__plugin_vue_export_helper.createVNode(InternalDropdown_default, {
14532
+ }, null, 8, _hoisted_8$4), require__plugin_vue_export_helper.createTextVNode(" " + require__plugin_vue_export_helper.toDisplayString(resolvedBadgeLabel.value), 1)])) : require__plugin_vue_export_helper.createCommentVNode("", true),
14533
+ shouldShowInternalExternal.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_9$3, [require__plugin_vue_export_helper.createVNode(InternalDropdown_default, {
14439
14534
  onClick: _cache[1] || (_cache[1] = require__plugin_vue_export_helper.withModifiers(() => {}, ["stop", "prevent"])),
14440
14535
  class: "sd-internal-dropdown",
14441
14536
  "is-disabled": isInternalDropdownDisabled.value,
14442
14537
  state: __props.comment.isInternal ? "internal" : "external",
14443
14538
  onSelect: handleInternalExternalSelect
14444
14539
  }, null, 8, ["is-disabled", "state"])])) : require__plugin_vue_export_helper.createCommentVNode("", true),
14540
+ commentSaveFailure.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("p", _hoisted_10$3, require__plugin_vue_export_helper.toDisplayString(commentSaveFailure.value), 1)) : require__plugin_vue_export_helper.createCommentVNode("", true),
14445
14541
  (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(visibleComments.value, (comment, index) => {
14446
14542
  return require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14447
14543
  key: comment.commentId,
@@ -14473,27 +14569,27 @@ var _sfc_main$33 = {
14473
14569
  "write-disabled-reason",
14474
14570
  "onOverflowSelect"
14475
14571
  ]),
14476
- comment.trackedChange ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_9$3, [
14572
+ comment.trackedChange ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_11$3, [
14477
14573
  require__plugin_vue_export_helper.createElementVNode("div", {
14478
14574
  class: require__plugin_vue_export_helper.normalizeClass(["tracked-change", index === 0 ? bodyOverflowClass.value : void 0]),
14479
14575
  "data-track-change-semantic-color-key": comment.semanticColorKey ?? void 0,
14480
14576
  ref_for: true,
14481
14577
  ref: index === 0 ? setParentBodyRef : void 0
14482
- }, [comment.trackedChangeLabel ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_11$3, [require__plugin_vue_export_helper.createElementVNode("span", _hoisted_12$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_13$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) => {
14578
+ }, [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) => {
14483
14579
  return require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14484
14580
  key: lineIndex,
14485
14581
  class: "tracked-change-detail-line"
14486
14582
  }, [
14487
- line.excerpt ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_14$2, "\"" + require__plugin_vue_export_helper.toDisplayString(line.excerpt) + "\"", 1)) : require__plugin_vue_export_helper.createCommentVNode("", true),
14488
- line.excerpt ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_15$2, " — ")) : require__plugin_vue_export_helper.createCommentVNode("", true),
14489
- require__plugin_vue_export_helper.createElementVNode("span", _hoisted_16$2, require__plugin_vue_export_helper.toDisplayString(line.label), 1)
14583
+ line.excerpt ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_16$2, "\"" + require__plugin_vue_export_helper.toDisplayString(line.excerpt) + "\"", 1)) : require__plugin_vue_export_helper.createCommentVNode("", true),
14584
+ line.excerpt ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("span", _hoisted_17$2, " — ")) : require__plugin_vue_export_helper.createCommentVNode("", true),
14585
+ require__plugin_vue_export_helper.createElementVNode("span", _hoisted_18$2, require__plugin_vue_export_helper.toDisplayString(line.label), 1)
14490
14586
  ]);
14491
- }), 128))])) : require__plugin_vue_export_helper.createCommentVNode("", true)])) : comment.trackedChangeDisplayType === "hyperlinkAdded" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_17$2, [_cache[2] || (_cache[2] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added hyperlink ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_18$2, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : comment.trackedChangeDisplayType === "hyperlinkModified" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_19$1, [_cache[3] || (_cache[3] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Changed hyperlink to ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_20$1, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : comment.trackedChangeDisplayType === "paragraphSplit" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_21$1, [..._cache[4] || (_cache[4] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added new line", -1)])])) : comment.trackedChangeDisplayType === "tableInsert" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_22$1, [..._cache[5] || (_cache[5] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added table", -1)])])) : comment.trackedChangeDisplayType === "tableDelete" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_23$1, [..._cache[6] || (_cache[6] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted table", -1)])])) : comment.trackedChangeType === "trackFormat" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_24, [_cache[7] || (_cache[7] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Format: ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_25, require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText), 1)])) : comment.trackedChangeType === "both" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_26, [
14587
+ }), 128))])) : require__plugin_vue_export_helper.createCommentVNode("", true)])) : comment.trackedChangeDisplayType === "hyperlinkAdded" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_19$1, [_cache[2] || (_cache[2] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added hyperlink ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_20$1, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : comment.trackedChangeDisplayType === "hyperlinkModified" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_21$1, [_cache[3] || (_cache[3] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Changed hyperlink to ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_22$1, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : comment.trackedChangeDisplayType === "paragraphSplit" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_23$1, [..._cache[4] || (_cache[4] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added new line", -1)])])) : comment.trackedChangeDisplayType === "tableInsert" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_24, [..._cache[5] || (_cache[5] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added table", -1)])])) : comment.trackedChangeDisplayType === "tableDelete" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_25, [..._cache[6] || (_cache[6] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted table", -1)])])) : comment.trackedChangeType === "trackFormat" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_26, [_cache[7] || (_cache[7] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Format: ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_27, require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText), 1)])) : comment.trackedChangeType === "both" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_28, [
14492
14588
  _cache[8] || (_cache[8] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Replaced ", -1)),
14493
- require__plugin_vue_export_helper.createElementVNode("span", _hoisted_27, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.deletedText) + "\"", 1),
14589
+ require__plugin_vue_export_helper.createElementVNode("span", _hoisted_29, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.deletedText) + "\"", 1),
14494
14590
  _cache[9] || (_cache[9] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, " with ", -1)),
14495
- require__plugin_vue_export_helper.createElementVNode("span", _hoisted_28, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)
14496
- ])) : comment.deletedText && comment.deletedText === "\n" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_29, [..._cache[10] || (_cache[10] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted line break", -1)])])) : comment.trackedChangeText && comment.trackedChangeText === "\n" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_30, [..._cache[11] || (_cache[11] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added line break", -1)])])) : comment.deletedText ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_31, [_cache[12] || (_cache[12] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_32, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.deletedText) + "\"", 1)])) : comment.trackedChangeText ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_33, [_cache[13] || (_cache[13] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_34, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : require__plugin_vue_export_helper.createCommentVNode("", true), comment.trackedChangeImagePreview?.src ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14591
+ require__plugin_vue_export_helper.createElementVNode("span", _hoisted_30, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)
14592
+ ])) : comment.deletedText && comment.deletedText === "\n" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_31, [..._cache[10] || (_cache[10] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted line break", -1)])])) : comment.trackedChangeText && comment.trackedChangeText === "\n" ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_32, [..._cache[11] || (_cache[11] = [require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added line break", -1)])])) : comment.deletedText ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_33, [_cache[12] || (_cache[12] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Deleted ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_34, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.deletedText) + "\"", 1)])) : comment.trackedChangeText ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_35, [_cache[13] || (_cache[13] = require__plugin_vue_export_helper.createElementVNode("span", { class: "change-type" }, "Added ", -1)), require__plugin_vue_export_helper.createElementVNode("span", _hoisted_36, "\"" + require__plugin_vue_export_helper.toDisplayString(comment.trackedChangeText) + "\"", 1)])) : require__plugin_vue_export_helper.createCommentVNode("", true), comment.trackedChangeImagePreview?.src ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14497
14593
  key: 12,
14498
14594
  class: "tracked-change-image-preview",
14499
14595
  "data-track-change-image-preview-role": comment.trackedChangeImagePreview.role ?? void 0
@@ -14504,7 +14600,7 @@ var _sfc_main$33 = {
14504
14600
  style: require__plugin_vue_export_helper.normalizeStyle(trackedChangeImagePreviewStyle(comment.trackedChangeImagePreview)),
14505
14601
  loading: "lazy",
14506
14602
  decoding: "async"
14507
- }, null, 12, _hoisted_36)], 8, _hoisted_35)) : require__plugin_vue_export_helper.createCommentVNode("", true)], 10, _hoisted_10$3),
14603
+ }, null, 12, _hoisted_38)], 8, _hoisted_37)) : require__plugin_vue_export_helper.createCommentVNode("", true)], 10, _hoisted_12$2),
14508
14604
  shouldTruncate.value && isTextOverflowing.value && index === 0 ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14509
14605
  key: 0,
14510
14606
  class: "show-more-toggle",
@@ -14516,29 +14612,29 @@ var _sfc_main$33 = {
14516
14612
  onClick: require__plugin_vue_export_helper.withModifiers(toggleTruncation, ["stop", "prevent"])
14517
14613
  }, " Show less ")) : require__plugin_vue_export_helper.createCommentVNode("", true)
14518
14614
  ])) : require__plugin_vue_export_helper.createCommentVNode("", true),
14519
- !comment.trackedChange ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_37, [
14615
+ !comment.trackedChange ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_39, [
14520
14616
  !require__plugin_vue_export_helper.unref(isDebugging) && !isEditingThisComment.value(comment) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14521
14617
  key: 0,
14522
14618
  class: require__plugin_vue_export_helper.normalizeClass(["comment", index === 0 ? bodyOverflowClass.value : void 0]),
14523
14619
  ref_for: true,
14524
14620
  ref: index === 0 ? setParentBodyRef : void 0,
14525
14621
  innerHTML: renderedCommentTexts.value.get(comment.commentId)
14526
- }, null, 10, _hoisted_38)) : require__plugin_vue_export_helper.unref(isDebugging) && !isEditingThisComment.value(comment) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_39, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(editorCommentPositions)[comment.importedId !== void 0 ? comment.importedId : comment.commentId]?.bounds), 1)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_40, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_41, [require__plugin_vue_export_helper.createVNode(CommentInput_default, {
14622
+ }, null, 10, _hoisted_40)) : require__plugin_vue_export_helper.unref(isDebugging) && !isEditingThisComment.value(comment) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_41, require__plugin_vue_export_helper.toDisplayString(require__plugin_vue_export_helper.unref(editorCommentPositions)[comment.importedId !== void 0 ? comment.importedId : comment.commentId]?.bounds), 1)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_42, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_43, [require__plugin_vue_export_helper.createVNode(CommentInput_default, {
14527
14623
  ref_for: true,
14528
14624
  ref: setEditCommentInputRef(comment.commentId),
14529
14625
  users: [],
14530
14626
  config: require__plugin_vue_export_helper.unref(getConfig),
14531
14627
  "include-header": false,
14532
14628
  comment
14533
- }, null, 8, ["config", "comment"])]), require__plugin_vue_export_helper.createElementVNode("div", _hoisted_42, [require__plugin_vue_export_helper.createElementVNode("button", {
14629
+ }, null, 8, ["config", "comment"])]), require__plugin_vue_export_helper.createElementVNode("div", _hoisted_44, [require__plugin_vue_export_helper.createElementVNode("button", {
14534
14630
  class: "sd-button reply-btn-cancel",
14535
14631
  onClick: require__plugin_vue_export_helper.withModifiers(($event) => handleCancel(comment), ["stop", "prevent"])
14536
- }, "Cancel", 8, _hoisted_43), require__plugin_vue_export_helper.createElementVNode("button", {
14632
+ }, "Cancel", 8, _hoisted_45), require__plugin_vue_export_helper.createElementVNode("button", {
14537
14633
  class: require__plugin_vue_export_helper.normalizeClass(["sd-button primary reply-btn-primary", { "sd-is-disabled": !hasTextContent.value || isV2WriteDisabled.value }]),
14538
14634
  onClick: require__plugin_vue_export_helper.withModifiers(($event) => handleCommentUpdate(comment), ["stop", "prevent"]),
14539
14635
  disabled: !hasTextContent.value || isV2WriteDisabled.value,
14540
14636
  "data-disabled-reason": isV2WriteDisabled.value ? v2WriteCapability.value?.reason ?? null : null
14541
- }, " Update ", 10, _hoisted_44)])])),
14637
+ }, " Update ", 10, _hoisted_46)])])),
14542
14638
  shouldTruncate.value && isTextOverflowing.value && index === 0 && !isEditingThisComment.value(comment) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
14543
14639
  key: 3,
14544
14640
  class: "show-more-toggle",
@@ -14553,29 +14649,29 @@ var _sfc_main$33 = {
14553
14649
  shouldCollapseThread.value && index === 0 ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 2 }, [_cache[14] || (_cache[14] = require__plugin_vue_export_helper.createElementVNode("div", { class: "comment-separator" }, null, -1)), require__plugin_vue_export_helper.createElementVNode("div", {
14554
14650
  class: "collapsed-replies",
14555
14651
  onClick: require__plugin_vue_export_helper.withModifiers(expandThread, ["stop", "prevent"])
14556
- }, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_45, [(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(collapsedReplyAuthors.value, (author) => {
14652
+ }, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_47, [(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(collapsedReplyAuthors.value, (author) => {
14557
14653
  return require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(Avatar_default, {
14558
14654
  key: author.email || author.name,
14559
14655
  user: author,
14560
14656
  class: "mini-avatar"
14561
14657
  }, null, 8, ["user"]);
14562
14658
  }), 128))]), require__plugin_vue_export_helper.createElementVNode("span", null, require__plugin_vue_export_helper.toDisplayString(collapsedReplyCount.value) + " more " + require__plugin_vue_export_helper.toDisplayString(collapsedReplyCount.value === 1 ? "reply" : "replies"), 1)])], 64)) : require__plugin_vue_export_helper.createCommentVNode("", true),
14563
- showSeparator.value(index) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_46)) : require__plugin_vue_export_helper.createCommentVNode("", true)
14659
+ showSeparator.value(index) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_48)) : require__plugin_vue_export_helper.createCommentVNode("", true)
14564
14660
  ]);
14565
14661
  }), 128)),
14566
- trackedChangeDecisionFailure.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_47, [require__plugin_vue_export_helper.createElementVNode("span", _hoisted_48, require__plugin_vue_export_helper.toDisplayString(trackedChangeDecisionFailureMessage.value), 1), require__plugin_vue_export_helper.createElementVNode("button", {
14662
+ trackedChangeDecisionFailure.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_49, [require__plugin_vue_export_helper.createElementVNode("span", _hoisted_50, require__plugin_vue_export_helper.toDisplayString(trackedChangeDecisionFailureMessage.value), 1), require__plugin_vue_export_helper.createElementVNode("button", {
14567
14663
  type: "button",
14568
14664
  class: "sd-button tracked-change-decision-alert__retry",
14569
14665
  onClick: require__plugin_vue_export_helper.withModifiers(retryTrackedChangeDecision, ["stop", "prevent"])
14570
14666
  }, " Retry ")])) : require__plugin_vue_export_helper.createCommentVNode("", true),
14571
- showInputSection.value && !require__plugin_vue_export_helper.unref(getConfig).readOnly ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 3 }, [!isReplying.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("button", {
14667
+ showInputSection.value && !require__plugin_vue_export_helper.unref(getConfig).readOnly ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock(require__plugin_vue_export_helper.Fragment, { key: 4 }, [!isReplying.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("button", {
14572
14668
  key: 0,
14573
14669
  type: "button",
14574
14670
  class: require__plugin_vue_export_helper.normalizeClass(["reply-pill", { "sd-is-disabled": isV2WriteDisabled.value }]),
14575
14671
  onClick: require__plugin_vue_export_helper.withModifiers(startReply, ["stop", "prevent"]),
14576
14672
  disabled: isV2WriteDisabled.value,
14577
14673
  "data-disabled-reason": isV2WriteDisabled.value ? v2WriteCapability.value?.reason ?? null : null
14578
- }, " Reply or add others with @ ", 10, _hoisted_49)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_50, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_51, [require__plugin_vue_export_helper.createVNode(CommentInput_default, {
14674
+ }, " Reply or add others with @ ", 10, _hoisted_51)) : (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", _hoisted_52, [require__plugin_vue_export_helper.createElementVNode("div", _hoisted_53, [require__plugin_vue_export_helper.createVNode(CommentInput_default, {
14579
14675
  ref_key: "commentInput",
14580
14676
  ref: commentInput,
14581
14677
  users: usersFiltered.value,
@@ -14586,7 +14682,7 @@ var _sfc_main$33 = {
14586
14682
  "users",
14587
14683
  "config",
14588
14684
  "comment"
14589
- ])]), require__plugin_vue_export_helper.createElementVNode("div", _hoisted_52, [require__plugin_vue_export_helper.createElementVNode("button", {
14685
+ ])]), require__plugin_vue_export_helper.createElementVNode("div", _hoisted_54, [require__plugin_vue_export_helper.createElementVNode("button", {
14590
14686
  class: "sd-button reply-btn-cancel",
14591
14687
  onClick: require__plugin_vue_export_helper.withModifiers(handleCancel, ["stop", "prevent"])
14592
14688
  }, "Cancel"), require__plugin_vue_export_helper.createElementVNode("button", {
@@ -14594,12 +14690,12 @@ var _sfc_main$33 = {
14594
14690
  onClick: require__plugin_vue_export_helper.withModifiers(handleAddComment, ["stop", "prevent"]),
14595
14691
  disabled: !hasTextContent.value || isV2WriteDisabled.value || isSubmittingReply.value,
14596
14692
  "data-disabled-reason": v2ReplyDisabledReason.value
14597
- }, " Reply ", 10, _hoisted_53)])]))], 64)) : require__plugin_vue_export_helper.createCommentVNode("", true)
14693
+ }, " Reply ", 10, _hoisted_55)])]))], 64)) : require__plugin_vue_export_helper.createCommentVNode("", true)
14598
14694
  ], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
14599
14695
  };
14600
14696
  }
14601
14697
  };
14602
- var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-939045c1"]]);
14698
+ var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-f8b79c74"]]);
14603
14699
  //#endregion
14604
14700
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
14605
14701
  var _hoisted_1$25 = [
@@ -15324,6 +15420,80 @@ var composeAuthorColorResolver = (config) => {
15324
15420
  };
15325
15421
  };
15326
15422
  //#endregion
15423
+ //#region ../document-api/src/errors.ts
15424
+ /**
15425
+ * Structured validation error thrown by document-api execute* functions.
15426
+ *
15427
+ * Consumers should prefer checking `error.code` over `instanceof` for resilience
15428
+ * across package boundaries and bundling scenarios.
15429
+ */
15430
+ var DocumentApiValidationError = class DocumentApiValidationError extends Error {
15431
+ constructor(code, message, details) {
15432
+ super(message);
15433
+ this.name = "DocumentApiValidationError";
15434
+ this.code = code;
15435
+ this.details = details;
15436
+ Object.setPrototypeOf(this, DocumentApiValidationError.prototype);
15437
+ }
15438
+ };
15439
+ //#endregion
15440
+ //#region ../document-api/src/export/export.types.ts
15441
+ /** Canonical tracked-change export modes accepted by every public export surface. */
15442
+ var SD_EXPORT_MODES = [
15443
+ "review-preserving",
15444
+ "final",
15445
+ "original"
15446
+ ];
15447
+ /** Default mode for modeful DOCX export. */
15448
+ var DEFAULT_SD_EXPORT_MODE = "review-preserving";
15449
+ var SD_COMMENT_EXPORT_POLICIES = [
15450
+ "preserve",
15451
+ "resolve",
15452
+ "remove"
15453
+ ];
15454
+ var SD_CONTENT_CONTROL_EXPORT_POLICIES = ["preserve", "flatten"];
15455
+ //#endregion
15456
+ //#region ../document-api/src/export/export.ts
15457
+ /**
15458
+ * Export namespace: engine-agnostic public API and adapter contract.
15459
+ *
15460
+ * Validates the requested mode at the public boundary so an invalid mode fails
15461
+ * closed with `INVALID_INPUT` before any document work happens, then delegates
15462
+ * byte production and degradation reporting to the engine adapter.
15463
+ */
15464
+ function resolveMode$1(input) {
15465
+ if (input != null && !require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "export.toDocx input must be an object.");
15466
+ const raw = input?.mode;
15467
+ if (raw === void 0) return DEFAULT_SD_EXPORT_MODE;
15468
+ 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(", ")}.`, {
15469
+ mode: raw,
15470
+ allowedModes: [...SD_EXPORT_MODES]
15471
+ });
15472
+ return raw;
15473
+ }
15474
+ function resolveDocxExportPolicies(input = {}) {
15475
+ if (!require_create_super_doc_ui.isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export input must be an object.");
15476
+ const mode = resolveMode$1(input);
15477
+ const policies = input.policies;
15478
+ if (policies !== void 0 && !require_create_super_doc_ui.isRecord(policies)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export policies must be an object.");
15479
+ const allowed = {
15480
+ trackedChanges: SD_EXPORT_MODES,
15481
+ comments: SD_COMMENT_EXPORT_POLICIES,
15482
+ contentControls: SD_CONTENT_CONTROL_EXPORT_POLICIES
15483
+ };
15484
+ 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}.`, {
15485
+ policy: key,
15486
+ value
15487
+ });
15488
+ const requested = policies;
15489
+ if (input.mode !== void 0 && requested?.trackedChanges !== void 0 && mode !== requested.trackedChanges) throw new DocumentApiValidationError("INVALID_INPUT", "mode conflicts with policies.trackedChanges.");
15490
+ return {
15491
+ trackedChanges: requested?.trackedChanges ?? mode,
15492
+ comments: requested?.comments ?? "preserve",
15493
+ contentControls: requested?.contentControls ?? "preserve"
15494
+ };
15495
+ }
15496
+ //#endregion
15327
15497
  //#region ../document-api/src/permission-ranges/permission-ranges.ts
15328
15498
  function editorKey(editor) {
15329
15499
  return editor.id?.trim() ? editor.id : editor.email?.trim() || void 0;
@@ -20083,6 +20253,28 @@ function useLinkPopover({ getSurfaceManager, getActiveEditor, getUi, getActivati
20083
20253
  };
20084
20254
  }
20085
20255
  //#endregion
20256
+ //#region src/core/helpers/resolve-docx-export.ts
20257
+ function resolveV2DocxExportOptions(options = {}) {
20258
+ const policies = resolveDocxExportPolicies({ policies: options.policies });
20259
+ if (options.isFinalDoc !== void 0) {
20260
+ if (typeof options.isFinalDoc !== "boolean") throw new DocumentApiValidationError("INVALID_INPUT", "isFinalDoc must be a boolean.");
20261
+ const legacy = options.isFinalDoc ? "final" : "review-preserving";
20262
+ if (options.policies?.trackedChanges !== void 0 && policies.trackedChanges !== legacy) throw new DocumentApiValidationError("INVALID_INPUT", "isFinalDoc conflicts with policies.trackedChanges.");
20263
+ policies.trackedChanges = legacy;
20264
+ }
20265
+ if (options.commentsType !== void 0) {
20266
+ if (options.commentsType !== "external" && options.commentsType !== "clean") throw new DocumentApiValidationError("INVALID_INPUT", "commentsType must be external or clean.");
20267
+ const legacy = options.commentsType === "clean" ? "remove" : "preserve";
20268
+ if (options.policies?.comments !== void 0 && policies.comments !== legacy) throw new DocumentApiValidationError("INVALID_INPUT", "commentsType conflicts with policies.comments.");
20269
+ policies.comments = legacy;
20270
+ }
20271
+ return {
20272
+ mode: policies.trackedChanges,
20273
+ commentExportMode: policies.comments === "remove" ? "strip" : policies.comments,
20274
+ contentControlExportMode: policies.contentControls
20275
+ };
20276
+ }
20277
+ //#endregion
20086
20278
  //#region src/core/editor-runtime/v2/v2-editor-runtime-adapter.ts
20087
20279
  var DEFAULT_V2_LEGACY_PROJECTION = Object.freeze({
20088
20280
  editorVersion: 2,
@@ -20722,7 +20914,7 @@ function createV2EditorRuntimeAdapter(options) {
20722
20914
  save: () => host.save(),
20723
20915
  exportDocx: (options) => host.save({
20724
20916
  format: "docx",
20725
- commentExportMode: options?.commentsType === "clean" ? "strip" : "preserve"
20917
+ ...resolveV2DocxExportOptions(options)
20726
20918
  }),
20727
20919
  async setZoom(percent) {
20728
20920
  const result = host.setZoom(percent);
@@ -22123,6 +22315,10 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22123
22315
  return layers.value.getBoundingClientRect().top + top * zoom;
22124
22316
  };
22125
22317
  const handleCommentToolClick = async () => {
22318
+ if (isV2Mode.value) {
22319
+ cancelScheduledV2DomSelectionSync();
22320
+ if (applyCurrentV2DomSelection()?.ok === false) return;
22321
+ }
22126
22322
  if ((await showAddComment(proxy.$superdoc, getPendingCommentTargetClientY()))?.ok === false) return;
22127
22323
  if (!isV2Mode.value) return;
22128
22324
  const pendingPosition = buildV2PendingPositionEntry();
@@ -22395,10 +22591,9 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22395
22591
  return host.save(saveOptions);
22396
22592
  });
22397
22593
  const exportV2Docx = async (options = {}) => {
22398
- const commentExportMode = options?.commentsType === "clean" ? "strip" : "preserve";
22399
22594
  const bytes = await saveV2Bytes({
22400
22595
  format: "docx",
22401
- commentExportMode
22596
+ ...resolveV2DocxExportOptions(options)
22402
22597
  });
22403
22598
  return new Blob([bytes], { type: DOCX });
22404
22599
  };
@@ -22673,6 +22868,9 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22673
22868
  subscribe: (listener) => v2ReviewWindowController.subscribe?.(listener) ?? (() => void 0)
22674
22869
  },
22675
22870
  extensions: createV2ExtensionsFacet(host),
22871
+ get visuals() {
22872
+ return typeof host?.getHostVisuals === "function" ? host.getHostVisuals() : null;
22873
+ },
22676
22874
  fonts: fonts ?? host?.getFontRuntime?.() ?? null,
22677
22875
  /**
22678
22876
  * The v2 active-editor facade explicitly does NOT carry v1 commands /
@@ -22838,7 +23036,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22838
23036
  const result = handles?.selection?.applyDomSelection?.(selection);
22839
23037
  if (!result?.ok || result.mode !== "range") {
22840
23038
  clearV2SelectionToolbarState();
22841
- return;
23039
+ return { ok: false };
22842
23040
  }
22843
23041
  v2DomMirroredRange.value = true;
22844
23042
  v2HasRangeSelection.value = true;
@@ -23300,7 +23498,8 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23300
23498
  return;
23301
23499
  }
23302
23500
  const collaborationException = createCollaborationException(reason, documentId);
23303
- const message = collaborationException?.error.message ?? getV2EditorFailureMessage(reason);
23501
+ const baseMessage = collaborationException?.error.message ?? getV2EditorFailureMessage(reason);
23502
+ const message = reason === "collaboration-config-invalid" && detail ? `${baseMessage} ${detail}` : baseMessage;
23304
23503
  const workerFailure = payload?.workerFailure && typeof payload.workerFailure === "object" ? payload.workerFailure : null;
23305
23504
  setV2EditorFailure(documentId, {
23306
23505
  reason,
@@ -23316,7 +23515,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23316
23515
  };
23317
23516
  if (reason === "collaboration-v1-config-unsupported" || reason === "collaboration-room-format-unsupported" || reason === "collaboration-room-format-conflict" || reason === "collaboration-room-corrupt" || reason === "collaboration-v2-room-missing" || reason === "collaboration-v2-room-already-exists" || reason === "collaboration-v2-room-initializing" || reason === "collaboration-v2-room-bootstrap-stalled" || reason === "collaboration-open-intent-invalid" || reason === "collaboration-config-invalid") console.warn(`[SuperDoc] ${message}`, logContext);
23318
23517
  else console.error(`[SuperDoc] ${message}`, logContext);
23319
- proxy.$superdoc.emit("exception", collaborationException ?? {
23518
+ proxy.$superdoc.emit("exception", collaborationException && reason !== "collaboration-config-invalid" ? collaborationException : {
23320
23519
  error: new Error(message),
23321
23520
  code: reason,
23322
23521
  ...documentId ? { documentId } : {},
@@ -24544,7 +24743,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
24544
24743
  ], 46, _hoisted_1$17);
24545
24744
  };
24546
24745
  }
24547
- }, [["__scopeId", "data-v-143de6c8"]]);
24746
+ }, [["__scopeId", "data-v-0f22e103"]]);
24548
24747
  //#endregion
24549
24748
  //#region src/core/create-app.js
24550
24749
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -46273,7 +46472,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46273
46472
  }
46274
46473
  this.userColorMap = /* @__PURE__ */ new Map();
46275
46474
  this.colorIndex = 0;
46276
- this.version = "2.28.0-next.5";
46475
+ this.version = "2.28.0-next.7";
46277
46476
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46278
46477
  this.superdocId = config.superdocId || require_uuid.v4();
46279
46478
  this.colors = this.config.colors ?? [];
@@ -46989,7 +47188,8 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46989
47188
  ...syncTimeoutOption,
46990
47189
  ...target.serverUrl ? { serverUrl: target.serverUrl } : {},
46991
47190
  ...target.params ? { params: target.params } : {},
46992
- ...target.token ? { token: target.token } : {}
47191
+ ...target.token ? { token: target.token } : {},
47192
+ ...target.retry !== void 0 ? { retry: target.retry } : {}
46993
47193
  };
46994
47194
  return {
46995
47195
  providerType: "y-websocket",
@@ -48226,12 +48426,13 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48226
48426
  * Export the superdoc to a file
48227
48427
  * @param params - Export configuration
48228
48428
  */
48229
- async export({ exportType = ["docx"], commentsType = "external", exportedName, additionalFiles = [], additionalFileNames = [], isFinalDoc = false, triggerDownload = true, fieldsHighlightColor = null } = {}) {
48429
+ async export({ exportType = ["docx"], commentsType, exportedName, additionalFiles = [], additionalFileNames = [], isFinalDoc, policies, triggerDownload = true, fieldsHighlightColor = null } = {}) {
48230
48430
  if (!Array.isArray(exportType) || exportType.length !== 1 || exportType[0] !== "docx") throw new TypeError("SuperDoc.export() only supports exportType: [\"docx\"].");
48231
48431
  const baseFileName = exportedName ? cleanName(exportedName) : cleanName(this.config.title);
48232
48432
  const docxFiles = await this.exportEditorsToDOCX({
48233
48433
  commentsType,
48234
48434
  isFinalDoc,
48435
+ policies,
48235
48436
  fieldsHighlightColor
48236
48437
  });
48237
48438
  const blobsToZip = [...additionalFiles];
@@ -48317,7 +48518,12 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48317
48518
  * Export editors to DOCX format.
48318
48519
  * @param [options]
48319
48520
  */
48320
- async exportEditorsToDOCX({ commentsType, isFinalDoc, fieldsHighlightColor } = {}) {
48521
+ async exportEditorsToDOCX({ commentsType, isFinalDoc, policies, fieldsHighlightColor } = {}) {
48522
+ if (policies !== void 0) resolveV2DocxExportOptions({
48523
+ policies,
48524
+ commentsType,
48525
+ isFinalDoc
48526
+ });
48321
48527
  const uiStoreHydrated = this.config?.modules?.comments !== false;
48322
48528
  let legacyComments;
48323
48529
  let legacyCommentsComputed = false;
@@ -48337,7 +48543,13 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48337
48543
  };
48338
48544
  this.on("exception", rememberBridgedExportError);
48339
48545
  try {
48340
- const docxPromises = this.#requireSuperdocStore("exportEditorsToDOCX").documents.map(async (doc) => {
48546
+ const documents = this.#requireSuperdocStore("exportEditorsToDOCX").documents;
48547
+ if (policies !== void 0 && documents.some((doc) => {
48548
+ if (doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return false;
48549
+ const editor = doc.getEditor?.();
48550
+ return editor?.editorVersion !== 2 || typeof editor.exportDocx !== "function";
48551
+ })) throw new Error("Independent DOCX export policies require a mounted V2 exporter for every document.");
48552
+ const docxPromises = documents.map(async (doc) => {
48341
48553
  if (!doc || doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return null;
48342
48554
  const editor = typeof doc.getEditor === "function" ? doc.getEditor() : null;
48343
48555
  const fallbackDocx = () => {
@@ -48354,6 +48566,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
48354
48566
  const exported = await editor.exportDocx(isV2Editor ? {
48355
48567
  isFinalDoc,
48356
48568
  commentsType,
48569
+ policies,
48357
48570
  fieldsHighlightColor
48358
48571
  } : {
48359
48572
  isFinalDoc,
@@ -48682,7 +48895,11 @@ function defineSuperDocExtension(extension) {
48682
48895
  return extension;
48683
48896
  }
48684
48897
  //#endregion
48685
- exports.BlankDOCX = require_blank_docx.blank_default;
48898
+ //#region src/public/index.ts
48899
+ /** URL to the blank DOCX template. */
48900
+ var BlankDOCX = require_blank_docx.blank_default;
48901
+ //#endregion
48902
+ exports.BlankDOCX = BlankDOCX;
48686
48903
  exports.DOCX = DOCX;
48687
48904
  exports.DocumentLoadError = DocumentLoadError;
48688
48905
  exports.HTML = HTML;