superdoc 2.0.0-next.44 → 2.0.0-next.46

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 (34) hide show
  1. package/AGENTS.md +15 -8
  2. package/dist/chunks/{create-super-doc-ui-DYky1UEo.cjs → create-super-doc-ui-6FUZ9d-y.cjs} +204 -159
  3. package/dist/chunks/{create-super-doc-ui-BFz0iim0.es.js → create-super-doc-ui-DCFTmVRK.es.js} +205 -160
  4. package/dist/collaboration-upgrade-engine.cjs +1 -1
  5. package/dist/collaboration-upgrade-engine.es.js +1 -1
  6. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  7. package/dist/document-api/src/contract/operation-definitions.d.ts +1 -1
  8. package/dist/public/ui-react.cjs +17 -14
  9. package/dist/public/ui-react.es.js +17 -14
  10. package/dist/public/ui.cjs +1 -1
  11. package/dist/public/ui.es.js +1 -1
  12. package/dist/style.css +28 -28
  13. package/dist/style.layered.css +28 -28
  14. package/dist/superdoc/src/components/surfaces/FindReplaceSurface.vue.d.ts +2 -2
  15. package/dist/superdoc/src/components/surfaces/PasswordPromptSurface.vue.d.ts +2 -2
  16. package/dist/superdoc/src/components/surfaces/SurfaceExternalMount.vue.d.ts +2 -2
  17. package/dist/superdoc/src/composables/use-find-replace.d.ts +2 -2
  18. package/dist/superdoc/src/core/SuperDoc.d.ts +41 -0
  19. package/dist/superdoc/src/core/types/index.d.ts +76 -30
  20. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +5 -5
  21. package/dist/superdoc/src/public/browser-document-api.d.ts +53 -0
  22. package/dist/superdoc/src/public/index.d.cts +4 -0
  23. package/dist/superdoc/src/public/index.d.ts +2 -0
  24. package/dist/superdoc/src/public/ui/react.d.ts +18 -7
  25. package/dist/superdoc/src/public/ui/types.d.ts +81 -12
  26. package/dist/superdoc/src/public/ui-react.d.ts +4 -3
  27. package/dist/superdoc/src/public/ui.d.cts +8 -0
  28. package/dist/superdoc/src/public/ui.d.ts +1 -1
  29. package/dist/superdoc.cjs +85 -141
  30. package/dist/superdoc.es.js +85 -141
  31. package/dist-cdn/style.layered.css +1 -1
  32. package/dist-cdn/superdoc.min.css +1 -1
  33. package/dist-cdn/superdoc.min.js +36 -36
  34. package/package.json +2 -2
@@ -5,7 +5,7 @@ import { t as v4_default } from "./chunks/uuid-B2Sqk-3p.es.js";
5
5
  import { a as init_dist, i as global, n as init_dist$1, r as process$1, t as require_jszip_min } from "./chunks/jszip-DzmwAHr3.es.js";
6
6
  import { t as __plugin_vue_export_helper_default } from "./chunks/_plugin-vue_export-helper-CInC0bKI.es.js";
7
7
  import { n as PDF_TO_CSS_UNITS } from "./chunks/constants-CY3R3_kF.es.js";
8
- import { a as createV2ReviewMutationReconciler, i as isV2EditableTextMutationEvent, o as getV2TrackedChangeMutationImpact, s as composeAuthorColorResolver, t as createSuperDocUI } from "./chunks/create-super-doc-ui-BFz0iim0.es.js";
8
+ import { a as createV2ReviewMutationReconciler, i as isV2EditableTextMutationEvent, o as getV2TrackedChangeMutationImpact, s as composeAuthorColorResolver, t as createSuperDocUI } from "./chunks/create-super-doc-ui-DCFTmVRK.es.js";
9
9
  import * as Vue from "vue";
