superdoc 2.28.0-next.16 → 2.28.0-next.18

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 (31) hide show
  1. package/dist/chunks/{create-super-doc-ui-DfSPIhxs.cjs → create-super-doc-ui-DOnTWcx7.cjs} +55 -17
  2. package/dist/chunks/{create-super-doc-ui-J7aMU_wd.es.js → create-super-doc-ui-gI3fiM_P.es.js} +50 -18
  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/contract/operation-definitions.d.ts +2 -2
  6. package/dist/document-api/src/types/receipt.d.ts +1 -1
  7. package/dist/public/ui-react.cjs +1 -1
  8. package/dist/public/ui-react.es.js +1 -1
  9. package/dist/public/ui-vue.cjs +1 -1
  10. package/dist/public/ui-vue.es.js +1 -1
  11. package/dist/public/ui.cjs +3 -2
  12. package/dist/public/ui.es.js +3 -2
  13. package/dist/shared/font-system/src/resolver.d.ts +3 -3
  14. package/dist/style.css +1 -1
  15. package/dist/style.layered.css +1 -1
  16. package/dist/superdoc/src/core/collaboration/helpers.d.ts +0 -5
  17. package/dist/superdoc/src/core/editor-runtime/types.d.ts +2 -0
  18. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -0
  19. package/dist/superdoc/src/helpers/v2-review-mutation-impact.d.ts +2 -0
  20. package/dist/superdoc/src/public/ui/types.d.ts +11 -0
  21. package/dist/superdoc/src/public/ui.d.cts +4 -0
  22. package/dist/superdoc/src/public/ui.d.ts +1 -1
  23. package/dist/superdoc/src/stores/comments-store.d.ts +4 -37
  24. package/dist/superdoc/src/stores/superdoc-store.d.ts +12 -111
  25. package/dist/superdoc.cjs +62 -139
  26. package/dist/superdoc.es.js +62 -139
  27. package/dist-cdn/style.layered.css +1 -1
  28. package/dist-cdn/superdoc.min.css +1 -1
  29. package/dist-cdn/superdoc.min.js +42 -42
  30. package/package.json +2 -2
  31. package/dist/superdoc/src/core/collaboration/collaboration.d.ts +0 -18
@@ -1,14 +1,12 @@
1
1
  import { i as __toESM$2 } from "./chunks/rolldown-runtime-0pSA04fp.es.js";
2
2
  import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
3
- import { _ as createInteractionHistory, a as registerFirstPartyCommandMutation, b as recordInteraction, c as applyV2CommentInvalidationFromMutation, d as createImageFilePicker, f as resolveImageSrc, g as closeInteractionHistory, h as DOM_CLASS_NAMES, i as readFirstPartyPageNumbers, l as getV2TrackedChangeMutationImpact, m as isSyntheticTrackedChangeCommentLaneItem, n as executeFirstPartyCommandAsync, o as isRecord, r as executeFirstPartyShortcutAsync, t as createSuperDocUI, u as isPlainObject$1, v as getWorkflowRecording, y as isWorkflowRecordingEnabled } from "./chunks/create-super-doc-ui-J7aMU_wd.es.js";
3
+ import { _ as closeInteractionHistory, a as registerFirstPartyCommandMutation, b as isWorkflowRecordingEnabled, c as applyV2CommentInvalidationFromMutation, d as isPlainObject$1, f as createImageFilePicker, g as DOM_CLASS_NAMES, h as isSyntheticTrackedChangeCommentLaneItem, i as readFirstPartyPageNumbers, l as getV2TrackedChangeMutationImpact, n as executeFirstPartyCommandAsync, o as isRecord, p as resolveImageSrc, r as executeFirstPartyShortcutAsync, t as createSuperDocUI, u as mutationCommittedEventChangedDocument, v as createInteractionHistory, x as recordInteraction, y as getWorkflowRecording } from "./chunks/create-super-doc-ui-gI3fiM_P.es.js";
4
4
  import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
5
5
  import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
