superdoc 2.18.0-next.10 → 2.18.0-next.12

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.
package/dist/superdoc.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./chunks/rolldown-runtime-74VwNCz7.cjs");
3
3
  const require_blank_docx = require("./chunks/blank-docx-BuFAbRjs.cjs");
4
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-D9JWPXRh.cjs");
4
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-BwM3I7-G.cjs");
5
5
  const require_eventemitter3 = require("./chunks/eventemitter3-C_TAnXOl.cjs");
6
6
  const require_uuid = require("./chunks/uuid-BhG0ngwk.cjs");
7
7
  const require_jszip = require("./chunks/jszip-D8mAFF-r.cjs");
@@ -316,7 +316,7 @@ var shuffleArray = (array) => {
316
316
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
317
317
  function getSuperdocVersion() {
318
318
  try {
319
- return "2.18.0-next.10";
319
+ return "2.18.0-next.12";
320
320
  } catch {
321
321
  return "unknown";
322
322
  }
@@ -22372,7 +22372,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22372
22372
  if (!payload) return;
22373
22373
  clearV2EditorFailure(payload.documentId ?? null);
22374
22374
  clearV2MutationRejectionNotifications(payload.documentId ?? null);
22375
- const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
22375
+ const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, connection, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
22376
22376
  documentOpenTelemetry?.trackDocumentOpen(documentOpenToken ?? null, documentId ?? null);
22377
22377
  const saveV2Bytes = createV2SaveQueue(async (saveOptions = {}) => {
22378
22378
  if (!host || typeof host.save !== "function") throw new Error("v2-editor: save unavailable");
@@ -22649,6 +22649,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22649
22649
  pageFurniture: pageFurniture ?? null,
22650
22650
  presence: presence ?? null,
22651
22651
  lock: lock ?? null,
22652
+ connection: connection ?? null,
22652
22653
  provider: collaborationProvider ?? null,
22653
22654
  reviewWindow: {
22654
22655
  getDiagnostics: () => v2ReviewWindowController.getDiagnostics(),
@@ -24494,7 +24495,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
24494
24495
  ], 38);
24495
24496
  };
24496
24497
  }
24497
- }, [["__scopeId", "data-v-4efb0cab"]]);
24498
+ }, [["__scopeId", "data-v-9da02d58"]]);
24498
24499
  //#endregion
24499
24500
  //#region src/core/create-app.js
24500
24501
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45370,6 +45371,14 @@ function contentControlSelectionKey(selection) {
45370
45371
  return null;
45371
45372
  }
45372
45373
  }
45374
+ function deriveCollaborationConnectionKind(snapshot, hasSyncedBefore) {
45375
+ switch (snapshot.state) {
45376
+ case "failed": return "failed";
45377
+ case "degraded": return snapshot.detail === "reconnecting" ? "reconnecting" : "lost";
45378
+ case "synced": return hasSyncedBefore ? "recovered" : "initial";
45379
+ default: return hasSyncedBefore ? "reconnecting" : "initial";
45380
+ }
45381
+ }
45373
45382
  function isV2ActiveEditorFacade(editor) {
45374
45383
  return Boolean(editor && typeof editor === "object" && editor.editorVersion === 2);
45375
45384
  }
@@ -45426,6 +45435,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45426
45435
  #destroyed;
45427
45436
  #diagnostics;
45428
45437
  #isUpgrading;
45438
+ #pendingUpgrade;
45429
45439
  /** Aborts an in-flight upgrade (sync wait or ready wait). */
45430
45440
  #abortUpgrade;
45431
45441
  /**
@@ -45437,6 +45447,12 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45437
45447
  #v2AwarenessUnsub;
45438
45448
  /** Unsubscribe handle for the v2 root-doc lock observer. */
45439
45449
  #v2LockUnsub;
45450
+ /** Unsubscribe handle for the v2 collaboration connection observer. */
45451
+ #v2ConnectionUnsub;
45452
+ /** Latest `collaboration-connection-change` payload, for late readers. */
45453
+ #v2ConnectionState;
45454
+ /** Whether the current collaboration room has completed a sync at least once. */
45455
+ #v2ConnectionHasSynced;
45440
45456
  /** Lock state captured before a local → v2 collaboration promotion remount. */
45441
45457
  #pendingV2LockSeed;
45442
45458
  #mountWrapper;
@@ -45525,9 +45541,13 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45525
45541
  super();
45526
45542
  this.#destroyed = false;
45527
45543
  this.#isUpgrading = false;
45544
+ this.#pendingUpgrade = null;
45528
45545
  this.#abortUpgrade = null;
45529
45546
  this.#v2AwarenessUnsub = null;
45530
45547
  this.#v2LockUnsub = null;