10
10
  import { Fragment, Teleport, Transition, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineAsyncComponent, defineComponent, getCurrentInstance, h, inject, markRaw, mergeProps, nextTick, normalizeClass, normalizeProps, normalizeStyle, onActivated, onBeforeUnmount, onDeactivated, onMounted, openBlock, reactive, ref, renderList, renderSlot, resolveDirective, resolveDynamicComponent, shallowRef, toDisplayString, toRaw, toRef, unref, useAttrs, vModelText, watch, withCtx, withDirectives, withKeys, withModifiers } from "vue";
11
11
  import "y-websocket";
@@ -3092,14 +3092,12 @@ const useCommentsStore = defineStore("comments", () => {
3092
3092
  const v2TrackedChangesAdapter = shallowRef(null);
3093
3093
  const setV2TrackedChangesAdapter = (adapter) => {
3094
3094
  v2TrackedChangesAdapter.value = adapter ?? null;
3095
- if (!adapter) postDecisionBackgroundReconcileByDocument.clear();
3096
3095
  };
3097
3096
  const getV2TrackedChangesAdapter = (superdoc) => {
3098
3097
  const fromFacade = superdoc?.activeEditor?.v2TrackedChanges ?? null;
3099
3098
  if (fromFacade) return fromFacade;
3100
3099
  return v2TrackedChangesAdapter.value;
3101
3100
  };
3102
- const postDecisionBackgroundReconcileByDocument = /* @__PURE__ */ new Map();
3103
3101
  const init = (config = {}) => {
3104
3102
  const updatedConfig = {
3105
3103
  ...commentsConfig,
@@ -5193,16 +5191,6 @@ const useCommentsStore = defineStore("comments", () => {
5193
5191
  removedIds
5194
5192
  };
5195
5193
  };
5196
- const waitForPostDecisionReconcileIdle = () => new Promise((resolve) => {
5197
- setTimeout(() => {
5198
- const requestIdle = globalThis?.requestIdleCallback;
5199
- if (typeof requestIdle === "function") {
5200
- requestIdle(() => resolve(void 0), { timeout: 2e3 });
5201
- return;
5202
- }
5203
- resolve(void 0);
5204
- }, 3e3);
5205
- });
5206
5194
  const clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
5207
5195
  if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
5208
5196
  try {
@@ -5228,76 +5216,6 @@ const useCommentsStore = defineStore("comments", () => {
5228
5216
  });
5229
5217
  } catch {}
5230
5218
  };
5231
- const tracePostDecisionBackgroundReconcile = (superdoc, event, payload = {}) => {
5232
- const record = {
5233
- event,
5234
- refreshReason: "post-decision-background",
5235
- blocking: false,
5236
- ...payload
5237
- };
5238
- tracePreviewComments(`post-decision-background:${event}`, record);
5239
- };
5240
- const schedulePostDecisionBackgroundReconcile = ({ superdoc, trackedChangesAdapter, commentsAdapter, documentId } = {}) => {
5241
- const normalizedDocumentId = normalizeCommentId(documentId);
5242
- if (!normalizedDocumentId || !trackedChangesAdapter) return null;
5243
- const existing = postDecisionBackgroundReconcileByDocument.get(normalizedDocumentId);
5244
- if (existing) return existing;
5245
- const reconcilePromise = waitForPostDecisionReconcileIdle().then(async () => {
5246
- tracePostDecisionBackgroundReconcile(superdoc, "start", { documentId: normalizedDocumentId });
5247
- const trackedResult = await hydrateTrackedChangesFromV2({
5248
- superdoc,
5249
- adapter: trackedChangesAdapter,
5250
- documentId: normalizedDocumentId,
5251
- trackedChangesListMode: "background-reconcile",
5252
- refreshReason: "post-decision-background",
5253
- blocking: false
5254
- });
5255
- if (!trackedResult?.ok) tracePostDecisionBackgroundReconcile(superdoc, "tracked-changes-failed", {
5256
- documentId: normalizedDocumentId,
5257
- reason: trackedResult?.reason ?? null,
5258
- detail: trackedResult?.detail ?? null
5259
- });
5260
- if (commentsAdapter && typeof commentsAdapter.refresh === "function" && isCurrentV2CommentsAdapter(commentsAdapter)) {
5261
- let commentsResult;
5262
- try {
5263
- commentsResult = await commentsAdapter.refresh();
5264
- } catch (err) {
5265
- commentsResult = {
5266
- ok: false,
5267
- reason: "comments-refresh-threw",
5268
- detail: err?.message ?? String(err)
5269
- };
5270
- }
5271
- if (isCurrentV2CommentsAdapter(commentsAdapter) && commentsResult?.ok) reconcileCommentsFromV2({
5272
- superdoc,
5273
- adapter: commentsAdapter,
5274
- documentId: commentsAdapter.documentId ?? normalizedDocumentId,
5275
- items: commentsResult.items ?? []
5276
- });
5277
- else if (!commentsResult?.ok) tracePostDecisionBackgroundReconcile(superdoc, "comments-failed", {
5278
- documentId: normalizedDocumentId,
5279
- reason: commentsResult?.reason ?? null,
5280
- detail: commentsResult?.detail ?? null
5281
- });
5282
- }
5283
- tracePostDecisionBackgroundReconcile(superdoc, "complete", { documentId: normalizedDocumentId });
5284
- return { ok: true };
5285
- }).catch((err) => {
5286
- tracePostDecisionBackgroundReconcile(superdoc, "failed", {
5287
- documentId: normalizedDocumentId,
5288
- detail: err?.message ?? String(err)
5289
- });
5290
- return {
5291
- ok: false,
5292
- reason: "post-decision-background-failed",
5293
- detail: err?.message ?? String(err)
5294
- };
5295
- }).finally(() => {
5296
- if (postDecisionBackgroundReconcileByDocument.get(normalizedDocumentId) === reconcilePromise) postDecisionBackgroundReconcileByDocument.delete(normalizedDocumentId);
5297
- });
5298
- postDecisionBackgroundReconcileByDocument.set(normalizedDocumentId, reconcilePromise);
5299
- return reconcilePromise;
5300
- };
5301
5219
  const decideTrackedChangeFromSidebar = ({ superdoc, comment, decision }) => {
5302
5220
  if (commentsAreReadOnly$1()) return {
5303
5221
  ok: false,
@@ -5424,12 +5342,6 @@ const useCommentsStore = defineStore("comments", () => {
5424
5342
  };
5425
5343
  if (!reliableDecidedIds.size || !effectiveDocumentId) return runBlockingPostDecisionReconcile();
5426
5344
  reliableDecidedIds.forEach((id$1) => clearV2ActiveTrackedChangeTarget(v2Adapter, id$1));
5427
- schedulePostDecisionBackgroundReconcile({
5428
- superdoc,
5429
- trackedChangesAdapter: v2Adapter,
5430
- commentsAdapter: getV2CommentsAdapter(superdoc),
5431
- documentId: effectiveDocumentId
5432
- });
5433
5345
  await waitForTrackedDecisionCanonicalPaint({
5434
5346
  superdoc,
5435
5347
  receipt: outcome.receipt
@@ -8746,16 +8658,38 @@ var FloatingComments_default = /* @__PURE__ */ __plugin_vue_export_helper_defaul
8746
8658
  };
8747
8659
  const getFloatingViewportRange = () => {
8748
8660
  const container = floatingCommentsContainer.value;
8749
- const viewportRect = props.parent?.getBoundingClientRect?.();
8750
- if (!container || !viewportRect) return null;
8661
+ if (!container) return null;
8751
8662
  const containerRect = container.getBoundingClientRect();
8752
- if (!Number.isFinite(containerRect.top) || !Number.isFinite(viewportRect.top) || !Number.isFinite(viewportRect.bottom)) return null;
8753
- const top = viewportRect.top - containerRect.top;
8754
- const bottom = viewportRect.bottom - containerRect.top;
8755
- return bottom >= top ? {
8756
- top,
8757
- bottom
8758
- } : null;
8663
+ if (!Number.isFinite(containerRect.top) || !Number.isFinite(window.innerHeight)) return null;
8664
+ let visibleClientTop = 0;
8665
+ let visibleClientBottom = window.innerHeight;
8666
+ for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement) {
8667
+ const overflowY = window.getComputedStyle(ancestor).overflowY;
8668
+ if (![
8669
+ "auto",
8670
+ "scroll",
8671
+ "hidden",
8672
+ "clip"
8673
+ ].includes(overflowY)) continue;
8674
+ const ancestorRect = ancestor.getBoundingClientRect();
8675
+ if (!Number.isFinite(ancestorRect.top) || !Number.isFinite(ancestorRect.bottom)) continue;
8676
+ visibleClientTop = Math.max(visibleClientTop, ancestorRect.top);
8677
+ visibleClientBottom = Math.min(visibleClientBottom, ancestorRect.bottom);
8678
+ }
8679
+ if (visibleClientBottom <= visibleClientTop) return null;
8680
+ const parentRect = props.parent?.getBoundingClientRect?.();
8681
+ if (parentRect && Number.isFinite(parentRect.top) && Number.isFinite(parentRect.bottom)) {
8682
+ const intersectedTop = Math.max(visibleClientTop, parentRect.top);
8683
+ const intersectedBottom = Math.min(visibleClientBottom, parentRect.bottom);
8684
+ if (intersectedBottom > intersectedTop) {
8685
+ visibleClientTop = intersectedTop;
8686
+ visibleClientBottom = intersectedBottom;
8687
+ }
8688
+ }
8689
+ return {
8690
+ top: visibleClientTop - containerRect.top,
8691
+ bottom: visibleClientBottom - containerRect.top
8692
+ };
8759
8693
  };
8760
8694
  const instantAlignmentInstanceKey = computed(() => {
8761
8695
  if (!instantSidebarAlignmentThreadId.value) return null;
@@ -9362,7 +9296,7 @@ var FloatingComments_default = /* @__PURE__ */ __plugin_vue_export_helper_defaul
9362
9296
  }), 128))], 4)], 36);
