superdoc 2.12.0-next.8 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/chunks/{FindReplaceSurface-40AnrqWk.es.js → FindReplaceSurface-CVKgivXi.es.js} +8 -2
  2. package/dist/chunks/{FindReplaceSurface-0p7EtMZh.cjs → FindReplaceSurface-qi9OhbwN.cjs} +8 -2
  3. package/dist/chunks/{create-super-doc-ui-CBFGggZ2.cjs → create-super-doc-ui-BWWWNPP8.cjs} +180 -84
  4. package/dist/chunks/{create-super-doc-ui-C-AuEM9F.es.js → create-super-doc-ui-FnwgTkUv.es.js} +180 -84
  5. package/dist/collaboration-upgrade-engine.cjs +1 -1
  6. package/dist/collaboration-upgrade-engine.es.js +1 -1
  7. package/dist/layout-engine/contracts/src/column-layout.d.ts +58 -1
  8. package/dist/layout-engine/contracts/src/graphic-placement.d.ts +3 -0
  9. package/dist/layout-engine/contracts/src/index.d.ts +17 -3
  10. package/dist/layout-engine/contracts/src/run-helpers.d.ts +8 -0
  11. package/dist/layout-engine/layout-bridge/src/cache.d.ts +5 -4
  12. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +4 -1
  13. package/dist/layout-engine/layout-bridge/src/note-marker-measure-key.d.ts +3 -0
  14. package/dist/layout-engine/layout-engine/src/column-balancing.d.ts +11 -7
  15. package/dist/layout-engine/layout-engine/src/layout-paragraph.d.ts +2 -6
  16. package/dist/layout-engine/painters/dom/src/derived-run-text-plane.d.ts +9 -0
  17. package/dist/layout-engine/painters/dom/src/index.d.ts +1 -0
  18. package/dist/layout-engine/painters/dom/src/page-content.d.ts +3 -1
  19. package/dist/layout-engine/painters/dom/src/persistent-page-surface.d.ts +2 -0
  20. package/dist/layout-engine/painters/dom/src/renderer.d.ts +9 -16
  21. package/dist/public/ui-react.cjs +18 -1
  22. package/dist/public/ui-react.es.js +18 -2
  23. package/dist/public/ui-vue.cjs +18 -1
  24. package/dist/public/ui-vue.es.js +18 -2
  25. package/dist/public/ui.cjs +1 -1
  26. package/dist/public/ui.es.js +1 -1
  27. package/dist/shared/font-system/src/index.d.ts +1 -1
  28. package/dist/shared/font-system/src/resolver.d.ts +11 -0
  29. package/dist/style.css +40 -40
  30. package/dist/style.layered.css +40 -40
  31. package/dist/superdoc/src/core/types/index.d.ts +20 -12
  32. package/dist/superdoc/src/public/ui/react.d.ts +3 -1
  33. package/dist/superdoc/src/public/ui/types.d.ts +67 -9
  34. package/dist/superdoc/src/public/ui/vue.d.ts +3 -1
  35. package/dist/superdoc/src/public/ui-react.d.cts +1 -0
  36. package/dist/superdoc/src/public/ui-react.d.ts +1 -1
  37. package/dist/superdoc/src/public/ui-vue.d.cts +1 -0
  38. package/dist/superdoc/src/public/ui-vue.d.ts +1 -1
  39. package/dist/superdoc.cjs +138 -12
  40. package/dist/superdoc.es.js +138 -12
  41. package/dist-cdn/style.layered.css +1 -1
  42. package/dist-cdn/superdoc.min.css +1 -1
  43. package/dist-cdn/superdoc.min.js +37 -37
  44. package/package.json +2 -2
@@ -106,6 +106,12 @@ var FindReplaceSurface_default = /*#__PURE__*/ _plugin_vue_export_helper_default
106
106
  if (fr.canReplace && fr.canReplace.value === false) return true;
107
107
  return false;
108
108
  });
109
+ const replaceAllDisabled = computed(() => {
110
+ if (replaceDisabled.value) return true;
111
+ const fr = props.findReplace;
112
+ if (fr.canReplaceAll && fr.canReplaceAll.value === false) return true;
113
+ return false;
114
+ });
109
115
  const showIgnoreDiacritics = computed(() => props.findReplace.ignoreDiacriticsSupported?.value !== false);
110
116
  const showReplaceControls = computed(() => props.findReplace.replaceEnabled && props.findReplace.replaceCanMutate?.value !== false);
111
117
  const showRegexToggle = computed(() => props.findReplace.regexSupported?.value === true);
@@ -331,7 +337,7 @@ var FindReplaceSurface_default = /*#__PURE__*/ _plugin_vue_export_helper_default
331
337
  }, toDisplayString(__props.findReplace.texts.replaceLabel), 9, _hoisted_17), createElementVNode("button", {
332
338
  type: "button",
333
339
  class: "sd-find-replace__btn sd-find-replace__btn--action",
334
- disabled: replaceDisabled.value,
340
+ disabled: replaceAllDisabled.value,
335
341
  title: __props.findReplace.texts.replaceAllLabel,
336
342
  onClick: _cache[13] || (_cache[13] = ($event) => __props.findReplace.replaceAll())
337
343
  }, toDisplayString(__props.findReplace.texts.replaceAllLabel), 9, _hoisted_18)])
@@ -340,6 +346,6 @@ var FindReplaceSurface_default = /*#__PURE__*/ _plugin_vue_export_helper_default
340
346
  ], 40, _hoisted_1);