45548
+ this.#v2ConnectionUnsub = null;
45549
+ this.#v2ConnectionState = null;
45550
+ this.#v2ConnectionHasSynced = false;
45531
45551
  this.#pendingV2LockSeed = null;
45532
45552
  this.#mountWrapper = null;
45533
45553
  this.#contentControlClickRoot = null;
@@ -45726,7 +45746,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45726
45746
  this.config.colors = shuffleArray(this.config.colors);
45727
45747
  this.userColorMap = /* @__PURE__ */ new Map();
45728
45748
  this.colorIndex = 0;
45729
- this.version = "2.18.0-next.10";
45749
+ this.version = "2.18.0-next.12";
45730
45750
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45731
45751
  this.superdocId = config.superdocId || require_uuid.v4();
45732
45752
  this.colors = this.config.colors ?? [];
@@ -45828,7 +45848,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45828
45848
  return this.#diagnostics;
45829
45849
  }
45830
45850
  emit(event, ...args) {
45831
- if (event === "exception" || event === "document-replaced" || event === "ready" || event === "active-editor-change" || event === "collaboration-ready" || event === "locked") require_create_super_doc_ui.recordInteraction(this, event, () => args[0]);
45851
+ if (event === "exception" || event === "document-replaced" || event === "ready" || event === "active-editor-change" || event === "collaboration-ready" || event === "collaboration-connection-change" || event === "locked") require_create_super_doc_ui.recordInteraction(this, event, () => args[0]);
45832
45852
  return super.emit(event, ...args);
45833
45853
  }
45834
45854
  on(event, fn, context) {
@@ -46070,6 +46090,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46070
46090
  this.#onConfig("pdf:document-ready", this.config.onPdfDocumentReady);
46071
46091
  this.#onConfig("sidebar-toggle", this.config.onSidebarToggle);
46072
46092
  this.#onConfig("collaboration-ready", this.config.onCollaborationReady);
46093
+ this.#onConfig("collaboration-connection-change", this.config.onCollaborationConnectionChange);
46073
46094
  this.on("collaboration-ready", (payload) => this.#startV2CollaborationEventBridge(payload?.editor ?? null));
46074
46095
  this.#onConfig("editor-update", this.config.onEditorUpdate);
46075
46096
  this.#onConfig("tracked-changes:bulk-decision", this.config.onTrackedChangesBulkDecision);
@@ -46160,12 +46181,59 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46160
46181
  } catch {}
46161
46182
  this.#v2LockUnsub = null;
46162
46183
  }
46184
+ if (this.#v2ConnectionUnsub) {
46185
+ try {
46186
+ this.#v2ConnectionUnsub();
46187
+ } catch {}
46188
+ this.#v2ConnectionUnsub = null;
46189
+ }
46163
46190
  }
46164
46191
  #startV2CollaborationEventBridge(editor) {
46165
46192
  this.#stopV2CollaborationEventBridge();
46166
46193
  if (!isV2ActiveEditorFacade(editor)) return;
46167
46194
  this.#startV2AwarenessBridge(editor);
46168
46195
  this.#startV2LockBridge(editor);
