superdoc 2.4.0-next.16 → 2.4.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.
@@ -3,7 +3,7 @@ import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
3
3
  import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
4
4
  import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
5
5
  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";
6
- import { a as createV2ReviewMutationReconciler, i as isV2EditableTextMutationEvent, o as getV2TrackedChangeMutationImpact, s as DOM_CLASS_NAMES, t as createSuperDocUI } from "./chunks/create-super-doc-ui-BRBwfV-s.es.js";
6
+ import { a as getV2TrackedChangeMutationImpact, i as createV2ReviewMutationReconciler, o as DOM_CLASS_NAMES, t as createSuperDocUI } from "./chunks/create-super-doc-ui-BbNbi0cj.es.js";
7
7
  import { t as _plugin_vue_export_helper_default } from "./chunks/_plugin-vue_export-helper-BOaGB7Aw.es.js";
8
8
  import { t as PDF_TO_CSS_UNITS } from "./chunks/constants-B6VBlmKp.es.js";
9
9
  import * as Vue from "vue";
@@ -7761,6 +7761,7 @@ var useCommentsStore = defineStore("comments", () => {
7761
7761
  syncResolvedCommentsWithDocument();
7762
7762
  });
7763
7763
  watch(commentsList, () => {
7764
+ canonicalizeActiveCommentAlias();
7764
7765
  syncResolvedCommentsWithDocument();
7765
7766
  }, { deep: false });
