superdoc 2.28.0-next.16 → 2.28.0-next.17

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.
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-DfSPIhxs.cjs");
4
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-CXdsObDZ.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");
@@ -9,8 +9,6 @@ const require_jszip = require("./chunks/jszip-D8mAFF-r.cjs");
9
9
  const require_constants = require("./chunks/constants-DpXuDx_g.cjs");
10
10
  let superdoc_entry_vue = require("vue");
11
11
  superdoc_entry_vue = require_rolldown_runtime.__toESM(superdoc_entry_vue, 1);
12
- require("y-websocket");
13
- require("@hocuspocus/provider");
14
12
  let yjs = require("yjs");
15
13
  //#region src/core/v2-integration/browser-peer-runtime.js
16
14
  var SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY = "__SUPERDOC_V2_BROWSER_RUNTIME__";
@@ -260,7 +258,7 @@ var v_click_outside_default = {
260
258
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
261
259
  function getSuperdocVersion() {
262
260
  try {
263
- return "2.28.0-next.16";
261
+ return "2.28.0-next.17";
264
262
  } catch {
265
263
  return "unknown";
266
264
  }
@@ -7604,6 +7602,11 @@ var useCommentsStore = defineStore("comments", () => {
7604
7602
  const suppressInternalExternal = require__plugin_vue_export_helper.ref(true);
7605
7603
  const currentCommentText = require__plugin_vue_export_helper.ref("");
7606
7604
  const currentCommentMentions = require__plugin_vue_export_helper.ref([]);
7605
+ let commentDraftRevision = 0;
7606
+ require__plugin_vue_export_helper.watch([currentCommentText, currentCommentMentions], () => commentDraftRevision++, {
7607
+ deep: true,
7608
+ flush: "sync"
7609
+ });
7607
7610
  const commentsList = require__plugin_vue_export_helper.ref([]);
7608
7611
  const reviewDirectoryList = require__plugin_vue_export_helper.shallowRef([]);
7609
7612
  let priorTrackedChangeThreadIndex = /* @__PURE__ */ new Map();
@@ -8688,9 +8691,12 @@ var useCommentsStore = defineStore("comments", () => {
8688
8691
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
8689
8692
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8690
8693
  if (v2Adapter && !comment.trackedChange) {
8691
- const submittedPendingComment = pendingComment.value;
8694
+ const pendingDraft = pendingComment.value;
8695
+ const draftRevision = commentDraftRevision;
8696
+ const draftActiveComment = activeComment.value;
8697
+ const draftActiveInstance = activeFloatingCommentInstanceId.value;
8692
8698
  const submittedPendingRequest = pendingCommentRequest;
8693
- const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8699
+ const text = normalizeV2CommentDraftText(pendingDraft ? currentCommentText.value : comment.commentText);
8694
8700
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8695
8701
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
8696
8702
  const parentCommentId = comment.parentCommentId ? String(comment.parentCommentId) : pendingComment.value ? null : null;
@@ -8726,6 +8732,7 @@ var useCommentsStore = defineStore("comments", () => {
8726
8732
  });
8727
8733
  return outcome;
8728
8734
  }
8735
+ const ownsActiveDraftBeforeReconcile = activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance;
8729
8736
  const reconciled = reconcileCommentsFromV2({
8730
8737
  superdoc,
8731
8738
  adapter: v2Adapter,
@@ -8737,14 +8744,17 @@ var useCommentsStore = defineStore("comments", () => {
8737
8744
  reconciled,
8738
8745
  documentId: v2Adapter.documentId
8739
8746
  });
8740
- const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8747
+ const createdId = created?.commentId ?? null;
8748
+ const createdIsActive = createdId !== null && activeComment.value === createdId;
8749
+ const createdInstance = createdIsActive ? activeFloatingCommentInstanceId.value : null;
8741
8750
  const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8742
- if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8751
+ const reconciliationClearedActiveDraft = ownsActiveDraftBeforeReconcile && activeComment.value === null && activeFloatingCommentInstanceId.value === null;
8752
+ const ownsPendingDraft = pendingDraft !== null && pendingComment.value === pendingDraft && commentDraftRevision === draftRevision && (createdIsActive || reconciliationClearedActiveDraft || activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance);
8753
+ if (ownsPendingDraft) if (ownsSubmittedRequest) removePendingComment(superdoc);
8743
8754
  else resetPendingCommentState(superdoc, false);
8744
- const createdId = created?.commentId ?? null;
8745
- if (hadPendingComment && ownsSubmittedRequest && createdId) {
8755
+ if (ownsPendingDraft && ownsSubmittedRequest && createdId) {
8746
8756
  setActiveComment(superdoc, createdId);
8747
- setActiveFloatingCommentInstance(createdId);
8757
+ setActiveFloatingCommentInstance(createdInstance ?? createdId);
8748
8758
  }
8749
8759
  if (broadcastChanges) superdoc.emit("comments-update", {
8750
8760
  type: COMMENT_EVENTS.ADD,
@@ -12383,6 +12393,7 @@ var _hoisted_53 = { class: "reply-input-wrapper" };
12383
12393
  var _hoisted_54 = { class: "reply-actions" };
12384
12394
  var _hoisted_55 = ["disabled", "data-disabled-reason"];
12385
12395
  var commentEditSessions = /* @__PURE__ */ new WeakMap();
12396
+ var commentReplySessions = /* @__PURE__ */ new WeakMap();
12386
12397
  var _sfc_main$33 = {
12387
12398
  __name: "CommentDialog",
12388
12399
  props: {
@@ -12432,9 +12443,13 @@ var _sfc_main$33 = {
12432
12443
  const superdocStore = useSuperdocStore();
12433
12444
  const commentsStore = useCommentsStore();
12434
12445
  const editSessionOwner = {};
12446
+ const replySessionOwner = {};
12435
12447
  const retireOwnEditSession = () => {
12436
12448
  if (commentEditSessions.get(commentsStore)?.owner === editSessionOwner) commentEditSessions.delete(commentsStore);
12437
12449
  };
12450
+ const retireOwnReplySession = () => {
12451
+ if (commentReplySessions.get(commentsStore)?.owner === replySessionOwner) commentReplySessions.delete(commentsStore);
12452
+ };
12438
12453
  const { addComment, cancelComment, deleteComment, getCommentAliasIds, removePendingComment, getCommentDocumentId, requestInstantSidebarAlignment, resolveCommentPositionEntry, clearInstantSidebarAlignment, setActiveFloatingCommentInstance } = commentsStore;
12439
12454
  const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, currentCommentMentions, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
12440
12455
  const isInternal = require__plugin_vue_export_helper.ref(true);
@@ -12635,6 +12650,11 @@ var _sfc_main$33 = {
12635
12650
  const isReplying = require__plugin_vue_export_helper.ref(false);
12636
12651
  const isSubmittingReply = require__plugin_vue_export_helper.ref(false);
12637
12652
  const isSubmittingNewComment = require__plugin_vue_export_helper.ref(false);
12653
+ let replyDraftRevision = 0;
12654
+ require__plugin_vue_export_helper.watch([currentCommentText, currentCommentMentions], () => replyDraftRevision++, {
12655
+ deep: true,
12656
+ flush: "sync"
12657
+ });
12638
12658
  const commentSaveFailure = require__plugin_vue_export_helper.ref("");
12639
12659
  const commentSaveFailureMessage = (outcome, hasDraft = true) => {
12640
12660
  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."}`;
@@ -12645,6 +12665,7 @@ var _sfc_main$33 = {
12645
12665
  ok: false,
12646
12666
  reason: v2WriteCapability.value?.reason ?? "v2-write-unavailable"
12647
12667
  };
12668
+ commentReplySessions.set(commentsStore, { owner: replySessionOwner });
12648
12669
  commentSaveFailure.value = "";
12649
12670
  isReplying.value = true;
12650
12671
  require__plugin_vue_export_helper.nextTick(() => {
@@ -12883,6 +12904,15 @@ var _sfc_main$33 = {
12883
12904
  commentsStore.setActiveComment(proxy.$superdoc, activeComment.value);
12884
12905
  isCommentHighlighted.value = false;
12885
12906
  };
12907
+ const captureCommentEditorOwner = () => {
12908
+ const editor = proxy.$superdoc.activeEditor;
12909
+ const adapter = editor.v2Comments;
12910
+ const document = editor.doc;
12911
+ return {
12912
+ adapter,
12913
+ isCurrent: () => proxy.$superdoc.activeEditor === editor && editor.v2Comments === adapter && editor.doc === document
12914
+ };
12915
+ };
12886
12916
  const handleAddComment = async () => {
12887
12917
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
12888
12918
  if (isV2WriteDisabled.value) return {
@@ -12897,6 +12927,13 @@ var _sfc_main$33 = {
12897
12927
  isSubmittingReply.value = true;
12898
12928
  commentSaveFailure.value = "";
12899
12929
  try {
12930
+ const session = commentReplySessions.get(commentsStore);
12931
+ const draftRevision = replyDraftRevision;
12932
+ const editorOwner = captureCommentEditorOwner();
12933
+ const threadId = props.comment.commentId;
12934
+ const fileId = props.comment.fileId;
12935
+ const pendingDraft = pendingComment.value;
12936
+ const edit = editingCommentId.value;
12900
12937
  const parentCommentId = getV2ExistingReplyParentId(props.comment);
12901
12938
  const trackedChangeTarget = getV2TrackedChangeCommentTarget(props.comment);
12902
12939
  const outcome = await commentsStore.replyCommentV2({
@@ -12911,6 +12948,8 @@ var _sfc_main$33 = {
12911
12948
  require__plugin_vue_export_helper.nextTick(() => emit("resize"));
12912
12949
  return outcome;
12913
12950
  }
12951
+ 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;
12952
+ retireOwnReplySession();
12914
12953
  isReplying.value = false;
12915
12954
  currentCommentText.value = "";
12916
12955
  currentCommentMentions.value = [];
@@ -13257,10 +13296,8 @@ var _sfc_main$33 = {
13257
13296
  const session = commentEditSessions.get(commentsStore);
13258
13297
  const submission = Symbol("comment-edit-submission");
13259
13298
  if (session?.owner === editSessionOwner) session.submission = submission;
13260
- const editor = proxy.$superdoc.activeEditor;
13261
- const adapter = editor.v2Comments;
13262
- const documentId = adapter.documentId;
13263
- const document = editor.doc;
13299
+ const editorOwner = captureCommentEditorOwner();
13300
+ const documentId = editorOwner.adapter.documentId;
13264
13301
  const thread = props.comment;
13265
13302
  const draft = currentCommentText.value;
13266
13303
  const outcome = await commentsStore.editCommentV2({
@@ -13268,7 +13305,7 @@ var _sfc_main$33 = {
13268
13305
  commentId: comment.commentId,
13269
13306
  text: draft
13270
13307
  });
13271
- 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;
13308
+ 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;
13272
13309
  if (!outcome?.ok) {
13273
13310
  commentSaveFailure.value = commentSaveFailureMessage(outcome);
13274
13311
  return outcome;
@@ -13307,6 +13344,7 @@ var _sfc_main$33 = {
13307
13344
  const handleCancel = (comment) => {
13308
13345
  commentSaveFailure.value = "";
13309
13346
  retireOwnEditSession();
13347
+ retireOwnReplySession();
13310
13348
  editingCommentId.value = null;
13311
13349
  isReplying.value = false;
13312
13350
  cancelComment(proxy.$superdoc);
@@ -13333,6 +13371,7 @@ var _sfc_main$33 = {
13333
13371
  });
13334
13372
  require__plugin_vue_export_helper.onBeforeUnmount(() => {
13335
13373
  retireOwnEditSession();
13374
+ retireOwnReplySession();
13336
13375
  proxy.$superdoc?.off?.("active-editor-change", refreshActiveEditor);
13337
13376
  });
13338
13377
  require__plugin_vue_export_helper.watch(showInputSection, (isVisible) => {
@@ -13584,7 +13623,7 @@ var _sfc_main$33 = {
13584
13623
  };
13585
13624
  }
13586
13625
  };
13587
- var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-f8b79c74"]]);
13626
+ var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-239e0310"]]);
13588
13627
  //#endregion
13589
13628
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
13590
13629
  var _hoisted_1$25 = [
@@ -19711,6 +19750,7 @@ function createV2EditorRuntimeAdapter(options) {
19711
19750
  }
19712
19751
  const result = await host.dispatch(mapped);
19713
19752
  switch (result.status) {
19753
+ case "selected": return { status: "selected" };
19714
19754
  case "committed":
19715
19755
  invalidatePositionTokens();
19716
19756
  return {
@@ -22249,7 +22289,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22249
22289
  if (event.type === "mutation:committed") {
22250
22290
  const bulkDecisionEvent = toV2BulkDecisionEvent(documentId, event.trackedChangeBulkDecision);
22251
22291
  if (bulkDecisionEvent) proxy.$superdoc.emit("tracked-changes:bulk-decision", bulkDecisionEvent);
22252
- emitV2EditorUpdate();
22292
+ if (require_create_super_doc_ui.mutationCommittedEventChangedDocument(event)) emitV2EditorUpdate();
22253
22293
  }
22254
22294
  if (event.type !== "mutation:committed") return;
22255
22295
  if (event.origin === "history") v2ReviewWindowController.refreshCommittedWindow(`history-${event.direction}`);
@@ -23626,7 +23666,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23626
23666
  ], 46, _hoisted_1$17);
23627
23667
  };
23628
23668
  }
23629
- }, [["__scopeId", "data-v-9c1ff6d7"]]);
23669
+ }, [["__scopeId", "data-v-2c57eaa1"]]);
23630
23670
  //#endregion
23631
23671
  //#region src/core/create-app.js
23632
23672
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45358,7 +45398,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45358
45398
  }
45359
45399
  this.userColorMap = /* @__PURE__ */ new Map();
45360
45400
  this.colorIndex = 0;
45361
- this.version = "2.28.0-next.16";
45401
+ this.version = "2.28.0-next.17";
45362
45402
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45363
45403
  this.superdocId = config.superdocId || require_uuid.v4();
45364
45404
  this.colors = this.config.colors ?? [];
@@ -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-CAfcpwSS.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.17";
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();
@@ -8686,9 +8689,12 @@ var useCommentsStore = defineStore("comments", () => {
8686
8689
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
8687
8690
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8688
8691
  if (v2Adapter && !comment.trackedChange) {
8689
- const submittedPendingComment = pendingComment.value;
8692
+ const pendingDraft = pendingComment.value;
8693
+ const draftRevision = commentDraftRevision;
8694
+ const draftActiveComment = activeComment.value;
8695
+ const draftActiveInstance = activeFloatingCommentInstanceId.value;
8690
8696
  const submittedPendingRequest = pendingCommentRequest;
8691
- const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8697
+ const text = normalizeV2CommentDraftText(pendingDraft ? currentCommentText.value : comment.commentText);
8692
8698
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8693
8699
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
8694
8700
  const parentCommentId = comment.parentCommentId ? String(comment.parentCommentId) : pendingComment.value ? null : null;
@@ -8724,6 +8730,7 @@ var useCommentsStore = defineStore("comments", () => {
8724
8730
  });
8725
8731
  return outcome;
8726
8732
  }
8733
+ const ownsActiveDraftBeforeReconcile = activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance;
8727
8734
  const reconciled = reconcileCommentsFromV2({
8728
8735
  superdoc,
8729
8736
  adapter: v2Adapter,
@@ -8735,14 +8742,17 @@ var useCommentsStore = defineStore("comments", () => {
8735
8742
  reconciled,
8736
8743
  documentId: v2Adapter.documentId
8737
8744
  });
8738
- const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8745
+ const createdId = created?.commentId ?? null;
8746
+ const createdIsActive = createdId !== null && activeComment.value === createdId;
8747
+ const createdInstance = createdIsActive ? activeFloatingCommentInstanceId.value : null;
8739
8748
  const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8740
- if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8749
+ const reconciliationClearedActiveDraft = ownsActiveDraftBeforeReconcile && activeComment.value === null && activeFloatingCommentInstanceId.value === null;
8750
+ const ownsPendingDraft = pendingDraft !== null && pendingComment.value === pendingDraft && commentDraftRevision === draftRevision && (createdIsActive || reconciliationClearedActiveDraft || activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance);
8751
+ if (ownsPendingDraft) if (ownsSubmittedRequest) removePendingComment(superdoc);
8741
8752
  else resetPendingCommentState(superdoc, false);
8742
- const createdId = created?.commentId ?? null;
8743
- if (hadPendingComment && ownsSubmittedRequest && createdId) {
8753
+ if (ownsPendingDraft && ownsSubmittedRequest && createdId) {
8744
8754
  setActiveComment(superdoc, createdId);
8745
- setActiveFloatingCommentInstance(createdId);
8755
+ setActiveFloatingCommentInstance(createdInstance ?? createdId);
8746
8756
  }
8747
8757
  if (broadcastChanges) superdoc.emit("comments-update", {
8748
8758
  type: COMMENT_EVENTS.ADD,
@@ -12376,6 +12386,7 @@ var _hoisted_53 = { class: "reply-input-wrapper" };
12376
12386
  var _hoisted_54 = { class: "reply-actions" };
12377
12387
  var _hoisted_55 = ["disabled", "data-disabled-reason"];
12378
12388
  var commentEditSessions = /* @__PURE__ */ new WeakMap();
12389
+ var commentReplySessions = /* @__PURE__ */ new WeakMap();
12379
12390
  var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12380
12391
  __name: "CommentDialog",
12381
12392
  props: {
@@ -12425,9 +12436,13 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12425
12436
  const superdocStore = useSuperdocStore();
12426
12437
  const commentsStore = useCommentsStore();
12427
12438
  const editSessionOwner = {};
12439
+ const replySessionOwner = {};
12428
12440
  const retireOwnEditSession = () => {
12429
12441
  if (commentEditSessions.get(commentsStore)?.owner === editSessionOwner) commentEditSessions.delete(commentsStore);
12430
12442
  };
12443
+ const retireOwnReplySession = () => {
12444
+ if (commentReplySessions.get(commentsStore)?.owner === replySessionOwner) commentReplySessions.delete(commentsStore);
12445
+ };
12431
12446
  const { addComment, cancelComment, deleteComment, getCommentAliasIds, removePendingComment, getCommentDocumentId, requestInstantSidebarAlignment, resolveCommentPositionEntry, clearInstantSidebarAlignment, setActiveFloatingCommentInstance } = commentsStore;
12432
12447
  const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, currentCommentMentions, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
12433
12448
  const isInternal = ref(true);
@@ -12628,6 +12643,11 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12628
12643
  const isReplying = ref(false);
12629
12644
  const isSubmittingReply = ref(false);
12630
12645
  const isSubmittingNewComment = ref(false);
12646
+ let replyDraftRevision = 0;
12647
+ watch$1([currentCommentText, currentCommentMentions], () => replyDraftRevision++, {
12648
+ deep: true,
12649
+ flush: "sync"
12650
+ });
12631
12651
  const commentSaveFailure = ref("");
12632
12652
  const commentSaveFailureMessage = (outcome, hasDraft = true) => {
12633
12653
  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 +12658,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12638
12658
  ok: false,
12639
12659
  reason: v2WriteCapability.value?.reason ?? "v2-write-unavailable"
12640
12660
  };
12661
+ commentReplySessions.set(commentsStore, { owner: replySessionOwner });
12641
12662
  commentSaveFailure.value = "";
12642
12663
  isReplying.value = true;
12643
12664
  nextTick(() => {
@@ -12876,6 +12897,15 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12876
12897
  commentsStore.setActiveComment(proxy.$superdoc, activeComment.value);
12877
12898
  isCommentHighlighted.value = false;
12878
12899
  };
12900
+ const captureCommentEditorOwner = () => {
12901
+ const editor = proxy.$superdoc.activeEditor;
12902
+ const adapter = editor.v2Comments;
12903
+ const document = editor.doc;
12904
+ return {
12905
+ adapter,
12906
+ isCurrent: () => proxy.$superdoc.activeEditor === editor && editor.v2Comments === adapter && editor.doc === document
12907
+ };
12908
+ };
12879
12909
  const handleAddComment = async () => {
12880
12910
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
12881
12911
  if (isV2WriteDisabled.value) return {
@@ -12890,6 +12920,13 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12890
12920
  isSubmittingReply.value = true;
12891
12921
  commentSaveFailure.value = "";
12892
12922
  try {
12923
+ const session = commentReplySessions.get(commentsStore);
12924
+ const draftRevision = replyDraftRevision;
12925
+ const editorOwner = captureCommentEditorOwner();
12926
+ const threadId = props.comment.commentId;
12927
+ const fileId = props.comment.fileId;
12928
+ const pendingDraft = pendingComment.value;
12929
+ const edit = editingCommentId.value;
12893
12930
  const parentCommentId = getV2ExistingReplyParentId(props.comment);
12894
12931
  const trackedChangeTarget = getV2TrackedChangeCommentTarget(props.comment);
12895
12932
  const outcome = await commentsStore.replyCommentV2({
@@ -12904,6 +12941,8 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
12904
12941
  nextTick(() => emit("resize"));
12905
12942
  return outcome;
12906
12943
  }
12944
+ 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;
12945
+ retireOwnReplySession();
12907
12946
  isReplying.value = false;
12908
12947
  currentCommentText.value = "";
12909
12948
  currentCommentMentions.value = [];
@@ -13250,10 +13289,8 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13250
13289
  const session = commentEditSessions.get(commentsStore);
13251
13290
  const submission = Symbol("comment-edit-submission");
13252
13291
  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;
13292
+ const editorOwner = captureCommentEditorOwner();
13293
+ const documentId = editorOwner.adapter.documentId;
13257
13294
  const thread = props.comment;
13258
13295
  const draft = currentCommentText.value;
13259
13296
  const outcome = await commentsStore.editCommentV2({
@@ -13261,7 +13298,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13261
13298
  commentId: comment.commentId,
13262
13299
  text: draft
13263
13300
  });
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;
13301
+ 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
13302
  if (!outcome?.ok) {
13266
13303
  commentSaveFailure.value = commentSaveFailureMessage(outcome);
13267
13304
  return outcome;
@@ -13300,6 +13337,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13300
13337
  const handleCancel = (comment) => {
13301
13338
  commentSaveFailure.value = "";
13302
13339
  retireOwnEditSession();
13340
+ retireOwnReplySession();
13303
13341
  editingCommentId.value = null;
13304
13342
  isReplying.value = false;
13305
13343
  cancelComment(proxy.$superdoc);
@@ -13326,6 +13364,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13326
13364
  });
13327
13365
  onBeforeUnmount(() => {
13328
13366
  retireOwnEditSession();
13367
+ retireOwnReplySession();
13329
13368
  proxy.$superdoc?.off?.("active-editor-change", refreshActiveEditor);
13330
13369
  });
13331
13370
  watch$1(showInputSection, (isVisible) => {
@@ -13576,7 +13615,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13576
13615
  ], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
13577
13616
  };
13578
13617
  }
13579
- }, [["__scopeId", "data-v-f8b79c74"]]);
13618
+ }, [["__scopeId", "data-v-239e0310"]]);
13580
13619
  //#endregion
13581
13620
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
13582
13621
  var _hoisted_1$25 = [
@@ -19679,6 +19718,7 @@ function createV2EditorRuntimeAdapter(options) {
19679
19718
  }
19680
19719
  const result = await host.dispatch(mapped);
19681
19720
  switch (result.status) {
19721
+ case "selected": return { status: "selected" };
19682
19722
  case "committed":
19683
19723
  invalidatePositionTokens();
19684
19724
  return {
@@ -22209,7 +22249,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22209
22249
  if (event.type === "mutation:committed") {
22210
22250
  const bulkDecisionEvent = toV2BulkDecisionEvent(documentId, event.trackedChangeBulkDecision);
22211
22251
  if (bulkDecisionEvent) proxy.$superdoc.emit("tracked-changes:bulk-decision", bulkDecisionEvent);
22212
- emitV2EditorUpdate();
22252
+ if (mutationCommittedEventChangedDocument(event)) emitV2EditorUpdate();
22213
22253
  }
22214
22254
  if (event.type !== "mutation:committed") return;
22215
22255
  if (event.origin === "history") v2ReviewWindowController.refreshCommittedWindow(`history-${event.direction}`);
@@ -23586,7 +23626,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23586
23626
  ], 46, _hoisted_1$17);
23587
23627
  };
23588
23628
  }
23589
- }, [["__scopeId", "data-v-9c1ff6d7"]]);
23629
+ }, [["__scopeId", "data-v-2c57eaa1"]]);
23590
23630
  //#endregion
23591
23631
  //#region src/core/create-app.js
23592
23632
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45286,7 +45326,7 @@ var SuperDoc = class extends import_eventemitter3.default {
45286
45326
  }
45287
45327
  this.userColorMap = /* @__PURE__ */ new Map();
45288
45328
  this.colorIndex = 0;
45289
- this.version = "2.28.0-next.16";
45329
+ this.version = "2.28.0-next.17";
45290
45330
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45291
45331
  this.superdocId = config.superdocId || v4();
45292
45332
  this.colors = this.config.colors ?? [];