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.
@@ -763,56 +763,6 @@ function createV2ReviewMutationReconciler({ getContext, reconcile, hydrate, onRe
763
763
  };
764
764
  }
765
765
  //#endregion
766
- //#region src/helpers/v2-typing-mutation-event.js
767
- /**
768
- * Command kinds whose committed mutations belong to the sustained typing
769
- * cadence class (insert / replace / plain paste / Backspace / Delete).
770
- *
771
- * The SuperDoc shell debounces per-keystroke review-row hydration for these
772
- * kinds instead of refreshing comments + tracked changes on every commit —
773
- * hydrating immediately per keystroke was a measured worker-read storm during
774
- * typing and backspace bursts. The `text.*` aliases cover integrations that
775
- * forward Document API style command ids rather than editable-input kinds.
776
- */
777
- var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
778
- "insert-text",
779
- "replace-text",
780
- "plain-text-paste",
781
- "delete-backward",
782
- "delete-forward",
783
- "text.insert",
784
- "text.replace",
785
- "text.pastePlain",
786
- "text.deleteBackward",
787
- "text.deleteForward",
788
- "structural.enter",
789
- "structural:enter-split-paragraph",
790
- "structural:enter-insert-paragraph-before",
791
- "structural:enter-insert-paragraph-after",
792
- "structural:shift-enter-line-break",
793
- "structural:backspace-boundary-merge-with-previous",
794
- "structural:delete-boundary-merge-with-next",
795
- "backspace:boundary-merge-with-previous",
796
- "backspace:list-remove",
797
- "backspace:list-outdent"
798
- ]);
799
- /**
800
- * True when a forwarded v2 host event is a committed editable-input mutation
801
- * of the sustained-typing class, i.e. review-row hydration for it should be
802
- * debounced rather than fired immediately.
803
- *
804
- * Events without a forwarded `editableCommandKind` (programmatic Document API
805
- * mutations, history commits, unclassified structural commands) return false
806
- * so they keep hydrating immediately.
807
- *
808
- * @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
809
- * @returns {boolean}
810
- */
811
- var isV2EditableTextMutationEvent = (event) => {
812
- if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
813
- return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
814
- };
815
- //#endregion
816
766
  //#region src/public/ui/reasons.ts
817
767
  /**
818
768
  * Stable public reason taxonomy for the v2-native `superdoc/ui` controller.
@@ -1768,6 +1718,56 @@ function selectionKey(selection) {
1768
1718
  }
1769
1719
  }
1770
1720
  //#endregion
1721
+ //#region src/helpers/v2-typing-mutation-event.js
1722
+ /**
1723
+ * Command kinds whose committed mutations belong to the sustained typing
1724
+ * cadence class (insert / replace / plain paste / Backspace / Delete).
1725
+ *
1726
+ * The SuperDoc shell debounces per-keystroke review-row hydration for these
1727
+ * kinds instead of refreshing comments + tracked changes on every commit —
1728
+ * hydrating immediately per keystroke was a measured worker-read storm during
1729
+ * typing and backspace bursts. The `text.*` aliases cover integrations that
1730
+ * forward Document API style command ids rather than editable-input kinds.
1731
+ */
1732
+ var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
1733
+ "insert-text",
1734
+ "replace-text",
1735
+ "plain-text-paste",
1736
+ "delete-backward",
1737
+ "delete-forward",
1738
+ "text.insert",
1739
+ "text.replace",
1740
+ "text.pastePlain",
1741
+ "text.deleteBackward",
1742
+ "text.deleteForward",
1743
+ "structural.enter",
1744
+ "structural:enter-split-paragraph",
1745
+ "structural:enter-insert-paragraph-before",
1746
+ "structural:enter-insert-paragraph-after",
1747
+ "structural:shift-enter-line-break",
1748
+ "structural:backspace-boundary-merge-with-previous",
1749
+ "structural:delete-boundary-merge-with-next",
1750
+ "backspace:boundary-merge-with-previous",
1751
+ "backspace:list-remove",
1752
+ "backspace:list-outdent"
1753
+ ]);
1754
+ /**
1755
+ * True when a forwarded v2 host event is a committed editable-input mutation
1756
+ * of the sustained-typing class, i.e. review-row hydration for it should be
1757
+ * debounced rather than fired immediately.
1758
+ *
1759
+ * Events without a forwarded `editableCommandKind` (programmatic Document API
1760
+ * mutations, history commits, unclassified structural commands) return false
1761
+ * so they keep hydrating immediately.
1762
+ *
1763
+ * @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
1764
+ * @returns {boolean}
1765
+ */
1766
+ var isV2EditableTextMutationEvent = (event) => {
1767
+ if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
1768
+ return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
1769
+ };
1770
+ //#endregion
1771
1771
  //#region src/public/ui/entity-at.ts