341
347
  };
342
348
  }
343
- }, [["__scopeId", "data-v-41f37c29"]]);
349
+ }, [["__scopeId", "data-v-5dba4c36"]]);
344
350
  //#endregion
345
351
  export { FindReplaceSurface_default as default };
@@ -106,6 +106,12 @@ var _sfc_main = {
106
106
  if (fr.canReplace && fr.canReplace.value === false) return true;
107
107
  return false;
108
108
  });
109
+ const replaceAllDisabled = (0, vue.computed)(() => {
110
+ if (replaceDisabled.value) return true;
111
+ const fr = props.findReplace;
112
+ if (fr.canReplaceAll && fr.canReplaceAll.value === false) return true;
113
+ return false;
114
+ });
109
115
  const showIgnoreDiacritics = (0, vue.computed)(() => props.findReplace.ignoreDiacriticsSupported?.value !== false);
110
116
  const showReplaceControls = (0, vue.computed)(() => props.findReplace.replaceEnabled && props.findReplace.replaceCanMutate?.value !== false);
111
117
  const showRegexToggle = (0, vue.computed)(() => props.findReplace.regexSupported?.value === true);
@@ -331,7 +337,7 @@ var _sfc_main = {
331
337
  }, (0, vue.toDisplayString)(__props.findReplace.texts.replaceLabel), 9, _hoisted_17), (0, vue.createElementVNode)("button", {
332
338
  type: "button",
333
339
  class: "sd-find-replace__btn sd-find-replace__btn--action",
334
- disabled: replaceDisabled.value,
340
+ disabled: replaceAllDisabled.value,
335
341
  title: __props.findReplace.texts.replaceAllLabel,
336
342
  onClick: _cache[13] || (_cache[13] = ($event) => __props.findReplace.replaceAll())
337
343
  }, (0, vue.toDisplayString)(__props.findReplace.texts.replaceAllLabel), 9, _hoisted_18)])
@@ -341,6 +347,6 @@ var _sfc_main = {
341
347
  };
342
348
  }
343
349
  };
344
- var FindReplaceSurface_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main, [["__scopeId", "data-v-41f37c29"]]);
350
+ var FindReplaceSurface_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_vue_export_helper_default(_sfc_main, [["__scopeId", "data-v-5dba4c36"]]);
345
351
  //#endregion
346
352
  exports.default = FindReplaceSurface_default;
@@ -3553,7 +3553,8 @@ function createSuperDocUI(options) {
3553
3553
  try {
3554
3554
  surface.close();
3555
3555
  } catch {}
3556
- }
3556
+ },
3557
+ contextAt
3557
3558
  };
3558
3559
  /** Read the live browser Document API facade (or null). */