46196
+ this.#startV2ConnectionBridge(editor);
46197
+ }
46198
+ #startV2ConnectionBridge(editor) {
46199
+ const connection = editor.connection;
46200
+ if (!connection || typeof connection.subscribe !== "function") return;
46201
+ const { documentId } = connection;
46202
+ if (this.#v2ConnectionState?.documentId !== documentId) {
46203
+ this.#v2ConnectionState = null;
46204
+ this.#v2ConnectionHasSynced = false;
46205
+ }
46206
+ const publish = (snapshot) => {
46207
+ if (this.#destroyed) return;
46208
+ const previous = this.#v2ConnectionState;
46209
+ if (previous && previous.state === snapshot.state && previous.detail === (snapshot.detail ?? null)) return;
46210
+ const payload = {
46211
+ documentId,
46212
+ state: snapshot.state,
46213
+ previousState: previous?.state ?? null,
46214
+ kind: deriveCollaborationConnectionKind(snapshot, this.#v2ConnectionHasSynced),
46215
+ detail: snapshot.detail ?? null,
46216
+ superdoc: this
46217
+ };
46218
+ this.#v2ConnectionState = payload;
46219
+ if (snapshot.state === "synced") this.#v2ConnectionHasSynced = true;
46220
+ this.emit("collaboration-connection-change", payload);
46221
+ };
46222
+ try {
46223
+ const initialSnapshot = connection.getSnapshot?.();
46224
+ if (initialSnapshot) publish(initialSnapshot);
46225
+ this.#v2ConnectionUnsub = connection.subscribe(publish);
46226
+ } catch (err) {
46227
+ console.warn("[SuperDoc] v2 connection bridge failed to subscribe", err);
46228
+ }
46229
+ }
46230
+ /**
46231
+ * Latest v2 collaboration connection change, or `null` when no v2
46232
+ * collaboration session has reported one. Same payload as the
46233
+ * `collaboration-connection-change` event.
46234
+ */
46235
+ getCollaborationConnectionState() {
46236
+ return this.#v2ConnectionState;
46169
46237
  }
46170
46238
  #startV2AwarenessBridge(editor) {
46171
46239
  const presence = editor.presence;
@@ -46253,29 +46321,78 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46253
46321
  * - A supported v2 single-doc `v2Collaboration` target
46254
46322
  * - Create-and-upgrade only (no merge semantics)
46255
46323
  *
46256
- * @returns Resolves once the collaborative runtime is ready
46324
+ * @returns The attached room and document once the collaborative runtime is ready
46257
46325
  */
46258
46326
  async upgradeToCollaboration(options) {
46327
+ if (this.#pendingUpgrade) {
46328
+ const { target } = this.#resolveCollaborationUpgradeTarget(options);
46329
+ if (this.#sameUpgradeTarget(target, this.#pendingUpgrade.target)) return this.#pendingUpgrade.promise;
46330
+ throw Object.assign(/* @__PURE__ */ new Error("SuperDoc: a different collaboration target is already upgrading"), { code: "collaboration-upgrade-target-conflict" });
46331
+ }
46259
46332
  const { target } = this.#validateUpgradePrerequisites(options);
46260
46333
  this.#isUpgrading = true;
46261
- try {
46262
- const localSource = await this.#captureCurrentDocxSourceForUpgrade();
46263
- const rollback = this.#snapshotV2UpgradeState();
46264
- const lockSeed = this.#snapshotV2LockSeed();
46265
- this.#assertNotDestroyed();
46334
+ const operation = (async () => {
46266
46335
  try {
46267
- this.#pendingV2LockSeed = lockSeed;
46268
- const promotion = await this.#promoteSingleDocumentToV2Collaboration(target, localSource);
46269
- this.#finalizeSingleDocumentV2Collaboration(promotion, target);
46270
- this.#pendingV2LockSeed = null;
46271
- } catch (err) {
46272
- this.#rollbackV2UpgradeState(rollback);
46273
- throw err;
46274
- }
46275
- } finally {
46276
- this.#abortUpgrade = null;
46277
- this.#isUpgrading = false;
46278
- }
46336
+ const localSource = await this.#captureCurrentDocxSourceForUpgrade();
46337
+ const rollback = this.#snapshotV2UpgradeState();
46338
+ const lockSeed = this.#snapshotV2LockSeed();
46339
+ this.#assertNotDestroyed();
46340
+ try {
46341
+ this.#pendingV2LockSeed = lockSeed;
46342
+ const promotion = await this.#promoteSingleDocumentToV2Collaboration(target, localSource);
46343
+ this.#finalizeSingleDocumentV2Collaboration(promotion, target);
46344
+ this.#pendingV2LockSeed = null;
46345
+ const attachedDocumentId = this.activeEditor?.options?.documentId;
46346
+ const attachedRoomId = promotion.configDoc.v2Collaboration?.documentId;
46347
+ if (typeof attachedDocumentId !== "string" || attachedDocumentId !== promotion.configDoc.id || typeof attachedRoomId !== "string" || attachedRoomId !== target.documentId) throw new Error("SuperDoc: collaboration upgrade did not attach the expected room and document");
46348
+ return {
46349
+ roomId: attachedRoomId,
46350
+ documentId: attachedDocumentId
46351
+ };
46352
+ } catch (err) {
46353
+ this.#rollbackV2UpgradeState(rollback);
46354
+ throw err;
46355
+ }
46356
+ } finally {
46357
+ this.#abortUpgrade = null;
46358
+ this.#isUpgrading = false;
46359
+ this.#pendingUpgrade = null;
46360
+ }
46361
+ })();
46362
+ this.#pendingUpgrade = {
46363
+ target,
46364
+ promise: operation
46365
+ };
46366
+ return operation;
46367
+ }
46368
+ #sameUpgradeTarget(left, right) {
46369
+ if (left.token !== right.token) return false;
46370
+ const seen = /* @__PURE__ */ new WeakMap();
46371
+ const sameValue = (first, second) => {
46372
+ if (Object.is(first, second)) return true;
46373
+ if (!first || !second || typeof first !== "object" || typeof second !== "object") return false;
46374
+ if (Object.getPrototypeOf(first) !== Object.getPrototypeOf(second)) return false;
46375
+ if (seen.has(first)) return seen.get(first) === second;
46376
+ seen.set(first, second);
46377
+ if (first instanceof Date && second instanceof Date) return first.getTime() === second.getTime();
46378
+ if (first instanceof RegExp && second instanceof RegExp) return first.source === second.source && first.flags === second.flags;
46379
+ if (first instanceof ArrayBuffer && second instanceof ArrayBuffer) return sameValue(Array.from(new Uint8Array(first)), Array.from(new Uint8Array(second)));
46380
+ if (ArrayBuffer.isView(first) && ArrayBuffer.isView(second)) return first.constructor === second.constructor && sameValue(Array.from(new Uint8Array(first.buffer, first.byteOffset, first.byteLength)), Array.from(new Uint8Array(second.buffer, second.byteOffset, second.byteLength)));
46381
+ if (first instanceof Map && second instanceof Map) return first.size === second.size && sameValue(Array.from(first.entries()), Array.from(second.entries()));
46382
+ if (first instanceof Set && second instanceof Set) return first.size === second.size && sameValue(Array.from(first.values()), Array.from(second.values()));
46383
+ if (Array.isArray(first) && Array.isArray(second)) return first.length === second.length && first.every((value, index) => sameValue(value, second[index]));
46384
+ if (Object.getPrototypeOf(first) !== Object.prototype && Object.getPrototypeOf(first) !== null) return false;
46385
+ const keys = Object.keys(first).sort();
46386
+ const otherKeys = Object.keys(second).sort();
46387
+ return keys.length === otherKeys.length && keys.every((key, index) => key === otherKeys[index] && sameValue(first[key], second[key]));
46388
+ };
46389
+ return sameValue({
46390
+ ...left,
46391
+ token: void 0
46392
+ }, {
46393
+ ...right,
46394
+ token: void 0
46395
+ });
46279
46396
  }
