superdoc 2.0.0-next.50 → 2.0.0-next.52

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.
@@ -1886,6 +1886,48 @@ function readEntityTarget(row) {
1886
1886
  const target = row.target;
1887
1887
  return target && typeof target === "object" ? target : null;
1888
1888
  }
1889
+ function isHostGeometryTarget(target) {
1890
+ if (!target || typeof target !== "object") return false;
1891
+ const record = target;
1892
+ const isTextPoint = (point) => {
1893
+ if (!point || typeof point !== "object") return false;
1894
+ const candidate = point;
1895
+ return candidate.kind === "text" && typeof candidate.blockId === "string" && typeof candidate.offset === "number";
1896
+ };
1897
+ const isTextSegment = (segment) => {
1898
+ if (!segment || typeof segment !== "object") return false;
1899
+ const candidate = segment;
1900
+ const range$1 = candidate.range;
1901
+ return typeof candidate.blockId === "string" && typeof range$1?.start === "number" && typeof range$1.end === "number";
1902
+ };
1903
+ if (Array.isArray(record.segments)) {
1904
+ const first = record.segments[0];
1905
+ const last = record.segments[record.segments.length - 1];
1906
+ return isTextSegment(first) && isTextSegment(last);
1907
+ }
1908
+ if (record.kind === "selection") return isTextPoint(record.start) && isTextPoint(record.end);
1909
+ if (record.kind !== "text" || typeof record.blockId !== "string") return false;
1910
+ const range = record.range;
1911
+ return typeof range?.start === "number" && typeof range.end === "number";
1912
+ }
1913
+ function readTrackedChangeNavigationTarget(row) {
1914
+ if (!row || typeof row !== "object") return null;
1915
+ const target = readEntityTarget(row);
1916
+ if (isHostGeometryTarget(target)) return target;
1917
+ const record = row;
1918
+ const navigationTarget = record.navigationTarget && typeof record.navigationTarget === "object" ? record.navigationTarget : null;
1919
+ if (navigationTarget?.kind === "block" && typeof navigationTarget.blockId === "string" && navigationTarget.blockId.length > 0) return {
1920
+ kind: "text",
1921
+ blockId: navigationTarget.blockId,
1922
+ range: {
1923
+ start: 0,
1924
+ end: 0
1925
+ },
1926
+ ...navigationTarget.story && typeof navigationTarget.story === "object" ? { story: navigationTarget.story } : {},
1927
+ ...record.address && typeof record.address === "object" ? { address: record.address } : {}
1928
+ };
1929
+ return target;
1930
+ }
1889
1931
  function storyLocatorSignature(story) {
1890
1932
  if (!story || typeof story !== "object") return "story:body";
1891
1933
  const record = story;
@@ -3082,11 +3124,14 @@ function createSuperDocUI(options) {
3082
3124
  let explicitActiveChange = null;
3083
3125
  let explicitActiveChangeRevision = 0;
3084
3126
  let queuedTrackChangeNavigationInvalidation = 0;
3127
+ let trackChangeRevealInvalidation = 0;
3128
+ const pendingTrackChangeRevealFocuses = /* @__PURE__ */ new Set();
3085
3129
  const explicitActiveChangesEqual = (left, right) => {
3086
3130
  if (left === right) return true;
3087
3131
  if (!left || !right) return false;
3088
3132
  return left.id === right.id && left.paintedEntityId === right.paintedEntityId && storyLocatorSignature(left.story) === storyLocatorSignature(right.story);
3089
3133
  };
3134
+ const hasPendingTrackChangeRevealFocus = (focus) => Array.from(pendingTrackChangeRevealFocuses).some((pendingFocus) => explicitActiveChangesEqual(pendingFocus, focus));
3090
3135
  const mirrorTrackedChangeFocusToHost = (next) => {
3091
3136
  const host = getHost();
3092
3137
  if (typeof host?.getHandles !== "function") return;
@@ -3115,6 +3160,7 @@ function createSuperDocUI(options) {
3115
3160
  const setExplicitActiveChange = (next, options$1) => {
3116
3161
  explicitActiveChange = next;
3117
3162
  explicitActiveChangeRevision += 1;
3163
+ trackChangeRevealInvalidation += 1;
3118
3164
  if (options$1?.invalidateQueuedNavigation !== false) queuedTrackChangeNavigationInvalidation += 1;
3119
3165
  };
3120
3166
  const listeners = /* @__PURE__ */ new Set();
@@ -5852,6 +5898,7 @@ function createSuperDocUI(options) {
5852
5898
  ...typeof target.paintedEntityId === "string" && target.paintedEntityId.length > 0 ? { paintedEntityId: target.paintedEntityId } : {}
5853
5899
  };
5854
5900
  }
5901
+ if (rawTarget == null && next == null && explicitActiveChange != null && hasPendingTrackChangeRevealFocus(explicitActiveChange)) return false;
5855
5902
  if (explicitActiveChangesEqual(explicitActiveChange, next)) return false;
5856
5903
  setExplicitActiveChange(next);
5857
5904
  return true;
@@ -6122,8 +6169,13 @@ function createSuperDocUI(options) {
6122
6169
  const story = selectionStoryLocator(state.selection);
6123
6170
  const item = items.find((candidate) => entityRowMatchesRequest(candidate, activeId, story));
6124
6171
  if (!item) return "unavailable";
6125
- const type = trackChangesItemPayload(item).type;
6126
- const grouping = trackChangesItemPayload(item).grouping;
6172
+ const change = trackChangesItemPayload(item);
6173
+ const type = change.type;
6174
+ const grouping = change.grouping;
6175
+ if (type === "replacement" && grouping === "replacement-pair") {
6176
+ if (typeof change.insertedText === "string" && state.selection.quotedText === change.insertedText) return "id";
6177
+ return "range";
6178
+ }
6127
6179
  return (type === "insertion" || type === "deletion" || type === "insert" || type === "delete") && grouping === "standalone" ? "range" : "id";
6128
6180
  }
6129
6181
  function resolveTrackDecisionTarget(command, payload) {
@@ -6175,6 +6227,15 @@ function createSuperDocUI(options) {
6175
6227
  const target = trackDecisionRangeFromSelection(state.selection);
6176
6228
  return target ? executeTrackDecisionTarget(command.kind, target, null) : false;
6177
6229
  }
6230
+ if (route === "id") {
6231
+ const activeId = state.selection.activeChangeIds[0];
6232
+ const selectedStory = selectionStoryLocator(state.selection);
6233
+ const story = selectedStory && storyLocatorSignature(selectedStory) !== storyLocatorSignature(null) ? selectedStory : void 0;
6234
+ return executeTrackDecision(command.kind, story ? {
6235
+ id: activeId,
6236
+ story
6237
+ } : activeId);
6238
+ }
6178
6239
  }
6179
6240
  }
6180
6241
  const resolved = resolveTrackDecisionTarget(command, payload);
@@ -7699,11 +7760,12 @@ function createSuperDocUI(options) {
7699
7760
  reason: SUPERDOC_UI_REASONS.hostCapabilityUnavailable
7700
7761
  };
7701
7762
  try {
7702
- const result = await Promise.resolve(scroll.call(host, {
7763
+ const input = {
7703
7764
  target,
7704
7765
  block: options$1?.block ?? "center",
7705
7766
  behavior: options$1?.behavior ?? "smooth"
7706
- }));
7767
+ };
7768
+ const result = await Promise.resolve(options$1?.shouldContinue ? scroll.call(host, input, options$1.shouldContinue) : scroll.call(host, input));
7707
7769
  if (result && typeof result === "object" && result.success === false) return {
7708
7770
  success: false,
7709
7771
  ok: false,
@@ -7733,19 +7795,32 @@ function createSuperDocUI(options) {
7733
7795
  story: requestedStory
7734
7796
  };
7735
7797
  };
7736
- const fromList = readEntityTarget(loaded.find((row) => entityRowMatchesRequest(row, id, requestedStory)));
7737
- if (fromList) return withRequestedStory(fromList);
7798
+ const readTarget = namespace === "trackChanges" ? readTrackedChangeNavigationTarget : readEntityTarget;
7799
+ const loadedRow = loaded.find((row) => entityRowMatchesRequest(row, id, requestedStory));
7800
+ const loadedRecord = loadedRow && typeof loadedRow === "object" ? loadedRow : null;
7801
+ const moveSide = namespace === "trackChanges" && loadedRecord?.type === "move" && (loadedRecord.subtype === "move-to" || loadedRecord.subtype === "move-from") ? loadedRecord.subtype : null;
7802
+ const trackedChangeLookupId = moveSide && typeof loadedRecord?.trackedChangeCanonicalId === "string" ? loadedRecord.trackedChangeCanonicalId : id;
7803
+ const readResolvedTarget = (row) => {
7804
+ if (!moveSide) return readTarget(row);
7805
+ const moveTarget = readEntityTarget(row);
7806
+ if (moveTarget?.kind !== "move") return null;
7807
+ const sideTarget = moveSide === "move-to" ? moveTarget.destination : moveTarget.source;
7808
+ return isHostGeometryTarget(sideTarget) ? sideTarget : null;
7809
+ };
7810
+ const fromList = readTarget(loadedRow);
7811
+ const listTargetIsAuthoritative = namespace !== "trackChanges" || !moveSide && isHostGeometryTarget(readEntityTarget(loadedRow));
7812
+ if (fromList && listTargetIsAuthoritative) return withRequestedStory(fromList);
7738
7813
  const api = getDoc()?.[namespace];
7739
7814
  const input = namespace === "comments" ? { commentId: id } : {
7740
- id,
7815
+ id: trackedChangeLookupId,
7741
7816
  ...requestedStory ? { story: requestedStory } : {}
7742
7817
  };
7743
7818
  const get = api?.get;
7744
- if (typeof get !== "function") return null;
7819
+ if (typeof get !== "function") return withRequestedStory(fromList);
7745
7820
  try {
7746
- return withRequestedStory(readEntityTarget(await Promise.resolve(get.call(api, input))));
7821
+ return withRequestedStory(readResolvedTarget(await Promise.resolve(get.call(api, input))) ?? fromList);
7747
7822
  } catch {
7748
- return null;
7823
+ return withRequestedStory(fromList);
7749
7824
  }
7750
7825
  };
7751
7826
  function patchCommentStatus(commentId, status) {
@@ -7907,33 +7982,41 @@ function createSuperDocUI(options) {
7907
7982
  if (activeId == null) return { success: false };
7908
7983
  const optimisticActiveChange = explicitActiveChange;
7909
7984
  const optimisticRevision = explicitActiveChangeRevision;
7910
- const isCurrent = () => explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
7985
+ const isCurrent = () => queuedTrackChangeNavigationInvalidation === requestedAtInvalidation && explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
7911
7986
  const rollback = () => {
7912
7987
  if (!isCurrent()) return;
7913
7988
  setExplicitActiveChange(previousActiveChange, { invalidateQueuedNavigation: false });
7914
7989
  recompute();
7915
7990
  };
7916
- const target = await resolveEntityTarget("trackChanges", activeId, trackChangesSub.get().items, optimisticActiveChange?.story ? { story: optimisticActiveChange.story } : void 0);
7917
- if (!isCurrent()) return { success: false };
7918
- if (!target) {
7919
- rollback();
7920
- return { success: false };
7921
- }
7922
- trackedChangeNavigationInFlight += 1;
7991
+ if (optimisticActiveChange) pendingTrackChangeRevealFocuses.add(optimisticActiveChange);
7923
7992
  try {
7924
- const result = await scrollTargetIntoView(target, { behavior: "auto" });
7993
+ const target = await resolveEntityTarget("trackChanges", activeId, trackChangesSub.get().items, optimisticActiveChange?.story ? { story: optimisticActiveChange.story } : void 0);
7925
7994
  if (!isCurrent()) return { success: false };
7926
- if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
7995
+ if (!target) {
7927
7996
  rollback();
7928
- mirrorTrackedChangeFocusToHost(previousActiveChange);
7929
- } else mirrorTrackedChangeFocusToHost(optimisticActiveChange);
7930
- return { success: result.ok };
7931
- } finally {
7932
- trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
7933
- if (trackedChangeNavigationInFlight === 0) {
7934
- if (!isCurrent()) mirrorTrackedChangeFocusToHost(explicitActiveChange);
7935
- else if (currentHostReviewSource) syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(currentHostReviewSource));
7997
+ return { success: false };
7998
+ }
7999
+ trackedChangeNavigationInFlight += 1;
8000
+ try {
8001
+ const result = await scrollTargetIntoView(target, {
8002
+ behavior: "auto",
8003
+ shouldContinue: isCurrent
8004
+ });
8005
+ if (!isCurrent()) return { success: false };
8006
+ if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
8007
+ rollback();
8008
+ mirrorTrackedChangeFocusToHost(previousActiveChange);
8009
+ } else mirrorTrackedChangeFocusToHost(optimisticActiveChange);
8010
+ return { success: result.ok };
8011
+ } finally {
8012
+ trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
8013
+ if (trackedChangeNavigationInFlight === 0) {
8014
+ if (!isCurrent()) mirrorTrackedChangeFocusToHost(explicitActiveChange);
8015
+ else if (currentHostReviewSource) syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(currentHostReviewSource));
8016
+ }
7936
8017
  }
8018
+ } finally {
8019
+ if (optimisticActiveChange) pendingTrackChangeRevealFocuses.delete(optimisticActiveChange);
7937
8020
  }
7938
8021
  };