6
6
  import { $ as vModelText, A as onActivated, B as renderSlot, C as isRef$1, D as normalizeClass, E as nextTick, F as openBlock, G as toRaw$2, H as resolveDynamicComponent, I as provide$1, J as unref, K as toRef, L as reactive, M as onDeactivated, N as onMounted, O as normalizeProps, P as onScopeDispose$1, Q as vModelSelect, R as ref, S as isReactive$1, T as mergeProps, U as shallowRef$1, V as resolveDirective, W as toDisplayString, X as useSlots, Y as useAttrs, Z as vModelCheckbox, _ as getCurrentInstance, a as computed$1, b as hasInjectionContext, c as createCommentVNode, d as createStaticVNode, et as watch$1, f as createTextVNode, g as effectScope, h as defineComponent, i as Transition, it as withModifiers, j as onBeforeUnmount, k as normalizeStyle, l as createElementBlock, m as defineAsyncComponent, n as Fragment, nt as withDirectives, o as createApp, p as createVNode, q as toRefs, r as Teleport, rt as withKeys, s as createBlock, t as _plugin_vue_export_helper_default, tt as withCtx, u as createElementVNode, v as getCurrentScope, w as markRaw, x as inject$1, y as h, z as renderList } from "./chunks/_plugin-vue_export-helper-7ZiLY07t.es.js";
7
7
  import { a as init_dist$1, i as global, n as init_dist$2, o as Buffer, r as process$1, s as init_dist, t as require_jszip_min } from "./chunks/jszip-BzJ3CyxR.es.js";
8
8
  import { t as PDF_TO_CSS_UNITS } from "./chunks/constants-B6VBlmKp.es.js";
9
9
  import * as Vue from "vue";
10
- import "y-websocket";
11
- import "@hocuspocus/provider";
12
10
  import { Map as Map$1 } from "yjs";
13
11
  //#region src/core/v2-integration/browser-peer-runtime.js
14
12
  var SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY = "__SUPERDOC_V2_BROWSER_RUNTIME__";