46280
46397
  #snapshotV2LockSeed() {
46281
46398
  return {
@@ -46602,9 +46719,13 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46602
46719
  if (docxDocs.length > 1) throw new Error("SuperDoc: upgradeToCollaboration() only supports a single DOCX document");
46603
46720
  if (cfg.documents.length !== docxDocs.length) throw new Error("SuperDoc: upgradeToCollaboration() only supports single-DOCX instances");
46604
46721
  if (!isV2ActiveEditorFacade(this.#resolveSourceEditor())) throw new Error("SuperDoc: upgradeToCollaboration() requires a ready v2 DOCX editor");
46605
- const configDoc = docxDocs[0];
46606
- const mountedDocumentId = configDoc.id;
46722
+ const mountedDocumentId = docxDocs[0].id;
46607
46723
  if (typeof mountedDocumentId !== "string" || mountedDocumentId.length === 0) throw new Error("SuperDoc: source document is missing its mounted document identity");
46724
+ return this.#resolveCollaborationUpgradeTarget(options);
46725
+ }
46726
+ #resolveCollaborationUpgradeTarget(options) {
46727
+ const cfg = this.config;
46728
+ const configDoc = cfg.documents.find((doc) => doc.type === DOCX);
46608
46729
  const collaborationModule = cfg.modules?.collaboration;
46609
46730
  const legacyCollaboration = options.ydoc || options.provider ? {
46610
46731
  ydoc: options.ydoc,
@@ -46620,7 +46741,10 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
46620
46741
  ...typeof window !== "undefined" ? { authEndpointBaseUrl: window.location.href } : {}
46621
46742
  });
46622
46743
  if (!resolution.ok) throw new Error(`SuperDoc: upgradeToCollaboration() ${resolution.reason}: ${resolution.message}`);
46623
- return { target: resolution.target };
46744
+ return { target: {
46745
+ ...resolution.target,
46746
+ roomMode: "create"
46747
+ } };
46624
46748
  }
46625
46749
  #unwrapMaybeRef(value) {
46626
46750
  if (value && typeof value === "object" && "value" in value) return value.value;
@@ -1,6 +1,6 @@
1
1
  import { i as __toESM$2 } from "./chunks/rolldown-runtime-0pSA04fp.es.js";
2
2
  import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
3
- import { a as getV2TrackedChangeMutationImpact, c as createInteractionHistory, i as applyV2CommentInvalidationFromMutation, l as recordInteraction, o as DOM_CLASS_NAMES, s as closeInteractionHistory, t as createSuperDocUI } from "./chunks/create-super-doc-ui-qTSa0PbD.es.js";
3
+ import { a as getV2TrackedChangeMutationImpact, c as createInteractionHistory, i as applyV2CommentInvalidationFromMutation, l as recordInteraction, o as DOM_CLASS_NAMES, s as closeInteractionHistory, t as createSuperDocUI } from "./chunks/create-super-doc-ui-Ci7OxbXV.es.js";
4
4
  import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