7939
8022
  const navigateAndScroll = (step) => {
@@ -8035,47 +8118,65 @@ function createSuperDocUI(options) {
8035
8118
  ok: false,
8036
8119
  reason: getEditor() ? SUPERDOC_UI_REASONS.documentApiUnavailable : SUPERDOC_UI_REASONS.notReady
8037
8120
  };
8121
+ queuedTrackChangeNavigationInvalidation += 1;
8122
+ trackChangeRevealInvalidation += 1;
8123
+ const requestedAtInvalidation = trackChangeRevealInvalidation;
8038
8124
  const loadedItems = trackChangesSub.get().items;
8039
- const story = readEntityRequestStory(loadedItems.find((item) => readEntityId(item) === changeId));
8040
- const target = await resolveEntityTarget("trackChanges", changeId, loadedItems, story ? { story } : void 0);
8041
- if (!target) return {
8042
- success: false,
8043
- ok: false,
8044
- reason: SUPERDOC_UI_REASONS.targetUnresolved
8045
- };
8125
+ const publicId = buildTrackedChangeIdContext(loadedItems).toPublicId(changeId) ?? changeId;
8126
+ const story = readEntityRequestStory(loadedItems.find((item) => readEntityId(item) === publicId));
8046
8127
  const previousActiveChange = explicitActiveChange;
8047
- const requestedActiveChange = story ? {
8048
- id: changeId,
8049
- story
8050
- } : { id: changeId };
8051
- setExplicitActiveChange(requestedActiveChange);
8052
- recompute();
8053
- const optimisticActiveChange = explicitActiveChange;
8054
- const optimisticRevision = explicitActiveChangeRevision;
8055
- const isCurrent = () => explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
8056
- const rollback = () => {
8057
- if (!isCurrent()) return;
8058
- setExplicitActiveChange(previousActiveChange, { invalidateQueuedNavigation: false });
8059
- recompute();
8128
+ const requestedActiveChange = {
8129
+ id: publicId,
8130
+ ...story ? { story } : {},
8131
+ ...publicId !== changeId ? { paintedEntityId: changeId } : {}
8060
8132
  };
8061
- trackedChangeNavigationInFlight += 1;
8133
+ pendingTrackChangeRevealFocuses.add(requestedActiveChange);
8062
8134
  try {
8063
- const result = await scrollTargetIntoView(target, { behavior: "auto" });
8064
- if (!isCurrent()) return {
8135
+ const target = await resolveEntityTarget("trackChanges", publicId, loadedItems, story ? { story } : void 0);
8136
+ if (trackChangeRevealInvalidation !== requestedAtInvalidation) return {
8065
8137
  success: false,
8066
8138
  ok: false
8067
8139
  };
8068
- if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
8069
- rollback();
8070
- mirrorTrackedChangeFocusToHost(previousActiveChange);
8071
- } else mirrorTrackedChangeFocusToHost(requestedActiveChange);
8072
- return result;
8073
- } finally {
8074
- trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
8075
- if (trackedChangeNavigationInFlight === 0) {
8076
- if (!isCurrent()) mirrorTrackedChangeFocusToHost(explicitActiveChange);
8077
- else if (currentHostReviewSource) syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(currentHostReviewSource));
8140
+ if (!target) return {
8141
+ success: false,
8142
+ ok: false,
8143
+ reason: SUPERDOC_UI_REASONS.targetUnresolved
8144
+ };
8145
+ setExplicitActiveChange(requestedActiveChange);
8146
+ const revealInvalidation = trackChangeRevealInvalidation;
8147
+ const optimisticActiveChange = explicitActiveChange;
8148
+ const optimisticRevision = explicitActiveChangeRevision;
8149
+ const isCurrent = () => trackChangeRevealInvalidation === revealInvalidation && explicitActiveChange === optimisticActiveChange && explicitActiveChangeRevision === optimisticRevision;
8150
+ const rollback = () => {
8151
+ if (!isCurrent()) return;
8152
+ setExplicitActiveChange(previousActiveChange, { invalidateQueuedNavigation: false });
8153
+ recompute();
8154
+ };
8155
+ recompute();
8156
+ trackedChangeNavigationInFlight += 1;
8157
+ try {
8158
+ const result = await scrollTargetIntoView(target, {
8159
+ behavior: "auto",
8160
+ shouldContinue: isCurrent
8161
+ });
8162
+ if (!isCurrent()) return {
8163
+ success: false,
8164
+ ok: false
8165
+ };
8166
+ if (!result.ok && result.reason !== SUPERDOC_UI_REASONS.targetNotVisible) {
8167
+ rollback();
8168
+ mirrorTrackedChangeFocusToHost(previousActiveChange);
8169
+ } else mirrorTrackedChangeFocusToHost(requestedActiveChange);
8170
+ return result;
8171
+ } finally {
8172
+ trackedChangeNavigationInFlight = Math.max(0, trackedChangeNavigationInFlight - 1);
8173
+ if (trackedChangeNavigationInFlight === 0) {
8174
+ if (!isCurrent()) mirrorTrackedChangeFocusToHost(explicitActiveChange);
8175
+ else if (currentHostReviewSource) syncTrackedChangeFocusFromHostReviewTarget(readHostActiveReviewTarget(currentHostReviewSource));
8176
+ }
8078
8177
  }
8178
+ } finally {
8179
+ pendingTrackChangeRevealFocuses.delete(requestedActiveChange);
8079
8180
  }
8080
8181
  }
8081
8182
  };