1772
1772
  function parseCommaSeparatedIds(value) {
1773
1773
  return value.split(",").map((id) => id.trim()).filter(Boolean);
@@ -3727,6 +3727,23 @@ function createSuperDocUI(options) {
3727
3727
  const trackedChanges = getEditor()?.v2TrackedChanges;
3728
3728
  return trackedChanges && typeof trackedChanges === "object" ? trackedChanges : null;
3729
3729
  };
3730
+ /** Read the committed V2 page-window review feed (never a document catalog). */
3731
+ const getV2ReviewWindowSource = () => {
3732
+ const editor = getEditor();
3733
+ if (editor?.editorVersion !== 2) return null;
3734
+ const reviewHydration = editor.reviewHydration;
3735
+ return reviewHydration && typeof reviewHydration === "object" ? reviewHydration : null;
3736
+ };
3737
+ const getV2ReviewWindowSnapshot = () => {
3738
+ const source = getV2ReviewWindowSource();
3739
+ if (!source || typeof source.getSnapshot !== "function") return null;
3740
+ return safeCall(() => source.getSnapshot(), null);
3741
+ };
3742
+ const hasV2ReviewWindowFeed = () => typeof getV2ReviewWindowSource()?.getSnapshot === "function";
3743
+ const reviewWindowSliceStatus = (snapshot) => {
3744
+ const status = snapshot?.status;
3745
+ return status === "ready" || status === "stale" ? status : "pending";
3746
+ };
3730
3747
  /** Read the live v2 editor host (inline mode only), when exposed. */
3731
3748
  const getHost = () => {
3732
3749
  const host = getEditor()?.host;
@@ -4481,6 +4498,12 @@ function createSuperDocUI(options) {
4481
4498
  if (entry?.hasSettled || entry?.inflightToken != null) return;
4482
4499
  demandHeavyDocRead("trackChanges");
4483
4500
  };
4501
+ /** Demand-driven route for an explicitly consumed comments list. */
4502
+ const ensureCommentsCatalog = () => {
4503
+ const entry = asyncReads.get("comments");
4504
+ if (entry?.hasSettled || entry?.inflightToken != null) return;
4505
+ demandHeavyDocRead("comments");
4506
+ };
4484
4507
  const HEAVY_READ_IDLE_MS = 6500;
4485
4508
  const HEAVY_READ_IDLE_POLL_MS = 250;
4486
4509
  let lastEditableMutationAtMs = 0;
@@ -5114,7 +5137,12 @@ function createSuperDocUI(options) {
5114
5137
  };
5115
5138
  const computeComments = (selection) => {
5116
5139
  const commentsApi = getDoc()?.comments;
5117
- const { value, status: listStatus } = readAsync("comments", contentToken(), () => commentsApi?.list ? commentsApi.list() : void 0, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5140
+ const reviewWindow = getV2ReviewWindowSnapshot();
5141
+ const catalog = readAsync("comments", contentToken(), () => commentsApi?.list ? commentsApi.list() : void 0, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5142
+ const windowItems = hasV2ReviewWindowFeed() && Array.isArray(reviewWindow?.commentItems) ? reviewWindow.commentItems : null;
5143
+ const useWindowSlice = catalog.status === "pending" && windowItems != null;
5144
+ const value = useWindowSlice ? windowItems : catalog.value;
5145
+ const listStatus = useWindowSlice ? reviewWindowSliceStatus(reviewWindow) : catalog.status;
5118
5146
  const items = value ?? [];
5119
5147
  const activeIds = selection.activeCommentIds;
5120
5148
  if (explicitActiveCommentId && !items.some((item) => readEntityId(item) === explicitActiveCommentId)) explicitActiveCommentId = null;
@@ -5157,13 +5185,18 @@ function createSuperDocUI(options) {
5157
5185
  const token = contentToken();
5158
5186
  const postDecisionIds = postDecisionTrackChangeIdsForToken(token);
5159
5187
  const heldEntry = asyncReads.get("trackChanges");
5160
- const { value, status: listStatus } = authoritativeTrackChangesPendingToken === token ? {
5188
+ const reviewWindow = getV2ReviewWindowSnapshot();
5189
+ const catalog = authoritativeTrackChangesPendingToken === token ? {
5161
5190
  value: heldEntry?.hasSettled ? heldEntry.value : null,
5162
5191
  status: heldEntry?.hasSettled ? "stale" : "pending"
5163
5192
  } : readAsync("trackChanges", token, () => {
5164
5193
  if (listTrackedChanges) return runUiTrackedChangesCatalogRead(() => tcApi?.list?.());
5165
5194
  return tcApi?.list ? tcApi.list({ in: "all" }) : void 0;
5166
5195
  }, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5196
+ const windowItems = hasV2ReviewWindowFeed() && Array.isArray(reviewWindow?.trackedChangeItems) ? reviewWindow.trackedChangeItems : null;
5197
+ const useWindowSlice = catalog.status === "pending" && windowItems != null;
5198
+ const value = useWindowSlice ? windowItems : catalog.value;
5199
+ const listStatus = useWindowSlice ? reviewWindowSliceStatus(reviewWindow) : catalog.status;
5167
5200
  const items = (value ?? []).map(projectTrackChangesItem).filter((item) => item != null).filter((item) => {
5168
5201
  const id = readEntityId(item);
5169
5202
  return !id || !postDecisionIds?.has(id);
@@ -6934,6 +6967,8 @@ function createSuperDocUI(options) {
6934
6967
  let detachHostSelection = null;
6935
6968
  let currentEditCommandsSource = null;
6936
6969
  let detachEditCommands = null;
6970
+ let currentV2ReviewWindowSource = null;
6971
+ let detachV2ReviewWindow = null;
6937
6972
  let editCommandsRecomputeQueued = false;
6938
6973
  const requestEditCommandsRecompute = () => {
6939
6974
  if (disposed || editCommandsRecomputeQueued) return;
@@ -6963,6 +6998,22 @@ function createSuperDocUI(options) {
6963
6998
  currentEditCommandsSource = null;
6964
6999
  }
6965
7000
  };
7001
+ const syncV2ReviewWindowSubscription = () => {
7002
+ const next = getV2ReviewWindowSource();
7003
+ if (next === currentV2ReviewWindowSource) return;
7004
+ if (detachV2ReviewWindow) {
7005
+ detachV2ReviewWindow();
7006
+ detachV2ReviewWindow = null;
7007
+ }
7008
+ currentV2ReviewWindowSource = next;
7009
+ if (!next || typeof next.subscribe !== "function") return;
7010
+ try {
7011
+ const unsubscribe = next.subscribe(() => recompute());
7012
+ if (typeof unsubscribe === "function") detachV2ReviewWindow = unsubscribe;
7013
+ } catch {
7014
+ currentV2ReviewWindowSource = null;
7015
+ }
7016
+ };
6966
7017
  let currentHostReviewSource = null;
6967
7018
  let detachHostReview = null;
6968
7019
  let currentHostEventsSource = null;
@@ -7195,6 +7246,7 @@ function createSuperDocUI(options) {
7195
7246
  syncCoordinatorEditor();
7196
7247
  syncHostSelectionSubscription();
7197
7248
  syncEditCommandsSubscription();
7249
+ syncV2ReviewWindowSubscription();
7198
7250
  syncHostReviewSubscription();
7199
7251
  syncDocumentSelectionFallbackSubscription();
7200
7252
  syncHostEventsSubscription();
@@ -7267,6 +7319,7 @@ function createSuperDocUI(options) {
7267
7319
  attach(superdoc, HOST_EVENTS);
7268
7320
  syncHostSelectionSubscription();
7269
7321
  syncEditCommandsSubscription();
7322
+ syncV2ReviewWindowSubscription();
7270
7323
  syncHostReviewSubscription();
7271
7324
  syncDocumentSelectionFallbackSubscription();
7272
7325
  syncHostEventsSubscription();
@@ -9189,6 +9242,7 @@ function createSuperDocUI(options) {
9189
9242
  subscribe: commentsSnap.subscribe,
9190
9243
  observe: commentsSnap.observe,
9191
9244
  list: (query) => {
9245
+ ensureCommentsCatalog();
9192
9246
  const snapshot = commentsSub.get();
9193
9247
  if (snapshot.status !== "pending") return filterCommentsSnapshot(snapshot.items, query);
9194
9248
  const commentsApi = getDoc()?.comments;
@@ -9323,6 +9377,19 @@ function createSuperDocUI(options) {
9323
9377
  recompute();
9324
9378
  return activeId;
9325
9379
  };
9380
+ const restampVisibleTrackedChangeCarrierAliases = async (publicId) => {
9381
+ const v2TrackedChanges = getV2TrackedChanges();
9382
+ const listTrackedChanges = v2TrackedChanges?.listTrackedChanges;
9383
+ if (typeof listTrackedChanges !== "function") return;
9384
+ try {
9385
+ await Promise.resolve(listTrackedChanges.call(v2TrackedChanges, {
9386
+ mode: "visible-window",
9387
+ targetIds: [publicId],
9388
+ refreshReason: "ui-track-change-reveal-restamp",
9389
+ blocking: true
9390
+ }));
9391
+ } catch {}
9392
+ };
9326
9393
  let trackChangeNavigationTail = Promise.resolve();
9327
9394
  const navigateAndScrollNow = (step) => {
9328
9395
  const requestedAtInvalidation = queuedTrackChangeNavigationInvalidation;
@@ -9359,7 +9426,11 @@ function createSuperDocUI(options) {
9359
9426
  if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
9360
9427
  rollback();
9361
9428
  mirrorTrackedChangeFocusToHost(previousActiveChange);
9362
- } else mirrorTrackedChangeFocusToHost(optimisticActiveChange);
9429
+ } else {
9430
+ if (result.ok) await restampVisibleTrackedChangeCarrierAliases(activeId);
9431
+ if (!isCurrent()) return { success: false };
9432
+ mirrorTrackedChangeFocusToHost(optimisticActiveChange);
9433
+ }
9363
9434
  return { success: result.ok };
9364
9435
  } finally {
9365
9436
  trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
@@ -9509,7 +9580,14 @@ function createSuperDocUI(options) {
9509
9580
  if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
9510
9581
  rollback();
9511
9582
  mirrorTrackedChangeFocusToHost(previousActiveChange);
9512
- } else mirrorTrackedChangeFocusToHost(requestedActiveChange);
9583
+ } else {
9584
+ if (result.ok) await restampVisibleTrackedChangeCarrierAliases(publicId);
9585
+ if (!isCurrent()) return {
9586
+ success: false,
9587
+ ok: false
9588
+ };
9589
+ mirrorTrackedChangeFocusToHost(requestedActiveChange);
9590
+ }
9513
9591
  return result;
9514
9592
  } finally {
9515
9593
  trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
@@ -10681,6 +10759,9 @@ function createSuperDocUI(options) {
10681
10759
  if (detachEditCommands) detachEditCommands();
10682
10760
  detachEditCommands = null;
10683
10761
  currentEditCommandsSource = null;
10762
+ if (detachV2ReviewWindow) detachV2ReviewWindow();
10763
+ detachV2ReviewWindow = null;
10764
+ currentV2ReviewWindowSource = null;
10684
10765
  if (detachHostReview) detachHostReview();
10685
10766
  detachHostReview = null;
10686
10767
  currentHostReviewSource = null;
@@ -10928,4 +11009,4 @@ function commandIsActive(descriptor, selection) {
10928
11009
  return descriptor.activeMark ? selection.activeMarks.includes(descriptor.activeMark) : false;
10929
11010
  }
10930
11011
  //#endregion
10931
- export { createV2ReviewMutationReconciler as a, isV2EditableTextMutationEvent as i, shallowEqual as n, getV2TrackedChangeMutationImpact as o, BUILT_IN_COMMAND_IDS as r, DOM_CLASS_NAMES as s, createSuperDocUI as t };
11012
+ export { getV2TrackedChangeMutationImpact as a, createV2ReviewMutationReconciler as i, shallowEqual as n, DOM_CLASS_NAMES as o, BUILT_IN_COMMAND_IDS as r, createSuperDocUI as t };
@@ -763,56 +763,6 @@ function createV2ReviewMutationReconciler({ getContext, reconcile, hydrate, onRe
763
763
  };
764
764
  }
765
765
  //#endregion
766
- //#region src/helpers/v2-typing-mutation-event.js
767
- /**
768
- * Command kinds whose committed mutations belong to the sustained typing
769
- * cadence class (insert / replace / plain paste / Backspace / Delete).
770
- *
771
- * The SuperDoc shell debounces per-keystroke review-row hydration for these
772
- * kinds instead of refreshing comments + tracked changes on every commit —
773
- * hydrating immediately per keystroke was a measured worker-read storm during
774
- * typing and backspace bursts. The `text.*` aliases cover integrations that
775
- * forward Document API style command ids rather than editable-input kinds.
776
- */
777
- var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
778
- "insert-text",
779
- "replace-text",
780
- "plain-text-paste",
781
- "delete-backward",
782
- "delete-forward",
783
- "text.insert",
784
- "text.replace",
785
- "text.pastePlain",
786
- "text.deleteBackward",
787
- "text.deleteForward",
788
- "structural.enter",
789
- "structural:enter-split-paragraph",
790
- "structural:enter-insert-paragraph-before",
791
- "structural:enter-insert-paragraph-after",
792
- "structural:shift-enter-line-break",
793
- "structural:backspace-boundary-merge-with-previous",
794
- "structural:delete-boundary-merge-with-next",
795
- "backspace:boundary-merge-with-previous",
796
- "backspace:list-remove",
797
- "backspace:list-outdent"
798
- ]);
799
- /**
800
- * True when a forwarded v2 host event is a committed editable-input mutation
801
- * of the sustained-typing class, i.e. review-row hydration for it should be
802
- * debounced rather than fired immediately.
803
- *
804
- * Events without a forwarded `editableCommandKind` (programmatic Document API
805
- * mutations, history commits, unclassified structural commands) return false
806
- * so they keep hydrating immediately.
807
- *
808
- * @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
809
- * @returns {boolean}
810
- */
811
- var isV2EditableTextMutationEvent = (event) => {
812
- if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
813
- return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
814
- };
815
- //#endregion
816
766
  //#region src/public/ui/reasons.ts
817
767
  /**
818
768
  * Stable public reason taxonomy for the v2-native `superdoc/ui` controller.
@@ -1768,6 +1718,56 @@ function selectionKey(selection) {
1768
1718
  }
1769
1719
  }
1770
1720
  //#endregion
1721
+ //#region src/helpers/v2-typing-mutation-event.js
1722
+ /**
1723
+ * Command kinds whose committed mutations belong to the sustained typing
1724
+ * cadence class (insert / replace / plain paste / Backspace / Delete).
1725
+ *
1726
+ * The SuperDoc shell debounces per-keystroke review-row hydration for these
1727
+ * kinds instead of refreshing comments + tracked changes on every commit —
1728
+ * hydrating immediately per keystroke was a measured worker-read storm during
1729
+ * typing and backspace bursts. The `text.*` aliases cover integrations that
1730
+ * forward Document API style command ids rather than editable-input kinds.
1731
+ */
1732
+ var V2_TYPING_COMMAND_KINDS = /* @__PURE__ */ new Set([
1733
+ "insert-text",
1734
+ "replace-text",
1735
+ "plain-text-paste",
1736
+ "delete-backward",
1737
+ "delete-forward",
1738
+ "text.insert",
1739
+ "text.replace",
1740
+ "text.pastePlain",
1741
+ "text.deleteBackward",
1742
+ "text.deleteForward",
1743
+ "structural.enter",
1744
+ "structural:enter-split-paragraph",
1745
+ "structural:enter-insert-paragraph-before",
1746
+ "structural:enter-insert-paragraph-after",
1747
+ "structural:shift-enter-line-break",
1748
+ "structural:backspace-boundary-merge-with-previous",
1749
+ "structural:delete-boundary-merge-with-next",
1750
+ "backspace:boundary-merge-with-previous",
1751
+ "backspace:list-remove",
1752
+ "backspace:list-outdent"
1753
+ ]);
1754
+ /**
1755
+ * True when a forwarded v2 host event is a committed editable-input mutation
1756
+ * of the sustained-typing class, i.e. review-row hydration for it should be
1757
+ * debounced rather than fired immediately.
1758
+ *
1759
+ * Events without a forwarded `editableCommandKind` (programmatic Document API
1760
+ * mutations, history commits, unclassified structural commands) return false
1761
+ * so they keep hydrating immediately.
1762
+ *
1763
+ * @param {{ type?: string, origin?: string, editableCommandKind?: string } | null | undefined} event
1764
+ * @returns {boolean}
1765
+ */
1766
+ var isV2EditableTextMutationEvent = (event) => {
1767
+ if (event?.type !== "mutation:committed" || event.origin !== "command") return false;
1768
+ return V2_TYPING_COMMAND_KINDS.has(event.editableCommandKind);
1769
+ };
1770
+ //#endregion
1771
1771
  //#region src/public/ui/entity-at.ts
1772
1772
  function parseCommaSeparatedIds(value) {
1773
1773
  return value.split(",").map((id) => id.trim()).filter(Boolean);
@@ -3727,6 +3727,23 @@ function createSuperDocUI(options) {
3727
3727
  const trackedChanges = getEditor()?.v2TrackedChanges;
3728
3728
  return trackedChanges && typeof trackedChanges === "object" ? trackedChanges : null;
3729
3729
  };
3730
+ /** Read the committed V2 page-window review feed (never a document catalog). */
3731
+ const getV2ReviewWindowSource = () => {
3732
+ const editor = getEditor();
3733
+ if (editor?.editorVersion !== 2) return null;
3734
+ const reviewHydration = editor.reviewHydration;
3735
+ return reviewHydration && typeof reviewHydration === "object" ? reviewHydration : null;
3736
+ };
3737
+ const getV2ReviewWindowSnapshot = () => {
3738
+ const source = getV2ReviewWindowSource();
3739
+ if (!source || typeof source.getSnapshot !== "function") return null;
3740
+ return safeCall(() => source.getSnapshot(), null);
3741
+ };
3742
+ const hasV2ReviewWindowFeed = () => typeof getV2ReviewWindowSource()?.getSnapshot === "function";
3743
+ const reviewWindowSliceStatus = (snapshot) => {
3744
+ const status = snapshot?.status;
3745
+ return status === "ready" || status === "stale" ? status : "pending";
3746
+ };
3730
3747
  /** Read the live v2 editor host (inline mode only), when exposed. */
3731
3748
  const getHost = () => {
3732
3749
  const host = getEditor()?.host;
@@ -4481,6 +4498,12 @@ function createSuperDocUI(options) {
4481
4498
  if (entry?.hasSettled || entry?.inflightToken != null) return;
4482
4499
  demandHeavyDocRead("trackChanges");
4483
4500
  };
4501
+ /** Demand-driven route for an explicitly consumed comments list. */
4502
+ const ensureCommentsCatalog = () => {
4503
+ const entry = asyncReads.get("comments");
4504
+ if (entry?.hasSettled || entry?.inflightToken != null) return;
4505
+ demandHeavyDocRead("comments");
4506
+ };
4484
4507
  const HEAVY_READ_IDLE_MS = 6500;
4485
4508
  const HEAVY_READ_IDLE_POLL_MS = 250;
4486
4509
  let lastEditableMutationAtMs = 0;
@@ -5114,7 +5137,12 @@ function createSuperDocUI(options) {
5114
5137
  };
5115
5138
  const computeComments = (selection) => {
5116
5139
  const commentsApi = getDoc()?.comments;
5117
- const { value, status: listStatus } = readAsync("comments", contentToken(), () => commentsApi?.list ? commentsApi.list() : void 0, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5140
+ const reviewWindow = getV2ReviewWindowSnapshot();
5141
+ const catalog = readAsync("comments", contentToken(), () => commentsApi?.list ? commentsApi.list() : void 0, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5142
+ const windowItems = hasV2ReviewWindowFeed() && Array.isArray(reviewWindow?.commentItems) ? reviewWindow.commentItems : null;
5143
+ const useWindowSlice = catalog.status === "pending" && windowItems != null;
5144
+ const value = useWindowSlice ? windowItems : catalog.value;
5145
+ const listStatus = useWindowSlice ? reviewWindowSliceStatus(reviewWindow) : catalog.status;
5118
5146
  const items = value ?? [];
5119
5147
  const activeIds = selection.activeCommentIds;
5120
5148
  if (explicitActiveCommentId && !items.some((item) => readEntityId(item) === explicitActiveCommentId)) explicitActiveCommentId = null;
@@ -5157,13 +5185,18 @@ function createSuperDocUI(options) {
5157
5185
  const token = contentToken();
5158
5186
  const postDecisionIds = postDecisionTrackChangeIdsForToken(token);
5159
5187
  const heldEntry = asyncReads.get("trackChanges");
5160
- const { value, status: listStatus } = authoritativeTrackChangesPendingToken === token ? {
5188
+ const reviewWindow = getV2ReviewWindowSnapshot();
5189
+ const catalog = authoritativeTrackChangesPendingToken === token ? {
5161
5190
  value: heldEntry?.hasSettled ? heldEntry.value : null,
5162
5191
  status: heldEntry?.hasSettled ? "stale" : "pending"
5163
5192
  } : readAsync("trackChanges", token, () => {
5164
5193
  if (listTrackedChanges) return runUiTrackedChangesCatalogRead(() => tcApi?.list?.());
5165
5194
  return tcApi?.list ? tcApi.list({ in: "all" }) : void 0;
5166
5195
  }, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
5196
+ const windowItems = hasV2ReviewWindowFeed() && Array.isArray(reviewWindow?.trackedChangeItems) ? reviewWindow.trackedChangeItems : null;
5197
+ const useWindowSlice = catalog.status === "pending" && windowItems != null;
5198
+ const value = useWindowSlice ? windowItems : catalog.value;
5199
+ const listStatus = useWindowSlice ? reviewWindowSliceStatus(reviewWindow) : catalog.status;
5167
5200
  const items = (value ?? []).map(projectTrackChangesItem).filter((item) => item != null).filter((item) => {
5168
5201
  const id = readEntityId(item);
5169
5202
  return !id || !postDecisionIds?.has(id);
@@ -6934,6 +6967,8 @@ function createSuperDocUI(options) {
6934
6967
  let detachHostSelection = null;
6935
6968
  let currentEditCommandsSource = null;
6936
6969
  let detachEditCommands = null;
6970
+ let currentV2ReviewWindowSource = null;
6971
+ let detachV2ReviewWindow = null;
6937
6972
  let editCommandsRecomputeQueued = false;
6938
6973
  const requestEditCommandsRecompute = () => {
6939
6974
  if (disposed || editCommandsRecomputeQueued) return;
@@ -6963,6 +6998,22 @@ function createSuperDocUI(options) {
6963
6998
  currentEditCommandsSource = null;
6964
6999
  }
6965
7000
  };
7001
+ const syncV2ReviewWindowSubscription = () => {
7002
+ const next = getV2ReviewWindowSource();
7003
+ if (next === currentV2ReviewWindowSource) return;
7004
+ if (detachV2ReviewWindow) {
7005
+ detachV2ReviewWindow();
7006
+ detachV2ReviewWindow = null;
7007
+ }
7008
+ currentV2ReviewWindowSource = next;
7009
+ if (!next || typeof next.subscribe !== "function") return;
7010
+ try {
7011
+ const unsubscribe = next.subscribe(() => recompute());
7012
+ if (typeof unsubscribe === "function") detachV2ReviewWindow = unsubscribe;
7013
+ } catch {
7014
+ currentV2ReviewWindowSource = null;
7015
+ }
7016
+ };
6966
7017
  let currentHostReviewSource = null;
6967
7018
  let detachHostReview = null;
6968
7019
  let currentHostEventsSource = null;
@@ -7195,6 +7246,7 @@ function createSuperDocUI(options) {
7195
7246
  syncCoordinatorEditor();
7196
7247
  syncHostSelectionSubscription();
7197
7248
  syncEditCommandsSubscription();
7249
+ syncV2ReviewWindowSubscription();
7198
7250
  syncHostReviewSubscription();
7199
7251
  syncDocumentSelectionFallbackSubscription();
7200
7252
  syncHostEventsSubscription();
@@ -7267,6 +7319,7 @@ function createSuperDocUI(options) {
7267
7319
  attach(superdoc, HOST_EVENTS);
7268
7320
  syncHostSelectionSubscription();
7269
7321
  syncEditCommandsSubscription();
7322
+ syncV2ReviewWindowSubscription();
7270
7323
  syncHostReviewSubscription();
7271
7324
  syncDocumentSelectionFallbackSubscription();
7272
7325
  syncHostEventsSubscription();
@@ -9189,6 +9242,7 @@ function createSuperDocUI(options) {
9189
9242
  subscribe: commentsSnap.subscribe,
9190
9243
  observe: commentsSnap.observe,
9191
9244
  list: (query) => {
9245
+ ensureCommentsCatalog();
9192
9246
  const snapshot = commentsSub.get();
9193
9247
  if (snapshot.status !== "pending") return filterCommentsSnapshot(snapshot.items, query);
9194
9248
  const commentsApi = getDoc()?.comments;
@@ -9323,6 +9377,19 @@ function createSuperDocUI(options) {
9323
9377
  recompute();
9324
9378
  return activeId;
9325
9379
  };
9380
+ const restampVisibleTrackedChangeCarrierAliases = async (publicId) => {
9381
+ const v2TrackedChanges = getV2TrackedChanges();
9382
+ const listTrackedChanges = v2TrackedChanges?.listTrackedChanges;
9383
+ if (typeof listTrackedChanges !== "function") return;
9384
+ try {
9385
+ await Promise.resolve(listTrackedChanges.call(v2TrackedChanges, {
9386
+ mode: "visible-window",
9387
+ targetIds: [publicId],
9388
+ refreshReason: "ui-track-change-reveal-restamp",
9389
+ blocking: true
9390
+ }));
9391
+ } catch {}
9392
+ };
9326
9393
  let trackChangeNavigationTail = Promise.resolve();
9327
9394
  const navigateAndScrollNow = (step) => {
9328
9395
  const requestedAtInvalidation = queuedTrackChangeNavigationInvalidation;
@@ -9359,7 +9426,11 @@ function createSuperDocUI(options) {
9359
9426
  if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
9360
9427
  rollback();
9361
9428
  mirrorTrackedChangeFocusToHost(previousActiveChange);
9362
- } else mirrorTrackedChangeFocusToHost(optimisticActiveChange);
9429
+ } else {
9430
+ if (result.ok) await restampVisibleTrackedChangeCarrierAliases(activeId);
9431
+ if (!isCurrent()) return { success: false };
9432
+ mirrorTrackedChangeFocusToHost(optimisticActiveChange);
9433
+ }
9363
9434
  return { success: result.ok };
9364
9435
  } finally {
9365
9436
  trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
@@ -9509,7 +9580,14 @@ function createSuperDocUI(options) {
9509
9580
  if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
9510
9581
  rollback();
9511
9582
  mirrorTrackedChangeFocusToHost(previousActiveChange);
9512
- } else mirrorTrackedChangeFocusToHost(requestedActiveChange);
9583
+ } else {
9584
+ if (result.ok) await restampVisibleTrackedChangeCarrierAliases(publicId);
9585
+ if (!isCurrent()) return {
9586
+ success: false,
9587
+ ok: false
9588
+ };
9589
+ mirrorTrackedChangeFocusToHost(requestedActiveChange);
9590
+ }
9513
9591
  return result;
9514
9592
  } finally {
9515
9593
  trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
@@ -10681,6 +10759,9 @@ function createSuperDocUI(options) {
10681
10759
  if (detachEditCommands) detachEditCommands();
10682
10760
  detachEditCommands = null;
10683
10761
  currentEditCommandsSource = null;
10762
+ if (detachV2ReviewWindow) detachV2ReviewWindow();
10763
+ detachV2ReviewWindow = null;
10764
+ currentV2ReviewWindowSource = null;
10684
10765
  if (detachHostReview) detachHostReview();
10685
10766
  detachHostReview = null;
10686
10767
  currentHostReviewSource = null;
@@ -10958,12 +11039,6 @@ Object.defineProperty(exports, "getV2TrackedChangeMutationImpact", {
10958
11039
  return getV2TrackedChangeMutationImpact;
10959
11040
  }
10960
11041
  });
10961
- Object.defineProperty(exports, "isV2EditableTextMutationEvent", {
10962
- enumerable: true,
10963
- get: function() {
10964
- return isV2EditableTextMutationEvent;
10965
- }
10966
- });
10967
11042
  Object.defineProperty(exports, "shallowEqual", {
10968
11043
  enumerable: true,
10969
11044
  get: function() {
@@ -19,7 +19,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
19
19
  var PRIVATE_ENGINE_INFO = (0, _superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
20
20
  var ENGINE_INFO = Object.freeze({
21
21
  ...PRIVATE_ENGINE_INFO,
22
- superdocVersion: "2.4.0-next.16",
22
+ superdocVersion: "2.4.0-next.18",
23
23
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
24
24
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
25
25
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -18,7 +18,7 @@ var COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
18
18
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
19
19
  var ENGINE_INFO = Object.freeze({
20
20
  ...PRIVATE_ENGINE_INFO,
21
- superdocVersion: "2.4.0-next.16",
21
+ superdocVersion: "2.4.0-next.18",
22
22
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
23
23
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
24
24
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -200,6 +200,13 @@ export interface CommentsListQuery {
200
200
  includeResolved?: boolean;
201
201
  limit?: number;
202
202
  offset?: number;
203
+ /**
204
+ * Optional bounded review-window filter. Each id may be canonical or an
205
+ * imported/source alias. Only matching visible threads are projected.
206
+ */
207
+ visibleCommentIds?: readonly string[];
208
+ /** Include every reply belonging to a matched visible thread. */
209
+ includeThreadReplies?: boolean;
203
210
  }
204
211
  /**
205
212
  * Domain fields for a comment discovery item (C2).
@@ -12,6 +12,7 @@ export type { BoundaryRange } from './text-boundaries.js';
12
12
  export { buildSectionAwareHeaderFooterLayoutKey, buildSectionContentWidth, buildEffectiveHeaderFooterRefsBySection, collectReferencedHeaderFooterRIds, buildSectionAwareHeaderFooterMeasurementGroups, } from './sectionAwareHeaderFooter.js';
13
13
  export type { HeaderFooterSectionKind, HeaderFooterRefs, SectionAwareHeaderFooterMeasurementGroup, } from './sectionAwareHeaderFooter.js';
14
14
  export { clearIncrementalModuleState, incrementalLayout, measureCache, normalizeMargin, hydrateTableTextboxMeasures, } from './incrementalLayout.js';
15
+ export { hashMeasureContent } from './cache.js';
15
16
  export type { HeaderFooterLayoutResult, IncrementalLayoutBridgeTiming, IncrementalLayoutResult, IncrementalMeasureReuseProof, IncrementalLayoutReuseOptions, IncrementalLayoutReuseSummary, IncrementalSectionPageNumberTransform, IncrementalLayoutTailAdoption, IncrementalLayoutTailDisposition, IncrementalPaginationProof, LayoutPositionTransform, FootnoteReserveSeed, } from './incrementalLayout.js';
16
17
  export { collectFootnoteLedgers, getPreferredReserveCandidates, getPreferredReserveTrialTargets, isMandatoryOnlyFootnotePage, scoreFootnoteWindow, summarizeFootnoteWindow, } from './footnote-scorer.js';
17
18
  export type { FootnotePreferredReserveCandidate, FootnoteWindowScoreInput, FootnoteWindowScoreReason, FootnoteWindowScoreResult, FootnoteWindowStats, } from './footnote-scorer.js';
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CTe12b19.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CPuOlTWb.cjs");
3
3
  let react = require("react");
4
4
  //#region src/public/ui/react.ts
5
5
  /**
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BRBwfV-s.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BbNbi0cj.es.js";
2
2
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  //#region src/public/ui/react.ts
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CTe12b19.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CPuOlTWb.cjs");
3
3
  exports.BUILT_IN_COMMAND_IDS = require_create_super_doc_ui.BUILT_IN_COMMAND_IDS;
4
4
  exports.createSuperDocUI = require_create_super_doc_ui.createSuperDocUI;
5
5
  exports.shallowEqual = require_create_super_doc_ui.shallowEqual;