7766
7767
  /**
@@ -8560,6 +8561,61 @@ var useCommentsStore = defineStore("comments", () => {
8560
8561
  syncCommentsToClients(superdoc, event);
8561
8562
  return Promise.resolve({ ok: true });
8562
8563
  };
8564
+ const applyV2ThreadLifecycleReceipt = ({ superdoc, documentId, lifecycle } = {}) => {
8565
+ const commentId = normalizeCommentId(lifecycle?.commentId);
8566
+ const status = lifecycle?.status;
8567
+ if (!commentId || status !== "open" && status !== "resolved") return null;
8568
+ const normalizedDocumentId = normalizeCommentId(documentId);
8569
+ const rows = commentsList.value.filter((comment) => {
8570
+ if (!comment || comment.trackedChange === true || isV2SyntheticTrackedChangeRow(comment)) return false;
8571
+ const rowDocumentId = normalizeCommentId(comment.fileId);
8572
+ return normalizedDocumentId == null || rowDocumentId == null || rowDocumentId === normalizedDocumentId;
8573
+ });
8574
+ const byAlias = /* @__PURE__ */ new Map();
8575
+ const childrenByParentAlias = /* @__PURE__ */ new Map();
8576
+ for (const row of rows) {
8577
+ for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(Boolean)) if (!byAlias.has(alias)) byAlias.set(alias, row);
8578
+ const parentId = normalizeCommentId(row.parentCommentId);
8579
+ if (parentId) {
8580
+ const children = childrenByParentAlias.get(parentId) ?? [];
8581
+ children.push(row);
8582
+ childrenByParentAlias.set(parentId, children);
8583
+ }
8584
+ }
8585
+ let root = byAlias.get(commentId) ?? null;
8586
+ const seenParents = /* @__PURE__ */ new Set();
8587
+ while (root?.parentCommentId != null) {
8588
+ const parentId = normalizeCommentId(root.parentCommentId);
8589
+ if (!parentId || seenParents.has(parentId)) break;
8590
+ seenParents.add(parentId);
8591
+ const parent = byAlias.get(parentId);
8592
+ if (!parent) break;
8593
+ root = parent;
8594
+ }
8595
+ if (!root) return null;
8596
+ const family = [];
8597
+ const queue = [root];
8598
+ const visited = /* @__PURE__ */ new Set();
8599
+ while (queue.length > 0) {
8600
+ const row = queue.shift();
8601
+ if (!row || visited.has(row)) continue;
8602
+ visited.add(row);
8603
+ family.push(row);
8604
+ for (const alias of [row.commentId, row.importedId].map(normalizeCommentId).filter(Boolean)) queue.push(...childrenByParentAlias.get(alias) ?? []);
8605
+ }
8606
+ const isResolved = status === "resolved";
8607
+ const resolvedAt = Date.now();
8608
+ for (const row of family) {
8609
+ row.resolvedTime = isResolved ? row.resolvedTime ?? resolvedAt : null;
8610
+ row.resolvedById = isResolved ? superdoc?.user?.id ?? null : null;
8611
+ row.resolvedByEmail = isResolved ? superdoc?.user?.email ?? null : null;
8612
+ row.resolvedByName = isResolved ? superdoc?.user?.name ?? null : null;
8613
+ }
8614
+ return {
8615
+ added: null,
8616
+ lifecycleUpdated: family.length
8617
+ };
8618
+ };
8563
8619
  const runV2CommentMutation = async ({ superdoc, adapter, fileId, operation, eventType, rejectionFallbackReason, rejectionEventExtras = {}, validateOutcome, successEventBuilder }) => {
8564
8620
  let outcome;
8565
8621
  try {
@@ -8609,11 +8665,17 @@ var useCommentsStore = defineStore("comments", () => {
8609
8665
  superdoc?.emit?.("comments-update", rejectedEvent);
8610
8666
  return failedOutcome;
8611
8667
  }
8612
- const reconciled = reconcileCommentsFromV2({
8668
+ const documentId = adapter.documentId ?? fileId;
8669
+ const reconciled = applyV2ThreadLifecycleReceipt({
8670
+ superdoc,
8671
+ documentId,
8672
+ lifecycle: outcome.threadLifecycle
8673
+ }) ?? reconcileCommentsFromV2({
8613
8674
  superdoc,
8614
8675
  adapter,
8615
- documentId: adapter.documentId ?? fileId,
8616
- items: outcome.items ?? []
8676
+ documentId,
8677
+ items: outcome.items ?? [],
8678
+ pruneStale: outcome.complete !== false
8617
8679
  });
8618
8680
  const successEvent = successEventBuilder?.({
8619
8681
  outcome,
@@ -8623,7 +8685,11 @@ var useCommentsStore = defineStore("comments", () => {
8623
8685
  return {
8624
8686
  ok: true,
8625
8687
  items: outcome.items ?? [],
8626
- reconciled
8688
+ reconciled,
8689
+ ...outcome.complete === false ? { complete: false } : {},
8690
+ ...outcome.visibleWindowSource != null ? { visibleWindowSource: outcome.visibleWindowSource } : {},
8691
+ ...outcome.threadLifecycle != null ? { threadLifecycle: outcome.threadLifecycle } : {},
8692
+ ...outcome.mutationPath != null ? { mutationPath: outcome.mutationPath } : {}
8627
8693
  };
8628
8694
  };
8629
8695
  const mapV2OutcomeCommentInputs = ({ outcome, adapter, fileId }) => {
@@ -8639,6 +8705,23 @@ var useCommentsStore = defineStore("comments", () => {
8639
8705
  const commentInputParentId = (input) => input?.parentCommentId != null ? String(input.parentCommentId) : null;
8640
8706
  const validateV2ThreadLifecycleRefresh = ({ outcome, adapter, fileId, commentId, expectedResolved, operation }) => {
8641
8707
  const id = commentId != null ? String(commentId) : null;
8708
+ const receiptLifecycle = outcome?.threadLifecycle;
8709
+ if (receiptLifecycle != null) {
8710
+ const observedId = normalizeCommentId(receiptLifecycle.commentId);
8711
+ const observedResolved = receiptLifecycle.status === "resolved";
8712
+ if (observedId === id && observedResolved === expectedResolved) return { ok: true };
8713
+ return {
8714
+ ok: false,
8715
+ reason: `v2-${operation}-receipt-lifecycle-mismatch`,
8716
+ detail: {
8717
+ expected: {
8718
+ commentId: id,
8719
+ status: expectedResolved ? "resolved" : "open"
8720
+ },
8721
+ observed: receiptLifecycle
8722
+ }
8723
+ };
8724
+ }
8642
8725
  const inputs = mapV2OutcomeCommentInputs({
8643
8726
  outcome,
8644
8727
  adapter,
@@ -8784,8 +8867,8 @@ var useCommentsStore = defineStore("comments", () => {
8784
8867
  * Resolve an existing comment through the v2 adapter.
8785
8868
  *
8786
8869
  * Plan §4.3 rules:
8787
- * - successful resolve refreshes from v2 list and clears the active
8788
- * comment / dialog target if the resolved comment was active
8870
+ * - successful resolve applies the committed lifecycle receipt to the
8871
+ * hydrated thread and clears the active comment / dialog target
8789
8872
  * - rejection leaves the row active, emits a rejected event
8790
8873
  * - active state must never reference a deleted/missing anchor — the
8791
8874
  * reconciler is already family-scoped (see TCS 001 §5)
@@ -8843,18 +8926,19 @@ var useCommentsStore = defineStore("comments", () => {
8843
8926
  *
8844
8927
  * Symmetric inverse of {@link resolveCommentV2}. The adapter routes the
8845
8928
  * reopen through `activeEditor.doc.comments.patch({ status: 'active' })`,
8846
- * which removes the resolved anchors and restores the live comment mark,
8847
- * then refreshes from the v2 comment list. Rules:
8929
+ * which removes the resolved anchors and restores the live comment mark.
8930
+ * The successful receipt updates the hydrated thread immediately while
8931
+ * normal review hydration remains the eventual reconciliation path. Rules:
8848
8932
  * - the store owns mutation gating (via the adapter capability state),
8849
- * adapter identity stamping, refresh reconciliation, and event emission
8933
+ * adapter identity stamping, local lifecycle projection, and event emission
8850
8934
  * - there is no dedicated REOPENED event in the comment event enum, so a
8851
- * successful reopen emits an UPDATE event with the refreshed (now open)
8935
+ * successful reopen emits an UPDATE event with the now-open
8852
8936
  * comment payload
8853
8937
  * - rejection is non-mutating and emits the same rejected-event shape as
8854
8938
  * the other v2 comment mutations; the row stays resolved so the user can
8855
8939
  * retry
8856
- * - body / replies / anchor identity are preserved by the reconciler; we
8857
- * only confirm the open state after the refreshed list lands
8940
+ * - body / replies / anchor identity are preserved; only lifecycle metadata
8941
+ * changes on the hydrated thread
8858
8942
  */
8859
8943
  const reopenCommentV2 = async ({ superdoc, commentId } = {}) => {
8860
8944
  if (commentsAreReadOnly()) return readOnlyMutationOutcome();
@@ -9019,7 +9103,7 @@ var useCommentsStore = defineStore("comments", () => {
9019
9103
  trackedItems: preparedParams.length
9020
9104
  };
9021
9105
  });
9022
- const hydrateCommentsFromV2 = async ({ superdoc, adapter, documentId, trackedChangesListMode = "all", isCurrent, signal, hydrationGeneration } = {}) => withInteractionSpan("store.comments.hydrateFromV2", "comments-list", { documentId: documentId ?? null }, async () => {
9106
+ const hydrateCommentsFromV2 = async ({ superdoc, adapter, documentId, trackedChangesListMode = "all", commentIds, isCurrent, signal, hydrationGeneration } = {}) => withInteractionSpan("store.comments.hydrateFromV2", "comments-list", { documentId: documentId ?? null }, async () => {
9023
9107
  const effectiveAdapter = adapter ?? getV2CommentsAdapter(superdoc);
9024
9108
  const visibleWindow = trackedChangesListMode === "visible-window";
9025
9109
  const read = visibleWindow ? effectiveAdapter?.selectVisibleReviewComments : effectiveAdapter?.refresh;
@@ -9041,6 +9125,7 @@ var useCommentsStore = defineStore("comments", () => {
9041
9125
  let result;
9042
9126
  try {
9043
9127
  const refreshOptions = {};
9128
+ if (visibleWindow && Array.isArray(commentIds)) refreshOptions.targetIds = commentIds;
9044
9129
  if (signal) refreshOptions.signal = signal;
9045
9130
  if (typeof hydrationGeneration === "number") refreshOptions.hydrationGeneration = hydrationGeneration;
9046
9131
  result = Object.keys(refreshOptions).length > 0 ? await read.call(effectiveAdapter, refreshOptions) : await read.call(effectiveAdapter);
@@ -9071,7 +9156,7 @@ var useCommentsStore = defineStore("comments", () => {
9071
9156
  adapter: effectiveAdapter,
9072
9157
  documentId,
9073
9158
  items: result.items ?? [],
9074
- pruneStale: !visibleWindow,
9159
+ pruneStale: !visibleWindow || Array.isArray(commentIds) && (!Array.isArray(result.unresolvedIds) || result.unresolvedIds.length === 0),
9075
9160
  hydrationGeneration
9076
9161
  });
9077
9162
  return {
@@ -9304,6 +9389,27 @@ var useCommentsStore = defineStore("comments", () => {
9304
9389
  storySnapshots
9305
9390
  };
9306
9391
  };
9392
+ const reconcileAuthoritativeV2TrackedChangeSidebar = ({ superdoc, editor, documentId, refreshReason = "tracked-change-sidebar-authoritative" } = {}) => {
9393
+ const adapter = getV2TrackedChangesAdapter(superdoc) ?? editor?.v2TrackedChanges ?? null;
9394
+ if (!adapter || typeof adapter.listTrackedChanges !== "function" || typeof adapter.mapV2TrackedChangeToCommentParams !== "function") return false;
9395
+ const effectiveDocumentId = documentId ?? adapter.documentId ?? editor?.documentId ?? editor?.options?.documentId ?? superdoc?.activeEditor?.documentId ?? superdoc?.activeEditor?.options?.documentId ?? null;
9396
+ if (effectiveDocumentId == null) return false;
9397
+ const normalizedDocumentId = String(effectiveDocumentId);
9398
+ hydrateTrackedChangesFromV2({
9399
+ superdoc,
9400
+ adapter,
9401
+ documentId: normalizedDocumentId,
9402
+ trackedChangesListMode: "background-reconcile",
9403
+ refreshReason,
9404
+ blocking: false,
9405
+ isCurrent: () => {
9406
+ const activeEditor = superdoc?.activeEditor ?? null;
9407
+ const activeDocumentId = activeEditor?.documentId ?? activeEditor?.options?.documentId ?? null;
9408
+ return activeDocumentId == null || String(activeDocumentId) === normalizedDocumentId;
9409
+ }
9410
+ });
9411
+ return true;
9412
+ };
9307
9413
  /**
9308
9414
  * Bootstrap tracked-change comment threads after a DOCX import finishes.
9309
9415
  *
@@ -9341,6 +9447,12 @@ var useCommentsStore = defineStore("comments", () => {
9341
9447
  editor,
9342
9448
  structuralChanges: captured.structuralChanges
9343
9449
  });
9450
+ reconcileAuthoritativeV2TrackedChangeSidebar({
9451
+ superdoc,
9452
+ editor,
9453
+ documentId: editor?.options?.documentId,
9454
+ refreshReason: "import-bootstrap-authoritative"
9455
+ });
9344
9456
  return true;
9345
9457
  };
9346
9458
  const isCurrentImportedTrackedChangeBootstrap = (task) => {
@@ -10326,7 +10438,8 @@ var useCommentsStore = defineStore("comments", () => {
10326
10438
  lateResultDropped: true
10327
10439
  };
10328
10440
  if (!result?.ok) return result;
10329
- const pruneStale = !(trackedChangesListMode === "startup-page" || trackedChangesListMode === "interaction-prime" || trackedChangesListMode === "visible-window") && result.visibleWindowSource == null && result.complete === true && result.sourceCoverageComplete === true;
10441
+ const partialListMode = trackedChangesListMode === "startup-page" || trackedChangesListMode === "interaction-prime" || trackedChangesListMode === "visible-window";
10442
+ const pruneStale = trackedChangesListMode === "visible-window" && Array.isArray(targetIds) && (!Array.isArray(result.visibleTrackedChangeFailedIds) || result.visibleTrackedChangeFailedIds.length === 0) || !partialListMode && result.visibleWindowSource == null && result.complete === true && result.sourceCoverageComplete === true;
10330
10443
  if (signal?.aborted || trackedChangeSyncGeneration(effectiveAdapter) !== syncGeneration) return {
10331
10444
  ok: false,
10332
10445
  reason: "review-hydration-superseded",
@@ -10730,6 +10843,12 @@ var useCommentsStore = defineStore("comments", () => {
10730
10843
  broadcastChanges,
10731
10844
  structuralChanges: captured.structuralChanges
10732
10845
  });
10846
+ reconcileAuthoritativeV2TrackedChangeSidebar({
10847
+ superdoc,
10848
+ editor,
10849
+ documentId: activeDocumentId,
10850
+ refreshReason: "sync-authoritative"
10851
+ });
10733
10852
  };
10734
10853
  /**
10735
10854
  * Surface decidable whole-table structural tracked changes (table insert /
@@ -11200,6 +11319,16 @@ var useCommentsStore = defineStore("comments", () => {
11200
11319
  const syncActiveFloatingInstanceWithComment = (commentId) => {
11201
11320
  if (!doesFloatingInstanceBelongToComment(activeFloatingCommentInstanceId.value, commentId)) setActiveFloatingCommentInstance(null);
11202
11321
  };
11322
+ function canonicalizeActiveCommentAlias() {
11323
+ const activeId = normalizeCommentId(activeComment.value);
11324
+ if (!activeId) return false;
11325
+ const comment = getComment(activeId);
11326
+ const canonicalId = normalizeCommentId(comment?.commentId);
11327
+ if (!canonicalId || canonicalId === activeId) return false;
11328
+ activeComment.value = canonicalId;
11329
+ syncActiveFloatingInstanceWithComment(canonicalId);
11330
+ return true;
11331
+ }
11203
11332
  const setViewingVisibility = ({ documentMode, commentsVisible, trackChangesVisible } = {}) => {
11204
11333
  if (typeof documentMode === "string") viewingVisibility.documentMode = documentMode;
11205
11334
  if (typeof commentsVisible === "boolean") viewingVisibility.commentsVisible = commentsVisible;
@@ -13896,6 +14025,12 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13896
14025
  setup(__props) {
13897
14026
  const ESTIMATED_HEIGHT = 110;
13898
14027
  const OBSERVER_MARGIN = 600;
14028
+ const SCROLL_OWNER_OVERFLOW_VALUES = /* @__PURE__ */ new Set([
14029
+ "auto",
14030
+ "scroll",
14031
+ "hidden",
14032
+ "clip"
14033
+ ]);
13899
14034
  const resolveCollisions = (positions, activeIndex, gap) => {
13900
14035
  if (activeIndex >= 0) {
13901
14036
  positions[activeIndex].top = positions[activeIndex].anchorTop;
@@ -14300,6 +14435,8 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14300
14435
  let activeLayoutContinuityFrame = null;
14301
14436
  let directDecisionContinuity = null;
14302
14437
  let directDecisionSourceId = null;
14438
+ let ownerScrollContinuityResetFrame = null;
14439
+ const ownerScrollTargets = /* @__PURE__ */ new Set();
14303
14440
  const releaseDirectDecisionContinuity = () => {
14304
14441
  directDecisionContinuity = null;
14305
14442
  directDecisionSourceId = null;
@@ -14363,6 +14500,36 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14363
14500
  }
14364
14501
  setInstantLayoutTransitionsDisabled(false);
14365
14502
  };
14503
+ const releaseDecisionContinuityForOwnerScroll = () => {
14504
+ if (!directDecisionContinuity && !sidebarContinuityAnchor) return;
14505
+ releaseDirectDecisionContinuity();
14506
+ clearSidebarContinuityAnchor();
14507
+ setInstantLayoutTransitionsDisabled(true);
14508
+ sidebarOffsetY.value = 0;
14509
+ if (ownerScrollContinuityResetFrame != null) cancelAnimationFrame(ownerScrollContinuityResetFrame);
14510
+ ownerScrollContinuityResetFrame = requestAnimationFrame(() => {
14511
+ ownerScrollContinuityResetFrame = null;
14512
+ if (!directDecisionContinuity && !sidebarContinuityAnchor) setInstantLayoutTransitionsDisabled(false);
14513
+ });
14514
+ };
14515
+ const handleOwnerScroll = () => {
14516
+ releaseDecisionContinuityForOwnerScroll();
14517
+ refreshViewportWindow();
14518
+ };
14519
+ const registerOwnerScrollListeners = () => {
14520
+ const addTarget = (target) => {
14521
+ if (!target?.addEventListener || ownerScrollTargets.has(target)) return;
14522
+ target.addEventListener("scroll", handleOwnerScroll, { passive: true });
14523
+ ownerScrollTargets.add(target);
14524
+ };
14525
+ addTarget(props.parent);
14526
+ for (let ancestor = floatingCommentsContainer.value?.parentElement; ancestor; ancestor = ancestor.parentElement) if (SCROLL_OWNER_OVERFLOW_VALUES.has(window.getComputedStyle(ancestor).overflowY)) addTarget(ancestor);
14527
+ addTarget(window);
14528
+ };
14529
+ const unregisterOwnerScrollListeners = () => {
14530
+ for (const target of ownerScrollTargets) target.removeEventListener?.("scroll", handleOwnerScroll);
14531
+ ownerScrollTargets.clear();
14532
+ };
14366
14533
  const scheduleSidebarContinuityAlignment = () => {
14367
14534
  if (!sidebarContinuityAnchor || continuityAlignmentScheduled) return;
14368
14535
  continuityAlignmentScheduled = true;
@@ -14615,7 +14782,7 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14615
14782
  });
14616
14783
  onMounted(() => {
14617
14784
  setupObserver();
14618
- props.parent?.addEventListener?.("scroll", refreshViewportWindow, { passive: true });
14785
+ registerOwnerScrollListeners();
14619
14786
  window.addEventListener("resize", refreshViewportWindow, { passive: true });
14620
14787
  document.addEventListener("pointerdown", releaseDirectDecisionContinuityForUnrelatedPointer, true);
14621
14788
  nextTick(observePlaceholders);
@@ -14629,7 +14796,11 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14629
14796
  cancelAnimationFrame(activeLayoutContinuityFrame);
14630
14797
  activeLayoutContinuityFrame = null;
14631
14798
  }
14632
- props.parent?.removeEventListener?.("scroll", refreshViewportWindow);
14799
+ if (ownerScrollContinuityResetFrame != null) {
14800
+ cancelAnimationFrame(ownerScrollContinuityResetFrame);
14801
+ ownerScrollContinuityResetFrame = null;
14802
+ }
14803
+ unregisterOwnerScrollListeners();
14633
14804
  window.removeEventListener("resize", refreshViewportWindow);
14634
14805
  document.removeEventListener("pointerdown", releaseDirectDecisionContinuityForUnrelatedPointer, true);
14635
14806
  if (viewportFrame != null) {
@@ -14697,7 +14868,7 @@ var FloatingComments_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14697
14868
  }), 128))], 4)], 36);
14698
14869
  };
14699
14870
  }
14700
- }, [["__scopeId", "data-v-a0a841ce"]]);
14871
+ }, [["__scopeId", "data-v-d8d03209"]]);
14701
14872
  //#endregion
14702
14873
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue
14703
14874
  var _hoisted_1$22 = {
@@ -15373,6 +15544,19 @@ var VALID_COMMENTS_DISPLAY_MODES = /* @__PURE__ */ new Set([
15373
15544
  "inline"
15374
15545
  ]);
15375
15546
  /**
15547
+ * Whether a context-menu event landed inside the tracked-change carrier that
15548
+ * is already visually active. The review visual owner maintains this marker,
15549
+ * so the right-click path can stay synchronous and avoid a catalog lookup or
15550
+ * document-wide DOM query.
15551
+ *
15552
+ * @param {EventTarget | null} target
15553
+ * @returns {boolean}
15554
+ */
15555
+ function isActiveTrackedChangeContextMenuTarget(target) {
15556
+ const element = target;
15557
+ return typeof element?.closest === "function" && element.closest(".track-change-focused") != null;
15558
+ }
15559
+ /**
15376
15560
  * Normalize adaptive comments UI policy fields.
15377
15561
  *
15378
15562
  * @param {false | Record<string, unknown> | undefined} commentsConfig
@@ -15808,74 +15992,6 @@ function resolveV2ReviewTargetCommentId(target, getComment) {
15808
15992
  return commentId != null ? String(commentId) : null;
15809
15993
  }
15810
15994
  //#endregion
15811
- //#region src/helpers/v2-remote-review-hydration.js
15812
- function normalizeDocumentId(value) {
15813
- return value == null ? null : String(value);
15814
- }
15815
- function createV2RemoteReviewHydrationScheduler({ hydrate, getActiveDocumentId, debounceMs = 250, ceilingMs = 1e3, now = () => Date.now(), setTimer = (callback, delay) => setTimeout(callback, delay), clearTimer = (timer) => clearTimeout(timer) }) {
15816
- let timer = null;
15817
- let heldSinceMs = null;
15818
- let pendingDocumentId = null;
15819
- const matchesActiveDocument = (documentId) => {
15820
- return normalizeDocumentId(getActiveDocumentId()) === documentId;
15821
- };
15822
- const clear = () => {
15823
- if (timer != null) clearTimer(timer);
15824
- timer = null;
15825
- heldSinceMs = null;
15826
- pendingDocumentId = null;
15827
- };
15828
- const schedule = (documentId) => {
15829
- const normalizedDocumentId = normalizeDocumentId(documentId);
15830
- if (!matchesActiveDocument(normalizedDocumentId)) return false;
15831
- if (pendingDocumentId !== normalizedDocumentId) clear();
15832
- const scheduledAtMs = now();
15833
- pendingDocumentId = normalizedDocumentId;
15834
- heldSinceMs ??= scheduledAtMs;
15835
- if (timer != null) clearTimer(timer);
15836
- const ceilingRemainingMs = Math.max(0, ceilingMs - (scheduledAtMs - heldSinceMs));
15837
- timer = setTimer(() => {
15838
- const deliveredDocumentId = pendingDocumentId;
15839
- timer = null;
15840
- heldSinceMs = null;
15841
- pendingDocumentId = null;
15842
- if (matchesActiveDocument(deliveredDocumentId)) hydrate();
15843
- }, Math.min(debounceMs, ceilingRemainingMs));
15844
- return true;
15845
- };
15846
- return {
15847
- schedule,
15848
- clear
15849
- };
15850
- }
15851
- //#endregion
15852
- //#region src/helpers/v2-typing-review-hydration.js
15853
- /**
15854
- * Coalesce automatic review-catalog reconciliation behind a genuine typing
15855
- * quiet period. Every typing signal restarts the trailing timer; there is no
15856
- * maximum-wait escape hatch because that would deliberately run the expensive
15857
- * catalog reads in the middle of a sustained input burst.
15858
- */
15859
- function createV2TypingReviewHydrationScheduler({ hydrate, idleMs = 6500, setTimer = (callback, delay) => setTimeout(callback, delay), clearTimer = (timer) => clearTimeout(timer) }) {
15860
- let timer = null;
15861
- const clear = () => {
15862
- if (timer != null) clearTimer(timer);
15863
- timer = null;
15864
- };
15865
- const schedule = () => {
15866
- clear();
15867
- timer = setTimer(() => {
15868
- timer = null;
15869
- hydrate();
15870
- }, idleMs);
15871
- };
15872
- return {
15873
- schedule,
15874
- clear,
15875
- isPending: () => timer != null
15876
- };
15877
- }
15878
- //#endregion
15879
15995
  //#region src/helpers/v2-author-required-rejection.js
15880
15996
  var NO_AUTHOR_SIGNAL = "no-author-configured";
15881
15997
  /** Stable, non-terminal exception code surfaced to consumers. */
@@ -20312,9 +20428,9 @@ var _hoisted_1$16 = {
20312
20428
  var _hoisted_2$13 = ["innerHTML"];
20313
20429
  var _hoisted_3$10 = { class: "superdoc__document document" };
20314
20430
  var _hoisted_4$7 = { class: "floating-comments" };
20431
+ var TRACKED_CHANGE_CARRIERS_RESTAMPED_EVENT = "superdoc:v2-tracked-change-carriers-restamped";
20315
20432
  var UNAVAILABLE_COMMAND_RESULT = false;
20316
20433
  var V2_SELECTION_TOOLBAR_SYNC_RETRY_FRAMES = 3;
20317
- var V2_TYPING_REVIEW_HYDRATION_IDLE_MS = 6500;
20318
20434
  var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
20319
20435
  __name: "SuperDoc",
20320
20436
  emits: ["selection-update"],
@@ -20477,6 +20593,27 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
20477
20593
  editor: proxy.$superdoc?.activeEditor
20478
20594
  });
20479
20595
  };
20596
+ const reconcileAuthoritativeV2TrackedChangeSidebar = ({ adapter, documentId, refreshReason = "startup-authoritative" } = {}) => {
20597
+ if (!adapter || typeof adapter.listTrackedChanges !== "function") return false;
20598
+ const normalizedDocumentId = documentId == null ? null : String(documentId);
20599
+ if (!normalizedDocumentId) return false;
20600
+ commentsStore.hydrateTrackedChangesFromV2?.({
20601
+ superdoc: proxy.$superdoc,
20602
+ adapter,
20603
+ documentId: normalizedDocumentId,
20604
+ trackedChangesListMode: "background-reconcile",
20605
+ refreshReason,
20606
+ blocking: false,
20607
+ isCurrent: () => {
20608
+ const activeEditor = proxy.$superdoc?.activeEditor ?? null;
20609
+ const activeDocumentId = activeEditor?.documentId ?? activeEditor?.options?.documentId ?? null;
20610
+ if (activeDocumentId != null && String(activeDocumentId) !== normalizedDocumentId) return false;
20611
+ const activeAdapter = activeEditor?.v2TrackedChanges ?? commentsStore.getV2TrackedChangesAdapter?.(proxy.$superdoc);
20612
+ return !activeAdapter || activeAdapter === adapter;
20613
+ }
20614
+ });
20615
+ return true;
20616
+ };
20480
20617
  const scheduleReplayTrackedChangeSync = () => {
20481
20618
  pendingReplayTrackedChangeSync.value = true;
20482
20619
  nextTick(() => {
@@ -21020,7 +21157,11 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21020
21157
  pageFurniture: pageFurniture ?? null,
21021
21158
  presence: presence ?? null,
21022
21159
  lock: lock ?? null,
21023
- reviewHydration: { getDiagnostics: () => v2ReviewHydrationController.getDiagnostics() },
21160
+ reviewHydration: {
21161
+ getDiagnostics: () => v2ReviewHydrationController.getDiagnostics(),
21162
+ getSnapshot: () => v2ReviewHydrationController.getSnapshot?.() ?? null,
21163
+ subscribe: (listener) => v2ReviewHydrationController.subscribe?.(listener) ?? (() => void 0)
21164
+ },
21024
21165
  extensions: createV2ExtensionsFacet(host),
21025
21166
  fonts: fonts ?? host?.getFontRuntime?.() ?? null,
21026
21167
  /**
@@ -21076,6 +21217,11 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21076
21217
  console.warn("[SuperDoc][v2] initial render-readiness snapshot failed", err);
21077
21218
  }
21078
21219
  }
21220
+ if (commentsModuleEnabled && trackedChangesAdapter) reconcileAuthoritativeV2TrackedChangeSidebar({
21221
+ adapter: trackedChangesAdapter,
21222
+ documentId,
21223
+ refreshReason: "startup-authoritative"
21224
+ });
21079
21225
  if (areDocumentsReady.value && !proxy.$superdoc.config.collaboration) isReady.value = true;
21080
21226
  isFloatingCommentsReady.value = true;
21081
21227
  hasInitializedLocations.value = true;
@@ -21344,7 +21490,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21344
21490
  }
21345
21491
  },
21346
21492
  onCommittedPagePaint: (commit) => {
21347
- if (commit?.routeLane === "canonical.typing-mutation" || v2TypingReviewHydrationScheduler.isPending()) return;
21348
21493
  v2ReviewHydrationController.onCommittedPagePaint?.({
21349
21494
  ...commit,
21350
21495
  documentId: commit?.payload?.documentId ?? null
@@ -21389,7 +21534,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21389
21534
  const onV2RenderReadiness = (payload) => {
21390
21535
  const snapshot = payload?.snapshot ?? payload ?? null;
21391
21536
  if (!snapshot) return;
21392
- if (v2TypingReviewHydrationScheduler.isPending()) return;
21393
21537
  v2ReviewHydrationController.onRenderReadiness(snapshot);
21394
21538
  };
21395
21539
  const v2PageMetricsSnapshot = shallowRef(null);
@@ -21439,8 +21583,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21439
21583
  if (latestV2MountStage && (clearedDocumentId == null || latestV2MountStage.dataset?.superdocV2DocumentId === clearedDocumentId)) latestV2MountStage = null;
21440
21584
  v2ReviewHydrationController.reset("render-cleared");
21441
21585
  v2ReviewMutationReconciler.reset();
21442
- clearV2TypingReviewHydrationTimer();
21443
- v2RemoteReviewHydrationScheduler.clear();
21444
21586
  commentsStore.setV2CommentsAdapter?.(null);
21445
21587
  commentsStore.setV2TrackedChangesAdapter?.(null);
21446
21588
  commentsStore.clearEditorCommentPositions?.();
@@ -21449,26 +21591,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21449
21591
  v2RulerHostStyle.value = {};
21450
21592
  v2RulerReady.value = false;
21451
21593
  };
21452
- const hydrateV2CommentRowsFromHost = () => {
21453
- const commentsAdapter = proxy.$superdoc?.activeEditor?.v2Comments ?? null;
21454
- if (!commentsAdapter) return;
21455
- commentsStore.hydrateCommentsFromV2?.({
21456
- superdoc: proxy.$superdoc,
21457
- adapter: commentsAdapter,
21458
- documentId: proxy.$superdoc?.activeEditor?.documentId ?? null
21459
- });
21460
- };
21461
- const hydrateV2ReviewRowsFromHost = (options = {}) => {
21462
- hydrateV2CommentRowsFromHost();
21463
- const trackedChangesAdapter = proxy.$superdoc?.activeEditor?.v2TrackedChanges ?? null;
21464
- if (!trackedChangesAdapter) return;
21465
- commentsStore.hydrateTrackedChangesFromV2?.({
21466
- superdoc: proxy.$superdoc,
21467
- adapter: trackedChangesAdapter,
21468
- documentId: proxy.$superdoc?.activeEditor?.documentId ?? null,
21469
- ...options
21470
- });
21471
- };
21472
21594
  const v2ReviewMutationReconciler = createV2ReviewMutationReconciler({
21473
21595
  getContext: () => {
21474
21596
  const activeEditor = proxy.$superdoc?.activeEditor ?? null;
@@ -21498,31 +21620,10 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21498
21620
  reason: "review-reconcile"
21499
21621
  })
21500
21622
  });
21501
- const v2TypingReviewHydrationScheduler = createV2TypingReviewHydrationScheduler({
21502
- idleMs: V2_TYPING_REVIEW_HYDRATION_IDLE_MS,
21503
- hydrate: () => v2ReviewHydrationController.reconcileInBackground?.("typing-idle")
21504
- });
21505
- const clearV2TypingReviewHydrationTimer = () => {
21506
- v2TypingReviewHydrationScheduler.clear();
21507
- };
21508
- const scheduleV2TypingReviewHydration = () => {
21509
- v2TypingReviewHydrationScheduler.schedule();
21510
- };
21511
- const v2RemoteReviewHydrationScheduler = createV2RemoteReviewHydrationScheduler({
21512
- hydrate: () => {
21513
- if (v2TypingReviewHydrationScheduler.isPending()) return false;
21514
- return v2ReviewHydrationController.reconcileInBackground?.("remote-review-change");
21515
- },
21516
- getActiveDocumentId: () => {
21517
- const activeEditor = proxy.$superdoc?.activeEditor ?? null;
21518
- return activeEditor?.documentId ?? activeEditor?.options?.documentId ?? null;
21519
- }
21520
- });
21521
21623
  const onV2HostEvent = (document, event) => {
21522
21624
  if (!event) return;
21523
21625
  const documentId = document?.id ?? null;
21524
21626
  if (event.type === "review-mutation:started") {
21525
- clearV2TypingReviewHydrationTimer();
21526
21627
  const activeEditor = proxy.$superdoc?.activeEditor ?? null;
21527
21628
  commentsStore.supersedeV2ReviewHydration?.({
21528
21629
  commentsAdapter: activeEditor?.v2Comments ?? null,
@@ -21544,8 +21645,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21544
21645
  return;
21545
21646
  }
21546
21647
  if (event.type === "collaboration:remote-changed") {
21547
- v2ReviewHydrationController.invalidate("collaboration:remote-changed");
21548
- v2RemoteReviewHydrationScheduler.schedule(documentId);
21648
+ if (event.reviewChanged !== false) v2ReviewHydrationController.invalidate("collaboration:remote-review-changed");
21549
21649
  return;
21550
21650
  }
21551
21651
  if (event.type === "source:complete") {
@@ -21570,11 +21670,12 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21570
21670
  emitV2EditorUpdate();
21571
21671
  }
21572
21672
  if (event.type !== "mutation:committed") return;
21573
- v2ReviewHydrationController.invalidate("mutation-committed");
21673
+ if (event.reviewSidecarOnly === true) v2ReviewHydrationController.hydrateNow("review-sidecar-committed");
21574
21674
  const reviewImpact = getV2TrackedChangeMutationImpact(event);
21575
21675
  if (Array.isArray(reviewImpact?.remappedPairs) && reviewImpact.remappedPairs.length > 0) commentsStore.remapTrackedChangeIdentities?.(reviewImpact.remappedPairs, { documentId });
21576
21676
  if (reviewImpact) armV2TrackedChangeRestampGeometryRetention("tracked-change-mutation");
21577
- const readiness = (proxy.$superdoc?.activeEditor ?? null)?.documentMutationReadiness ?? null;
21677
+ const activeEditor = proxy.$superdoc?.activeEditor ?? null;
21678
+ const readiness = activeEditor?.documentMutationReadiness ?? null;
21578
21679
  const receipt = event.origin === "history" ? null : event.receipt;
21579
21680
  const canWaitForExactPaint = reviewImpact && typeof receipt?.txId === "string" && receipt.txId.length > 0 && typeof readiness?.whenPainted === "function";
21580
21681
  const reconciliation = v2ReviewMutationReconciler.enqueueAfterPaint(reviewImpact, canWaitForExactPaint ? () => readiness.whenPainted.call(readiness, receipt) : null);
@@ -21589,43 +21690,37 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21589
21690
  resumeDomains: reconciledAllResolved ? ["comments"] : ["comments", "trackedChanges"],
21590
21691
  trackedRowCount: commentsStore.getV2TrackedChangeRowCount?.(documentId) ?? null
21591
21692
  });
21693
+ if (!reconciledAllResolved) reconcileAuthoritativeV2TrackedChangeSidebar({
21694
+ adapter: activeEditor?.v2TrackedChanges ?? null,
21695
+ documentId,
21696
+ refreshReason: "mutation-authoritative"
21697
+ });
21592
21698
  };
21593
21699
  Promise.resolve(reconciliation).then(settleReviewMutation, () => settleReviewMutation(false));
21594
21700
  return;
21595
21701
  }
21596
- const isTypingMutation = isV2EditableTextMutationEvent(event);
21597
- if (!isTypingMutation) clearV2TypingReviewHydrationTimer();
21598
- if (reviewImpact?.reconcileMode === "authoritative" && reviewImpact.upsertIds.size > 0) {
21599
- hydrateV2CommentRowsFromHost();
21600
- return;
21601
- }
21602
- if (isTypingMutation) {
21603
- scheduleV2TypingReviewHydration();
21604
- return;
21605
- }
21702
+ if (reviewImpact?.reconcileMode === "authoritative" && reviewImpact.upsertIds.size > 0) return;
21606
21703
  if (reviewImpact?.removedIds.size > 0 && reviewImpact.upsertIds.size === 0) return;
21607
- hydrateV2ReviewRowsFromHost();
21608
21704
  };
21609
21705
  const onV2LinkClick = (payload) => {
21610
21706
  linkPopover.handleLinkClick(payload);
21611
21707
  };
21612
- const recollectV2GeometryIfActive = () => {
21708
+ const recollectV2GeometryIfActive = (options = void 0) => {
21613
21709
  if (!isV2Mode.value) return;
21614
21710
  if (!v2GeometryPublisher.getLastPayload()) return;
21615
21711
  if (v2GeometryRafHandle && typeof cancelAnimationFrame === "function") cancelAnimationFrame(v2GeometryRafHandle);
21616
21712
  if (typeof requestAnimationFrame !== "function") {
21617
- v2GeometryPublisher.recollect();
21713
+ v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21618
21714
  return;
21619
21715
  }
21620
21716
  v2GeometryRafHandle = requestAnimationFrame(() => {
21621
21717
  v2GeometryRafHandle = 0;
21622
- v2GeometryPublisher.recollect();
21718
+ v2GeometryPublisher.recollect(resolveV2GeometryPublishOptions(options));
21623
21719
  });
21624
21720
  };
21625
21721
  const handleV2DocumentModeChange = () => {
21626
21722
  if (!isV2Mode.value) return;
21627
21723
  try {
21628
- clearV2TypingReviewHydrationTimer();
21629
21724
  v2ReviewHydrationController.hydrateNow("document-mode-change");
21630
21725
  } catch (err) {
21631
21726
  console.warn("[SuperDoc][v2] document-mode-change rehydrate failed", err);
@@ -21644,22 +21739,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21644
21739
  else republishGeometry();
21645
21740
  });
21646
21741
  };
21647
- let v2BuiltInReviewSurfaceOpen = false;
21648
- let v2ExternalReviewSurfaceOpen = false;
21649
- const syncV2ReviewCatalogDemand = () => {
21650
- if (!isV2Mode.value) return;
21651
- if (!v2BuiltInReviewSurfaceOpen && !v2ExternalReviewSurfaceOpen) {
21652
- v2ReviewHydrationController.releaseCatalogDemand();
21653
- return;
21654
- }
21655
- clearV2TypingReviewHydrationTimer();
21656
- v2ReviewHydrationController.demandCatalog("review-sidebar-visible");
21657
- };
21658
- const handleV2CommentsListChange = ({ isRendered } = {}) => {
21659
- v2ExternalReviewSurfaceOpen = isRendered === true;
21660
- syncV2ReviewCatalogDemand();
21661
- };
21662
- proxy.$superdoc?.on?.("comments-list-change", handleV2CommentsListChange);
21663
21742
  const getV2EditorFailureMessage = (reason) => {
21664
21743
  switch (reason) {
21665
21744
  case "editing-mount-required": return "SuperDoc could not load the document editor because the page did not provide a mount container.";
@@ -21734,7 +21813,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21734
21813
  if (!root) return;
21735
21814
  if (!(event.target instanceof Node) || !root.contains(event.target)) return;
21736
21815
  if (layers.value?.contains(event.target)) {
21737
- commentsStore.setActiveComment(proxy.$superdoc, null);
21816
+ if (!isActiveTrackedChangeContextMenuTarget(event.target)) commentsStore.setActiveComment(proxy.$superdoc, null);
21738
21817
  commentsStore.removePendingComment(proxy.$superdoc);
21739
21818
  resetClickAnchor();
21740
21819
  }
@@ -21787,16 +21866,17 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21787
21866
  onFontsResolved: onFontsResolvedFn,
21788
21867
  onPageCountKnown: proxy.$superdoc.config.onPageCountKnown ?? null,
21789
21868
  onReviewWindowPlanned: (payload) => {
21790
- if (payload?.routeLane === "canonical.typing-mutation") {
21791
- v2TypingReviewHydrationScheduler.schedule();
21792
- return;
21793
- }
21794
- if (v2TypingReviewHydrationScheduler.isPending()) return;
21795
21869
  v2ReviewHydrationController.onReviewWindowPlanned?.({
21796
21870
  ...payload,
21797
21871
  documentId: doc.id
21798
21872
  });
21799
21873
  },
21874
+ onReviewWindowCommitted: (payload) => {
21875
+ v2ReviewHydrationController.onCommittedPagePaint?.({
21876
+ ...payload,
21877
+ documentId: doc.id
21878
+ });
21879
+ },
21800
21880
  fontAssets: proxy.$superdoc.config.fonts,
21801
21881
  proofing: resolvedProofingConfig.value,
21802
21882
  isNewFile,
@@ -22124,8 +22204,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22124
22204
  });
22125
22205
  watch(showCommentsSidebar, (value) => {
22126
22206
  proxy.$superdoc.broadcastSidebarToggle(value);
22127
- v2BuiltInReviewSurfaceOpen = value === true;
22128
- syncV2ReviewCatalogDemand();
22129
22207
  });
22130
22208
  useViewportFit({
22131
22209
  getSuperdoc: () => proxy.$superdoc,
@@ -22150,6 +22228,16 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22150
22228
  const handleViewportScrollOrResize = () => {
22151
22229
  recollectV2GeometryIfActive();
22152
22230
  };
22231
+ const handleV2TrackedChangeCarriersRestamped = (event) => {
22232
+ if (!isV2Mode.value) return;
22233
+ const itemIds = Array.isArray(event?.detail?.itemIds) ? event.detail.itemIds.map((id) => id == null ? "" : String(id)).filter(Boolean) : [];
22234
+ armV2TrackedChangeRestampGeometryRetention(event?.detail?.refreshReason ?? "tracked-change-restamp");
22235
+ recollectV2GeometryIfActive({
22236
+ retainMissingTrackedChangeGeometry: true,
22237
+ ...itemIds.length > 0 ? { retainedTrackedChangeIds: itemIds } : {},
22238
+ reason: "tracked-change-restamp"
22239
+ });
22240
+ };
22153
22241
  onMounted(() => {
22154
22242
  document.addEventListener("contextmenu", handleDocumentContextMenu, true);
22155
22243
  document.addEventListener("keydown", handleDocumentShortcut, true);
@@ -22157,6 +22245,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22157
22245
  claimFindShortcut(findShortcutOwner);
22158
22246
  superdocRoot.value?.addEventListener("pointerdown", handleFindOwnershipInteraction, true);
22159
22247
  superdocRoot.value?.addEventListener("focusin", handleFindOwnershipInteraction, true);
22248
+ superdocRoot.value?.addEventListener(TRACKED_CHANGE_CARRIERS_RESTAMPED_EVENT, handleV2TrackedChangeCarriersRestamped);
22160
22249
  if (typeof window !== "undefined") {
22161
22250
  window.addEventListener("scroll", handleViewportScrollOrResize, true);
22162
22251
  window.addEventListener("resize", handleViewportScrollOrResize, true);
@@ -22273,6 +22362,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22273
22362
  proxy.$superdoc?.off?.("search:open", handleOpenFindRequest);
22274
22363
  superdocRoot.value?.removeEventListener("pointerdown", handleFindOwnershipInteraction, true);
22275
22364
  superdocRoot.value?.removeEventListener("focusin", handleFindOwnershipInteraction, true);
22365
+ superdocRoot.value?.removeEventListener(TRACKED_CHANGE_CARRIERS_RESTAMPED_EVENT, handleV2TrackedChangeCarriersRestamped);
22276
22366
  releaseFindShortcut(findShortcutOwner);
22277
22367
  if (typeof window !== "undefined") {
22278
22368
  window.removeEventListener("scroll", handleViewportScrollOrResize, true);
@@ -22282,8 +22372,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22282
22372
  cancelAnimationFrame(v2GeometryRafHandle);
22283
22373
  v2GeometryRafHandle = 0;
22284
22374
  }
22285
- clearV2TypingReviewHydrationTimer();
22286
- v2RemoteReviewHydrationScheduler.clear();
22287
22375
  document.removeEventListener("focusin", handleRuntimeFocusIn, true);
22288
22376
  document.removeEventListener("pointerdown", handleRuntimePointerDown, true);
22289
22377
  document.removeEventListener("mousedown", handleRuntimeMouseDown, true);
@@ -22291,7 +22379,6 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22291
22379
  document.removeEventListener("mouseup", handleDocumentSelectionChange, true);
22292
22380
  document.removeEventListener("selectionchange", handleDocumentSelectionChange);
22293
22381
  proxy.$superdoc?.off?.("document-mode-change", handleV2DocumentModeChange);
22294
- proxy.$superdoc?.off?.("comments-list-change", handleV2CommentsListChange);
22295
22382
  });
22296
22383
  const selectionLayer = ref(null);
22297
22384
  const isDragging = ref(false);
@@ -22787,7 +22874,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22787
22874
  ], 38);
22788
22875
  };
22789
22876
  }
22790
- }, [["__scopeId", "data-v-25570fd2"]]);
22877
+ }, [["__scopeId", "data-v-6833a014"]]);
22791
22878
  //#endregion
22792
22879
  //#region src/core/create-app.js
22793
22880
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -43264,7 +43351,7 @@ var SuperDoc = class extends import_eventemitter3.default {
43264
43351
  this.config.colors = shuffleArray(this.config.colors);
43265
43352
  this.userColorMap = /* @__PURE__ */ new Map();
43266
43353
  this.colorIndex = 0;
43267
- this.version = "2.4.0-next.16";
43354
+ this.version = "2.4.0-next.18";
43268
43355
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
43269
43356
  this.superdocId = config.superdocId || v4();
43270
43357
  this.colors = this.config.colors ?? [];