@@ -7,7 +7,7 @@ const COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
7
7
  var PRIVATE_ENGINE_INFO = (0, __superdoc_docx_engine_collaboration_upgrade_engine.getCollaborationUpgradeEngineInfo)();
8
8
  var ENGINE_INFO = Object.freeze({
9
9
  ...PRIVATE_ENGINE_INFO,
10
- superdocVersion: "2.0.0-next.50",
10
+ superdocVersion: "2.0.0-next.52",
11
11
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
12
12
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
13
13
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -6,7 +6,7 @@ const COLLABORATION_UPGRADE_ENGINE_MINIMUM_NODE_MAJOR = 20;
6
6
  var PRIVATE_ENGINE_INFO = getCollaborationUpgradeEngineInfo$1();
7
7
  var ENGINE_INFO = Object.freeze({
8
8
  ...PRIVATE_ENGINE_INFO,
9
- superdocVersion: "2.0.0-next.50",
9
+ superdocVersion: "2.0.0-next.52",
10
10
  roomSchemaVersion: Object.freeze({ ...PRIVATE_ENGINE_INFO.roomSchemaVersion }),
11
11
  supportedBundleVersions: SUPPORTED_COLLABORATION_UPGRADE_BUNDLE_VERSIONS,
12
12
  supportedV1ReaderContractVersions: SUPPORTED_V1_READER_CONTRACT_VERSIONS
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("../chunks/rolldown-runtime-_dR15c8t.cjs");
3
- const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-DlSN0ENQ.cjs");
3
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CMnnWkHC.cjs");
4
4
  let react = require("react");
5
5
  var SuperDocUIContext = (0, react.createContext)(null);
6
6
  function disposeOwnedUi(ref) {
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-D4UDePxr.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-9N3-Jxnj.es.js";
2
2
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  var SuperDocUIContext = createContext(null);
4
4
  function disposeOwnedUi(ref) {
@@ -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-DlSN0ENQ.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-CMnnWkHC.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;
@@ -1,2 +1,2 @@
1
- import { n as shallowEqual, r as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-D4UDePxr.es.js";
1
+ import { n as shallowEqual, r as BUILT_IN_COMMAND_IDS, t as createSuperDocUI } from "../chunks/create-super-doc-ui-9N3-Jxnj.es.js";
2
2
  export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };