superdoc 2.30.0-next.4 → 2.30.0-next.9

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 (48) hide show
  1. package/dist/chunks/{create-super-doc-ui-CbEDXtpm.es.js → create-super-doc-ui-Cq8trPVC.es.js} +494 -107
  2. package/dist/chunks/{create-super-doc-ui--kQBNTyt.cjs → create-super-doc-ui-FH5GSHph.cjs} +492 -105
  3. package/dist/collaboration-upgrade-engine.cjs +1 -1
  4. package/dist/collaboration-upgrade-engine.es.js +1 -1
  5. package/dist/document-api/src/comments/comment-create-attribution.d.ts +4 -0
  6. package/dist/document-api/src/comments/comments.types.d.ts +4 -0
  7. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  8. package/dist/document-api/src/contract/operation-definitions.d.ts +25 -7
  9. package/dist/document-api/src/contract/operation-registry.d.ts +2 -2
  10. package/dist/document-api/src/contract/schemas.d.ts +7 -1
  11. package/dist/document-api/src/index.d.ts +7 -1
  12. package/dist/document-api/src/paragraphs/paragraphs.d.ts +8 -3
  13. package/dist/document-api/src/paragraphs/paragraphs.types.d.ts +49 -5
  14. package/dist/document-api/src/tables/data/table-preset-appearance.generated.d.ts +2 -0
  15. package/dist/document-api/src/tables/table-style-presets.d.ts +73 -0
  16. package/dist/document-api/src/tables/tables.d.ts +4 -1
  17. package/dist/document-api/src/types/sd-props.d.ts +7 -0
  18. package/dist/document-api/src/types/table-operations.types.d.ts +12 -15
  19. package/dist/layout-engine/contracts/src/index.d.ts +1 -0
  20. package/dist/layout-engine/contracts/src/table-cell-vector-overlay.d.ts +2 -0
  21. package/dist/layout-engine/painters/dom/src/index.d.ts +2 -0
  22. package/dist/public/ui-react.cjs +1 -1
  23. package/dist/public/ui-react.es.js +1 -1
  24. package/dist/public/ui-vue.cjs +1 -1
  25. package/dist/public/ui-vue.es.js +1 -1
  26. package/dist/public/ui.cjs +1 -1
  27. package/dist/public/ui.es.js +1 -1
  28. package/dist/style.css +1 -1
  29. package/dist/style.layered.css +1 -1
  30. package/dist/superdoc/src/composables/use-comment-sidebar.d.ts +6 -0
  31. package/dist/superdoc/src/core/config/normalize-interaction-config.d.ts +10 -1
  32. package/dist/superdoc/src/core/editor-runtime/types.d.ts +4 -0
  33. package/dist/superdoc/src/core/types/index.d.ts +39 -0
  34. package/dist/superdoc/src/public/index.d.cts +4 -0
  35. package/dist/superdoc/src/public/index.d.ts +1 -1
  36. package/dist/superdoc/src/public/ui/format-painter-paragraph.d.ts +7 -0
  37. package/dist/superdoc/src/public/ui/format-painter-state.d.ts +5 -9
  38. package/dist/superdoc/src/public/ui/inline-values.d.ts +1 -1
  39. package/dist/superdoc/src/public/ui/reasons.d.ts +1 -0
  40. package/dist/superdoc/src/public/ui/selection-targets.d.ts +2 -0
  41. package/dist/superdoc/src/stores/comments-store.d.ts +21 -9
  42. package/dist/superdoc/src/stores/helpers/review-presentation.d.ts +1 -0
  43. package/dist/superdoc.cjs +239 -60
  44. package/dist/superdoc.es.js +239 -60
  45. package/dist-cdn/style.layered.css +1 -1
  46. package/dist-cdn/superdoc.min.css +1 -1
  47. package/dist-cdn/superdoc.min.js +38 -38
  48. package/package.json +2 -2
package/dist/superdoc.cjs CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_rolldown_runtime = require("./chunks/rolldown-runtime-74VwNCz7.cjs");
3
3
  const require__plugin_vue_export_helper = require("./chunks/_plugin-vue_export-helper-BzM2_tVU.cjs");
4
4
  const require_blank_docx = require("./chunks/blank-docx-BuFAbRjs.cjs");
5
- const require_create_super_doc_ui = require("./chunks/create-super-doc-ui--kQBNTyt.cjs");
5
+ const require_create_super_doc_ui = require("./chunks/create-super-doc-ui-FH5GSHph.cjs");
6
6
  const require_eventemitter3 = require("./chunks/eventemitter3-C_TAnXOl.cjs");
7
7
  const require_uuid = require("./chunks/uuid-BhG0ngwk.cjs");
8
8
  const require_jszip = require("./chunks/jszip-D8mAFF-r.cjs");
@@ -259,7 +259,7 @@ var v_click_outside_default = {
259
259
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
260
260
  function getSuperdocVersion() {
261
261
  try {
262
- return "2.30.0-next.4";
262
+ return "2.30.0-next.9";
263
263
  } catch {
264
264
  return "unknown";
265
265
  }
@@ -6829,6 +6829,18 @@ function resolveDocxExportPolicies(input = {}) {
6829
6829
  contentControls: requested?.contentControls ?? "preserve"
6830
6830
  };
6831
6831
  }
6832
+ new TextEncoder();
6833
+ function normalizeCommentIdentity(value) {
6834
+ if (value === null) return null;
6835
+ if (typeof value !== "object" || Array.isArray(value) || !("providerId" in value) || !("userId" in value) || !xmlIdentityString(value.providerId) || !xmlIdentityString(value.userId)) throw new TypeError("commentIdentity requires XML-safe non-empty providerId and userId strings.");
6836
+ return {
6837
+ providerId: value.providerId,
6838
+ userId: value.userId
6839
+ };
6840
+ }
6841
+ function xmlIdentityString(value) {
6842
+ return typeof value === "string" && value.trim().length > 0 && !/[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}]/u.test(value);
6843
+ }
6832
6844
  //#endregion
6833
6845
  //#region ../document-api/src/permission-ranges/permission-ranges.ts