5
5
  import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
6
6
  import { a as init_dist$1, i as global, n as init_dist$2, o as Buffer, r as process$1, s as init_dist, t as require_jszip_min } from "./chunks/jszip-BzJ3CyxR.es.js";
@@ -315,7 +315,7 @@ var shuffleArray = (array) => {
315
315
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
316
316
  function getSuperdocVersion() {
317
317
  try {
318
- return "2.18.0-next.10";
318
+ return "2.18.0-next.12";
319
319
  } catch {
320
320
  return "unknown";
321
321
  }
@@ -22332,7 +22332,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22332
22332
  if (!payload) return;
22333
22333
  clearV2EditorFailure(payload.documentId ?? null);
22334
22334
  clearV2MutationRejectionNotifications(payload.documentId ?? null);
22335
- const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
22335
+ const { host, mount, documentId, capabilities, editCommands, bindEditShortcuts, bindSessionShortcuts, commentsAdapter, trackedChangesAdapter, contextMenu, documentApi, documentMutationReadiness, documentApiUnavailableReason, pageMetrics, pageLayout, pageFurniture, presence, lock, connection, collaborationProvider, fonts, replaceFile, upgradeToCollaboration, documentOpenToken } = payload;
22336
22336
  documentOpenTelemetry?.trackDocumentOpen(documentOpenToken ?? null, documentId ?? null);
22337
22337
  const saveV2Bytes = createV2SaveQueue(async (saveOptions = {}) => {
22338
22338
  if (!host || typeof host.save !== "function") throw new Error("v2-editor: save unavailable");
@@ -22609,6 +22609,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22609
22609
  pageFurniture: pageFurniture ?? null,
22610
22610
  presence: presence ?? null,
22611
22611
  lock: lock ?? null,
22612
+ connection: connection ?? null,
22612
22613
  provider: collaborationProvider ?? null,
22613
22614
  reviewWindow: {
22614
22615
  getDiagnostics: () => v2ReviewWindowController.getDiagnostics(),
@@ -24454,7 +24455,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
24454
24455
  ], 38);
24455
24456
  };
24456
24457
  }
24457
- }, [["__scopeId", "data-v-4efb0cab"]]);
24458
+ }, [["__scopeId", "data-v-9da02d58"]]);
24458
24459
  //#endregion
24459
24460
  //#region src/core/create-app.js
24460
24461
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45301,6 +45302,14 @@ function contentControlSelectionKey(selection) {
45301
45302
  return null;
45302
45303
  }
45303
45304
  }
45305
+ function deriveCollaborationConnectionKind(snapshot, hasSyncedBefore) {
45306
+ switch (snapshot.state) {
45307
+ case "failed": return "failed";
45308
+ case "degraded": return snapshot.detail === "reconnecting" ? "reconnecting" : "lost";
45309
+ case "synced": return hasSyncedBefore ? "recovered" : "initial";
45310
+ default: return hasSyncedBefore ? "reconnecting" : "initial";
45311
+ }
45312
+ }
45304
45313
  function isV2ActiveEditorFacade(editor) {
45305
45314
  return Boolean(editor && typeof editor === "object" && editor.editorVersion === 2);
45306
45315
  }