3559
3560
  const getDoc = () => {
@@ -4071,8 +4072,11 @@ function createSuperDocUI(options) {
4071
4072
  const incompleteTrackChangesDirectoryReadTokens = /* @__PURE__ */ new Map();
4072
4073
  const postSourceCompletionRefreshTokens = /* @__PURE__ */ new Map();
4073
4074
  let sourceCompletionObservedToken = null;
4074
- let commentsDirectoryLeaseCount = 0;
4075
- let trackChangesDirectoryLeaseCount = 0;
4075
+ const directoryLeaseCounts = {
4076
+ comments: 0,
4077
+ trackChanges: 0,
4078
+ contentControls: 0
4079
+ };
4076
4080
  const demandHeavyDocRead = (key) => {
4077
4081
  const token = contentToken();
4078
4082
  if (demandedHeavyReads.get(key) === token) return;
@@ -4107,16 +4111,14 @@ function createSuperDocUI(options) {
4107
4111
  if (invalidated) scheduleAsyncRefresh();
4108
4112
  };
4109
4113
  const acquireDirectoryLease = (family) => {
4110
- if (family === "comments") commentsDirectoryLeaseCount += 1;
4111
- else trackChangesDirectoryLeaseCount += 1;
4114
+ directoryLeaseCounts[family] += 1;
4112
4115
  demandHeavyDocRead(family);
4113
4116
  let released = false;
4114
4117
  return () => {
4115
4118
  if (released) return;
4116
4119
  released = true;
4117
- if (family === "comments") commentsDirectoryLeaseCount = Math.max(0, commentsDirectoryLeaseCount - 1);
4118
- else trackChangesDirectoryLeaseCount = Math.max(0, trackChangesDirectoryLeaseCount - 1);
4119
- if ((family === "comments" ? commentsDirectoryLeaseCount : trackChangesDirectoryLeaseCount) === 0 && demandedHeavyReads.get(family) === contentToken()) demandedHeavyReads.delete(family);
4120
+ directoryLeaseCounts[family] = Math.max(0, directoryLeaseCounts[family] - 1);
4121
+ if (directoryLeaseCounts[family] === 0 && demandedHeavyReads.get(family) === contentToken()) demandedHeavyReads.delete(family);
4120
4122
  scheduleAsyncRefresh();
4121
4123
  };
4122
4124
  };
@@ -4887,7 +4889,7 @@ function createSuperDocUI(options) {
4887
4889
  const activeIds = selection.activeCommentIds;
4888
4890
  const directory = asyncReads.get("comments");
4889
4891
  const directoryItems = directory?.token === contentToken() && directory.hasSettled && Array.isArray(directory.value) ? directory.value : null;
4890
- const activeValidationItems = commentsDirectoryLeaseCount > 0 ? directoryItems : items;
4892
+ const activeValidationItems = directoryLeaseCounts.comments > 0 ? directoryItems : items;
4891
4893
  if (explicitActiveCommentId && activeValidationItems && !activeValidationItems.some((item) => readEntityId(item) === explicitActiveCommentId)) explicitActiveCommentId = null;
4892
4894
  const activeId = explicitActiveCommentId ?? activeIds[0] ?? null;
4893
4895
  return {
@@ -4962,7 +4964,7 @@ function createSuperDocUI(options) {
4962
4964
  if (active && !pendingTrackChangeRevealFocuses.has(active)) {
4963
4965
  const directory = asyncReads.get("trackChanges");
4964
4966
  const directoryItems = directory?.token === token && directory.hasSettled && Array.isArray(directory.value) ? filterPostDecisionTrackChanges(projectTrackChangesItems(directory.value), postDecisionIds) : null;
4965
- const activeValidationItems = trackChangesDirectoryLeaseCount > 0 ? directoryItems : active.story ? allStoryItems : items;
4967
+ const activeValidationItems = directoryLeaseCounts.trackChanges > 0 ? directoryItems : active.story ? allStoryItems : items;
4966
4968
  if (activeValidationItems && !activeValidationItems.some((row) => entityRowMatchesRequest(row, active.id, active.story))) setExplicitActiveChange(null);
4967
4969
  }
4968
4970
  const publicIdItems = allStoryItems ?? items;
@@ -7242,6 +7244,12 @@ function createSuperDocUI(options) {
7242
7244
  * reports the previous document's match count.
7243
7245
  */
7244
7246
  const documentResetHooks = [];
7247
+ /**
7248
+ * Slices that publish through their own listener set rather than the
7249
+ * aggregate `listeners`. `recompute()` never reaches them, so a mode change
7250
+ * that alters what the host reports must republish them explicitly.
7251
+ */
7252
+ const documentModeChangeHooks = [];
7245
7253
  const runHooks = (hooks) => {
7246
7254
  for (const reset of hooks) try {
7247
7255
  reset();
@@ -7249,6 +7257,7 @@ function createSuperDocUI(options) {
7249
7257
  };
7250
7258
  const runActiveEditorResetHooks = () => runHooks(activeEditorResetHooks);
7251
7259
  const runDocumentResetHooks = () => runHooks(documentResetHooks);
7260
+ const runDocumentModeChangeHooks = () => runHooks(documentModeChangeHooks);
7252
7261
  const detachers = [];
7253
7262
  const attach = (source, events) => {
7254
7263
  if (!source || typeof source.on !== "function") return;
@@ -7268,6 +7277,9 @@ function createSuperDocUI(options) {
7268
7277
  asyncReads.clear();
7269
7278
  invalidateDocumentContent();
7270
7279
  recompute();
7280
+ } : event === "document-mode-change" ? () => {
7281
+ recompute();
7282
+ runDocumentModeChangeHooks();
7271
7283
  } : () => recompute();
7272
7284
  try {
7273
7285
  source.on(event, handler);
@@ -7453,11 +7465,8 @@ function createSuperDocUI(options) {
7453
7465
  return false;
7454
7466
  }
7455
7467
  }
7456
- function resolveTrackDecisionTarget(command, payload) {
7457
- if (command.scope === "all") return {
7458
- target: { kind: "all" },
7459
- changeId: null
7460
- };
7468
+ /** A decision target carried by the payload itself, independent of the selection. */
7469
+ function explicitTrackDecisionTarget(payload) {
7461
7470
  if (typeof payload === "string" && payload.length > 0) return {
7462
7471
  target: {
7463
7472
  kind: "id",
@@ -7482,6 +7491,15 @@ function createSuperDocUI(options) {
7482
7491
  story: record.story
7483
7492
  };
7484
7493
  }
7494
+ return null;
7495
+ }
7496
+ function resolveTrackDecisionTarget(command, payload) {
7497
+ if (command.scope === "all") return {
7498
+ target: { kind: "all" },
7499
+ changeId: null
7500
+ };
7501
+ const explicit = explicitTrackDecisionTarget(payload);
7502
+ if (explicit) return explicit;
7485
7503
  const selectedId = state.selection.activeChangeIds[0];
7486
7504
  const story = nonBodySelectionStoryLocator(state.selection);
7487
7505
  return selectedId ? {
@@ -8435,6 +8453,7 @@ function createSuperDocUI(options) {
8435
8453
  const commandNeedsFreshSelection = (id, payload) => {
8436
8454
  const trackCommand = trackDecisionCommand(id);
8437
8455
  const descriptor = getCommandDescriptor(id);
8456
+ if (trackCommand?.scope === "id" && explicitTrackDecisionTarget(payload)) return false;
8438
8457
  if (trackCommand?.scope !== "id" && !descriptorNeedsFreshSelection(descriptor)) return false;
8439
8458
  return !commandSelectionIsReady(id, descriptor, payload);
8440
8459
  };
@@ -9212,6 +9231,7 @@ function createSuperDocUI(options) {
9212
9231
  */
9213
9232
  const resolveEntityTarget = async (namespace, id, loaded, request) => {
9214
9233
  const requestedStory = namespace === "trackChanges" ? request?.story : void 0;
9234
+ const rowStory = namespace === "trackChanges" ? request?.matchStory ?? requestedStory : void 0;
9215
9235
  const withRequestedStory = (target) => {
9216
9236
  if (!requestedStory || !target || typeof target !== "object") return target;
9217
9237
  const record = target;
@@ -9223,7 +9243,7 @@ function createSuperDocUI(options) {
9223
9243
  };
9224
9244
  };
9225
9245
  const readTarget = namespace === "trackChanges" ? readTrackedChangeNavigationTarget : readEntityTarget;
9226
- const loadedRow = loaded.find((row) => entityRowMatchesRequest(row, id, requestedStory));
9246
+ const loadedRow = loaded.find((row) => entityRowMatchesRequest(row, id, rowStory));
9227
9247
  const loadedRecord = loadedRow && typeof loadedRow === "object" ? loadedRow : null;
9228
9248
  const moveSide = namespace === "trackChanges" && loadedRecord?.type === "move" && (loadedRecord.subtype === "move-to" || loadedRecord.subtype === "move-from") ? loadedRecord.subtype : null;
9229
9249
  const trackedChangeLookupId = moveSide && typeof loadedRecord?.trackedChangeCanonicalId === "string" ? loadedRecord.trackedChangeCanonicalId : id;
@@ -9517,9 +9537,13 @@ function createSuperDocUI(options) {
9517
9537
  });
9518
9538
  },
9519
9539
  accept: (changeId) => executeTrackDecision("accept", changeId),
9540
+ acceptAsync: (changeId) => settleTrackDecision(() => executeTrackDecision("accept", changeId)),
9520
9541
  reject: (changeId) => executeTrackDecision("reject", changeId),
9542
+ rejectAsync: (changeId) => settleTrackDecision(() => executeTrackDecision("reject", changeId)),
9521
9543
  acceptAll: () => executeTrackDecisionTarget("accept", { kind: "all" }, null),
9544
+ acceptAllAsync: () => settleTrackDecision(() => executeTrackDecisionTarget("accept", { kind: "all" }, null)),
9522
9545
  rejectAll: () => executeTrackDecisionTarget("reject", { kind: "all" }, null),
9546
+ rejectAllAsync: () => settleTrackDecision(() => executeTrackDecisionTarget("reject", { kind: "all" }, null)),
9523
9547
  next: () => navigateTrackChange(1),
9524
9548
  previous: () => navigateTrackChange(-1),
9525
9549
  navigateNext: () => navigateAndScroll(1),
@@ -9584,19 +9608,27 @@ function createSuperDocUI(options) {
9584
9608
  recompute();
9585
9609
  return true;
9586
9610
  },
9587
- scrollTo: async (changeId) => {
9611
+ scrollTo: async (input) => {
9588
9612
  if (!getDoc()) return {
9589
9613
  success: false,
9590
9614
  ok: false,
9591
9615
  reason: getEditor() ? SUPERDOC_UI_REASONS.documentApiUnavailable : SUPERDOC_UI_REASONS.notReady
9592
9616
  };
9617
+ const changeId = typeof input === "string" ? input : input.id;
9618
+ const matchStory = typeof input === "string" || !input.story || typeof input.story !== "object" ? void 0 : input.story;
9619
+ const requestedStory = matchStory ? readEntityRequestStory({ address: { story: matchStory } }) : void 0;
9620
+ if (typeof changeId !== "string" || changeId.length === 0) return {
9621
+ success: false,
9622
+ ok: false,
9623
+ reason: SUPERDOC_UI_REASONS.targetUnresolved
9624
+ };
9593
9625
  queuedTrackChangeNavigationInvalidation += 1;
9594
9626
  trackChangeRevealInvalidation += 1;
9595
9627
  const requestedAtInvalidation = trackChangeRevealInvalidation;
9596
- const loadedItems = trackChangesSub.get().items;
9597
- const publicId = buildTrackedChangeIdContext(loadedItems).toPublicId(changeId) ?? changeId;
9598
- const matchingRow = loadedItems.find((item) => readEntityId(item) === publicId);
9599
- const story = readEntityRequestStory(matchingRow);
9628
+ const loadedItems = matchStory ? readAllStoryTrackChanges() ?? trackChangesSub.get().items : trackChangesSub.get().items;
9629
+ const publicId = matchStory ? buildStoryScopedTrackedChangeIdContext(loadedItems, matchStory).toPublicId(changeId) ?? changeId : buildTrackedChangeIdContext(loadedItems).toPublicId(changeId) ?? changeId;
9630
+ const matchingRow = matchStory ? loadedItems.find((item) => entityRowMatchesRequest(item, publicId, matchStory)) : loadedItems.find((item) => readEntityId(item) === publicId);
9631
+ const story = matchStory ? requestedStory : readEntityRequestStory(matchingRow);
9600
9632
  const importedId = deriveTrackedChangeImportedId(matchingRow);
9601
9633
  const previousActiveChange = explicitActiveChange;
9602
9634
  const requestedActiveChange = {
@@ -9606,7 +9638,10 @@ function createSuperDocUI(options) {
9606
9638
  };
9607
9639
  pendingTrackChangeRevealFocuses.add(requestedActiveChange);
9608
9640
  try {
9609
- const target = await resolveEntityTarget("trackChanges", publicId, loadedItems, story ? { story } : void 0);
9641
+ const target = await resolveEntityTarget("trackChanges", publicId, loadedItems, story || matchStory ? {
9642
+ story,
9643
+ matchStory
9644
+ } : void 0);
9610
9645
  if (trackChangeRevealInvalidation !== requestedAtInvalidation) return {
9611
9646
  success: false,
9612
9647
  ok: false
@@ -9666,6 +9701,7 @@ function createSuperDocUI(options) {
9666
9701
  id: input,
9667
9702
  story: void 0
9668
9703
  } : input;
9704
+ if (typeof id !== "string" || id.length === 0) return false;
9669
9705
  const target = {
9670
9706
  kind: "id",
9671
9707
  id,
@@ -9673,6 +9709,19 @@ function createSuperDocUI(options) {
9673
9709
  };
9674
9710
  return executeTrackDecisionTarget(kind, target, id, story);
9675
9711
  };
9712
+ /**
9713
+ * Run a domain decision and resolve with its settled result. The domain
9714
+ * helpers call the decision route directly so an application command that
9715
+ * reuses a built-in tracked-change id cannot intercept them; only the command
9716
+ * registry (`commands.execute*`) honours those overrides.
9717
+ */
9718
+ const settleTrackDecision = (run) => {
9719
+ pendingCommandSettlement = null;
9720
+ lastCommandSettlement = Promise.resolve(false);
9721
+ if (disposed) return Promise.resolve(false);
9722
+ if (run() === false) return Promise.resolve(false);
9723
+ return lastCommandSettlement;
9724
+ };
9676
9725
  const executeTrackDecisionTarget = (kind, target, changeId, story) => {
9677
9726
  try {
9678
9727
  return settleCommandExecution(callTrackDecisionTarget(kind, target, changeId, story));
@@ -9705,12 +9754,16 @@ function createSuperDocUI(options) {
9705
9754
  const findContentControl = (id) => {
9706
9755
  return contentControlsSub.get().items.find((item) => item?.id === id) ?? null;
9707
9756
  };
9708
- const contentControlsSnap = snapshotHandle(contentControlsSub);
9757
+ const contentControlsSnap = directorySnapshotHandle(contentControlsSub, select((s) => {
9758
+ if (directoryLeaseCounts.contentControls > 0) demandHeavyDocRead("contentControls");
9759
+ return s.contentControls;
9760
+ }), "contentControls");
9709
9761
  const contentControlsGet = ((input) => {
9710
9762
  if (input === void 0) return contentControlsSnap.get();
9711
9763
  const id = readContentControlRequestId(input);
9712
9764
  return id ? findContentControl(id) : null;
9713
9765
  });
9766
+ const contentControlsPassiveSnap = snapshotHandle(contentControlsSub);
9714
9767
  const contentControls = {
9715
9768
  get: ((input) => {
9716
9769
  if (input !== void 0) ensureContentControlsCatalog("api");
@@ -9719,6 +9772,7 @@ function createSuperDocUI(options) {
9719
9772
  getSnapshot: contentControlsSnap.getSnapshot,
9720
9773
  subscribe: contentControlsSnap.subscribe,
9721
9774
  observe: contentControlsSnap.observe,
9775
+ observeActivePath: contentControlsPassiveSnap.observe,
9722
9776
  list: () => {
9723
9777
  ensureContentControlsCatalog("api");
9724
9778
  return contentControlsSub.get().items;
@@ -9958,6 +10012,23 @@ function createSuperDocUI(options) {
9958
10012
  if (typeof xOrInput === "object") return pointEntityHits(xOrInput?.x, xOrInput?.y);
9959
10013
  return null;
9960
10014
  }
10015
+ function contextAt(input) {
10016
+ const validInput = !!input && typeof input.x === "number" && typeof input.y === "number";
10017
+ const point = validInput ? {
10018
+ x: input.x,
10019
+ y: input.y
10020
+ } : {
10021
+ x: 0,
10022
+ y: 0
10023
+ };
10024
+ return {
10025
+ point,
10026
+ entities: validInput ? entityAt(point) : [],
10027
+ selection: state.selection,
10028
+ position: null,
10029
+ insideSelection: false
10030
+ };
10031
+ }
9961
10032
  const geometryObservers = /* @__PURE__ */ new Set();
9962
10033
  let geometryReleaseScheduled = false;
9963
10034
  const bindGeometryObserver = (entry) => {
@@ -10077,24 +10148,7 @@ function createSuperDocUI(options) {
10077
10148
  },
10078
10149
  getHost: () => resolveVisibleHost(),
10079
10150
  entityAt,
10080
- contextAt: (input) => {
10081
- const validInput = !!input && typeof input.x === "number" && typeof input.y === "number";
10082
- const x = validInput ? input.x : 0;
10083
- const y = validInput ? input.y : 0;
10084
- return {
10085
- point: {
10086
- x,
10087
- y
10088
- },
10089
- entities: validInput ? entityAt({
10090
- x,
10091
- y
10092
- }) : [],
10093
- selection: state.selection,
10094
- position: null,
10095
- insideSelection: false
10096
- };
10097
- },
10151
+ contextAt,
10098
10152
  scrollIntoView: async (input) => {
10099
10153
  const rawTarget = input?.target;
10100
10154
  if (!rawTarget) return { success: false };
@@ -10212,6 +10266,7 @@ function createSuperDocUI(options) {
10212
10266
  includeDeletedText: false,
10213
10267
  regex: false,
10214
10268
  canReplace: false,
10269
+ canReplaceAll: false,
10215
10270
  reason: SUPERDOC_UI_REASONS.searchUnavailable
10216
10271
  };
10217
10272
  let searchState = { ...SEARCH_UNAVAILABLE_SLICE };
@@ -10249,6 +10304,7 @@ function createSuperDocUI(options) {
10249
10304
  return searchState;
10250
10305
  };
10251
10306
  let searchRequestGeneration = 0;
10307
+ let pendingFallbackGeneration = null;
10252
10308
  /**
10253
10309
  * How to tear down the session that is currently open, captured when it was
10254
10310
  * opened.
@@ -10292,6 +10348,8 @@ function createSuperDocUI(options) {
10292
10348
  */
10293
10349
  const resetSearchForActiveEditorChange = () => {
10294
10350
  searchRequestGeneration += 1;
10351
+ pendingFallbackGeneration = null;
10352
+ shellFallbackOutstanding = false;
10295
10353
  releaseSearchSession();
10296
10354
  const available = searchIsAvailable();
10297
10355
  searchState = {
@@ -10302,6 +10360,12 @@ function createSuperDocUI(options) {
10302
10360
  emitSearch();
10303
10361
  };
10304
10362
  documentResetHooks.push(resetSearchForActiveEditorChange);
10363
+ documentModeChangeHooks.push(() => {
10364
+ if (pendingFallbackGeneration === searchRequestGeneration) return;
10365
+ const before = searchState;
10366
+ const after = syncSearchStateFromHost();
10367
+ if (after.canReplace !== before.canReplace || after.canReplaceAll !== before.canReplaceAll || after.available !== before.available || after.reason !== before.reason) emitSearch();
10368
+ });
10305
10369
  const readSearchQueryError = (record) => {
10306
10370
  if (!record) return false;
10307
10371
  const queryError = record.queryError;
@@ -10309,34 +10373,42 @@ function createSuperDocUI(options) {
10309
10373
  const rejection = record.rejection;
10310
10374
  return record.status === "rejected" && Boolean(rejection) && typeof rejection === "object" && rejection.code === "invalid-pattern";
10311
10375
  };
10312
- const normalizeHostSearchResult = (result, fallbackCanReplace = false) => {
10376
+ const normalizeHostSearchResult = (result, fallbackCanReplace = false, fallbackCanReplaceAll = fallbackCanReplace) => {
10313
10377
  const record = result && typeof result === "object" ? result : null;
10314
10378
  if (!record) return null;
10315
10379
  const matches = Array.isArray(record.matches) ? record.matches : [];
10316
10380
  const total = typeof record.total === "number" && Number.isFinite(record.total) ? record.total : matches.length;
10317
10381
  const activeIndex = typeof record.activeMatchIndex === "number" ? record.activeMatchIndex : typeof record.activeIndex === "number" ? record.activeIndex : -1;
10382
+ const canReplace = record.canReplace === true || fallbackCanReplace;
10318
10383
  return {
10319
10384
  ...typeof record.query === "string" ? { query: record.query } : {},
10320
10385
  total,
10321
10386
  activeIndex,
10322
- canReplace: record.canReplace === true || fallbackCanReplace,
10387
+ canReplace,
10388
+ canReplaceAll: canReplace && total > 0 && record.truncated !== true && (record.canReplace === true || fallbackCanReplaceAll),
10389
+ ...typeof record.caseSensitive === "boolean" ? { caseSensitive: record.caseSensitive } : {},
10323
10390
  ...typeof record.includeDeletedText === "boolean" ? { includeDeletedText: record.includeDeletedText } : {},
10324
10391
  ...record.regex === true ? { regex: true } : {},
10325
10392
  ...readSearchQueryError(record) ? { invalidPattern: true } : {}
10326
10393
  };
10327
10394
  };
10328
- const readEditCommandCanReplace = () => {
10329
- const replaceEntry = readEditCommandStateEntry("find.replace");
10330
- const replaceAllEntry = readEditCommandStateEntry("find.replaceAll");
10331
- return replaceEntry?.enabled === true || replaceAllEntry?.enabled === true;
10395
+ let shellFallbackOutstanding = false;
10396
+ const cancelOutstandingShellFallback = () => {
10397
+ if (!shellFallbackOutstanding) return;
10398
+ shellFallbackOutstanding = false;
10399
+ const editSearch = getEditCommandSearch();
10400
+ if (editSearch && typeof editSearch.query === "function") safeCall(() => editSearch.query({ query: "" }), null);
10332
10401
  };
10333
- const applyHostSearchResult = (result, fallbackCanReplace = false) => {
10334
- const snapshot = normalizeHostSearchResult(result, fallbackCanReplace);
10402
+ const readEditCommandCanReplace = () => readEditCommandStateEntry("find.replace")?.enabled === true;
10403
+ const readEditCommandCanReplaceAll = () => readEditCommandStateEntry("find.replaceAll")?.enabled === true;
10404
+ const applyHostSearchResult = (result, fallbackCanReplace = false, fallbackCanReplaceAll = fallbackCanReplace) => {
10405
+ const snapshot = normalizeHostSearchResult(result, fallbackCanReplace, fallbackCanReplaceAll);
10335
10406
  if (!snapshot) {
10336
10407
  setSearchState({
10337
10408
  total: 0,
10338
10409
  activeIndex: -1,
10339
10410
  canReplace: false,
10411
+ canReplaceAll: false,
10340
10412
  reason: void 0
10341
10413
  });
10342
10414
  return;
@@ -10346,6 +10418,7 @@ function createSuperDocUI(options) {
10346
10418
  total: snapshot.total,
10347
10419
  activeIndex: snapshot.activeIndex,
10348
10420
  canReplace: snapshot.canReplace,
10421
+ canReplaceAll: snapshot.canReplaceAll,
10349
10422
  ...snapshot.includeDeletedText !== void 0 ? { includeDeletedText: snapshot.includeDeletedText } : {},
10350
10423
  ...snapshot.regex !== void 0 ? { regex: snapshot.regex } : {},
10351
10424
  reason: snapshot.invalidPattern ? SUPERDOC_UI_REASONS.searchInvalidPattern : void 0
@@ -10364,7 +10437,8 @@ function createSuperDocUI(options) {
10364
10437
  if (!host) {
10365
10438
  const editSearch = getEditCommandSearch();
10366
10439
  if (editSearch && typeof editSearch.getState === "function") {
10367
- const editSnapshot = normalizeHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace());
10440
+ const editSnapshot = normalizeHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10441
+ if (pendingFallbackGeneration === searchRequestGeneration) return searchState;
10368
10442
  if (editSnapshot) {
10369
10443
  searchState = {
10370
10444
  ...searchState,
@@ -10372,6 +10446,7 @@ function createSuperDocUI(options) {
10372
10446
  total: editSnapshot.total,
10373
10447
  activeIndex: editSnapshot.activeIndex,
10374
10448
  canReplace: editSnapshot.canReplace,
10449
+ canReplaceAll: editSnapshot.canReplaceAll,
10375
10450
  available: true,
10376
10451
  reason: editSnapshot.invalidPattern ? SUPERDOC_UI_REASONS.searchInvalidPattern : void 0,
10377
10452
  open: searchState.open || Boolean(editSnapshot.query)
@@ -10396,6 +10471,7 @@ function createSuperDocUI(options) {
10396
10471
  total: snapshot.total,
10397
10472
  activeIndex: snapshot.activeIndex,
10398
10473
  canReplace: snapshot.canReplace,
10474
+ canReplaceAll: snapshot.canReplaceAll,
10399
10475
  ...snapshot.includeDeletedText !== void 0 ? { includeDeletedText: snapshot.includeDeletedText } : {},
10400
10476
  ...snapshot.includeDeletedText !== void 0 ? { includeTrackedDeletions: snapshot.includeDeletedText } : {},
10401
10477
  ...snapshot.regex !== void 0 ? { regex: snapshot.regex } : {},
@@ -10478,14 +10554,20 @@ function createSuperDocUI(options) {
10478
10554
  const includeDeletedText = (options?.includeTrackedDeletions ?? options?.includeDeletedText) === true;
10479
10555
  const regex = options?.regex === true;
10480
10556
  const generation = ++searchRequestGeneration;
10557
+ cancelOutstandingShellFallback();
10481
10558
  if (!host || typeof host.setSession !== "function") {
10482
10559
  const editSearch = getEditCommandSearch();
10483
10560
  if (editSearch && typeof editSearch.query === "function" && typeof editSearch.getState === "function") {
10561
+ pendingFallbackGeneration = generation;
10484
10562
  setSearchState({
10485
10563
  query,
10486
10564
  caseSensitive,
10487
10565
  includeDeletedText,
10488
10566
  regex,
10567
+ total: 0,
10568
+ activeIndex: -1,
10569
+ canReplace: false,
10570
+ canReplaceAll: false,
10489
10571
  available: true,
10490
10572
  open: true,
10491
10573
  reason: void 0
@@ -10499,18 +10581,26 @@ function createSuperDocUI(options) {
10499
10581
  includeDeletedText,
10500
10582
  regex
10501
10583
  }), null);
10502
- if (isPromiseLike(result)) Promise.resolve(result).then((resolved) => {
10503
- if (generation !== searchRequestGeneration) return;
10504
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10505
- }, () => {
10506
- if (generation !== searchRequestGeneration) return;
10507
- setSearchState({
10508
- available: false,
10509
- reason: SUPERDOC_UI_REASONS.searchUnavailable
10584
+ if (isPromiseLike(result)) {
10585
+ shellFallbackOutstanding = true;
10586
+ Promise.resolve(result).then((resolved) => {
10587
+ if (generation !== searchRequestGeneration) return;
10588
+ shellFallbackOutstanding = false;
10589
+ pendingFallbackGeneration = null;
10590
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10591
+ }, () => {
10592
+ if (generation !== searchRequestGeneration) return;
10593
+ shellFallbackOutstanding = false;
10594
+ setSearchState({
10595
+ available: false,
10596
+ reason: SUPERDOC_UI_REASONS.searchUnavailable
10597
+ });
10510
10598
  });
10511
- });
10512
- else applyHostSearchResult(result, readEditCommandCanReplace());
10513
- applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace());
10599
+ return searchState;
10600
+ }
10601
+ pendingFallbackGeneration = null;
10602
+ applyHostSearchResult(result, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10603
+ applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10514
10604
  return searchState;
10515
10605
  }
10516
10606
  return setSearchState({
@@ -10557,18 +10647,22 @@ function createSuperDocUI(options) {
10557
10647
  includeDeletedText,
10558
10648
  regex
10559
10649
  }), null);
10560
- if (isPromiseLike(commandResult)) Promise.resolve(commandResult).then((resolved) => {
10561
- if (generation !== searchRequestGeneration) return;
10562
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10563
- }, () => {
10564
- if (generation !== searchRequestGeneration) return;
10565
- setSearchState({
10566
- available: false,
10567
- reason: SUPERDOC_UI_REASONS.searchUnavailable
10650
+ if (isPromiseLike(commandResult)) {
10651
+ shellFallbackOutstanding = true;
10652
+ Promise.resolve(commandResult).then((resolved) => {
10653
+ if (generation !== searchRequestGeneration) return;
10654
+ shellFallbackOutstanding = false;
10655
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10656
+ }, () => {
10657
+ if (generation !== searchRequestGeneration) return;
10658
+ shellFallbackOutstanding = false;
10659
+ setSearchState({
10660
+ available: false,
10661
+ reason: SUPERDOC_UI_REASONS.searchUnavailable
10662
+ });
10568
10663
  });
10569
- });
10570
- else applyHostSearchResult(commandResult, readEditCommandCanReplace());
10571
- applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace());
10664
+ } else applyHostSearchResult(commandResult, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10665
+ applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10572
10666
  }
10573
10667
  }
10574
10668
  return searchState;
@@ -10591,7 +10685,7 @@ function createSuperDocUI(options) {
10591
10685
  const generation = searchRequestGeneration;
10592
10686
  Promise.resolve(result).then((resolved) => {
10593
10687
  if (generation !== searchRequestGeneration) return;
10594
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10688
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10595
10689
  }).catch(() => {
10596
10690
  if (generation !== searchRequestGeneration) return;
10597
10691
  setSearchState({
@@ -10599,8 +10693,8 @@ function createSuperDocUI(options) {
10599
10693
  reason: SUPERDOC_UI_REASONS.searchUnavailable
10600
10694
  });
10601
10695
  });
10602
- } else applyHostSearchResult(result, readEditCommandCanReplace());
10603
- applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace());
10696
+ } else applyHostSearchResult(result, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10697
+ applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10604
10698
  return { ok: true };
10605
10699
  }
10606
10700
  if (searchState.total === 0) return {
@@ -10627,7 +10721,7 @@ function createSuperDocUI(options) {
10627
10721
  const generation = searchRequestGeneration;
10628
10722
  Promise.resolve(result).then((resolved) => {
10629
10723
  if (generation !== searchRequestGeneration) return;
10630
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10724
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10631
10725
  }).catch(() => {
10632
10726
  if (generation !== searchRequestGeneration) return;
10633
10727
  setSearchState({
@@ -10635,8 +10729,8 @@ function createSuperDocUI(options) {
10635
10729
  reason: SUPERDOC_UI_REASONS.searchUnavailable
10636
10730
  });
10637
10731
  });
10638
- } else applyHostSearchResult(result, readEditCommandCanReplace());
10639
- applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace());
10732
+ } else applyHostSearchResult(result, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10733
+ applyHostSearchResult(safeCall(() => editSearch.getState(), null), readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10640
10734
  return { ok: true };
10641
10735
  }
10642
10736
  if (searchState.total === 0) return {
@@ -10648,6 +10742,7 @@ function createSuperDocUI(options) {
10648
10742
  },
10649
10743
  clear: () => {
10650
10744
  searchRequestGeneration += 1;
10745
+ cancelOutstandingShellFallback();
10651
10746
  const host = getHostSearch();
10652
10747
  if (host && typeof host.clear === "function") safeCall(() => host.clear(), null);
10653
10748
  if (!host || typeof host.clear !== "function") {
@@ -10658,7 +10753,9 @@ function createSuperDocUI(options) {
10658
10753
  query: "",
10659
10754
  total: 0,
10660
10755
  activeIndex: -1,
10661
- canReplace: false
10756
+ canReplace: false,
10757
+ canReplaceAll: false,
10758
+ reason: void 0
10662
10759
  });
10663
10760
  },
10664
10761
  replace: (replacement) => {
@@ -10681,7 +10778,7 @@ function createSuperDocUI(options) {
10681
10778
  const isCurrent = () => generation === searchRequestGeneration;
10682
10779
  return Promise.resolve(result).then((resolved) => {
10683
10780
  if (isCurrent()) {
10684
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10781
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10685
10782
  syncSearchStateFromHost();
10686
10783
  emitSearch();
10687
10784
  }
@@ -10718,7 +10815,7 @@ function createSuperDocUI(options) {
10718
10815
  ok: false,
10719
10816
  reason: SUPERDOC_UI_REASONS.searchUnavailable
10720
10817
  };
10721
- if (!readEditCommandCanReplace()) return {
10818
+ if (!readEditCommandCanReplaceAll()) return {
10722
10819
  ok: false,
10723
10820
  reason: SUPERDOC_UI_REASONS.operationUnavailable
10724
10821
  };
@@ -10730,7 +10827,7 @@ function createSuperDocUI(options) {
10730
10827
  const isCurrent = () => generation === searchRequestGeneration;
10731
10828
  return Promise.resolve(result).then((resolved) => {
10732
10829
  if (isCurrent()) {
10733
- applyHostSearchResult(resolved, readEditCommandCanReplace());
10830
+ applyHostSearchResult(resolved, readEditCommandCanReplace(), readEditCommandCanReplaceAll());
10734
10831
  syncSearchStateFromHost();
10735
10832
  emitSearch();
10736
10833
  }
@@ -10822,8 +10919,7 @@ function createSuperDocUI(options) {
10822
10919
  if (detachSourceLoading) detachSourceLoading();
10823
10920
  detachSourceLoading = null;
10824
10921
  sourceLoadingSubscriptionHost = null;
10825
- commentsDirectoryLeaseCount = 0;
10826
- trackChangesDirectoryLeaseCount = 0;
10922
+ for (const family of Object.keys(directoryLeaseCounts)) directoryLeaseCounts[family] = 0;
10827
10923
  demandedHeavyReads.clear();
10828
10924
  incompleteTrackChangesDirectoryReadTokens.clear();
10829
10925
  postSourceCompletionRefreshTokens.clear();