9363
9297
  };
9364
9298
  }
9365
- }, [["__scopeId", "data-v-7f4821a8"]]);
9299
+ }, [["__scopeId", "data-v-a1bd2282"]]);
9366
9300
  var _hoisted_1$22 = {
9367
9301
  class: "superdoc__pdf-comments-layer pdf-comments-layer",
9368
9302
  "aria-hidden": "false"
@@ -13834,6 +13768,7 @@ var _hoisted_1$16 = {
13834
13768
  var _hoisted_2$13 = ["innerHTML"];
13835
13769
  var _hoisted_3$10 = { class: "superdoc__document document" };
13836
13770
  var _hoisted_4$7 = { class: "floating-comments" };
13771
+ var UNAVAILABLE_COMMAND_RESULT = false;
13837
13772
  var V2_SELECTION_TOOLBAR_SYNC_RETRY_FRAMES = 3;
13838
13773
  var V2_TYPING_REVIEW_HYDRATION_IDLE_MS = 6500;
13839
13774
  var V2_TYPING_REVIEW_HYDRATION_CEILING_MS = 8e3;
@@ -13954,19 +13889,19 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
13954
13889
  const v2GeometryEpoch = ref(null);
13955
13890
  let v2GeometryRafHandle = 0;
13956
13891
  const activeEditorRef = computed(() => proxy.$superdoc.activeEditor);
13957
- let linkPopoverUi = null;
13892
+ const getSuperDocUI = () => proxy.$superdoc?.ui ?? null;
13893
+ const UNAVAILABLE_COMMAND_STATE = Object.freeze({
13894
+ enabled: false,
13895
+ active: false,
13896
+ supported: false
13897
+ });
13958
13898
  const findReplace = useFindReplace({
13959
13899
  getSurfaceManager: () => surfaceManager,
13960
13900
  getActiveEditor: () => proxy.$superdoc?.activeEditor,
13961
13901
  activeEditorRef,
13962
13902
  getFindReplaceConfig: () => proxy.$superdoc?.config?.modules?.surfaces?.findReplace,
13963
- getSuperDocUI: () => getLinkPopoverUi()
13903
+ getSuperDocUI
13964
13904
  });
13965
- const getLinkPopoverUi = () => {
13966
- if (proxy.$superdoc?.toolbar?.ui) return proxy.$superdoc.toolbar.ui;
13967
- if (!linkPopoverUi && proxy.$superdoc) linkPopoverUi = createSuperDocUI({ superdoc: proxy.$superdoc });
13968
- return linkPopoverUi;
13969
- };
13970
13905
  const getLinkPopoverSurfaceManager = () => {
13971
13906
  if (surfaceManager) return surfaceManager;
13972
13907
  if (typeof proxy.$superdoc?.openSurface !== "function") return null;
@@ -13975,7 +13910,7 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
13975
13910
  const linkPopover = useLinkPopover({
13976
13911
  getSurfaceManager: getLinkPopoverSurfaceManager,
13977
13912
  getActiveEditor: () => proxy.$superdoc?.activeEditor,
13978
- getUi: getLinkPopoverUi,
13913
+ getUi: getSuperDocUI,
13979
13914
  getResolver: () => proxy.$superdoc?.config?.modules?.links?.popoverResolver,
13980
13915
  getLayerElement: () => layers.value,
13981
13916
  emitException: (payload) => {
@@ -14046,11 +13981,6 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
14046
13981
  } catch (err) {
14047
13982
  console.warn("[SuperDoc] v2 command-shortcut unbind failed", err);
14048
13983
  }
14049
- try {
14050
- entry.ui?.destroy?.();
14051
- } catch (err) {
14052
- console.warn("[SuperDoc] v2 command-shortcut UI teardown failed", err);
14053
- }
14054
13984
  };
14055
13985
  const resolveV2LinkWorkflowOpener = () => {
14056
13986
  const toolbar = proxy.$superdoc?.toolbar;
@@ -14066,20 +13996,19 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
14066
13996
  if (!documentId) return;
14067
13997
  clearV2CommandShortcutBinding(documentId);
14068
13998
  if (typeof bindEditShortcuts !== "function") return;
14069
- const fallbackUi = createSuperDocUI({ superdoc: proxy.$superdoc });
14070
- const resolveUi = () => proxy.$superdoc?.toolbar?.ui ?? fallbackUi;
14071
13999
  const openLinkWorkflow = resolveV2LinkWorkflowOpener();
14072
14000
  const unbind = bindEditShortcuts({
14073
14001
  commandRoute: {
14074
- executeAsync: (commandId, payload) => resolveUi().commands.executeAsync(commandId, payload),
14075
- getState: (commandId) => resolveUi().commands.get(commandId).getState()
14002
+ executeAsync: (commandId, payload) => {
14003
+ const ui = getSuperDocUI();
14004
+ if (!ui) return Promise.resolve(UNAVAILABLE_COMMAND_RESULT);
14005
+ return ui.commands.executeAsync(commandId, payload);
14006
+ },
14007
+ getState: (commandId) => getSuperDocUI()?.commands.get(commandId).getState() ?? UNAVAILABLE_COMMAND_STATE
14076
14008
  },
14077
14009
  ...openLinkWorkflow ? { openLinkWorkflow } : {}
14078
14010
  });
14079
- v2CommandShortcutBindings.set(documentId, {
14080
- unbind,
14081
- ui: fallbackUi
14082
- });
14011
+ v2CommandShortcutBindings.set(documentId, { unbind });
14083
14012
  };
14084
14013
  const clearV2SessionShortcutBinding = (documentId) => {
14085
14014
  const entry = v2SessionShortcutBindings.get(documentId);
@@ -15631,8 +15560,6 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
15631
15560
  passwordPrompt.destroy();
15632
15561
  findReplace.destroy();
15633
15562
  linkPopover.destroy();
15634
- linkPopoverUi?.destroy?.();
15635
- linkPopoverUi = null;
15636
15563
  cancelScheduledV2DomSelectionSync();
15637
15564
  cancelScheduledV2SelectionToolbarSync();
15638
15565
  for (const documentId of Array.from(v2Runtimes.keys())) clearV2RuntimeRegistration(documentId);
@@ -16148,7 +16075,7 @@ var SuperDoc_default = /* @__PURE__ */ __plugin_vue_export_helper_default({
16148
16075
  ], 38);
16149
16076
  };
16150
16077
  }
16151
- }, [["__scopeId", "data-v-91c4cd11"]]);
16078
+ }, [["__scopeId", "data-v-41f40a40"]]);
16152
16079
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
16153
16080
  var PINIA_DEVTOOLS_PLUGIN_ID = "dev.esm.pinia";