@@ -45357,6 +45366,7 @@ var SuperDoc = class extends import_eventemitter3.default {
45357
45366
  #destroyed;
45358
45367
  #diagnostics;
45359
45368
  #isUpgrading;
45369
+ #pendingUpgrade;
45360
45370
  /** Aborts an in-flight upgrade (sync wait or ready wait). */
45361
45371
  #abortUpgrade;
45362
45372
  /**
@@ -45368,6 +45378,12 @@ var SuperDoc = class extends import_eventemitter3.default {
45368
45378
  #v2AwarenessUnsub;
45369
45379
  /** Unsubscribe handle for the v2 root-doc lock observer. */
45370
45380
  #v2LockUnsub;
45381
+ /** Unsubscribe handle for the v2 collaboration connection observer. */
45382
+ #v2ConnectionUnsub;
45383
+ /** Latest `collaboration-connection-change` payload, for late readers. */
45384
+ #v2ConnectionState;
45385
+ /** Whether the current collaboration room has completed a sync at least once. */
45386
+ #v2ConnectionHasSynced;
45371
45387
  /** Lock state captured before a local → v2 collaboration promotion remount. */
45372
45388
  #pendingV2LockSeed;
45373
45389
  #mountWrapper;
@@ -45456,9 +45472,13 @@ var SuperDoc = class extends import_eventemitter3.default {
45456
45472
  super();
45457
45473
  this.#destroyed = false;
45458
45474
  this.#isUpgrading = false;
45475
+ this.#pendingUpgrade = null;
45459
45476
  this.#abortUpgrade = null;
45460
45477
  this.#v2AwarenessUnsub = null;
45461
45478
  this.#v2LockUnsub = null;
45479
+ this.#v2ConnectionUnsub = null;
45480
+ this.#v2ConnectionState = null;
45481
+ this.#v2ConnectionHasSynced = false;
45462
45482
  this.#pendingV2LockSeed = null;
45463
45483
  this.#mountWrapper = null;
45464
45484
  this.#contentControlClickRoot = null;
@@ -45657,7 +45677,7 @@ var SuperDoc = class extends import_eventemitter3.default {
45657
45677
  this.config.colors = shuffleArray(this.config.colors);
45658
45678
  this.userColorMap = /* @__PURE__ */ new Map();
45659
45679
  this.colorIndex = 0;
45660
- this.version = "2.18.0-next.10";
45680
+ this.version = "2.18.0-next.12";
45661
45681
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45662
45682
  this.superdocId = config.superdocId || v4();
45663
45683
  this.colors = this.config.colors ?? [];
@@ -45759,7 +45779,7 @@ var SuperDoc = class extends import_eventemitter3.default {
45759
45779
  return this.#diagnostics;
45760
45780
  }
45761
45781
  emit(event, ...args) {
45762
- if (event === "exception" || event === "document-replaced" || event === "ready" || event === "active-editor-change" || event === "collaboration-ready" || event === "locked") recordInteraction(this, event, () => args[0]);
45782
+ if (event === "exception" || event === "document-replaced" || event === "ready" || event === "active-editor-change" || event === "collaboration-ready" || event === "collaboration-connection-change" || event === "locked") recordInteraction(this, event, () => args[0]);
45763
45783
  return super.emit(event, ...args);
45764
45784
  }
45765
45785
  on(event, fn, context) {
@@ -46001,6 +46021,7 @@ var SuperDoc = class extends import_eventemitter3.default {
46001
46021
  this.#onConfig("pdf:document-ready", this.config.onPdfDocumentReady);
46002
46022
  this.#onConfig("sidebar-toggle", this.config.onSidebarToggle);
46003
46023
  this.#onConfig("collaboration-ready", this.config.onCollaborationReady);
46024
+ this.#onConfig("collaboration-connection-change", this.config.onCollaborationConnectionChange);
46004
46025
  this.on("collaboration-ready", (payload) => this.#startV2CollaborationEventBridge(payload?.editor ?? null));
46005
46026
  this.#onConfig("editor-update", this.config.onEditorUpdate);
46006
46027
  this.#onConfig("tracked-changes:bulk-decision", this.config.onTrackedChangesBulkDecision);
@@ -46091,12 +46112,59 @@ var SuperDoc = class extends import_eventemitter3.default {
46091
46112
  } catch {}
46092
46113
  this.#v2LockUnsub = null;
46093
46114
  }
46115
+ if (this.#v2ConnectionUnsub) {
46116
+ try {
46117
+ this.#v2ConnectionUnsub();
46118
+ } catch {}
46119
+ this.#v2ConnectionUnsub = null;
46120
+ }
46094
46121
  }
46095
46122
  #startV2CollaborationEventBridge(editor) {
46096
46123
  this.#stopV2CollaborationEventBridge();
46097
46124
  if (!isV2ActiveEditorFacade(editor)) return;
46098
46125
  this.#startV2AwarenessBridge(editor);
46099
46126
  this.#startV2LockBridge(editor);
46127
+ this.#startV2ConnectionBridge(editor);
46128
+ }
46129
+ #startV2ConnectionBridge(editor) {
46130
+ const connection = editor.connection;
46131
+ if (!connection || typeof connection.subscribe !== "function") return;
46132
+ const { documentId } = connection;
46133
+ if (this.#v2ConnectionState?.documentId !== documentId) {
46134
+ this.#v2ConnectionState = null;
46135
+ this.#v2ConnectionHasSynced = false;
46136
+ }
46137
+ const publish = (snapshot) => {
46138
+ if (this.#destroyed) return;
46139
+ const previous = this.#v2ConnectionState;
46140
+ if (previous && previous.state === snapshot.state && previous.detail === (snapshot.detail ?? null)) return;
46141
+ const payload = {
46142
+ documentId,
46143
+ state: snapshot.state,
46144
+ previousState: previous?.state ?? null,
46145
+ kind: deriveCollaborationConnectionKind(snapshot, this.#v2ConnectionHasSynced),
46146
+ detail: snapshot.detail ?? null,
46147
+ superdoc: this
46148
+ };
46149
+ this.#v2ConnectionState = payload;
46150
+ if (snapshot.state === "synced") this.#v2ConnectionHasSynced = true;
46151
+ this.emit("collaboration-connection-change", payload);
46152
+ };
46153
+ try {
46154
+ const initialSnapshot = connection.getSnapshot?.();
46155
+ if (initialSnapshot) publish(initialSnapshot);
46156
+ this.#v2ConnectionUnsub = connection.subscribe(publish);
46157
+ } catch (err) {
46158
+ console.warn("[SuperDoc] v2 connection bridge failed to subscribe", err);
46159
+ }
46160
+ }
46161
+ /**
46162
+ * Latest v2 collaboration connection change, or `null` when no v2
46163
+ * collaboration session has reported one. Same payload as the
46164
+ * `collaboration-connection-change` event.
46165
+ */
46166
+ getCollaborationConnectionState() {
46167
+ return this.#v2ConnectionState;
46100
46168
  }
46101
46169
  #startV2AwarenessBridge(editor) {
46102
46170
  const presence = editor.presence;
@@ -46184,29 +46252,78 @@ var SuperDoc = class extends import_eventemitter3.default {
46184
46252
  * - A supported v2 single-doc `v2Collaboration` target
46185
46253
  * - Create-and-upgrade only (no merge semantics)
46186
46254
  *
46187
- * @returns Resolves once the collaborative runtime is ready
46255
+ * @returns The attached room and document once the collaborative runtime is ready
46188
46256
  */
46189
46257
  async upgradeToCollaboration(options) {
46258
+ if (this.#pendingUpgrade) {
46259
+ const { target } = this.#resolveCollaborationUpgradeTarget(options);
46260
+ if (this.#sameUpgradeTarget(target, this.#pendingUpgrade.target)) return this.#pendingUpgrade.promise;
46261
+ throw Object.assign(/* @__PURE__ */ new Error("SuperDoc: a different collaboration target is already upgrading"), { code: "collaboration-upgrade-target-conflict" });
46262
+ }
46190
46263
  const { target } = this.#validateUpgradePrerequisites(options);
46191
46264
  this.#isUpgrading = true;
46192
- try {
46193
- const localSource = await this.#captureCurrentDocxSourceForUpgrade();
46194
- const rollback = this.#snapshotV2UpgradeState();
46195
- const lockSeed = this.#snapshotV2LockSeed();
46196
- this.#assertNotDestroyed();
46265
+ const operation = (async () => {
46197
46266
  try {
46198
- this.#pendingV2LockSeed = lockSeed;
46199
- const promotion = await this.#promoteSingleDocumentToV2Collaboration(target, localSource);
46200
- this.#finalizeSingleDocumentV2Collaboration(promotion, target);
46201
- this.#pendingV2LockSeed = null;
46202
- } catch (err) {
46203
- this.#rollbackV2UpgradeState(rollback);
46204
- throw err;
46205
- }
46206
- } finally {
46207
- this.#abortUpgrade = null;
46208
- this.#isUpgrading = false;
46209
- }
46267
+ const localSource = await this.#captureCurrentDocxSourceForUpgrade();
46268
+ const rollback = this.#snapshotV2UpgradeState();
46269
+ const lockSeed = this.#snapshotV2LockSeed();
46270
+ this.#assertNotDestroyed();
46271
+ try {
46272
+ this.#pendingV2LockSeed = lockSeed;
46273
+ const promotion = await this.#promoteSingleDocumentToV2Collaboration(target, localSource);
46274
+ this.#finalizeSingleDocumentV2Collaboration(promotion, target);
46275
+ this.#pendingV2LockSeed = null;
46276
+ const attachedDocumentId = this.activeEditor?.options?.documentId;
46277
+ const attachedRoomId = promotion.configDoc.v2Collaboration?.documentId;
46278
+ if (typeof attachedDocumentId !== "string" || attachedDocumentId !== promotion.configDoc.id || typeof attachedRoomId !== "string" || attachedRoomId !== target.documentId) throw new Error("SuperDoc: collaboration upgrade did not attach the expected room and document");
46279
+ return {
46280
+ roomId: attachedRoomId,
46281
+ documentId: attachedDocumentId
46282
+ };
46283
+ } catch (err) {
46284
+ this.#rollbackV2UpgradeState(rollback);
46285
+ throw err;
46286
+ }
46287
+ } finally {
46288
+ this.#abortUpgrade = null;
46289
+ this.#isUpgrading = false;
46290
+ this.#pendingUpgrade = null;
46291
+ }
46292
+ })();
46293
+ this.#pendingUpgrade = {
46294
+ target,
46295
+ promise: operation
46296
+ };
46297
+ return operation;
46298
+ }
46299
+ #sameUpgradeTarget(left, right) {
46300
+ if (left.token !== right.token) return false;
46301
+ const seen = /* @__PURE__ */ new WeakMap();
46302
+ const sameValue = (first, second) => {
46303
+ if (Object.is(first, second)) return true;
46304
+ if (!first || !second || typeof first !== "object" || typeof second !== "object") return false;
46305
+ if (Object.getPrototypeOf(first) !== Object.getPrototypeOf(second)) return false;
46306
+ if (seen.has(first)) return seen.get(first) === second;
46307
+ seen.set(first, second);
46308
+ if (first instanceof Date && second instanceof Date) return first.getTime() === second.getTime();
46309
+ if (first instanceof RegExp && second instanceof RegExp) return first.source === second.source && first.flags === second.flags;
46310
+ if (first instanceof ArrayBuffer && second instanceof ArrayBuffer) return sameValue(Array.from(new Uint8Array(first)), Array.from(new Uint8Array(second)));
46311
+ if (ArrayBuffer.isView(first) && ArrayBuffer.isView(second)) return first.constructor === second.constructor && sameValue(Array.from(new Uint8Array(first.buffer, first.byteOffset, first.byteLength)), Array.from(new Uint8Array(second.buffer, second.byteOffset, second.byteLength)));
46312
+ if (first instanceof Map && second instanceof Map) return first.size === second.size && sameValue(Array.from(first.entries()), Array.from(second.entries()));
46313
+ if (first instanceof Set && second instanceof Set) return first.size === second.size && sameValue(Array.from(first.values()), Array.from(second.values()));
46314
+ if (Array.isArray(first) && Array.isArray(second)) return first.length === second.length && first.every((value, index) => sameValue(value, second[index]));
46315
+ if (Object.getPrototypeOf(first) !== Object.prototype && Object.getPrototypeOf(first) !== null) return false;
46316
+ const keys = Object.keys(first).sort();
46317
+ const otherKeys = Object.keys(second).sort();
46318
+ return keys.length === otherKeys.length && keys.every((key, index) => key === otherKeys[index] && sameValue(first[key], second[key]));
46319
+ };
46320
+ return sameValue({
46321
+ ...left,
46322
+ token: void 0
46323
+ }, {
46324
+ ...right,
46325
+ token: void 0
46326
+ });
46210
46327
  }
46211
46328
  #snapshotV2LockSeed() {
46212
46329
  return {
@@ -46533,9 +46650,13 @@ var SuperDoc = class extends import_eventemitter3.default {
46533
46650
  if (docxDocs.length > 1) throw new Error("SuperDoc: upgradeToCollaboration() only supports a single DOCX document");
46534
46651
  if (cfg.documents.length !== docxDocs.length) throw new Error("SuperDoc: upgradeToCollaboration() only supports single-DOCX instances");
46535
46652
  if (!isV2ActiveEditorFacade(this.#resolveSourceEditor())) throw new Error("SuperDoc: upgradeToCollaboration() requires a ready v2 DOCX editor");
46536
- const configDoc = docxDocs[0];
46537
- const mountedDocumentId = configDoc.id;
46653
+ const mountedDocumentId = docxDocs[0].id;
46538
46654
  if (typeof mountedDocumentId !== "string" || mountedDocumentId.length === 0) throw new Error("SuperDoc: source document is missing its mounted document identity");
46655
+ return this.#resolveCollaborationUpgradeTarget(options);
46656
+ }
46657
+ #resolveCollaborationUpgradeTarget(options) {
46658
+ const cfg = this.config;
46659
+ const configDoc = cfg.documents.find((doc) => doc.type === DOCX);
46539
46660
  const collaborationModule = cfg.modules?.collaboration;
46540
46661
  const legacyCollaboration = options.ydoc || options.provider ? {
46541
46662
  ydoc: options.ydoc,
@@ -46551,7 +46672,10 @@ var SuperDoc = class extends import_eventemitter3.default {
46551
46672
  ...typeof window !== "undefined" ? { authEndpointBaseUrl: window.location.href } : {}
46552
46673
  });
46553
46674
  if (!resolution.ok) throw new Error(`SuperDoc: upgradeToCollaboration() ${resolution.reason}: ${resolution.message}`);
46554
- return { target: resolution.target };
46675
+ return { target: {
46676
+ ...resolution.target,
46677
+ roomMode: "create"
46678
+ } };
46555
46679
  }
46556
46680
  #unwrapMaybeRef(value) {
46557
46681
  if (value && typeof value === "object" && "value" in value) return value.value;