superdoc 2.0.0-next.43 → 2.0.0-next.45

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.
@@ -1481,12 +1481,6 @@ const INLINE_PROPERTY_REGISTRY = [
1481
1481
  new Set(INLINE_PROPERTY_REGISTRY.map((entry) => entry.key));
1482
1482
  const INLINE_PROPERTY_BY_KEY = Object.fromEntries(INLINE_PROPERTY_REGISTRY.map((entry) => [entry.key, entry]));
1483
1483
  INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "mark").map((entry) => entry.key), INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "runAttribute").map((entry) => entry.key);
1484
- var POST_DECISION_TRACKED_CHANGES_LIST_OPTIONS = Object.freeze({
1485
- mode: "background-reconcile",
1486
- refreshReason: "post-decision-background",
1487
- blocking: false
1488
- });
1489
- var POST_DECISION_TRACKED_CHANGES_RECONCILE_DELAY_MS = 3e3;
1490
1484
  var SUPERDOC_UI_REASON_VALUES = new Set(Object.values(SUPERDOC_UI_REASONS));
1491
1485
  function coerceSuperDocUIReason(reason, fallback) {
1492
1486
  return typeof reason === "string" && SUPERDOC_UI_REASON_VALUES.has(reason) ? reason : fallback;
@@ -2911,7 +2905,6 @@ function createSuperDocUI(options) {
2911
2905
  let foregroundAsyncRetryTimer = null;
2912
2906
  let pendingSelectionSeedValidationToken = null;
2913
2907
  let typingContentInvalidationTimer = null;
2914
- let postDecisionTrackChangesReconcileTimer = null;
2915
2908
  const scheduleAsyncRefresh = () => {
2916
2909
  if (asyncRefreshScheduled || disposed) return;
2917
2910
  asyncRefreshScheduled = true;
@@ -2958,14 +2951,12 @@ function createSuperDocUI(options) {
2958
2951
  };
2959
2952
  let scheduleAuthoritativeTrackChangesRetry = (_reconcileToken) => void 0;
2960
2953
  let postDecisionTrackChangesToken = null;
2961
- let postDecisionTrackChangesReconcileToken = null;
2962
2954
  let postDecisionTrackChangeIds = /* @__PURE__ */ new Set();
2963
2955
  let selectionEpoch = 0;
2964
2956
  let lastCoordinatorEditor = null;
2965
2957
  const contentToken = () => `${editorIdentityId(getEditor())}|m${documentMutationRevision}`;
2966
2958
  const clearPostDecisionTrackChanges = () => {
2967
2959
  postDecisionTrackChangesToken = null;
2968
- postDecisionTrackChangesReconcileToken = null;
2969
2960
  postDecisionTrackChangeIds = /* @__PURE__ */ new Set();
2970
2961
  };
2971
2962
  const applyPostDecisionTrackChangesToCache = (ids) => {
@@ -2983,25 +2974,6 @@ function createSuperDocUI(options) {
2983
2974
  });
2984
2975
  }
2985
2976
  };
2986
- const schedulePostDecisionTrackChangesReconcile = () => {
2987
- if (disposed || postDecisionTrackChangesReconcileTimer) return;
2988
- postDecisionTrackChangesReconcileTimer = setTimeout(() => {
2989
- postDecisionTrackChangesReconcileTimer = null;
2990
- const run = () => {
2991
- if (disposed || postDecisionTrackChangeIds.size === 0) return;
2992
- invalidateDocumentContent({ preservePostDecisionTrackChanges: true });
2993
- postDecisionTrackChangesToken = contentToken();
2994
- postDecisionTrackChangesReconcileToken = postDecisionTrackChangesToken;
2995
- recompute();
2996
- };
2997
- const requestIdle = globalThis.requestIdleCallback;
2998
- if (typeof requestIdle === "function") {
2999
- requestIdle(run, { timeout: 2e3 });
3000
- return;
3001
- }
3002
- run();
3003
- }, POST_DECISION_TRACKED_CHANGES_RECONCILE_DELAY_MS);
3004
- };
3005
2977
  const notifyPostDecisionTrackChanges = (receipt) => {
3006
2978
  const notify = () => {
3007
2979
  if (disposed) return;
@@ -3067,7 +3039,6 @@ function createSuperDocUI(options) {
3067
3039
  postDecisionTrackChangesToken = token;
3068
3040
  postDecisionTrackChangeIds = new Set([...alreadyRemoved, ...newlyRemoved]);
3069
3041
  applyPostDecisionTrackChangesToCache(postDecisionTrackChangeIds);
3070
- schedulePostDecisionTrackChangesReconcile();
3071
3042
  publishPostDecisionTrackChanges(newlyRemoved, receipt);
3072
3043
  };
3073
3044
  const postDecisionTrackChangeIdsForToken = (token) => postDecisionTrackChangesToken === token && postDecisionTrackChangeIds.size > 0 ? postDecisionTrackChangeIds : null;
@@ -3736,11 +3707,11 @@ function createSuperDocUI(options) {
3736
3707
  sourceLoadingSubscriptionHost = null;
3737
3708
  clearPostDecisionTrackChanges();
3738
3709
  };
3739
- const invalidateDocumentContent = (options$1) => {
3710
+ const invalidateDocumentContent = () => {
3740
3711
  const carryAuthoritativeTrackChangesHold = authoritativeTrackChangesPendingToken !== null;
3741
3712
  documentMutationRevision += 1;
3742
3713
  if (carryAuthoritativeTrackChangesHold) authoritativeTrackChangesPendingToken = contentToken();
3743
- if (!options$1?.preservePostDecisionTrackChanges) clearPostDecisionTrackChanges();
3714
+ clearPostDecisionTrackChanges();
3744
3715
  };
3745
3716
  const insertText = (text) => {
3746
3717
  if (typeof text !== "string" || text.length === 0) return failedReceipt("insertText requires a non-empty string.", "INVALID_INPUT");
@@ -3951,10 +3922,9 @@ function createSuperDocUI(options) {
3951
3922
  value: heldEntry?.hasSettled ? heldEntry.value : null,
3952
3923
  status: heldEntry?.hasSettled ? "stale" : "pending"
3953
3924
  } : readAsync("trackChanges", token, () => {
3954
- if (listTrackedChanges) return postDecisionTrackChangesToken === token ? listTrackedChanges.call(v2TrackedChanges, POST_DECISION_TRACKED_CHANGES_LIST_OPTIONS) : listTrackedChanges.call(v2TrackedChanges);
3925
+ if (listTrackedChanges) return listTrackedChanges.call(v2TrackedChanges);
3955
3926
  return tcApi?.list ? tcApi.list() : void 0;
3956
3927
  }, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
3957
- if (listStatus === "ready" && postDecisionTrackChangesReconcileToken === token) clearPostDecisionTrackChanges();
3958
3928
  const items = (value ?? []).map(projectTrackChangesItem).filter((item) => item != null).filter((item) => {
3959
3929
  const id = readEntityId(item);
3960
3930
  return !id || !postDecisionIds?.has(id);
@@ -8752,10 +8722,6 @@ function createSuperDocUI(options) {
8752
8722
  clearTimeout(typingContentInvalidationTimer);
8753
8723
  typingContentInvalidationTimer = null;
8754
8724
  }
8755
- if (postDecisionTrackChangesReconcileTimer) {
8756
- clearTimeout(postDecisionTrackChangesReconcileTimer);
8757
- postDecisionTrackChangesReconcileTimer = null;
8758
- }
8759
8725
  if (heavyReadCompletionRecomputeTimer) {
8760
8726
  clearTimeout(heavyReadCompletionRecomputeTimer);
8761
8727
  heavyReadCompletionRecomputeTimer = null;
@@ -1703,12 +1703,6 @@ const INLINE_PROPERTY_KEYS_BY_STORAGE = {
1703
1703
  mark: INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "mark").map((entry) => entry.key),
1704
1704
  runAttribute: INLINE_PROPERTY_REGISTRY.filter((entry) => entry.storage === "runAttribute").map((entry) => entry.key)
1705
1705
  };
1706
- var POST_DECISION_TRACKED_CHANGES_LIST_OPTIONS = Object.freeze({
1707
- mode: "background-reconcile",
1708
- refreshReason: "post-decision-background",
1709
- blocking: false
1710
- });
1711
- var POST_DECISION_TRACKED_CHANGES_RECONCILE_DELAY_MS = 3e3;
1712
1706
  var SUPERDOC_UI_REASON_VALUES = new Set(Object.values(SUPERDOC_UI_REASONS));
1713
1707
  function coerceSuperDocUIReason(reason, fallback) {
1714
1708
  return typeof reason === "string" && SUPERDOC_UI_REASON_VALUES.has(reason) ? reason : fallback;
@@ -3133,7 +3127,6 @@ function createSuperDocUI(options) {
3133
3127
  let foregroundAsyncRetryTimer = null;
3134
3128
  let pendingSelectionSeedValidationToken = null;
3135
3129
  let typingContentInvalidationTimer = null;
3136
- let postDecisionTrackChangesReconcileTimer = null;
3137
3130
  const scheduleAsyncRefresh = () => {
3138
3131
  if (asyncRefreshScheduled || disposed) return;
3139
3132
  asyncRefreshScheduled = true;
@@ -3180,14 +3173,12 @@ function createSuperDocUI(options) {
3180
3173
  };
3181
3174
  let scheduleAuthoritativeTrackChangesRetry = (_reconcileToken) => void 0;
3182
3175
  let postDecisionTrackChangesToken = null;
3183
- let postDecisionTrackChangesReconcileToken = null;
3184
3176
  let postDecisionTrackChangeIds = /* @__PURE__ */ new Set();
3185
3177
  let selectionEpoch = 0;
3186
3178
  let lastCoordinatorEditor = null;
3187
3179
  const contentToken = () => `${editorIdentityId(getEditor())}|m${documentMutationRevision}`;
3188
3180
  const clearPostDecisionTrackChanges = () => {
3189
3181
  postDecisionTrackChangesToken = null;
3190
- postDecisionTrackChangesReconcileToken = null;
3191
3182
  postDecisionTrackChangeIds = /* @__PURE__ */ new Set();
3192
3183
  };
3193
3184
  const applyPostDecisionTrackChangesToCache = (ids) => {
@@ -3205,25 +3196,6 @@ function createSuperDocUI(options) {
3205
3196
  });
3206
3197
  }
3207
3198
  };
3208
- const schedulePostDecisionTrackChangesReconcile = () => {
3209
- if (disposed || postDecisionTrackChangesReconcileTimer) return;
3210
- postDecisionTrackChangesReconcileTimer = setTimeout(() => {
3211
- postDecisionTrackChangesReconcileTimer = null;
3212
- const run = () => {
3213
- if (disposed || postDecisionTrackChangeIds.size === 0) return;
3214
- invalidateDocumentContent({ preservePostDecisionTrackChanges: true });
3215
- postDecisionTrackChangesToken = contentToken();
3216
- postDecisionTrackChangesReconcileToken = postDecisionTrackChangesToken;
3217
- recompute();
3218
- };
3219
- const requestIdle = globalThis.requestIdleCallback;
3220
- if (typeof requestIdle === "function") {
3221
- requestIdle(run, { timeout: 2e3 });
3222
- return;
3223
- }
3224
- run();
3225
- }, POST_DECISION_TRACKED_CHANGES_RECONCILE_DELAY_MS);
3226
- };
3227
3199
  const notifyPostDecisionTrackChanges = (receipt) => {
3228
3200
  const notify = () => {
3229
3201
  if (disposed) return;
@@ -3289,7 +3261,6 @@ function createSuperDocUI(options) {
3289
3261
  postDecisionTrackChangesToken = token;
3290
3262
  postDecisionTrackChangeIds = new Set([...alreadyRemoved, ...newlyRemoved]);
3291
3263
  applyPostDecisionTrackChangesToCache(postDecisionTrackChangeIds);
3292
- schedulePostDecisionTrackChangesReconcile();
3293
3264
  publishPostDecisionTrackChanges(newlyRemoved, receipt);
3294
3265
  };
3295
3266
  const postDecisionTrackChangeIdsForToken = (token) => postDecisionTrackChangesToken === token && postDecisionTrackChangeIds.size > 0 ? postDecisionTrackChangeIds : null;
@@ -3958,11 +3929,11 @@ function createSuperDocUI(options) {
3958
3929
  sourceLoadingSubscriptionHost = null;
3959
3930
  clearPostDecisionTrackChanges();
3960
3931
  };
3961
- const invalidateDocumentContent = (options$1) => {
3932
+ const invalidateDocumentContent = () => {
3962
3933
  const carryAuthoritativeTrackChangesHold = authoritativeTrackChangesPendingToken !== null;
3963
3934
  documentMutationRevision += 1;
3964
3935
  if (carryAuthoritativeTrackChangesHold) authoritativeTrackChangesPendingToken = contentToken();
3965
- if (!options$1?.preservePostDecisionTrackChanges) clearPostDecisionTrackChanges();
3936
+ clearPostDecisionTrackChanges();
3966
3937
  };
3967
3938
  const insertText = (text) => {
3968
3939
  if (typeof text !== "string" || text.length === 0) return failedReceipt("insertText requires a non-empty string.", "INVALID_INPUT");
@@ -4173,10 +4144,9 @@ function createSuperDocUI(options) {
4173
4144
  value: heldEntry?.hasSettled ? heldEntry.value : null,
4174
4145
  status: heldEntry?.hasSettled ? "stale" : "pending"
4175
4146
  } : readAsync("trackChanges", token, () => {
4176
- if (listTrackedChanges) return postDecisionTrackChangesToken === token ? listTrackedChanges.call(v2TrackedChanges, POST_DECISION_TRACKED_CHANGES_LIST_OPTIONS) : listTrackedChanges.call(v2TrackedChanges);
4147
+ if (listTrackedChanges) return listTrackedChanges.call(v2TrackedChanges);
4177
4148
  return tcApi?.list ? tcApi.list() : void 0;
4178
4149
  }, (raw) => raw && Array.isArray(raw.items) ? raw.items : []);
4179
- if (listStatus === "ready" && postDecisionTrackChangesReconcileToken === token) clearPostDecisionTrackChanges();
4180
4150
  const items = (value ?? []).map(projectTrackChangesItem).filter((item) => item != null).filter((item) => {
4181
4151
  const id = readEntityId(item);
4182
4152
  return !id || !postDecisionIds?.has(id);
@@ -8974,10 +8944,6 @@ function createSuperDocUI(options) {
8974
8944
  clearTimeout(typingContentInvalidationTimer);
8975
8945
  typingContentInvalidationTimer = null;
8976
8946
  }
8977
- if (postDecisionTrackChangesReconcileTimer) {
8978
- clearTimeout(postDecisionTrackChangesReconcileTimer);
8979
- postDecisionTrackChangesReconcileTimer = null;
8980
- }
8981
8947
  if (heavyReadCompletionRecomputeTimer) {
8982
8948
  clearTimeout(heavyReadCompletionRecomputeTimer);
8983
8949
  heavyReadCompletionRecomputeTimer = null;
@@ -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.43",
10
+ superdocVersion: "2.0.0-next.45",
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.43",
9
+ superdocVersion: "2.0.0-next.45",
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-DYky1UEo.cjs");
3
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-DDxbK_M7.cjs");
4
4
  let react = require("react");
5
5
  var SuperDocUIContext = (0, react.createContext)(null);
6
6
  function SuperDocUIProvider(props) {
@@ -1,4 +1,4 @@
1
- import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BFz0iim0.es.js";
1
+ import { t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTOlZen9.es.js";
2
2
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
3
3
  var SuperDocUIContext = createContext(null);
4
4
  function SuperDocUIProvider(props) {
@@ -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-DYky1UEo.cjs");
2
+ const require_create_super_doc_ui = require("../chunks/create-super-doc-ui-DDxbK_M7.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 BUILT_IN_COMMAND_IDS, r as shallowEqual, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BFz0iim0.es.js";
1
+ import { n as BUILT_IN_COMMAND_IDS, r as shallowEqual, t as createSuperDocUI } from "../chunks/create-super-doc-ui-BTOlZen9.es.js";
2
2
  export { BUILT_IN_COMMAND_IDS, createSuperDocUI, shallowEqual };
package/dist/style.css CHANGED
@@ -1368,28 +1368,28 @@ img[data-v-c95b2073] {
1368
1368
  background-color: #1355ff7f;
1369
1369
  }
1370
1370
 
1371
- .comment-placeholder[data-v-7f4821a8] {
1371
+ .comment-placeholder[data-v-a1bd2282] {
1372
1372
  position: absolute;
1373
1373
  width: 300px;
1374
1374
  transition: top 0.3s ease;
1375
1375
  }
1376
- .comment-placeholder.is-direct-decision-continuity-target[data-v-7f4821a8] .overflow-menu {
1376
+ .comment-placeholder.is-direct-decision-continuity-target[data-v-a1bd2282] .overflow-menu {
1377
1377
  opacity: 1;
1378
1378
  pointer-events: auto;
1379
1379
  }
1380
- .floating-comment[data-v-7f4821a8] {
1380
+ .floating-comment[data-v-a1bd2282] {
1381
1381
  position: relative;
1382
1382
  display: block;
1383
1383
  min-width: 300px;
1384
1384
  }
1385
- .sidebar-container[data-v-7f4821a8] {
1385
+ .sidebar-container[data-v-a1bd2282] {
1386
1386
  position: absolute;
1387
1387
  width: 300px;
1388
1388
  min-height: 300px;
1389
1389
  transition: transform 0.3s ease;
1390
1390
  will-change: transform;
1391
1391
  }
1392
- .section-wrapper[data-v-7f4821a8] {
1392
+ .section-wrapper[data-v-a1bd2282] {
1393
1393
  position: relative;
1394
1394
  min-height: 100%;
1395
1395
  width: 300px;
@@ -1368,28 +1368,28 @@ img[data-v-c95b2073] {
1368
1368
  background-color: #1355ff7f;
1369
1369
  }
1370
1370
 
1371
- .comment-placeholder[data-v-7f4821a8] {
1371
+ .comment-placeholder[data-v-a1bd2282] {
1372
1372
  position: absolute;
1373
1373
  width: 300px;
1374
1374
  transition: top 0.3s ease;
1375
1375
  }
1376
- .comment-placeholder.is-direct-decision-continuity-target[data-v-7f4821a8] .overflow-menu {
1376
+ .comment-placeholder.is-direct-decision-continuity-target[data-v-a1bd2282] .overflow-menu {
1377
1377
  opacity: 1;
1378
1378
  pointer-events: auto;
1379
1379
  }
1380
- .floating-comment[data-v-7f4821a8] {
1380
+ .floating-comment[data-v-a1bd2282] {
1381
1381
  position: relative;
1382
1382
  display: block;
1383
1383
  min-width: 300px;
1384
1384
  }
1385
- .sidebar-container[data-v-7f4821a8] {
1385
+ .sidebar-container[data-v-a1bd2282] {
1386
1386
  position: absolute;
1387
1387
  width: 300px;
1388
1388
  min-height: 300px;
1389
1389
  transition: transform 0.3s ease;
1390
1390
  will-change: transform;
1391
1391
  }
1392
- .section-wrapper[data-v-7f4821a8] {
1392
+ .section-wrapper[data-v-a1bd2282] {
1393
1393
  position: relative;
1394
1394
  min-height: 100%;
1395
1395
  width: 300px;
@@ -1639,17 +1639,31 @@ export interface Modules {
1639
1639
  /** Collaboration module configuration. */
1640
1640
  collaboration?: CollaborationConfig;
1641
1641
  /**
1642
- * Toolbar module configuration. Pass `true` to enable the toolbar with
1643
- * defaults (equivalent to an empty object). The `selector`, `groups`,
1644
- * `icons`, and `texts` fields fall back to the top-level `Config.toolbar`,
1645
- * `Config.toolbarGroups`, `Config.toolbarIcons`, and `Config.toolbarTexts`
1646
- * aliases respectively if not set here.
1642
+ * Toolbar module configuration. Pass `true` to configure the toolbar with
1643
+ * defaults (equivalent to an empty object).
1644
+ *
1645
+ * This field configures the toolbar's contents and behavior; it does not by
1646
+ * itself provide a place to render it. A toolbar is only rendered once a
1647
+ * mount target resolves, from either `selector` here or the top-level
1648
+ * `Config.toolbar`. Without one, SuperDoc still creates the
1649
+ * `superdoc.toolbar` handle (item lookup and command routing keep working)
1650
+ * but renders no toolbar UI.
1651
+ *
1652
+ * Fallbacks to the top-level aliases are per field: `selector` falls back to
1653
+ * `Config.toolbar`, `icons` to `Config.toolbarIcons`, and `texts` to
1654
+ * `Config.toolbarTexts`. `Config.toolbarGroups` supplies the group ordering,
1655
+ * not `groups`: the two are different settings. `groups` maps group ids to
1656
+ * item ids (composition) and has no top-level alias, so omitting it uses the
1657
+ * built-in composition. Supplying it also replaces the group ordering with
1658
+ * its own keys.
1647
1659
  */
1648
1660
  toolbar?: boolean | ({
1649
1661
  /**
1650
- * CSS selector (id or class) for the DOM element to render the toolbar
1651
- * into. Must be a string selector, not an `HTMLElement` reference. Falls
1652
- * back to `Config.toolbar` if omitted.
1662
+ * Selector for the DOM element to render the toolbar into: an id
1663
+ * selector (`#toolbar`), a class selector (`.toolbar`), or a bare
1664
+ * element id (`toolbar`). Must be a string, not an `HTMLElement`
1665
+ * reference — pass an element through the top-level `Config.toolbar`.
1666
+ * Falls back to `Config.toolbar` if omitted.
1653
1667
  */
1654
1668
  selector?: string;
1655
1669
  /** Toolbar item ids to hide from the default set. */
@@ -2348,7 +2362,18 @@ export interface Config {
2348
2362
  role?: 'editor' | 'viewer' | 'suggester';
2349
2363
  /**
2350
2364
  * The document to load. If a string, it will be treated as a URL. If a File
2351
- * or Blob, it will be used directly.
2365
+ * or Blob, it will be used directly. For a v2 collaboration room, pass a
2366
+ * structured document carrying `v2Collaboration`.
2367
+ *
2368
+ * Omitting this field and `documents` mounts a blank DOCX, so the Editor
2369
+ * opens a real document rather than an empty surface. The blank document is
2370
+ * a supported v2 source; it is seeded before mount and behaves like any
2371
+ * other opened DOCX, including export.
2372
+ *
2373
+ * Setting the v1 `modules.collaboration` field also suppresses that seeding,
2374
+ * but it is not a supported v2 path: the runtime fails closed with
2375
+ * `collaboration-v1-config-unsupported` and mounts only enough state to
2376
+ * report that error.
2352
2377
  */
2353
2378
  document?: object | string | globalThis.File | globalThis.Blob;
2354
2379
  /** Password for encrypted DOCX files. Forwarded during document load. */
@@ -2371,8 +2396,26 @@ export interface Config {
2371
2396
  modules?: Modules;
2372
2397
  /** Top-level override for permission checks. */
2373
2398
  permissionResolver?: (params: PermissionResolverParams) => boolean | undefined;
2374
- /** Optional DOM element to render the toolbar in. */
2375
- toolbar?: string;
2399
+ /**
2400
+ * Where to render the built-in toolbar. Either an `HTMLElement`, or a
2401
+ * selector string in one of the supported forms: an id selector (`#toolbar`),
2402
+ * a class selector (`.toolbar`), or a bare element id (`toolbar`). Other CSS
2403
+ * selector syntax is not supported — an attribute or descendant selector such
2404
+ * as `[data-toolbar]` resolves to nothing and leaves the toolbar unrendered.
2405
+ *
2406
+ * SuperDoc renders into the resolved element but does not manage its
2407
+ * placement, and never includes it in the `contained` layout calculation.
2408
+ * Where the application puts it therefore decides the space it needs: a
2409
+ * sibling of a 400px `contained` Editor adds its own height alongside it,
2410
+ * while a toolbar placed inside that host consumes part of the 400px and can
2411
+ * overflow it.
2412
+ *
2413
+ * Omitting this field (and `modules.toolbar.selector`) renders no toolbar.
2414
+ * `modules.toolbar: true` on its own does not render one either — it creates
2415
+ * the `superdoc.toolbar` handle without a mount target. See
2416
+ * {@link Modules.toolbar}.
2417
+ */
2418
+ toolbar?: string | HTMLElement;
2376
2419
  /** Toolbar groups to show. */
2377
2420
  toolbarGroups?: string[];
2378
2421
  /** Icons to show in the toolbar. */
@@ -2574,11 +2617,26 @@ export interface Config {
2574
2617
  /** Document view options (OOXML ST_View compatible). */
2575
2618
  viewOptions?: ViewOptions;
2576
2619
  /**
2577
- * Enable contained mode for fixed-height container embedding. When true,
2578
- * SuperDoc propagates height through its DOM tree and adds internal
2579
- * scrolling, so multi-page documents scroll within the consumer's
2580
- * fixed-height container. Default behavior (false) lets the document
2581
- * expand to its natural height.
2620
+ * Enable contained mode for fixed-height container embedding.
2621
+ *
2622
+ * SuperDoc supports two layout modes, and the host element's height
2623
+ * requirement differs between them:
2624
+ *
2625
+ * - Natural (default, `false`): the Editor grows to the document's full
2626
+ * height and the page scrolls. The host needs no height. Setting one does
2627
+ * not constrain the document or enable internal scrolling, because
2628
+ * SuperDoc leaves overflow visible in this mode, though application CSS
2629
+ * on the host can still clip what is drawn.
2630
+ * - Contained (`true`): SuperDoc propagates `height: 100%` through its DOM
2631
+ * tree and scrolls the document internally, so multi-page documents stay
2632
+ * inside the host. This mode requires the host to have a definite height
2633
+ * (for example `height: 400px`); without one there is nothing for the
2634
+ * percentage heights to resolve against.
2635
+ *
2636
+ * A toolbar mounted through `Config.toolbar` or `modules.toolbar.selector` is
2637
+ * never part of this calculation. Placed as a sibling of the host, its height
2638
+ * adds to the host's: a 400px host with a 40px toolbar occupies 440px in
2639
+ * total. Placed inside the host, it consumes part of the 400px instead.
2582
2640
  */
2583
2641
  contained?: boolean;
2584
2642
  /** Content Security Policy nonce for dynamically injected styles. */
package/dist/superdoc.cjs CHANGED
@@ -6,7 +6,7 @@ const require_uuid = require("./chunks/uuid-CFp0WGVU.cjs");
6
6
  const require_jszip = require("./chunks/jszip-BdUBlUeG.cjs");
7
7
  const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-BTwbGDKw.cjs");
8
8
  const require_constants = require("./chunks/constants-sbCZ2O_A.cjs");
9
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-DYky1UEo.cjs");
9
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-DDxbK_M7.cjs");
10
10
  let vue = require("vue");
11
11
  vue = require_rolldown_runtime.__toESM(vue);
12
12
  require("y-websocket");
@@ -3096,14 +3096,12 @@ const useCommentsStore = defineStore("comments", () => {
3096
3096
  const v2TrackedChangesAdapter = (0, vue.shallowRef)(null);
3097
3097
  const setV2TrackedChangesAdapter = (adapter) => {
3098
3098
  v2TrackedChangesAdapter.value = adapter ?? null;
3099
- if (!adapter) postDecisionBackgroundReconcileByDocument.clear();
3100
3099
  };
3101
3100
  const getV2TrackedChangesAdapter = (superdoc) => {
3102
3101
  const fromFacade = superdoc?.activeEditor?.v2TrackedChanges ?? null;
3103
3102
  if (fromFacade) return fromFacade;
3104
3103
  return v2TrackedChangesAdapter.value;
3105
3104
  };
3106
- const postDecisionBackgroundReconcileByDocument = /* @__PURE__ */ new Map();
3107
3105
  const init = (config = {}) => {
3108
3106
  const updatedConfig = {
3109
3107
  ...commentsConfig,
@@ -5197,16 +5195,6 @@ const useCommentsStore = defineStore("comments", () => {
5197
5195
  removedIds
5198
5196
  };
5199
5197
  };
5200
- const waitForPostDecisionReconcileIdle = () => new Promise((resolve) => {
5201
- setTimeout(() => {
5202
- const requestIdle = globalThis?.requestIdleCallback;
5203
- if (typeof requestIdle === "function") {
5204
- requestIdle(() => resolve(void 0), { timeout: 2e3 });
5205
- return;
5206
- }
5207
- resolve(void 0);
5208
- }, 3e3);
5209
- });
5210
5198
  const clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
5211
5199
  if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
5212
5200
  try {
@@ -5232,76 +5220,6 @@ const useCommentsStore = defineStore("comments", () => {
5232
5220
  });
5233
5221
  } catch {}
5234
5222
  };
5235
- const tracePostDecisionBackgroundReconcile = (superdoc, event, payload = {}) => {
5236
- const record = {
5237
- event,
5238
- refreshReason: "post-decision-background",
5239
- blocking: false,
5240
- ...payload
5241
- };
5242
- tracePreviewComments(`post-decision-background:${event}`, record);
5243
- };
5244
- const schedulePostDecisionBackgroundReconcile = ({ superdoc, trackedChangesAdapter, commentsAdapter, documentId } = {}) => {
5245
- const normalizedDocumentId = normalizeCommentId(documentId);
5246
- if (!normalizedDocumentId || !trackedChangesAdapter) return null;
5247
- const existing = postDecisionBackgroundReconcileByDocument.get(normalizedDocumentId);
5248
- if (existing) return existing;
5249
- const reconcilePromise = waitForPostDecisionReconcileIdle().then(async () => {
5250
- tracePostDecisionBackgroundReconcile(superdoc, "start", { documentId: normalizedDocumentId });
5251
- const trackedResult = await hydrateTrackedChangesFromV2({
5252
- superdoc,
5253
- adapter: trackedChangesAdapter,
5254
- documentId: normalizedDocumentId,
5255
- trackedChangesListMode: "background-reconcile",
5256
- refreshReason: "post-decision-background",
5257
- blocking: false
5258
- });
5259
- if (!trackedResult?.ok) tracePostDecisionBackgroundReconcile(superdoc, "tracked-changes-failed", {
5260
- documentId: normalizedDocumentId,
5261
- reason: trackedResult?.reason ?? null,
5262
- detail: trackedResult?.detail ?? null
5263
- });
5264
- if (commentsAdapter && typeof commentsAdapter.refresh === "function" && isCurrentV2CommentsAdapter(commentsAdapter)) {
5265
- let commentsResult;
5266
- try {
5267
- commentsResult = await commentsAdapter.refresh();
5268
- } catch (err) {
5269
- commentsResult = {
5270
- ok: false,
5271
- reason: "comments-refresh-threw",
5272
- detail: err?.message ?? String(err)
5273
- };
5274
- }
5275
- if (isCurrentV2CommentsAdapter(commentsAdapter) && commentsResult?.ok) reconcileCommentsFromV2({
5276
- superdoc,
5277
- adapter: commentsAdapter,
5278
- documentId: commentsAdapter.documentId ?? normalizedDocumentId,
5279
- items: commentsResult.items ?? []
5280
- });
5281
- else if (!commentsResult?.ok) tracePostDecisionBackgroundReconcile(superdoc, "comments-failed", {
5282
- documentId: normalizedDocumentId,
5283
- reason: commentsResult?.reason ?? null,
5284
- detail: commentsResult?.detail ?? null
5285
- });
5286
- }
5287
- tracePostDecisionBackgroundReconcile(superdoc, "complete", { documentId: normalizedDocumentId });
5288
- return { ok: true };
5289
- }).catch((err) => {
5290
- tracePostDecisionBackgroundReconcile(superdoc, "failed", {
5291
- documentId: normalizedDocumentId,
5292
- detail: err?.message ?? String(err)
5293
- });
5294
- return {
5295
- ok: false,
5296
- reason: "post-decision-background-failed",
5297
- detail: err?.message ?? String(err)
5298
- };
5299
- }).finally(() => {
5300
- if (postDecisionBackgroundReconcileByDocument.get(normalizedDocumentId) === reconcilePromise) postDecisionBackgroundReconcileByDocument.delete(normalizedDocumentId);
5301
- });
5302
- postDecisionBackgroundReconcileByDocument.set(normalizedDocumentId, reconcilePromise);
5303
- return reconcilePromise;
5304
- };
5305
5223
  const decideTrackedChangeFromSidebar = ({ superdoc, comment, decision }) => {
5306
5224
  if (commentsAreReadOnly$1()) return {
5307
5225
  ok: false,
@@ -5428,12 +5346,6 @@ const useCommentsStore = defineStore("comments", () => {
5428
5346
  };
5429
5347
  if (!reliableDecidedIds.size || !effectiveDocumentId) return runBlockingPostDecisionReconcile();
5430
5348
  reliableDecidedIds.forEach((id$1) => clearV2ActiveTrackedChangeTarget(v2Adapter, id$1));
5431
- schedulePostDecisionBackgroundReconcile({
5432
- superdoc,
5433
- trackedChangesAdapter: v2Adapter,
5434
- commentsAdapter: getV2CommentsAdapter(superdoc),
5435
- documentId: effectiveDocumentId
5436
- });
5437
5349
  await waitForTrackedDecisionCanonicalPaint({
5438
5350
  superdoc,
5439
5351
  receipt: outcome.receipt
@@ -8757,16 +8669,38 @@ var _sfc_main$30 = {
8757
8669
  };
8758
8670
  const getFloatingViewportRange = () => {
8759
8671
  const container = floatingCommentsContainer.value;
8760
- const viewportRect = props.parent?.getBoundingClientRect?.();
8761
- if (!container || !viewportRect) return null;
8672
+ if (!container) return null;
8762
8673
  const containerRect = container.getBoundingClientRect();
8763
- if (!Number.isFinite(containerRect.top) || !Number.isFinite(viewportRect.top) || !Number.isFinite(viewportRect.bottom)) return null;
8764
- const top = viewportRect.top - containerRect.top;
8765
- const bottom = viewportRect.bottom - containerRect.top;
8766
- return bottom >= top ? {
8767
- top,
8768
- bottom
8769
- } : null;
8674
+ if (!Number.isFinite(containerRect.top) || !Number.isFinite(window.innerHeight)) return null;
8675
+ let visibleClientTop = 0;
8676
+ let visibleClientBottom = window.innerHeight;
8677
+ for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement) {
8678
+ const overflowY = window.getComputedStyle(ancestor).overflowY;
8679
+ if (![
8680
+ "auto",
8681
+ "scroll",
8682
+ "hidden",
8683
+ "clip"
8684
+ ].includes(overflowY)) continue;
8685
+ const ancestorRect = ancestor.getBoundingClientRect();
8686
+ if (!Number.isFinite(ancestorRect.top) || !Number.isFinite(ancestorRect.bottom)) continue;
8687
+ visibleClientTop = Math.max(visibleClientTop, ancestorRect.top);
8688
+ visibleClientBottom = Math.min(visibleClientBottom, ancestorRect.bottom);
8689
+ }
8690
+ if (visibleClientBottom <= visibleClientTop) return null;
8691
+ const parentRect = props.parent?.getBoundingClientRect?.();
8692
+ if (parentRect && Number.isFinite(parentRect.top) && Number.isFinite(parentRect.bottom)) {
8693
+ const intersectedTop = Math.max(visibleClientTop, parentRect.top);
8694
+ const intersectedBottom = Math.min(visibleClientBottom, parentRect.bottom);
8695
+ if (intersectedBottom > intersectedTop) {
8696
+ visibleClientTop = intersectedTop;
8697
+ visibleClientBottom = intersectedBottom;
8698
+ }
8699
+ }
8700
+ return {
8701
+ top: visibleClientTop - containerRect.top,
8702
+ bottom: visibleClientBottom - containerRect.top
8703
+ };
8770
8704
  };
8771
8705
  const instantAlignmentInstanceKey = (0, vue.computed)(() => {
8772
8706
  if (!instantSidebarAlignmentThreadId.value) return null;
@@ -9374,7 +9308,7 @@ var _sfc_main$30 = {
9374
9308
  };
9375
9309
  }
9376
9310
  };
9377
- var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper.__plugin_vue_export_helper_default(_sfc_main$30, [["__scopeId", "data-v-7f4821a8"]]);
9311
+ var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper.__plugin_vue_export_helper_default(_sfc_main$30, [["__scopeId", "data-v-a1bd2282"]]);
9378
9312
  var _hoisted_1$22 = {
9379
9313
  class: "superdoc__pdf-comments-layer pdf-comments-layer",
9380
9314
  "aria-hidden": "false"
@@ -34763,7 +34697,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
34763
34697
  this.config.colors = shuffleArray(this.config.colors);
34764
34698
  this.userColorMap = /* @__PURE__ */ new Map();
34765
34699
  this.colorIndex = 0;
34766
- this.version = "2.0.0-next.43";
34700
+ this.version = "2.0.0-next.45";
34767
34701
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
34768
34702
  this.superdocId = config.superdocId || require_uuid.v4_default();
34769
34703
  this.colors = this.config.colors ?? [];