16154
16081
  var piniaDevtoolsSuppressionState = {
@@ -33933,24 +33860,31 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
33933
33860
  const uiFontFamily = (this.config?.uiDisplayFallbackFont || "").toString().trim() || "Arial, Helvetica, sans-serif";
33934
33861
  this.toolbarContainer.style.setProperty("--sd-ui-font-family", uiFontFamily);
33935
33862
  }
33936
- this.#initController();
33937
- this.#initToolbarGroups();
33938
- this.#makeToolbarItems();
33939
- this.#bindHostEvents();
33940
- this._lastFontOptionsSignature = this.#fontOptionsSignature();
33941
- if (!this.toolbarContainer) {
33863
+ try {
33864
+ this.#initController();
33865
+ this.#initToolbarGroups();
33866
+ this.#makeToolbarItems();
33867
+ this.#bindHostEvents();
33868
+ this._lastFontOptionsSignature = this.#fontOptionsSignature();
33869
+ if (!this.toolbarContainer) {
33870
+ this.updateToolbarState();
33871
+ return;
33872
+ }
33873
+ this.app = createApp(Toolbar_default);
33874
+ this.app.directive("click-outside", v_click_outside_default);
33875
+ this.app.config.globalProperties.$toolbar = this;
33876
+ this.toolbar = this.app.mount(this.toolbarContainer);
33942
33877
  this.updateToolbarState();
33943
- return;
33878
+ } catch (error) {
33879
+ try {
33880
+ this.destroy();
33881
+ } catch {}
33882
+ throw error;
33944
33883
  }
33945
- this.app = createApp(Toolbar_default);
33946
- this.app.directive("click-outside", v_click_outside_default);
33947
- this.app.config.globalProperties.$toolbar = this;
33948
- this.toolbar = this.app.mount(this.toolbarContainer);
33949
- this.updateToolbarState();
33950
33884
  }