@@ -258,7 +256,7 @@ var v_click_outside_default = {
258
256
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
259
257
  function getSuperdocVersion() {
260
258
  try {
261
- return "2.28.0-next.16";
259
+ return "2.28.0-next.18";
262
260
  } catch {
263
261
  return "unknown";
264
262
  }
@@ -7602,6 +7600,11 @@ var useCommentsStore = defineStore("comments", () => {
7602
7600
  const suppressInternalExternal = ref(true);
7603
7601
  const currentCommentText = ref("");
7604
7602
  const currentCommentMentions = ref([]);
7603
+ let commentDraftRevision = 0;
7604
+ watch$1([currentCommentText, currentCommentMentions], () => commentDraftRevision++, {
7605
+ deep: true,
7606
+ flush: "sync"
7607
+ });
7605
7608
  const commentsList = ref([]);
7606
7609
  const reviewDirectoryList = shallowRef$1([]);
7607
7610
  let priorTrackedChangeThreadIndex = /* @__PURE__ */ new Map();
@@ -7935,17 +7938,6 @@ var useCommentsStore = defineStore("comments", () => {
7935
7938
  comment.resolvedByName = null;
7936
7939
  comment.trackedChangeDecision = null;
7937
7940
  };
7938
- const restoreResolvedMetadata = (comment) => {
7939
- if (!comment) return false;
7940
- const snapshot = trackedChangeResolutionSnapshots.get(comment);
7941
- if (!snapshot) return false;
7942
- comment.resolvedTime = snapshot.resolvedTime ?? Date.now();
7943
- comment.resolvedById = snapshot.resolvedById ?? null;
7944
- comment.resolvedByEmail = snapshot.resolvedByEmail ?? null;
7945
- comment.resolvedByName = snapshot.resolvedByName ?? null;
7946
- comment.trackedChangeDecision = snapshot.trackedChangeDecision ?? null;
7947
- return true;
7948
- };
7949
7941
  const getCommentEventPayload = (comment) => typeof comment?.getValues === "function" ? comment.getValues() : { ...comment };
7950
7942
  /**
7951
7943
  * Check if a comment originated from the document editor (or has no explicit source).
@@ -7960,63 +7952,14 @@ var useCommentsStore = defineStore("comments", () => {
7960
7952
  return source === DOCUMENT_EDITOR_SELECTION_SOURCE;
7961
7953
  };
7962
7954
  const isTrackedChangeThread = (comment) => Boolean(comment?.trackedChange) || Boolean(trackedChangeThreadParentIdForComment$1(comment));
7963
- const collectStandardCommentDocumentState = (editor) => {
7964
- const doc = editor?.state?.doc;
7965
- if (!doc || typeof doc.descendants !== "function") return null;
7966
- const liveMarkIds = /* @__PURE__ */ new Set();
7967
- const resolvedAnchorIds = /* @__PURE__ */ new Set();
7968
- doc.descendants((node) => {
7969
- node.marks?.filter((mark) => mark?.type?.name === "commentMark").forEach((mark) => {
7970
- [mark.attrs?.commentId, mark.attrs?.importedId].map((id) => normalizeCommentId(id)).filter(Boolean).forEach((id) => liveMarkIds.add(id));
7971
- });
7972
- const typeName = node.type?.name;
7973
- if (typeName !== "commentRangeStart" && typeName !== "commentRangeEnd") return;
7974
- const anchorId = normalizeCommentId(node.attrs?.["w:id"]);
7975
- if (anchorId) resolvedAnchorIds.add(anchorId);
7976
- });
7977
- return {
7978
- liveMarkIds,
7979
- resolvedAnchorIds
7980
- };
7981
- };
7982
- /**
7983
- * Fall back to a live editor when the caller has none (the store watchers).
7984
- * `editorCommentPositions` refreshes asynchronously, so a positions-based
7985
- * decision taken mid-undo/redo can act on STALE keys — e.g. clearing the
7986
- * resolved metadata that the redo restore just wrote back. The document
7987
- * itself is the source of truth; prefer it whenever an editor is reachable.
7988
- */
7989
- const getFallbackCommentsEditor = () => {
7990
- const docs = superdocStore.documents;
7991
- if (!Array.isArray(docs)) return null;
7992
- for (const doc of docs) {
7993
- const editor = typeof doc?.getEditor === "function" ? doc.getEditor() : null;
7994
- if (editor?.state?.doc) return editor;
7995
- }
7996
- return null;
7997
- };
7998
- const syncResolvedCommentsWithDocument = ({ editor } = {}) => {
7955
+ const syncResolvedCommentsWithDocument = () => {
7999
7956
  if (v2CommentsAdapter.value) return 0;
8000
- const effectiveEditor = editor ?? getFallbackCommentsEditor();
8001
- const documentState = collectStandardCommentDocumentState(effectiveEditor);
8002
7957
  const docPositions = editorCommentPositions.value || {};
8003
7958
  const activeKeys = new Set(Object.keys(docPositions));
8004
- if (!documentState && !activeKeys.size) return 0;
7959
+ if (!activeKeys.size) return 0;
8005
7960
  let changed = 0;
8006
7961
  commentsList.value.forEach((comment) => {
8007
7962
  if (!isEditorBackedComment(comment) || isTrackedChangeThread(comment)) return;
8008
- if (documentState) {
8009
- const aliasIds = getCommentAliasIds(comment);
8010
- const hasLiveMark = aliasIds.some((id) => documentState.liveMarkIds.has(id));
8011
- const hasResolvedAnchor = aliasIds.some((id) => documentState.resolvedAnchorIds.has(id));
8012
- if (hasLiveMark && comment.resolvedTime != null) {
8013
- clearResolvedMetadata(comment);
8014
- changed += 1;
8015
- return;
8016
- }
8017
- if (!hasLiveMark && hasResolvedAnchor && comment.resolvedTime == null && restoreResolvedMetadata(comment)) changed += 1;
8018
- return;
8019
- }
8020
7963
  const { key } = resolveCommentPositionEntry(comment);
8021
7964
  if (!key) return;
8022
7965
  if (activeKeys.has(String(key)) && comment.resolvedTime != null) {
@@ -8034,23 +7977,6 @@ var useCommentsStore = defineStore("comments", () => {
8034
7977
  syncResolvedCommentsWithDocument();
8035
7978
  }, { deep: false });
8036
7979
  /**
8037
- * Normalize a position object to a consistent { start, end } format.
8038
- * Handles different editor position schemas (start/end, pos/to, from/to).
8039
- *
8040
- * @param {Object | null | undefined} position The position object
8041
- * @returns {{ start: number, end: number } | null} The normalized range or null
8042
- */
8043
- const getCommentPositionRange = (position) => {
8044
- if (!position) return null;
8045
- const start = position.start ?? position.pos ?? position.from;
8046
- const end = position.end ?? position.to ?? start;
8047
- if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
8048
- return {
8049
- start,
8050
- end
8051
- };
8052
- };
8053
- /**
8054
7980
  * Get the editor position data for a comment.
8055
7981
  *
8056
7982
  * @param {Object | string} commentOrId The comment object or comment ID
@@ -8059,44 +7985,6 @@ var useCommentsStore = defineStore("comments", () => {
8059
7985
  const getCommentPosition = (commentOrId) => {
8060
7986
  return resolveCommentPositionEntry(commentOrId).entry ?? null;
8061
7987
  };
8062
- /**
8063
- * Get the text that a comment is anchored to in the document.
8064
- *
8065
- * @param {Object | string} commentOrId The comment object or comment ID
8066
- * @param {Object} [options] Options for text extraction
8067
- * @param {string} [options.separator=' '] Separator for textBetween when crossing nodes
8068
- * @param {boolean} [options.trim=true] Whether to trim whitespace from the result
8069
- * @returns {string | null} The anchored text or null if unavailable
8070
- */
8071
- const getCommentAnchoredText = (commentOrId, options = {}) => {
8072
- const comment = typeof commentOrId === "object" ? commentOrId : getComment(commentOrId);
8073
- if (!comment) return null;
8074
- const position = resolveCommentPositionEntry(commentOrId).entry ?? null;
8075
- const range = getCommentPositionRange(position);
8076
- if (!range) return null;
8077
- const docNode = (superdocStore.getDocument(comment.fileId)?.getEditor?.())?.state?.doc;
8078
- if (!docNode?.textBetween) return null;
8079
- const separator = options.separator ?? " ";
8080
- const text = docNode.textBetween(range.start, range.end, separator, separator);
8081
- return options.trim === false ? text : text?.trim();
8082
- };
8083
- /**
8084
- * Get both position and anchored text data for a comment.
8085
- *
8086
- * @param {Object | string} commentOrId The comment object or comment ID
8087
- * @param {Object} [options] Options passed to getCommentAnchoredText
8088
- * @param {string} [options.separator=' '] Separator for textBetween when crossing nodes
8089
- * @param {boolean} [options.trim=true] Whether to trim whitespace from the result
8090
- * @returns {{ position: Object, anchoredText: string | null } | null} The anchor data or null
8091
- */
8092
- const getCommentAnchorData = (commentOrId, options = {}) => {
8093
- const position = getCommentPosition(commentOrId);
8094
- if (!position) return null;
8095
- return {
8096
- position,
8097
- anchoredText: getCommentAnchoredText(commentOrId, options)
8098
- };
8099
- };
8100
7988
  const isThreadVisible = (comment) => {
8101
7989
  if (!isViewingMode.value) return true;
8102
7990
  const parent = getThreadParent(comment);
@@ -8686,9 +8574,12 @@ var useCommentsStore = defineStore("comments", () => {
8686
8574
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
8687
8575
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8688
8576
  if (v2Adapter && !comment.trackedChange) {
8689
- const submittedPendingComment = pendingComment.value;
8577
+ const pendingDraft = pendingComment.value;
8578
+ const draftRevision = commentDraftRevision;
8579
+ const draftActiveComment = activeComment.value;
8580
+ const draftActiveInstance = activeFloatingCommentInstanceId.value;
8690
8581
  const submittedPendingRequest = pendingCommentRequest;
8691
- const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8582
+ const text = normalizeV2CommentDraftText(pendingDraft ? currentCommentText.value : comment.commentText);
8692
8583
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8693
8584
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
8694
8585
  const parentCommentId = comment.parentCommentId ? String(comment.parentCommentId) : pendingComment.value ? null : null;
@@ -8724,6 +8615,7 @@ var useCommentsStore = defineStore("comments", () => {
8724
8615
  });
8725
8616
  return outcome;
8726
8617
  }
8618
+ const ownsActiveDraftBeforeReconcile = activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance;
8727
8619
  const reconciled = reconcileCommentsFromV2({
8728
8620
  superdoc,
8729
8621
  adapter: v2Adapter,
@@ -8735,14 +8627,17 @@ var useCommentsStore = defineStore("comments", () => {
8735
8627
  reconciled,
8736
8628
  documentId: v2Adapter.documentId
8737
8629
  });
8738
- const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8630
+ const createdId = created?.commentId ?? null;
8631
+ const createdIsActive = createdId !== null && activeComment.value === createdId;
8632
+ const createdInstance = createdIsActive ? activeFloatingCommentInstanceId.value : null;
8739
8633
  const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8740
- if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8634
+ const reconciliationClearedActiveDraft = ownsActiveDraftBeforeReconcile && activeComment.value === null && activeFloatingCommentInstanceId.value === null;
8635
+ const ownsPendingDraft = pendingDraft !== null && pendingComment.value === pendingDraft && commentDraftRevision === draftRevision && (createdIsActive || reconciliationClearedActiveDraft || activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance);
8636
+ if (ownsPendingDraft) if (ownsSubmittedRequest) removePendingComment(superdoc);
8741
8637
  else resetPendingCommentState(superdoc, false);
8742
- const createdId = created?.commentId ?? null;
8743
- if (hadPendingComment && ownsSubmittedRequest && createdId) {
8638
+ if (ownsPendingDraft && ownsSubmittedRequest && createdId) {
8744
8639
  setActiveComment(superdoc, createdId);
8745
- setActiveFloatingCommentInstance(createdId);
8640
+ setActiveFloatingCommentInstance(createdInstance ?? createdId);
8746
8641
  }
8747
8642
  if (broadcastChanges) superdoc.emit("comments-update", {
8748
8643
  type: COMMENT_EVENTS.ADD,
@@ -11007,8 +10902,6 @@ var useCommentsStore = defineStore("comments", () => {
11007
10902
  getTrackedChangeThread,
11008
10903
  getCommentPositionKey,
11009
10904
  getCommentPosition,
11010
- getCommentAnchoredText,
11011
- getCommentAnchorData,
11012
10905
  resolveCommentPositionEntry,
11013
10906
  getCommentDocumentId,
11014
10907
  belongsToDocument,
@@ -12376,6 +12269,7 @@ var _hoisted_53 = { class: "reply-input-wrapper" };
12376
12269
  var _hoisted_54 = { class: "reply-actions" };
12377
12270
  var _hoisted_55 = ["disabled", "data-disabled-reason"];
12378
12271
  var commentEditSessions = /* @__PURE__ */ new WeakMap();
12272
+ var commentReplySessions = /* @__PURE__ */ new WeakMap();
12379
12273
  var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12380
12274
  __name: "CommentDialog",
12381
12275
  props: {
@@ -12425,9 +12319,13 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12425
12319
  const superdocStore = useSuperdocStore();
12426
12320
  const commentsStore = useCommentsStore();
12427
12321
  const editSessionOwner = {};
12322
+ const replySessionOwner = {};
12428
12323
  const retireOwnEditSession = () => {
12429
12324
  if (commentEditSessions.get(commentsStore)?.owner === editSessionOwner) commentEditSessions.delete(commentsStore);
12430
12325
  };
12326
+ const retireOwnReplySession = () => {
12327
+ if (commentReplySessions.get(commentsStore)?.owner === replySessionOwner) commentReplySessions.delete(commentsStore);
12328
+ };
12431
12329
  const { addComment, cancelComment, deleteComment, getCommentAliasIds, removePendingComment, getCommentDocumentId, requestInstantSidebarAlignment, resolveCommentPositionEntry, clearInstantSidebarAlignment, setActiveFloatingCommentInstance } = commentsStore;
12432
12330
  const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, currentCommentMentions, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
12433
12331
  const isInternal = ref(true);
@@ -12628,6 +12526,11 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12628
12526
  const isReplying = ref(false);
12629
12527
  const isSubmittingReply = ref(false);
12630
12528
  const isSubmittingNewComment = ref(false);
12529
+ let replyDraftRevision = 0;
12530
+ watch$1([currentCommentText, currentCommentMentions], () => replyDraftRevision++, {
12531
+ deep: true,
12532
+ flush: "sync"
12533
+ });
12631
12534
  const commentSaveFailure = ref("");
12632
12535
  const commentSaveFailureMessage = (outcome, hasDraft = true) => {
12633
12536
  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."}`;
@@ -12638,6 +12541,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12638
12541
  ok: false,
12639
12542
  reason: v2WriteCapability.value?.reason ?? "v2-write-unavailable"
12640
12543
  };
12544
+ commentReplySessions.set(commentsStore, { owner: replySessionOwner });
12641
12545
  commentSaveFailure.value = "";
12642
12546
  isReplying.value = true;
12643
12547
  nextTick(() => {
@@ -12876,6 +12780,15 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12876
12780
  commentsStore.setActiveComment(proxy.$superdoc, activeComment.value);
12877
12781
  isCommentHighlighted.value = false;
12878
12782
  };
12783
+ const captureCommentEditorOwner = () => {
12784
+ const editor = proxy.$superdoc.activeEditor;
12785
+ const adapter = editor.v2Comments;
12786
+ const document = editor.doc;
12787
+ return {
12788
+ adapter,
12789
+ isCurrent: () => proxy.$superdoc.activeEditor === editor && editor.v2Comments === adapter && editor.doc === document
12790
+ };
12791
+ };
12879
12792
  const handleAddComment = async () => {
12880
12793
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
12881
12794
  if (isV2WriteDisabled.value) return {
@@ -12890,6 +12803,13 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12890
12803
  isSubmittingReply.value = true;
12891
12804
  commentSaveFailure.value = "";
12892
12805
  try {
12806
+ const session = commentReplySessions.get(commentsStore);
12807
+ const draftRevision = replyDraftRevision;
12808
+ const editorOwner = captureCommentEditorOwner();
12809
+ const threadId = props.comment.commentId;
12810
+ const fileId = props.comment.fileId;
12811
+ const pendingDraft = pendingComment.value;
12812
+ const edit = editingCommentId.value;
12893
12813
  const parentCommentId = getV2ExistingReplyParentId(props.comment);
12894
12814
  const trackedChangeTarget = getV2TrackedChangeCommentTarget(props.comment);
12895
12815
  const outcome = await commentsStore.replyCommentV2({
@@ -12904,6 +12824,8 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12904
12824
  nextTick(() => emit("resize"));
12905
12825
  return outcome;
12906
12826
  }
12827
+ if (session?.owner !== replySessionOwner || commentReplySessions.get(commentsStore) !== session || replyDraftRevision !== draftRevision || !editorOwner.isCurrent() || props.comment.commentId !== threadId || props.comment.fileId !== fileId || pendingComment.value !== pendingDraft || editingCommentId.value !== edit || !isDialogActive.value || !isReplying.value) return outcome;
12828
+ retireOwnReplySession();
12907
12829
  isReplying.value = false;
12908
12830
  currentCommentText.value = "";
12909
12831
  currentCommentMentions.value = [];
@@ -13250,10 +13172,8 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13250
13172
  const session = commentEditSessions.get(commentsStore);
13251
13173
  const submission = Symbol("comment-edit-submission");
13252
13174
  if (session?.owner === editSessionOwner) session.submission = submission;
13253
- const editor = proxy.$superdoc.activeEditor;
13254
- const adapter = editor.v2Comments;
13255
- const documentId = adapter.documentId;
13256
- const document = editor.doc;
13175
+ const editorOwner = captureCommentEditorOwner();
13176
+ const documentId = editorOwner.adapter.documentId;
13257
13177
  const thread = props.comment;
13258
13178
  const draft = currentCommentText.value;
13259
13179
  const outcome = await commentsStore.editCommentV2({
@@ -13261,7 +13181,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13261
13181
  commentId: comment.commentId,
13262
13182
  text: draft
13263
13183
  });
13264
- 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;
13184
+ if (session?.owner !== editSessionOwner || commentEditSessions.get(commentsStore) !== session || session.submission !== submission || !editorOwner.isCurrent() || editorOwner.adapter.documentId !== documentId || props.comment !== thread || editingCommentId.value !== comment.commentId || currentCommentText.value !== draft) return outcome;
13265
13185
  if (!outcome?.ok) {
13266
13186
  commentSaveFailure.value = commentSaveFailureMessage(outcome);
13267
13187
  return outcome;
@@ -13300,6 +13220,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13300
13220
  const handleCancel = (comment) => {
13301
13221
  commentSaveFailure.value = "";
13302
13222
  retireOwnEditSession();
13223
+ retireOwnReplySession();
13303
13224
  editingCommentId.value = null;
13304
13225
  isReplying.value = false;
13305
13226
  cancelComment(proxy.$superdoc);
@@ -13326,6 +13247,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13326
13247
  });
13327
13248
  onBeforeUnmount(() => {
13328
13249
  retireOwnEditSession();
13250
+ retireOwnReplySession();
13329
13251
  proxy.$superdoc?.off?.("active-editor-change", refreshActiveEditor);
13330
13252
  });
13331
13253
  watch$1(showInputSection, (isVisible) => {
@@ -13576,7 +13498,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13576
13498
  ], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
13577
13499
  };
13578
13500
  }
13579
- }, [["__scopeId", "data-v-f8b79c74"]]);
13501
+ }, [["__scopeId", "data-v-239e0310"]]);
13580
13502
  //#endregion
13581
13503
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
13582
13504
  var _hoisted_1$25 = [
@@ -19679,6 +19601,7 @@ function createV2EditorRuntimeAdapter(options) {
19679
19601
  }
19680
19602
  const result = await host.dispatch(mapped);
19681
19603
  switch (result.status) {
19604
+ case "selected": return { status: "selected" };
19682
19605
  case "committed":
19683
19606
  invalidatePositionTokens();
19684
19607
  return {
@@ -22209,7 +22132,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22209
22132
  if (event.type === "mutation:committed") {
22210
22133
  const bulkDecisionEvent = toV2BulkDecisionEvent(documentId, event.trackedChangeBulkDecision);
22211
22134
  if (bulkDecisionEvent) proxy.$superdoc.emit("tracked-changes:bulk-decision", bulkDecisionEvent);
22212
- emitV2EditorUpdate();
22135
+ if (mutationCommittedEventChangedDocument(event)) emitV2EditorUpdate();
22213
22136
  }
22214
22137
  if (event.type !== "mutation:committed") return;
22215
22138
  if (event.origin === "history") v2ReviewWindowController.refreshCommittedWindow(`history-${event.direction}`);
@@ -23586,7 +23509,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23586
23509
  ], 46, _hoisted_1$17);
23587
23510
  };
23588
23511
  }
23589
- }, [["__scopeId", "data-v-9c1ff6d7"]]);
23512
+ }, [["__scopeId", "data-v-2c57eaa1"]]);
23590
23513
  //#endregion
23591
23514
  //#region src/core/create-app.js
23592
23515
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45286,7 +45209,7 @@ var SuperDoc = class extends import_eventemitter3.default {
45286
45209
  }
45287
45210
  this.userColorMap = /* @__PURE__ */ new Map();
45288
45211
  this.colorIndex = 0;
45289
- this.version = "2.28.0-next.16";
45212
+ this.version = "2.28.0-next.18";
45290
45213
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45291
45214
  this.superdocId = config.superdocId || v4();
45292
45215
  this.colors = this.config.colors ?? [];