6834
6846
  function editorKey(editor) {
@@ -8009,6 +8021,7 @@ var useCommentsStore = defineStore("comments", () => {
8009
8021
  });
8010
8022
  const debounceTimers = {};
8011
8023
  const trackedChangeResolutionSnapshots = /* @__PURE__ */ new WeakMap();
8024
+ let cachedTrackedChangeBatchIdentityIndex = null;
8012
8025
  const isBenchmarkCommentsDebugEnabled = () => {
8013
8026
  if (typeof window === "undefined") return false;
8014
8027
  return "__labsSuperDocV2BenchmarkDebug" in window;
@@ -8090,6 +8103,7 @@ var useCommentsStore = defineStore("comments", () => {
8090
8103
  const isV2EditorActive = (superdoc) => superdoc?.activeEditor?.editorVersion === 2 || v2CommentsAdapter.value !== null;
8091
8104
  const v2TrackedChangesAdapter = require__plugin_vue_export_helper.shallowRef(null);
8092
8105
  const setV2TrackedChangesAdapter = (adapter) => {
8106
+ cachedTrackedChangeBatchIdentityIndex = null;
8093
8107
  v2TrackedChangesAdapter.value = isV2TrackedChangesAdapter(adapter) ? adapter : null;
8094
8108
  };
8095
8109
  const getV2TrackedChangesAdapter = (superdoc) => {
@@ -8213,7 +8227,7 @@ var useCommentsStore = defineStore("comments", () => {
8213
8227
  * Called when a tracked change is updated. Creates a new comment if necessary,
8214
8228
  * or updates an existing tracked-change comment.
8215
8229
  */
8216
- const handleTrackedChangeUpdate = ({ superdoc, params, broadcastChanges = true, trackedChangeIdentityIndex = null }) => {
8230
+ const handleTrackedChangeUpdate = ({ superdoc, params, broadcastChanges = true, trackedChangeIdentityIndex = null, preserveDraft = false }) => {
8217
8231
  const span = startInteractionSpan("store.trackedChanges.handleUpdate", "store-reconciliation", {
8218
8232
  event: params?.event ?? null,
8219
8233
  changeId: params?.changeId ?? null,
@@ -8238,8 +8252,10 @@ var useCommentsStore = defineStore("comments", () => {
8238
8252
  const normalizedTrackedChangeLabel = typeof trackedChangeLabel === "string" && trackedChangeLabel.length > 0 ? trackedChangeLabel : null;
8239
8253
  const normalizedTrackedChangeDetailLines = normalizeTrackedChangeDetailLines(trackedChangeDetailLines);
8240
8254
  const normalizedTrackedChangeImagePreview = normalizeTrackedChangeImagePreview(trackedChangeImagePreview);
8255
+ const hasDraft = preserveDraft && (pendingComment.value !== null || currentCommentText.value !== "" || currentCommentMentions.value.length > 0);
8241
8256
  const comment = getPendingComment({
8242
8257
  documentId,
8258
+ ...hasDraft ? { commentText: "" } : {},
8243
8259
  commentId: normalizedChangeId ?? void 0,
8244
8260
  trackedChange: true,
8245
8261
  trackedChangeText,
@@ -8394,7 +8410,8 @@ var useCommentsStore = defineStore("comments", () => {
8394
8410
  addHydratedComment({
8395
8411
  superdoc: requireHost(superdoc, "handleTrackedChangeUpdate"),
8396
8412
  comment,
8397
- broadcastChanges
8413
+ broadcastChanges,
8414
+ preserveDraft: hasDraft
8398
8415
  });
8399
8416
  trackedChangeIdentityIndex?.add(comment);
8400
8417
  } else if (event === "update") {
@@ -8624,7 +8641,7 @@ var useCommentsStore = defineStore("comments", () => {
8624
8641
  /**
8625
8642
  * Add a new comment to the document
8626
8643
  */
8627
- const addCommentInternal = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true, isHydration = false }) => {
8644
+ const addCommentInternal = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true, isHydration = false, preserveDraft = false }) => {
8628
8645
  if (commentsAreReadOnly() && !isHydration) return readOnlyMutationOutcome();
8629
8646
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8630
8647
  if (v2Adapter && !comment.trackedChange) {
@@ -8703,23 +8720,25 @@ var useCommentsStore = defineStore("comments", () => {
8703
8720
  };
8704
8721
  });
8705
8722
  }
8706
- let parentComment = commentsList.value.find((c) => c.commentId === activeComment.value);
8723
+ const activeId = activeComment.value;
8724
+ const parent = require__plugin_vue_export_helper.toRaw(commentsList.value).find((c) => require__plugin_vue_export_helper.unref(c.commentId) === activeId);
8725
+ let parentComment = parent ? require__plugin_vue_export_helper.reactive(parent) : void 0;
8707
8726
  if (!parentComment) parentComment = comment;
8708
8727
  const newComment = useComment(comment.getValues());
8709
- if (pendingComment.value) newComment.setText({
8710
- text: currentCommentText.value,
8711
- suppressUpdate: true
8712
- });
8713
- else newComment.setText({
8714
- text: comment.commentText,
8728
+ const text = pendingComment.value && !preserveDraft ? currentCommentText.value : comment.commentText;
8729
+ if (text === "") {
8730
+ newComment.commentText = "";
8731
+ newComment.mentions = [];
8732
+ } else newComment.setText({
8733
+ text,
8715
8734
  suppressUpdate: true
8716
8735
  });
8717
- newComment.selection.source = pendingComment.value?.selection?.source ?? newComment.selection.source;
8736
+ if (!preserveDraft) newComment.selection.source = pendingComment.value?.selection?.source ?? newComment.selection.source;
8718
8737
  if (parentComment) newComment.isInternal = parentComment.isInternal;
8719
8738
  if (!superdoc.config.isInternal) newComment.isInternal = false;
8720
8739
  commentsList.value.push(newComment);
8721
- const hadPendingComment = !!pendingComment.value;
8722
- removePendingComment(superdoc);
8740
+ const hadPendingComment = !preserveDraft && !!pendingComment.value;
8741
+ if (!preserveDraft) removePendingComment(superdoc);
8723
8742
  if (hadPendingComment) {
8724
8743
  activeComment.value = newComment.commentId;
8725
8744
  setActiveFloatingCommentInstance(newComment.commentId);
@@ -8747,12 +8766,13 @@ var useCommentsStore = defineStore("comments", () => {
8747
8766
  skipEditorUpdate,
8748
8767
  broadcastChanges
8749
8768
  });
8750
- const addHydratedComment = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true }) => addCommentInternal({
8769
+ const addHydratedComment = ({ superdoc, comment, skipEditorUpdate = false, broadcastChanges = true, preserveDraft = false }) => addCommentInternal({
8751
8770
  superdoc,
8752
8771
  comment,
8753
8772
  skipEditorUpdate,
8754
8773
  broadcastChanges,
8755
- isHydration: true
8774
+ isHydration: true,
8775
+ preserveDraft
8756
8776
  });
8757
8777
  const deleteComment = ({ commentId: commentIdToDelete, superdoc }) => {
8758
8778
  if (commentsAreReadOnly()) return Promise.resolve(readOnlyMutationOutcome());
@@ -9477,6 +9497,11 @@ var useCommentsStore = defineStore("comments", () => {
9477
9497
  /** Keep one mounted review window plus rows whose interaction is still live. */
9478
9498
  const boundReviewPresentationRows = ({ documentId, visibleIds }) => {
9479
9499
  const currentRows = commentsList.value;
9500
+ if (currentRows.every((row) => {
9501
+ if (!belongsToTrackedChangeSyncDocument(row, documentId)) return true;
9502
+ const id = normalizeCommentId(row.commentId);
9503
+ return Boolean(id && visibleIds.has(id));
9504
+ })) return;
9480
9505
  const identityIdsByRow = /* @__PURE__ */ new Map();
9481
9506
  const identityIdsFor = (row) => {
9482
9507
  let ids = identityIdsByRow.get(row);
@@ -9693,7 +9718,8 @@ var useCommentsStore = defineStore("comments", () => {
9693
9718
  preparedParams,
9694
9719
  preparedPresentation: preparedReview?.presentation ?? null,
9695
9720
  previousPreparedPresentation,
9696
- pruneStale: false
9721
+ pruneStale: false,
9722
+ preserveDraft: true
9697
9723
  });
9698
9724
  reconcileCommentsFromV2({
9699
9725
  superdoc,
@@ -10439,6 +10465,10 @@ var useCommentsStore = defineStore("comments", () => {
10439
10465
  const byIdentityAlias = /* @__PURE__ */ new Map();
10440
10466
  const aliasesByRow = /* @__PURE__ */ new Map();
10441
10467
  const indexedRows = /* @__PURE__ */ new Set();
10468
+ const indexedIdentities = [];
10469
+ let building = true;
10470
+ let reusable = true;
10471
+ let reused = false;
10442
10472
  let aliasLookups = 0;
10443
10473
  let candidateVisits = 0;
10444
10474
  let rowAliasBuilds = 0;
@@ -10462,6 +10492,7 @@ var useCommentsStore = defineStore("comments", () => {
10462
10492
  index.set(alias, bucket);
10463
10493
  };
10464
10494
  const add = (comment) => {
10495
+ if (!building) reusable = false;
10465
10496
  if (!comment?.trackedChange) return;
10466
10497
  if (documentId && !belongsToTrackedChangeSyncDocument(comment, documentId)) return;
10467
10498
  indexedRows.add(comment);
@@ -10473,19 +10504,49 @@ var useCommentsStore = defineStore("comments", () => {
10473
10504
  rowAliasBuilds += 1;
10474
10505
  aliasesByRow.set(comment, aliases);
10475
10506
  aliases.forEach((alias) => addAlias(byIdentityAlias, alias, comment));
10507
+ if (building) indexedIdentities.push({
10508
+ row: comment,
10509
+ aliases,
10510
+ canonicalId: normalizeCommentId(comment.trackedChangeCanonicalId)
10511
+ });
10476
10512
  };
10477
10513
  commentsList.value.forEach(add);
10514
+ building = false;
10478
10515
  return {
10516
+ inUse: false,
10479
10517
  add,
10480
10518
  aliasesFor,
10481
- work: () => ({
10482
- trackedRowsIndexed: indexedRows.size,
10483
- invalidatedIdMembershipChecks: 0,
10484
- incomingAliasLookups: aliasLookups,
10485
- candidateVisits,
10486
- rowAliasBuilds,
10487
- rowAliasCacheHits
10488
- }),
10519
+ isCurrent: () => {
10520
+ if (!reusable) return false;
10521
+ let index = 0;
10522
+ for (const row of commentsList.value) {
10523
+ if (!row?.trackedChange || documentId && !belongsToTrackedChangeSyncDocument(row, documentId)) continue;
10524
+ const previous = indexedIdentities[index++];
10525
+ if (!previous || previous.row !== row || previous.canonicalId !== normalizeCommentId(row.trackedChangeCanonicalId)) return false;
10526
+ const aliases = getCommentAliasIds(row);
10527
+ rowAliasBuilds += 1;
10528
+ if (aliases.length !== previous.aliases.length || aliases.some((alias, i) => alias !== previous.aliases[i])) return false;
10529
+ }
10530
+ reused = index === indexedIdentities.length;
10531
+ return reused;
10532
+ },
10533
+ work: () => {
10534
+ const result = {
10535
+ trackedRowsIndexed: indexedRows.size,
10536
+ invalidatedIdMembershipChecks: 0,
10537
+ incomingAliasLookups: aliasLookups,
10538
+ candidateVisits,
10539
+ rowAliasBuilds,
10540
+ rowAliasCacheHits,
10541
+ indexReused: Number(reused)
10542
+ };
10543
+ aliasLookups = 0;
10544
+ candidateVisits = 0;
10545
+ rowAliasBuilds = 0;
10546
+ rowAliasCacheHits = 0;
10547
+ reused = false;
10548
+ return result;
10549
+ },
10489
10550
  candidates({ changeId, importedId, anchorKey, canonicalId, positionAliases = [] } = {}) {
10490
10551
  const out = /* @__PURE__ */ new Set();
10491
10552
  const include = (value) => {
@@ -10508,7 +10569,30 @@ var useCommentsStore = defineStore("comments", () => {
10508
10569
  }
10509
10570
  };
10510
10571
  };
10511
- const reconcileTrackedChangesFromV2 = ({ superdoc, adapter, documentId, items, pruneStale = true, preparedParams = null, preparedPresentation = null, previousPreparedPresentation = null, liveIds: suppliedLiveIds = null, liveAnchorKeys: suppliedLiveAnchorKeys = null, hydrationGeneration } = {}) => withInteractionSpan("store.trackedChanges.reconcile", "store-reconciliation", {
10572
+ const getTrackedChangeBatchIdentityIndex = (documentId) => {
10573
+ const cached = cachedTrackedChangeBatchIdentityIndex;
10574
+ if (cached?.documentId === documentId && !cached.index.inUse) {
10575
+ cached.index.inUse = true;
10576
+ let current = false;
10577
+ try {
10578
+ current = cached.index.isCurrent() && cachedTrackedChangeBatchIdentityIndex === cached;
10579
+ } finally {
10580
+ if (!current) {
10581
+ cached.index.inUse = false;
10582
+ if (cachedTrackedChangeBatchIdentityIndex === cached) cachedTrackedChangeBatchIdentityIndex = null;
10583
+ }
10584
+ }
10585
+ if (current) return cached.index;
10586
+ }
10587
+ const index = createTrackedChangeBatchIdentityIndex(documentId);
10588
+ index.inUse = true;
10589
+ cachedTrackedChangeBatchIdentityIndex = {
10590
+ documentId,
10591
+ index
10592
+ };
10593
+ return index;
10594
+ };
10595
+ const reconcileTrackedChangesFromV2 = ({ superdoc, adapter, documentId, items, pruneStale = true, preparedParams = null, preserveDraft = false, preparedPresentation = null, previousPreparedPresentation = null, liveIds: suppliedLiveIds = null, liveAnchorKeys: suppliedLiveAnchorKeys = null, hydrationGeneration } = {}) => withInteractionSpan("store.trackedChanges.reconcile", "store-reconciliation", {
10512
10596
  documentId: documentId ?? null,
10513
10597
  itemCount: Array.isArray(items) ? items.length : null,
10514
10598
  pruneStale,
@@ -10520,13 +10604,15 @@ var useCommentsStore = defineStore("comments", () => {
10520
10604
  const liveAnchorKeys = suppliedLiveAnchorKeys instanceof Set ? suppliedLiveAnchorKeys : /* @__PURE__ */ new Set();
10521
10605
  const liveIds = suppliedLiveIds instanceof Set ? suppliedLiveIds : /* @__PURE__ */ new Set();
10522
10606
  let appliedCount = 0;
10523
- const trackedChangeIdentityIndex = createTrackedChangeBatchIdentityIndex(effectiveDocumentId == null ? null : String(effectiveDocumentId));
10607
+ const trackedChangeIdentityIndex = getTrackedChangeBatchIdentityIndex(effectiveDocumentId == null ? null : String(effectiveDocumentId));
10524
10608
  const identitySpan = startInteractionSpan("store.trackedChanges.batchIdentity", "store-reconciliation", { itemCount: items.length });
10525
- const paramsList = Array.isArray(preparedParams) ? preparedParams : items.map((item) => adapter.mapV2TrackedChangeToCommentParams(item));
10526
- const previousCoordinate = previousPreparedPresentation?.coordinate;
10527
- const coordinate = preparedPresentation?.coordinate;
10528
- const retainUnchangedRows = !pruneStale && previousCoordinate && coordinate && coordinate.documentEpoch === preparedPresentation.epoch && coordinate.documentEpoch === previousPreparedPresentation.epoch && coordinate.documentEpoch === previousCoordinate.documentEpoch && typeof coordinate.mountId === "string" && coordinate.mountId.length > 0 && coordinate.mountId === previousCoordinate.mountId && preparedPresentation.baseVersion === previousPreparedPresentation.version && preparedPresentation.version === preparedPresentation.baseVersion + 1 && coordinate.reviewVersion === preparedPresentation.version && previousCoordinate.reviewVersion === previousPreparedPresentation.version && Number.isSafeInteger(coordinate.commitSequence) && Number.isSafeInteger(previousCoordinate.commitSequence) && coordinate.commitSequence >= previousCoordinate.commitSequence;
10609
+ let enteredBatch = false;
10529
10610
  try {
10611
+ const paramsList = Array.isArray(preparedParams) ? preparedParams : items.map((item) => adapter.mapV2TrackedChangeToCommentParams(item));
10612
+ const previousCoordinate = previousPreparedPresentation?.coordinate;
10613
+ const coordinate = preparedPresentation?.coordinate;
10614
+ const retainUnchangedRows = !pruneStale && previousCoordinate && coordinate && coordinate.documentEpoch === preparedPresentation.epoch && coordinate.documentEpoch === previousPreparedPresentation.epoch && coordinate.documentEpoch === previousCoordinate.documentEpoch && typeof coordinate.mountId === "string" && coordinate.mountId.length > 0 && coordinate.mountId === previousCoordinate.mountId && preparedPresentation.baseVersion === previousPreparedPresentation.version && preparedPresentation.version === preparedPresentation.baseVersion + 1 && coordinate.reviewVersion === preparedPresentation.version && previousCoordinate.reviewVersion === previousPreparedPresentation.version && Number.isSafeInteger(coordinate.commitSequence) && Number.isSafeInteger(previousCoordinate.commitSequence) && coordinate.commitSequence >= previousCoordinate.commitSequence;
10615
+ enteredBatch = true;
10530
10616
  for (const params of paramsList) {
10531
10617
  if (!params) continue;
10532
10618
  let retainUnchangedRow = false;
@@ -10561,12 +10647,15 @@ var useCommentsStore = defineStore("comments", () => {
10561
10647
  superdoc,
10562
10648
  params,
10563
10649
  broadcastChanges: false,
10564
- trackedChangeIdentityIndex
10650
+ trackedChangeIdentityIndex,
10651
+ preserveDraft
10565
10652
  });
10566
10653
  appliedCount += 1;
10567
10654
  }
10568
10655
  } finally {
10569
- endInteractionSpan(identitySpan, trackedChangeIdentityIndex.work());
10656
+ const work = trackedChangeIdentityIndex.work();
10657
+ trackedChangeIdentityIndex.inUse = false;
10658
+ if (enteredBatch) endInteractionSpan(identitySpan, work);
10570
10659
  }
10571
10660
  if (!effectiveDocumentId || !pruneStale) {
10572
10661
  if (effectiveDocumentId) compactDuplicateBodyTrackedChangeComments(String(effectiveDocumentId));
@@ -14111,18 +14200,42 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
14111
14200
  const { activeComment, activeFloatingCommentInstanceId, editorCommentPositions, pendingComment, editingCommentId, instantSidebarAlignmentTargetY, instantSidebarAlignmentThreadId, instantSidebarAlignmentInstanceId } = storeToRefs(piniaCommentsStore);
14112
14201
  const { activeZoom } = storeToRefs(superdocStore);
14113
14202
  const committedPresentation = require__plugin_vue_export_helper.computed(() => commentsStore.committedReviewPresentations?.[String(props.currentDocument?.id)] ?? null);
14203
+ const committedInstanceCache = /* @__PURE__ */ new Map();
14204
+ let committedInstanceCacheOwner = "";
14205
+ const sameReviewInstance = (cached, next) => {
14206
+ const before = Object.entries(cached).filter(([key]) => key !== "comment" && key !== "rowVersion");
14207
+ const after = Object.entries(next);
14208
+ if (before.length !== after.length) return false;
14209
+ const previous = new Map(before);
14210
+ return after.every(([key, value]) => previous.has(key) && (key === "positionEntry" ? JSON.stringify(previous.get(key)) === JSON.stringify(value) : Object.is(previous.get(key), value)));
14211
+ };
14114
14212
  const committedInstances = require__plugin_vue_export_helper.computed(() => {
14115
14213
  const presentation = committedPresentation.value;
14116
14214
  if (!presentation) return null;
14117
14215
  const rows = new Map(commentsStore.commentsList.filter((row) => String(row.fileId) === String(props.currentDocument?.id)).map((row) => [String(row.commentId), row]));
14118
- return presentation.instances.flatMap((instance) => {
14216
+ const owner = `${presentation.epoch}\u0000${presentation.coordinate?.mountId ?? ""}`;
14217
+ if (owner !== committedInstanceCacheOwner) {
14218
+ committedInstanceCache.clear();
14219
+ committedInstanceCacheOwner = owner;
14220
+ }
14221
+ const live = /* @__PURE__ */ new Set();
14222
+ const instances = presentation.instances.flatMap((instance) => {
14119
14223
  const comment = instance.rowId === "pending" ? pendingComment.value : rows.get(instance.rowId);
14120
- return comment ? [{
14224
+ if (!comment) return [];
14225
+ const rowVersion = presentation.rowVersions[instance.rowId] ?? 0;
14226
+ live.add(instance.id);
14227
+ const cached = committedInstanceCache.get(instance.id);
14228
+ if (cached && cached.comment === comment && cached.rowVersion === rowVersion && sameReviewInstance(cached, instance)) return [cached];
14229
+ const merged = {
14121
14230
  ...instance,
14122
14231
  comment,
14123
- rowVersion: presentation.rowVersions[instance.rowId] ?? 0
14124
- }] : [];
14232
+ rowVersion
14233
+ };
14234
+ committedInstanceCache.set(instance.id, merged);
14235
+ return [merged];
14125
14236
  });
14237
+ for (const id of committedInstanceCache.keys()) if (!live.has(id)) committedInstanceCache.delete(id);
14238
+ return instances;
14126
14239
  });
14127
14240
  const floatingCommentInstances = require__plugin_vue_export_helper.computed(() => {
14128
14241
  if (committedInstances.value) return committedInstances.value.filter((instance) => instance.rowId !== "pending");
@@ -14538,6 +14651,18 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
14538
14651
  scheduleDeferredRemeasure(() => allPositions.value.map((pos) => pos.id));
14539
14652
  });
14540
14653
  };
14654
+ const resizeHandlers = /* @__PURE__ */ new Map();
14655
+ const resizeHandlerFor = (id) => {
14656
+ let handler = resizeHandlers.get(id);
14657
+ if (!handler) {
14658
+ handler = () => {
14659
+ const position = allPositions.value.find((candidate) => candidate.id === id);
14660
+ if (position) handleResize(position);
14661
+ };
14662
+ resizeHandlers.set(id, handler);
14663
+ }
14664
+ return handler;
14665
+ };
14541
14666
  const setInstantLayoutTransitionsDisabled = (disabled) => {
14542
14667
  if (!disabled && directDecisionContinuityTargetId.value != null) return;
14543
14668
  disableInstantLayoutTransitions.value = disabled;
@@ -14942,6 +15067,7 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
14942
15067
  visibilityChanged = true;
14943
15068
  }
14944
15069
  if (visibilityChanged) visibleIds.value = newVisible;
15070
+ for (const id of resizeHandlers.keys()) if (!currentIds.has(id)) resizeHandlers.delete(id);
14945
15071
  for (const id of prevPositionIds) if (!currentIds.has(id)) delete _heightsCache[id];
14946
15072
  const setChanged = prevPositionIds.size !== currentIds.size || [...prevPositionIds].some((id) => !currentIds.has(id));
14947
15073
  const orderChanged = renderedPositionOrder.length !== positionOrder.length || renderedPositionOrder.some((id, index) => id !== positionOrder[index]);
@@ -15034,12 +15160,13 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15034
15160
  style: require__plugin_vue_export_helper.normalizeStyle({
15035
15161
  top: (pos.isOffscreenReviewCard && !committedPresentation.value ? pos.top - sidebarOffsetY.value : pos.top) + "px",
15036
15162
  height: pos.height + "px",
15037
- transition: committedPresentation.value || disableInstantLayoutTransitions.value ? "none" : void 0
15163
+ transition: committedPresentation.value || disableInstantLayoutTransitions.value ? "none" : void 0,
15164
+ visibility: pos.instanceRef?.provisional ? "hidden" : void 0
15038
15165
  })
15039
15166
  }, [shouldRenderDialog(pos) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createBlock(CommentDialog_default, {
15040
15167
  key: pos.id + commentsRenderKey.value,
15041
15168
  onReady: handleDialog,
15042
- onResize: ($event) => handleResize(pos),
15169
+ onResize: resizeHandlerFor(pos.id),
15043
15170
  class: "floating-comment",
15044
15171
  parent: __props.parent,
15045
15172
  comment: pos.commentRef,
@@ -15062,7 +15189,7 @@ var FloatingComments_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/
15062
15189
  });
15063
15190
  //#endregion
15064
15191
  //#region src/components/CommentsLayer/FloatingComments.vue
15065
- var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(FloatingComments_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-df897b8d"]]);
15192
+ var FloatingComments_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(FloatingComments_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-1070f5a1"]]);
15066
15193
  //#endregion
15067
15194
  //#region src/components/CommentsLayer/PdfCommentsLayer.vue?vue&type=script&setup=true&lang.ts
15068
15195
  var _hoisted_1$22 = {
@@ -15792,6 +15919,21 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
15792
15919
  };
15793
15920
  }
15794
15921
  //#endregion
15922
+ //#region src/composables/use-comment-sidebar.ts
15923
+ function useCommentSidebar({ documentKey, enabled, hasContent }) {
15924
+ const reserved = require__plugin_vue_export_helper.ref(false);
15925
+ require__plugin_vue_export_helper.watch(documentKey, () => {
15926
+ reserved.value = false;
15927
+ }, { flush: "sync" });
15928
+ require__plugin_vue_export_helper.watch(() => enabled.value && hasContent.value, (visible) => {
15929
+ if (visible) reserved.value = true;
15930
+ }, {
15931
+ immediate: true,
15932
+ flush: "sync"
15933
+ });
15934
+ return require__plugin_vue_export_helper.computed(() => enabled.value && (hasContent.value || reserved.value));
15935
+ }
15936
+ //#endregion
15795
15937
  //#region src/composables/use-compact-comment-popover.ts
15796
15938
  var POPOVER_WIDTH_PX = 320;
15797
15939
  var SAFE_MARGIN_PX = 12;
@@ -20693,7 +20835,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
20693
20835
  if (commentsConfig.highlightHoverColor) vars["--sd-comments-highlight-hover"] = commentsConfig.highlightHoverColor;
20694
20836
  const activeTrackChangeColors = {
20695
20837
  ...commentsConfig.trackChangeHighlightColors || {},
20696
- ...commentsConfig.trackChangeActiveHighlightColors || {}
20838
+ ...commentsConfig.trackChangeActiveHighlightColors
20697
20839
  };
20698
20840
  if (activeTrackChangeColors.insertBorder) vars["--sd-tracked-changes-insert-border"] = activeTrackChangeColors.insertBorder;
20699
20841
  if (activeTrackChangeColors.insertBackground) vars["--sd-tracked-changes-insert-background"] = activeTrackChangeColors.insertBackground;
@@ -21673,7 +21815,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
21673
21815
  const publishV2PendingPositionEntry = (entry) => {
21674
21816
  if (!entry) return;
21675
21817
  handleEditorLocationsUpdate({
21676
- ...editorCommentPositions.value ?? {},
21818
+ ...editorCommentPositions.value,
21677
21819
  pending: entry
21678
21820
  });
21679
21821
  };
@@ -22212,7 +22354,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
22212
22354
  documentLoading: proxy.$superdoc.uiConfig.loading.enabled,
22213
22355
  linkPopoverResolver: getHyperlinkActivationHandler(),
22214
22356
  layoutEngineOptions: useLayoutEngine ? {
22215
- ...proxy.$superdoc.config.layoutEngineOptions || {},
22357
+ ...proxy.$superdoc.config.layoutEngineOptions,
22216
22358
  proofing: resolvedProofingConfig.value,
22217
22359
  debugLabel: proxy.$superdoc.config.layoutEngineOptions?.debugLabel ?? doc.name ?? doc.id,
22218
22360
  zoom: (activeZoom.value ?? 100) / 100,
@@ -22475,11 +22617,16 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
22475
22617
  if (layout !== "auto") return true;
22476
22618
  return !isCompactCommentsMode.value;
22477
22619
  });
22478
- const showCommentsSidebar = require__plugin_vue_export_helper.computed(() => {
22620
+ const sidebarEnabled = require__plugin_vue_export_helper.computed(() => {
22479
22621
  if (isV2Mode.value && !v2GeometryAvailable.value && !v2ReviewSidebarUnlocked.value && !hasPdfFloatingComments.value) return false;
22480
22622
  if (!shouldRenderCommentsInViewing.value) return false;
22481
22623
  if (!shouldUseSidebarComments.value) return false;
22482
- return pendingComment.value || (floatingComments.value.length > 0 || hasOpenTrackedChanges.value) && isReady.value && layers.value && isCommentsEnabled.value && !isCommentsListVisible.value;
22624
+ return Boolean(pendingComment.value || isReady.value && layers.value && isCommentsEnabled.value && !isCommentsListVisible.value);
22625
+ });
22626
+ const showCommentsSidebar = useCommentSidebar({
22627
+ documentKey: require__plugin_vue_export_helper.computed(() => JSON.stringify(documents.value.map((document) => document.id))),
22628
+ enabled: sidebarEnabled,
22629
+ hasContent: require__plugin_vue_export_helper.computed(() => Boolean(pendingComment.value || floatingComments.value.length || hasOpenTrackedChanges.value))
22483
22630
  });
22484
22631
  const activeCompactComment = require__plugin_vue_export_helper.computed(() => {
22485
22632
  if (showCommentsSidebar.value) return null;
@@ -23103,7 +23250,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
23103
23250
  ref_key: "superdocRoot",
23104
23251
  ref: superdocRoot,
23105
23252
  class: require__plugin_vue_export_helper.normalizeClass(["superdoc", {
23106
- "superdoc--with-sidebar": showCommentsSidebar.value,
23253
+ "superdoc--with-sidebar": require__plugin_vue_export_helper.unref(showCommentsSidebar),
23107
23254
  "superdoc--web-layout": require__plugin_vue_export_helper.unref(proxy).$superdoc.config.viewOptions?.layout === "web",
23108
23255
  "superdoc--contained": require__plugin_vue_export_helper.unref(proxy).$superdoc.config.contained,
23109
23256
  "high-contrast": require__plugin_vue_export_helper.unref(isHighContrastMode)
@@ -23251,7 +23398,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
23251
23398
  onAnchorActivate: handleHighlightClick
23252
23399
  })) : require__plugin_vue_export_helper.createCommentVNode("", true)
23253
23400
  ])], 512),
23254
- showCommentsSidebar.value ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
23401
+ require__plugin_vue_export_helper.unref(showCommentsSidebar) ? (require__plugin_vue_export_helper.openBlock(), require__plugin_vue_export_helper.createElementBlock("div", {
23255
23402
  key: 0,
23256
23403
  ref_key: "rightSidebarRef",
23257
23404
  ref: rightSidebarRef,
@@ -23277,7 +23424,7 @@ var SuperDoc_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ require
23277
23424
  });
23278
23425
  //#endregion
23279
23426
  //#region src/SuperDoc.vue
23280
- var SuperDoc_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SuperDoc_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-7c932add"]]);
23427
+ var SuperDoc_default = /* @__PURE__ */ require__plugin_vue_export_helper._plugin_vue_export_helper_default(SuperDoc_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-451ab88f"]]);
23281
23428
  //#endregion
23282
23429
  //#region src/core/create-app.ts
23283
23430
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -36052,7 +36199,8 @@ function normalizeSuperDocUser(user) {
36052
36199
  if (!user || typeof user !== "object") return { ...DEFAULT_SUPERDOC_USER };
36053
36200
  return {
36054
36201
  ...DEFAULT_SUPERDOC_USER,
36055
- ...user
36202
+ ...user,
36203
+ ...user.commentIdentity !== void 0 ? { commentIdentity: normalizeCommentIdentity(user.commentIdentity) } : {}
36056
36204
  };
36057
36205
  }
36058
36206
  //#endregion
@@ -36571,6 +36719,7 @@ function normalizeUiConfig(config = {}) {
36571
36719
  * Keeping policy separate means an application can disable the built-in
36572
36720
  * comments UI without losing the rules enforced by its custom UI.
36573
36721
  */
36722
+ var isAutocapitalize = (value) => value === "off" || value === "sentences" || value === "words" || value === "characters";
36574
36723
  var isCommentInteractionLevel = (value) => value === "read" || value === "write" || value === "resolve";
36575
36724
  /**
36576
36725
  * Resolve the effective interaction policy.
@@ -36590,14 +36739,26 @@ function normalizeInteractionConfig(config = {}) {
36590
36739
  const canonicalLevel = interactionComments.level;
36591
36740
  const hasCanonicalLevel = isCommentInteractionLevel(canonicalLevel);
36592
36741
  const level = hasCanonicalLevel ? canonicalLevel : legacyReadOnly ? "read" : legacyAllowResolve ? "resolve" : "write";
36742
+ const interactionWritingAssistance = require__plugin_vue_export_helper.isPlainObject(interaction.writingAssistance) ? interaction.writingAssistance : {};
36743
+ const autocorrect = interactionWritingAssistance.autocorrect === true;
36744
+ const autocapitalize = isAutocapitalize(interactionWritingAssistance.autocapitalize) ? interactionWritingAssistance.autocapitalize : "off";
36745
+ const spellcheck = interactionWritingAssistance.spellcheck === true;
36593
36746
  const canonicalAllowDecisions = interactionTrackedChanges.allowDecisions;
36747
+ const interactionTouch = require__plugin_vue_export_helper.isPlainObject(interaction.touch) ? interaction.touch : {};
36594
36748
  return {
36595
36749
  comments: {
36596
36750
  level,
36597
36751
  readOnly: hasCanonicalLevel ? level === "read" : legacyReadOnly,
36598
36752
  allowResolve: hasCanonicalLevel ? level === "resolve" : legacyAllowResolve
36599
36753
  },
36600
- trackedChanges: { allowDecisions: typeof canonicalAllowDecisions === "boolean" ? canonicalAllowDecisions : !legacyReadOnly }
36754
+ trackedChanges: { allowDecisions: typeof canonicalAllowDecisions === "boolean" ? canonicalAllowDecisions : !legacyReadOnly },
36755
+ touch: { gestures: interactionTouch.gestures === true },
36756
+ writingAssistance: {
36757
+ enabled: autocorrect || autocapitalize !== "off" || spellcheck,
36758
+ autocorrect,
36759
+ autocapitalize,
36760
+ spellcheck
36761
+ }
36601
36762
  };
36602
36763
  }
36603
36764
  //#endregion
@@ -43139,7 +43300,7 @@ var V1_ENABLED_ON_SELECTION_REASON = /* @__PURE__ */ new Set([
43139
43300
  ]);
43140
43301
  var V1_ENABLED_ON_EMPTY_REASON = /* @__PURE__ */ new Set(["list", "numberedlist"]);
43141
43302
  function shouldKeepEnabledForV1ToolbarParity(name, commandState) {
43142
- if (name === "fontFamily" || name === "fontSize") return commandState?.reason !== "document-readonly";
43303
+ if (name === "fontFamily" || name === "fontSize") return commandState?.reason !== "document-readonly" && commandState?.reason !== "deleted-text-formatting-unsupported";
43143
43304
  if (V1_ENABLED_ON_EMPTY_REASON.has(name) && commandState?.disabled && commandState?.supported !== false && commandState?.reason == null) return true;
43144
43305
  if (!V1_ENABLED_ON_SELECTION_REASON.has(name)) return false;
43145
43306
  const reason = commandState?.reason;
@@ -43173,6 +43334,7 @@ var RESERVED_TOOLBAR_ITEM_NAMES = /* @__PURE__ */ new Set([
43173
43334
  * proof lane, and behavior tests resolve against a real object.
43174
43335
  */
43175
43336
  var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.default {
43337
+ #formattingRefusalTooltips;
43176
43338
  #imagePicker;
43177
43339
  #groupItems;
43178
43340
  #highlightOptions;
@@ -43204,6 +43366,7 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43204
43366
  showPageNumberButton: false
43205
43367
  };
43206
43368
  this.toolbarItems = [];
43369
+ this.#formattingRefusalTooltips = /* @__PURE__ */ new WeakMap();
43207
43370
  this.overflowItems = [];
43208
43371
  this.pendingSelectionCapture = void 0;
43209
43372
  this.#imagePicker = null;
@@ -43664,6 +43827,13 @@ var BuiltInToolbar = class extends require_eventemitter3.import_eventemitter3.de
43664
43827
  const commandId = resolveBuiltInItemCommandId(name);
43665
43828
  if (!commandId) return false;
43666
43829
  const commandState = this.snapshot?.commands?.[commandId];
43830
+ if (commandState?.reason === "deleted-text-formatting-unsupported") {
43831
+ if (!this.#formattingRefusalTooltips.has(item)) this.#formattingRefusalTooltips.set(item, item.tooltip.value);
43832
+ item.tooltip.value = "Select kept text, or accept or reject the deletion before formatting.";
43833
+ } else if (this.#formattingRefusalTooltips.has(item)) {
43834
+ item.tooltip.value = this.#formattingRefusalTooltips.get(item);
43835
+ this.#formattingRefusalTooltips.delete(item);
43836
+ }
43667
43837
  if ((name === "list" || name === "numberedlist") && item.attributes.value.ariaBusy !== Boolean(commandState?.pending)) item.attributes.value = {
43668
43838
  ...item.attributes.value,
43669
43839
  ariaBusy: Boolean(commandState?.pending)
@@ -44184,6 +44354,7 @@ function runtimeUserOf(user) {
44184
44354
  const text = (value) => typeof value === "string" && value ? value : void 0;
44185
44355
  return {
44186
44356
  name: text(user.name) ?? "",
44357
+ ...user.commentIdentity !== void 0 ? { commentIdentity: user.commentIdentity ? { ...user.commentIdentity } : null } : {},
44187
44358
  ...text(user.id) ? { id: text(user.id) } : {},
44188
44359
  ...text(user.email) ? { email: text(user.email) } : {},
44189
44360
  ...text(user.initials) ? { initials: text(user.initials) } : {}
@@ -44430,6 +44601,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44430
44601
  if (!config.selector) throw new Error("SuperDoc: selector is required");
44431
44602
  const container = typeof config.selector === "string" ? document.querySelector(config.selector) : config.selector;
44432
44603
  if (!(container instanceof HTMLElement)) throw new Error("SuperDoc: selector must be a valid CSS selector string or DOM element");
44604
+ const user = normalizeSuperDocUser(config.user);
44433
44605
  this.#diagnostics = require_create_super_doc_ui.createInteractionHistory(this, config, () => this.version, container);
44434
44606
  this.#surfaceManager = new SurfaceManager({ getModuleConfig: () => this.#surfacesConfig });
44435
44607
  this.#contentControlClickRoot = container;
@@ -44439,7 +44611,10 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44439
44611
  container.addEventListener("keydown", this.#handleContentControlKeyDown, true);
44440
44612
  container.addEventListener("click", this.#handleContentControlClick, true);
44441
44613
  this.#onConfig("content-control:active-change", config.onContentControlActiveChange);
44442
- this.#init(config, container);
44614
+ this.#init({
44615
+ ...config,
44616
+ user
44617
+ }, container);
44443
44618
  this.#contentControlEventBridgeReady = true;
44444
44619
  if (this.listenerCount("content-control:active-change") > 0) this.ui;
44445
44620
  }
@@ -44492,7 +44667,6 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44492
44667
  }
44493
44668
  this.editorVersion = 2;
44494
44669
  this.#validateLegacyConfig();
44495
- this.config.user = normalizeSuperDocUser(this.config.user);
44496
44670
  if (!this.config.layoutEngineOptions.virtualization) this.config.layoutEngineOptions.virtualization = {
44497
44671
  enabled: true,
44498
44672
  window: 5,
@@ -44518,7 +44692,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
44518
44692
  }
44519
44693
  this.userColorMap = /* @__PURE__ */ new Map();
44520
44694
  this.colorIndex = 0;
44521
- this.version = "2.30.0-next.4";
44695
+ this.version = "2.30.0-next.9";
44522
44696
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
44523
44697
  this.superdocId = config.superdocId || require_uuid.v4();
44524
44698
  this.colors = this.config.colors ?? [];
@@ -45391,10 +45565,15 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45391
45565
  this.#requireReady("setUser");
45392
45566
  const name = typeof user?.name === "string" ? user.name.trim() : "";
45393
45567
  if (!name) return Promise.reject(/* @__PURE__ */ new TypeError("SuperDoc.setUser requires a non-empty user name."));
45394
- const next = normalizeSuperDocUser({
45395
- ...user,
45396
- name
45397
- });
45568
+ let next;
45569
+ try {
45570
+ next = normalizeSuperDocUser({
45571
+ ...user,
45572
+ name
45573
+ });
45574
+ } catch (error) {
45575
+ return Promise.reject(error);
45576
+ }
45398
45577
  const applied = this.#userSwitch.then(() => this.#applyUser(next));
45399
45578
  this.#userSwitch = applied.catch(() => {});
45400
45579
  return applied;
@@ -45408,7 +45587,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45408
45587
  "email",
45409
45588
  "image",
45410
45589
  "initials"
45411
- ].every((key) => (current[key] ?? null) === (next[key] ?? null))) return;
45590
+ ].every((key) => (current[key] ?? null) === (next[key] ?? null)) && current.commentIdentity === void 0 === (next.commentIdentity === void 0) && (current.commentIdentity?.providerId ?? null) === (next.commentIdentity?.providerId ?? null) && (current.commentIdentity?.userId ?? null) === (next.commentIdentity?.userId ?? null)) return;
45412
45591
  const runtimes = this.#editorRuntimeRegistry.getAll();
45413
45592
  const results = await Promise.allSettled(runtimes.map((runtime) => runtime.setUser?.(runtimeUserOf(next))));
45414
45593
  const failure = results.find((result) => result.status === "rejected");