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
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-DOnTWcx7.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.18";
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();
@@ -7937,17 +7940,6 @@ var useCommentsStore = defineStore("comments", () => {
7937
7940
  comment.resolvedByName = null;
7938
7941
  comment.trackedChangeDecision = null;
7939
7942
  };
7940
- const restoreResolvedMetadata = (comment) => {
7941
- if (!comment) return false;
7942
- const snapshot = trackedChangeResolutionSnapshots.get(comment);
7943
- if (!snapshot) return false;
7944
- comment.resolvedTime = snapshot.resolvedTime ?? Date.now();
7945
- comment.resolvedById = snapshot.resolvedById ?? null;
7946
- comment.resolvedByEmail = snapshot.resolvedByEmail ?? null;
7947
- comment.resolvedByName = snapshot.resolvedByName ?? null;
7948
- comment.trackedChangeDecision = snapshot.trackedChangeDecision ?? null;
7949
- return true;
7950
- };
7951
7943
  const getCommentEventPayload = (comment) => typeof comment?.getValues === "function" ? comment.getValues() : { ...comment };
7952
7944
  /**
7953
7945
  * Check if a comment originated from the document editor (or has no explicit source).
@@ -7962,63 +7954,14 @@ var useCommentsStore = defineStore("comments", () => {
7962
7954
  return source === DOCUMENT_EDITOR_SELECTION_SOURCE;
7963
7955
  };
7964
7956
  const isTrackedChangeThread = (comment) => Boolean(comment?.trackedChange) || Boolean(trackedChangeThreadParentIdForComment$1(comment));
7965
- const collectStandardCommentDocumentState = (editor) => {
7966
- const doc = editor?.state?.doc;
7967
- if (!doc || typeof doc.descendants !== "function") return null;
7968
- const liveMarkIds = /* @__PURE__ */ new Set();
7969
- const resolvedAnchorIds = /* @__PURE__ */ new Set();
7970
- doc.descendants((node) => {
7971
- node.marks?.filter((mark) => mark?.type?.name === "commentMark").forEach((mark) => {
7972
- [mark.attrs?.commentId, mark.attrs?.importedId].map((id) => normalizeCommentId(id)).filter(Boolean).forEach((id) => liveMarkIds.add(id));
7973
- });
7974
- const typeName = node.type?.name;
7975
- if (typeName !== "commentRangeStart" && typeName !== "commentRangeEnd") return;
7976
- const anchorId = normalizeCommentId(node.attrs?.["w:id"]);
7977
- if (anchorId) resolvedAnchorIds.add(anchorId);
7978
- });
7979
- return {
7980
- liveMarkIds,
7981
- resolvedAnchorIds
7982
- };
7983
- };
7984
- /**
7985
- * Fall back to a live editor when the caller has none (the store watchers).
7986
- * `editorCommentPositions` refreshes asynchronously, so a positions-based
7987
- * decision taken mid-undo/redo can act on STALE keys — e.g. clearing the
7988
- * resolved metadata that the redo restore just wrote back. The document
7989
- * itself is the source of truth; prefer it whenever an editor is reachable.
7990
- */
7991
- const getFallbackCommentsEditor = () => {
7992
- const docs = superdocStore.documents;
7993
- if (!Array.isArray(docs)) return null;
7994
- for (const doc of docs) {
7995
- const editor = typeof doc?.getEditor === "function" ? doc.getEditor() : null;
7996
- if (editor?.state?.doc) return editor;
7997
- }
7998
- return null;
7999
- };
8000
- const syncResolvedCommentsWithDocument = ({ editor } = {}) => {
7957
+ const syncResolvedCommentsWithDocument = () => {
8001
7958
  if (v2CommentsAdapter.value) return 0;
8002
- const effectiveEditor = editor ?? getFallbackCommentsEditor();
8003
- const documentState = collectStandardCommentDocumentState(effectiveEditor);
8004
7959
  const docPositions = editorCommentPositions.value || {};
8005
7960
  const activeKeys = new Set(Object.keys(docPositions));
8006
- if (!documentState && !activeKeys.size) return 0;
7961
+ if (!activeKeys.size) return 0;
8007
7962
  let changed = 0;
8008
7963
  commentsList.value.forEach((comment) => {
8009
7964
  if (!isEditorBackedComment(comment) || isTrackedChangeThread(comment)) return;
8010
- if (documentState) {
8011
- const aliasIds = getCommentAliasIds(comment);
8012
- const hasLiveMark = aliasIds.some((id) => documentState.liveMarkIds.has(id));
8013
- const hasResolvedAnchor = aliasIds.some((id) => documentState.resolvedAnchorIds.has(id));
8014
- if (hasLiveMark && comment.resolvedTime != null) {
8015
- clearResolvedMetadata(comment);
8016
- changed += 1;
8017
- return;
8018
- }
8019
- if (!hasLiveMark && hasResolvedAnchor && comment.resolvedTime == null && restoreResolvedMetadata(comment)) changed += 1;
8020
- return;
8021
- }
8022
7965
  const { key } = resolveCommentPositionEntry(comment);
8023
7966
  if (!key) return;
8024
7967
  if (activeKeys.has(String(key)) && comment.resolvedTime != null) {
@@ -8036,23 +7979,6 @@ var useCommentsStore = defineStore("comments", () => {
8036
7979
  syncResolvedCommentsWithDocument();
8037
7980
  }, { deep: false });
8038
7981
  /**
8039
- * Normalize a position object to a consistent { start, end } format.
8040
- * Handles different editor position schemas (start/end, pos/to, from/to).
8041
- *
8042
- * @param {Object | null | undefined} position The position object
8043
- * @returns {{ start: number, end: number } | null} The normalized range or null
8044
- */
8045
- const getCommentPositionRange = (position) => {
8046
- if (!position) return null;
8047
- const start = position.start ?? position.pos ?? position.from;
8048
- const end = position.end ?? position.to ?? start;
8049
- if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
8050
- return {
8051
- start,
8052
- end
8053
- };
8054
- };
8055
- /**
8056
7982
  * Get the editor position data for a comment.
8057
7983
  *
8058
7984
  * @param {Object | string} commentOrId The comment object or comment ID
@@ -8061,44 +7987,6 @@ var useCommentsStore = defineStore("comments", () => {
8061
7987
  const getCommentPosition = (commentOrId) => {
8062
7988
  return resolveCommentPositionEntry(commentOrId).entry ?? null;
8063
7989
  };
8064
- /**
8065
- * Get the text that a comment is anchored to in the document.
8066
- *
8067
- * @param {Object | string} commentOrId The comment object or comment ID
8068
- * @param {Object} [options] Options for text extraction
8069
- * @param {string} [options.separator=' '] Separator for textBetween when crossing nodes
8070
- * @param {boolean} [options.trim=true] Whether to trim whitespace from the result
8071
- * @returns {string | null} The anchored text or null if unavailable
8072
- */
8073
- const getCommentAnchoredText = (commentOrId, options = {}) => {
8074
- const comment = typeof commentOrId === "object" ? commentOrId : getComment(commentOrId);
8075
- if (!comment) return null;
8076
- const position = resolveCommentPositionEntry(commentOrId).entry ?? null;
8077
- const range = getCommentPositionRange(position);
8078
- if (!range) return null;
8079
- const docNode = (superdocStore.getDocument(comment.fileId)?.getEditor?.())?.state?.doc;
8080
- if (!docNode?.textBetween) return null;
8081
- const separator = options.separator ?? " ";
8082
- const text = docNode.textBetween(range.start, range.end, separator, separator);
8083
- return options.trim === false ? text : text?.trim();
8084
- };
8085
- /**
8086
- * Get both position and anchored text data for a comment.
8087
- *
8088
- * @param {Object | string} commentOrId The comment object or comment ID
8089
- * @param {Object} [options] Options passed to getCommentAnchoredText
8090
- * @param {string} [options.separator=' '] Separator for textBetween when crossing nodes
8091
- * @param {boolean} [options.trim=true] Whether to trim whitespace from the result
8092
- * @returns {{ position: Object, anchoredText: string | null } | null} The anchor data or null
8093
- */
8094
- const getCommentAnchorData = (commentOrId, options = {}) => {
8095
- const position = getCommentPosition(commentOrId);
8096
- if (!position) return null;
8097
- return {
8098
- position,
8099
- anchoredText: getCommentAnchoredText(commentOrId, options)
8100
- };
8101
- };
8102
7990
  const isThreadVisible = (comment) => {
8103
7991
  if (!isViewingMode.value) return true;
8104
7992
  const parent = getThreadParent(comment);
@@ -8688,9 +8576,12 @@ var useCommentsStore = defineStore("comments", () => {
8688
8576
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
8689
8577
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8690
8578
  if (v2Adapter && !comment.trackedChange) {
8691
- const submittedPendingComment = pendingComment.value;
8579
+ const pendingDraft = pendingComment.value;
8580
+ const draftRevision = commentDraftRevision;
8581
+ const draftActiveComment = activeComment.value;
8582
+ const draftActiveInstance = activeFloatingCommentInstanceId.value;
8692
8583
  const submittedPendingRequest = pendingCommentRequest;
8693
- const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8584
+ const text = normalizeV2CommentDraftText(pendingDraft ? currentCommentText.value : comment.commentText);
8694
8585
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8695
8586
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
8696
8587
  const parentCommentId = comment.parentCommentId ? String(comment.parentCommentId) : pendingComment.value ? null : null;
@@ -8726,6 +8617,7 @@ var useCommentsStore = defineStore("comments", () => {
8726
8617
  });
8727
8618
  return outcome;
8728
8619
  }
8620
+ const ownsActiveDraftBeforeReconcile = activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance;
8729
8621
  const reconciled = reconcileCommentsFromV2({
8730
8622
  superdoc,
8731
8623
  adapter: v2Adapter,
@@ -8737,14 +8629,17 @@ var useCommentsStore = defineStore("comments", () => {
8737
8629
  reconciled,
8738
8630
  documentId: v2Adapter.documentId
8739
8631
  });
8740
- const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8632
+ const createdId = created?.commentId ?? null;
8633
+ const createdIsActive = createdId !== null && activeComment.value === createdId;
8634
+ const createdInstance = createdIsActive ? activeFloatingCommentInstanceId.value : null;
8741
8635
  const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8742
- if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8636
+ const reconciliationClearedActiveDraft = ownsActiveDraftBeforeReconcile && activeComment.value === null && activeFloatingCommentInstanceId.value === null;
8637
+ const ownsPendingDraft = pendingDraft !== null && pendingComment.value === pendingDraft && commentDraftRevision === draftRevision && (createdIsActive || reconciliationClearedActiveDraft || activeComment.value === draftActiveComment && activeFloatingCommentInstanceId.value === draftActiveInstance);
8638
+ if (ownsPendingDraft) if (ownsSubmittedRequest) removePendingComment(superdoc);
8743
8639
  else resetPendingCommentState(superdoc, false);
8744
- const createdId = created?.commentId ?? null;
8745
- if (hadPendingComment && ownsSubmittedRequest && createdId) {
8640
+ if (ownsPendingDraft && ownsSubmittedRequest && createdId) {
8746
8641
  setActiveComment(superdoc, createdId);
8747
- setActiveFloatingCommentInstance(createdId);
8642
+ setActiveFloatingCommentInstance(createdInstance ?? createdId);
8748
8643
  }
8749
8644
  if (broadcastChanges) superdoc.emit("comments-update", {
8750
8645
  type: COMMENT_EVENTS.ADD,
@@ -11009,8 +10904,6 @@ var useCommentsStore = defineStore("comments", () => {
11009
10904
  getTrackedChangeThread,
11010
10905
  getCommentPositionKey,
11011
10906
  getCommentPosition,
11012
- getCommentAnchoredText,
11013
- getCommentAnchorData,
11014
10907
  resolveCommentPositionEntry,
11015
10908
  getCommentDocumentId,
11016
10909
  belongsToDocument,
@@ -12383,6 +12276,7 @@ var _hoisted_53 = { class: "reply-input-wrapper" };
12383
12276
  var _hoisted_54 = { class: "reply-actions" };
12384
12277
  var _hoisted_55 = ["disabled", "data-disabled-reason"];
12385
12278
  var commentEditSessions = /* @__PURE__ */ new WeakMap();
12279
+ var commentReplySessions = /* @__PURE__ */ new WeakMap();
12386
12280
  var _sfc_main$33 = {
12387
12281
  __name: "CommentDialog",
12388
12282
  props: {
@@ -12432,9 +12326,13 @@ var _sfc_main$33 = {
12432
12326
  const superdocStore = useSuperdocStore();
12433
12327
  const commentsStore = useCommentsStore();
12434
12328
  const editSessionOwner = {};
12329
+ const replySessionOwner = {};
12435
12330
  const retireOwnEditSession = () => {
12436
12331
  if (commentEditSessions.get(commentsStore)?.owner === editSessionOwner) commentEditSessions.delete(commentsStore);
12437
12332
  };
12333
+ const retireOwnReplySession = () => {
12334
+ if (commentReplySessions.get(commentsStore)?.owner === replySessionOwner) commentReplySessions.delete(commentsStore);
12335
+ };
12438
12336
  const { addComment, cancelComment, deleteComment, getCommentAliasIds, removePendingComment, getCommentDocumentId, requestInstantSidebarAlignment, resolveCommentPositionEntry, clearInstantSidebarAlignment, setActiveFloatingCommentInstance } = commentsStore;
12439
12337
  const { suppressInternalExternal, getConfig, activeComment, activeFloatingCommentInstanceId, floatingCommentsOffset, pendingComment, currentCommentText, currentCommentMentions, isDebugging, editingCommentId, editorCommentPositions, isCommentHighlighted } = storeToRefs(commentsStore);
12440
12338
  const isInternal = require__plugin_vue_export_helper.ref(true);
@@ -12635,6 +12533,11 @@ var _sfc_main$33 = {
12635
12533
  const isReplying = require__plugin_vue_export_helper.ref(false);
12636
12534
  const isSubmittingReply = require__plugin_vue_export_helper.ref(false);
12637
12535
  const isSubmittingNewComment = require__plugin_vue_export_helper.ref(false);
12536
+ let replyDraftRevision = 0;
12537
+ require__plugin_vue_export_helper.watch([currentCommentText, currentCommentMentions], () => replyDraftRevision++, {
12538
+ deep: true,
12539
+ flush: "sync"
12540
+ });
12638
12541
  const commentSaveFailure = require__plugin_vue_export_helper.ref("");
12639
12542
  const commentSaveFailureMessage = (outcome, hasDraft = true) => {
12640
12543
  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 +12548,7 @@ var _sfc_main$33 = {
12645
12548
  ok: false,
12646
12549
  reason: v2WriteCapability.value?.reason ?? "v2-write-unavailable"
12647
12550
  };
12551
+ commentReplySessions.set(commentsStore, { owner: replySessionOwner });
12648
12552
  commentSaveFailure.value = "";
12649
12553
  isReplying.value = true;
12650
12554
  require__plugin_vue_export_helper.nextTick(() => {
@@ -12883,6 +12787,15 @@ var _sfc_main$33 = {
12883
12787
  commentsStore.setActiveComment(proxy.$superdoc, activeComment.value);
12884
12788
  isCommentHighlighted.value = false;
12885
12789
  };
12790
+ const captureCommentEditorOwner = () => {
12791
+ const editor = proxy.$superdoc.activeEditor;
12792
+ const adapter = editor.v2Comments;
12793
+ const document = editor.doc;
12794
+ return {
12795
+ adapter,
12796
+ isCurrent: () => proxy.$superdoc.activeEditor === editor && editor.v2Comments === adapter && editor.doc === document
12797
+ };
12798
+ };
12886
12799
  const handleAddComment = async () => {
12887
12800
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
12888
12801
  if (isV2WriteDisabled.value) return {
@@ -12897,6 +12810,13 @@ var _sfc_main$33 = {
12897
12810
  isSubmittingReply.value = true;
12898
12811
  commentSaveFailure.value = "";
12899
12812
  try {
12813
+ const session = commentReplySessions.get(commentsStore);
12814
+ const draftRevision = replyDraftRevision;
12815
+ const editorOwner = captureCommentEditorOwner();
12816
+ const threadId = props.comment.commentId;
12817
+ const fileId = props.comment.fileId;
12818
+ const pendingDraft = pendingComment.value;
12819
+ const edit = editingCommentId.value;
12900
12820
  const parentCommentId = getV2ExistingReplyParentId(props.comment);
12901
12821
  const trackedChangeTarget = getV2TrackedChangeCommentTarget(props.comment);
12902
12822
  const outcome = await commentsStore.replyCommentV2({
@@ -12911,6 +12831,8 @@ var _sfc_main$33 = {
12911
12831
  require__plugin_vue_export_helper.nextTick(() => emit("resize"));
12912
12832
  return outcome;
12913
12833
  }
12834
+ 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;
12835
+ retireOwnReplySession();
12914
12836
  isReplying.value = false;
12915
12837
  currentCommentText.value = "";
12916
12838
  currentCommentMentions.value = [];
@@ -13257,10 +13179,8 @@ var _sfc_main$33 = {
13257
13179
  const session = commentEditSessions.get(commentsStore);
13258
13180
  const submission = Symbol("comment-edit-submission");
13259
13181
  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;
13182
+ const editorOwner = captureCommentEditorOwner();
13183
+ const documentId = editorOwner.adapter.documentId;
13264
13184
  const thread = props.comment;
13265
13185
  const draft = currentCommentText.value;
13266
13186
  const outcome = await commentsStore.editCommentV2({
@@ -13268,7 +13188,7 @@ var _sfc_main$33 = {
13268
13188
  commentId: comment.commentId,
13269
13189
  text: draft
13270
13190
  });
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;
13191
+ 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
13192
  if (!outcome?.ok) {
13273
13193
  commentSaveFailure.value = commentSaveFailureMessage(outcome);
13274
13194
  return outcome;
@@ -13307,6 +13227,7 @@ var _sfc_main$33 = {
13307
13227
  const handleCancel = (comment) => {
13308
13228
  commentSaveFailure.value = "";
13309
13229
  retireOwnEditSession();
13230
+ retireOwnReplySession();
13310
13231
  editingCommentId.value = null;
13311
13232
  isReplying.value = false;
13312
13233
  cancelComment(proxy.$superdoc);
@@ -13333,6 +13254,7 @@ var _sfc_main$33 = {
13333
13254
  });
13334
13255
  require__plugin_vue_export_helper.onBeforeUnmount(() => {
13335
13256
  retireOwnEditSession();
13257
+ retireOwnReplySession();
13336
13258
  proxy.$superdoc?.off?.("active-editor-change", refreshActiveEditor);
13337
13259
  });
13338
13260
  require__plugin_vue_export_helper.watch(showInputSection, (isVisible) => {
@@ -13584,7 +13506,7 @@ var _sfc_main$33 = {
13584
13506
  };
13585
13507
  }
13586
13508
  };
13587
- var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-f8b79c74"]]);
13509
+ var CommentDialog_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main$33, [["__scopeId", "data-v-239e0310"]]);
13588
13510
  //#endregion
13589
13511
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
13590
13512
  var _hoisted_1$25 = [
@@ -19711,6 +19633,7 @@ function createV2EditorRuntimeAdapter(options) {
19711
19633
  }
19712
19634
  const result = await host.dispatch(mapped);
19713
19635
  switch (result.status) {
19636
+ case "selected": return { status: "selected" };
19714
19637
  case "committed":
19715
19638
  invalidatePositionTokens();
19716
19639
  return {
@@ -22249,7 +22172,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22249
22172
  if (event.type === "mutation:committed") {
22250
22173
  const bulkDecisionEvent = toV2BulkDecisionEvent(documentId, event.trackedChangeBulkDecision);
22251
22174
  if (bulkDecisionEvent) proxy.$superdoc.emit("tracked-changes:bulk-decision", bulkDecisionEvent);
22252
- emitV2EditorUpdate();
22175
+ if (require_create_super_doc_ui.mutationCommittedEventChangedDocument(event)) emitV2EditorUpdate();
22253
22176
  }
22254
22177
  if (event.type !== "mutation:committed") return;
22255
22178
  if (event.origin === "history") v2ReviewWindowController.refreshCommittedWindow(`history-${event.direction}`);
@@ -23626,7 +23549,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23626
23549
  ], 46, _hoisted_1$17);
23627
23550
  };
23628
23551
  }
23629
- }, [["__scopeId", "data-v-9c1ff6d7"]]);
23552
+ }, [["__scopeId", "data-v-2c57eaa1"]]);
23630
23553
  //#endregion
23631
23554
  //#region src/core/create-app.js
23632
23555
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45358,7 +45281,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45358
45281
  }
45359
45282
  this.userColorMap = /* @__PURE__ */ new Map();
45360
45283
  this.colorIndex = 0;
45361
- this.version = "2.28.0-next.16";
45284
+ this.version = "2.28.0-next.18";
45362
45285
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45363
45286
  this.superdocId = config.superdocId || require_uuid.v4();
45364
45287
  this.colors = this.config.colors ?? [];