33951
33885
  #initController() {
33952
- if (!this.superdoc) return;
33953
- this.ui = createSuperDocUI({ superdoc: this.superdoc });
33886
+ this.ui = this.superdoc?.ui ?? null;
33887
+ if (!this.ui) return;
33954
33888
  this.snapshot = this.ui.toolbar.getSnapshot();
33955
33889
  this._unsubscribeController = this.ui.toolbar.subscribe(() => {
33956
33890
  this.snapshot = this.ui.toolbar.getSnapshot();
@@ -33971,9 +33905,6 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
33971
33905
  reg.unregister?.();
33972
33906
  } catch {}
33973
33907
  this._customCommandRegs.clear();
33974
- try {
33975
- this.ui?.destroy?.();
33976
- } catch {}
33977
33908
  this.ui = null;
33978
33909
  this.snapshot = null;
33979
33910
  }
@@ -34594,6 +34525,7 @@ var SuperDoc = class extends import_eventemitter3.default {
34594
34525
  #v2LockUnsub = null;
34595
34526
  #pendingV2LockSeed = null;
34596
34527
  #mountWrapper = null;
34528
+ #ui = null;
34597
34529
  #surfaceManager;
34598
34530
  #editorRuntimeRegistry = new EditorRuntimeRegistry();
34599
34531
  #editorRuntimeRegistryUnsub = null;
@@ -34700,7 +34632,7 @@ var SuperDoc = class extends import_eventemitter3.default {
34700
34632
  this.config.colors = shuffleArray(this.config.colors);
34701
34633
  this.userColorMap = /* @__PURE__ */ new Map();
34702
34634
  this.colorIndex = 0;
34703
- this.version = "2.0.0-next.44";
34635
+ this.version = "2.0.0-next.46";
34704
34636
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
34705
34637
  this.superdocId = config.superdocId || v4_default();
34706
34638
  this.colors = this.config.colors ?? [];
@@ -34752,6 +34684,13 @@ var SuperDoc = class extends import_eventemitter3.default {
34752
34684
  get requiredNumberOfEditors() {
34753
34685
  return this.#requireSuperdocStore("requiredNumberOfEditors").documents.filter((d) => d.type === DOCX).length;
34754
34686
  }
34687
+ get ui() {
34688
+ if (!this.#ui) {
34689
+ this.#ui = createSuperDocUI({ superdoc: this });
34690
+ if (this.#destroyed) this.#ui.destroy();
34691
+ }
34692
+ return this.#ui;
34693
+ }
34755
34694
  get state() {
34756
34695
  return {
34757
34696
  documents: this.#requireSuperdocStore("state").documents,
@@ -35459,10 +35398,12 @@ var SuperDoc = class extends import_eventemitter3.default {
35459
35398
  return this.#fontsApi;
35460
35399
  }
35461
35400
  #clearActiveEditorProjection() {
35401
+ const hadActiveEditor = this.activeEditor !== null;
35462
35402
  this.#teardownV2FontsRelay();
35463
35403
  this.activeEditor = null;
35464
35404
  if (this.toolbar?.setActiveEditor) this.toolbar.setActiveEditor(null);
35465
35405
  else if (this.toolbar) this.toolbar.activeEditor = null;
35406
+ if (hadActiveEditor) this.emit("active-editor-change");
35466
35407
  }
35467
35408
  #v2FontsUnsub = null;
35468
35409
  #teardownV2FontsRelay() {
@@ -35497,9 +35438,11 @@ var SuperDoc = class extends import_eventemitter3.default {
35497
35438
  #setActiveEditorCompatibilityProjection(editor) {
35498
35439
  if (isV2ActiveEditorFacade(editor)) {
35499
35440
  if (!this.#applyingRuntimeActiveChange && this.#editorRuntimeRegistry.getActive()) this.#editorRuntimeRegistry.setActive(null, "set-active-v2-facade");
35441
+ const previous = this.activeEditor;
35500
35442
  this.activeEditor = editor;
35501
35443
  this.#wireV2FontsRelay(editor);
35502
35444
  this.toolbar?.setActiveEditor?.(editor);
35445
+ if (previous !== this.activeEditor) this.emit("active-editor-change");
35503
35446
  return;
35504
35447
  }
35505
35448
  this.#clearActiveEditorProjection();
@@ -36218,6 +36161,7 @@ var SuperDoc = class extends import_eventemitter3.default {
36218
36161
  delete this.app.config.globalProperties.$config;
36219
36162
  delete this.app.config.globalProperties.$superdoc;
36220
36163
  }
36164
+ this.#ui?.destroy();
36221
36165
  this.#cleanupCollaboration();
36222
36166
  this.#editorRuntimeRegistryUnsub?.();
36223
36167
  this.#editorRuntimeRegistryUnsub = null;