superdoc 2.29.0-next.13 → 2.29.0-next.17

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 (67) hide show
  1. package/dist/chunks/{FindReplaceSurface-BKVHzhQ4.es.js → FindReplaceSurface-B_5ggdWg.es.js} +1 -1
  2. package/dist/chunks/{FindReplaceSurface-BNDrJ6VS.cjs → FindReplaceSurface-fVHxPXtn.cjs} +1 -1
  3. package/dist/chunks/{PasswordPromptSurface-6mF6Azda.es.js → PasswordPromptSurface-CZqhDQQ1.es.js} +1 -1
  4. package/dist/chunks/{PasswordPromptSurface-BNkaztaP.cjs → PasswordPromptSurface-x8GNmMJT.cjs} +1 -1
  5. package/dist/chunks/{PdfViewer-aOWhUVI7.es.js → PdfViewer-CW09MNrB.es.js} +4 -10
  6. package/dist/chunks/{PdfViewer-DmSkZehl.cjs → PdfViewer-CkrAHpC-.cjs} +4 -10
  7. package/dist/chunks/{_plugin-vue_export-helper-6MBoygIY.cjs → _plugin-vue_export-helper-BkbCxNeT.cjs} +31 -7
  8. package/dist/chunks/{_plugin-vue_export-helper-CsJQtMvr.es.js → _plugin-vue_export-helper-DRPRMkeA.es.js} +20 -8
  9. package/dist/chunks/{create-super-doc-ui-DdT4b29f.es.js → create-super-doc-ui-Dc8dQAMc.es.js} +54 -77
  10. package/dist/chunks/{create-super-doc-ui-_SbygYQ4.cjs → create-super-doc-ui-L60GhVAX.cjs} +177 -206
  11. package/dist/collaboration-upgrade-engine.cjs +1 -1
  12. package/dist/collaboration-upgrade-engine.es.js +1 -1
  13. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  14. package/dist/public/ui-react.cjs +1 -1
  15. package/dist/public/ui-react.es.js +1 -1
  16. package/dist/public/ui-vue.cjs +1 -1
  17. package/dist/public/ui-vue.es.js +1 -1
  18. package/dist/public/ui.cjs +1 -1
  19. package/dist/public/ui.es.js +1 -1
  20. package/dist/style.css +1 -1
  21. package/dist/style.layered.css +1 -1
  22. package/dist/superdoc/src/components/CommentsLayer/collect-removed-comment-ids.d.ts +11 -1
  23. package/dist/superdoc/src/components/CommentsLayer/collect-tracked-change-thread.d.ts +19 -2
  24. package/dist/superdoc/src/components/CommentsLayer/comment-urls.d.ts +1 -1
  25. package/dist/superdoc/src/components/CommentsLayer/commentsList/super-comments-list.d.ts +23 -20
  26. package/dist/superdoc/src/components/CommentsLayer/helpers.d.ts +1 -4
  27. package/dist/superdoc/src/components/CommentsLayer/tracked-change-threading.d.ts +16 -1
  28. package/dist/superdoc/src/components/Whiteboard/WhiteboardLayer.vue.d.ts +4 -5
  29. package/dist/superdoc/src/components/Whiteboard/WhiteboardPage.vue.d.ts +3 -4
  30. package/dist/superdoc/src/components/Whiteboard/whiteboard-types.d.ts +2 -0
  31. package/dist/superdoc/src/composables/use-find-replace.d.ts +13 -3
  32. package/dist/superdoc/src/composables/use-password-prompt.d.ts +1 -1
  33. package/dist/superdoc/src/composables/use-viewport-fit.d.ts +27 -5
  34. package/dist/superdoc/src/core/SuperDoc.d.ts +3 -3
  35. package/dist/superdoc/src/core/pdf/pdf-adapter.d.ts +6 -2
  36. package/dist/superdoc/src/core/types/index.d.ts +36 -4
  37. package/dist/superdoc/src/core/v2-integration/browser-peer-runtime.d.ts +5 -3
  38. package/dist/superdoc/src/core/v2-integration/cdn-engine-loader.d.ts +3 -13
  39. package/dist/superdoc/src/core/v2-integration/internal-vue-runtime.d.ts +64 -59
  40. package/dist/superdoc/src/helpers/object-guards.d.ts +1 -0
  41. package/dist/superdoc/src/internal/diagnostics/translate-diagnostic.d.ts +6 -4
  42. package/dist/superdoc/src/internal/toolbar/built-in/PageNumberMenu.vue.d.ts +25 -15
  43. package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +3 -1
  44. package/dist/superdoc/src/internal/toolbar/built-in/font-options.d.ts +15 -1
  45. package/dist/superdoc/src/internal/toolbar/built-in/font-typeahead.d.ts +37 -7
  46. package/dist/superdoc/src/internal/toolbar/built-in/format-negation.d.ts +10 -4
  47. package/dist/superdoc/src/internal/toolbar/built-in/general.d.ts +12 -1
  48. package/dist/superdoc/src/internal/toolbar/built-in/helpers.d.ts +9 -4
  49. package/dist/superdoc/src/internal/toolbar/built-in/list-style-buttons.d.ts +2 -2
  50. package/dist/superdoc/src/internal/toolbar/built-in/page-number-feedback.d.ts +4 -5
  51. package/dist/superdoc/src/internal/toolbar/built-in/scroll-helpers.d.ts +3 -4
  52. package/dist/superdoc/src/internal/toolbar/built-in/toolbarIcons.d.ts +78 -145
  53. package/dist/superdoc/src/internal/toolbar/built-in/url-safety.d.ts +11 -3
  54. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +4 -3
  55. package/dist/superdoc/src/internal/toolbar/image-upload.d.ts +29 -39
  56. package/dist/superdoc/src/stores/comments-store.d.ts +7 -7
  57. package/dist/superdoc/src/stores/helpers/comment-document-scope.d.ts +22 -0
  58. package/dist/superdoc/src/stores/helpers/pending-selection-snapshot.d.ts +17 -0
  59. package/dist/superdoc/src/stores/helpers/tracked-change-compaction.d.ts +16 -0
  60. package/dist/superdoc/src/stores/helpers/tracked-change-decision.d.ts +45 -0
  61. package/dist/superdoc/src/stores/superdoc-store.d.ts +21 -21
  62. package/dist/superdoc.cjs +396 -423
  63. package/dist/superdoc.es.js +303 -330
  64. package/dist-cdn/style.layered.css +1 -1
  65. package/dist-cdn/superdoc.min.css +1 -1
  66. package/dist-cdn/superdoc.min.js +41 -41
  67. package/package.json +3 -2
@@ -1,20 +1,20 @@
1
1
  import { i as __toESM$2 } from "./chunks/rolldown-runtime-0pSA04fp.es.js";
2
+ import { $ as vModelSelect, A as onActivated, B as renderList, C as isRef$1, D as normalizeClass, E as nextTick, F as openBlock, G as toDisplayString, H as resolveDirective, I as provide$1, J as toRefs, K as toRaw$2, L as reactive, M as onDeactivated, N as onMounted, O as normalizeProps, P as onScopeDispose$1, Q as vModelCheckbox, R as readonly, S as isReactive$1, T as mergeProps, U as resolveDynamicComponent, V as renderSlot, W as shallowRef$1, X as useAttrs, Y as unref, Z as useSlots, _ as getCurrentInstance, a as computed$1, at as withModifiers, b as hasInjectionContext, c as createCommentVNode, d as createStaticVNode, et as vModelText, f as createTextVNode, g as effectScope, h as defineComponent, i as Transition, it as withKeys, j as onBeforeUnmount, k as normalizeStyle, l as createElementBlock, m as defineAsyncComponent, n as Fragment, nt as withCtx, o as createApp, ot as isPlainObject$1, p as createVNode, q as toRef, r as Teleport, rt as withDirectives, s as createBlock, st as isThenable$1, t as _plugin_vue_export_helper_default, tt as watch$1, u as createElementVNode, v as getCurrentScope, w as markRaw, x as inject$1, y as h, z as ref } from "./chunks/_plugin-vue_export-helper-DRPRMkeA.es.js";
2
3
  import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
3
- import { C as createInteractionHistory, E as recordInteraction, S as closeInteractionHistory, T as isWorkflowRecordingEnabled, _ as createTrackedChangePermissionResolver, a as registerFirstPartyCommandMutation, b as isPlainObject$1, c as getCommandDescriptor, d as mutationCommittedEventChangedDocument, f as createImageFilePicker, g as PERMISSIONS, h as BUILT_IN_PERMISSION_METHOD, i as readFirstPartyPageNumbers, l as applyV2CommentInvalidationFromMutation, n as executeFirstPartyCommandAsync, o as isRecord, p as resolveImageSrc, r as executeFirstPartyShortcutAsync, t as createSuperDocUI, u as getV2TrackedChangeMutationImpact, v as isAllowed, w as getWorkflowRecording, x as DOM_CLASS_NAMES, y as isSyntheticTrackedChangeCommentLaneItem } from "./chunks/create-super-doc-ui-DdT4b29f.es.js";
4
+ import { C as getWorkflowRecording, S as createInteractionHistory, T as recordInteraction, _ as createTrackedChangePermissionResolver, a as registerFirstPartyCommandMutation, b as DOM_CLASS_NAMES, c as getCommandDescriptor, d as mutationCommittedEventChangedDocument, f as createImageFilePicker, g as PERMISSIONS, h as BUILT_IN_PERMISSION_METHOD, i as readFirstPartyPageNumbers, l as applyV2CommentInvalidationFromMutation, n as executeFirstPartyCommandAsync, o as isRecord, p as resolveImageSrc, r as executeFirstPartyShortcutAsync, t as createSuperDocUI, u as getV2TrackedChangeMutationImpact, v as isAllowed, w as isWorkflowRecordingEnabled, x as closeInteractionHistory, y as isSyntheticTrackedChangeCommentLaneItem } from "./chunks/create-super-doc-ui-Dc8dQAMc.es.js";
4
5
  import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
5
6
  import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
6
- import { $ as vModelSelect, A as onActivated, B as renderList, C as isRef$1, D as normalizeClass, E as nextTick, F as openBlock, G as toDisplayString, H as resolveDirective, I as provide$1, J as toRefs, K as toRaw$2, L as reactive, M as onDeactivated, N as onMounted, O as normalizeProps, P as onScopeDispose$1, Q as vModelCheckbox, R as readonly, S as isReactive$1, T as mergeProps, U as resolveDynamicComponent, V as renderSlot, W as shallowRef$1, X as useAttrs, Y as unref, Z as useSlots, _ as getCurrentInstance, a as computed$1, at as withModifiers, b as hasInjectionContext, c as createCommentVNode, d as createStaticVNode, et as vModelText, f as createTextVNode, g as effectScope, h as defineComponent, i as Transition, it as withKeys, j as onBeforeUnmount, k as normalizeStyle, l as createElementBlock, m as defineAsyncComponent, n as Fragment, nt as withCtx, o as createApp, p as createVNode, q as toRef, r as Teleport, rt as withDirectives, s as createBlock, t as _plugin_vue_export_helper_default, tt as watch$1, u as createElementVNode, v as getCurrentScope, w as markRaw, x as inject$1, y as h, z as ref } from "./chunks/_plugin-vue_export-helper-CsJQtMvr.es.js";
7
7
  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";
8
8
  import { t as isFiniteNumber } from "./chunks/is-finite-number-BpL4F38c.es.js";
9
9
  import { t as PDF_TO_CSS_UNITS } from "./chunks/constants-BvNs_ybI.es.js";
10
10
  import * as Vue from "vue";
11
11
  import { Map as Map$1 } from "yjs";
12
12
  import Konva from "konva";
13
- //#region src/core/v2-integration/browser-peer-runtime.js
13
+ //#region src/core/v2-integration/browser-peer-runtime.ts
14
14
  var SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY = "__SUPERDOC_V2_BROWSER_RUNTIME__";
15
15
  function readInstalledRuntime(globalObject = globalThis) {
16
- const installed = globalObject[SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY];
17
- return installed && typeof installed === "object" ? installed : null;
16
+ const installed = Reflect.get(globalObject, SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY);
17
+ return isPlainObject$1(installed) ? installed : null;
18
18
  }
19
19
  function installSuperDocV2BrowserRuntime(runtime = {}, globalObject = globalThis) {
20
20
  const installed = readInstalledRuntime(globalObject) ?? {};
@@ -23,7 +23,7 @@ function installSuperDocV2BrowserRuntime(runtime = {}, globalObject = globalThis
23
23
  ...runtime,
24
24
  vue: runtime.vue ?? installed.vue ?? Vue
25
25
  };
26
- globalObject[SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY] = nextRuntime;
26
+ Reflect.set(globalObject, SUPERDOC_V2_BROWSER_RUNTIME_GLOBAL_KEY, nextRuntime);
27
27
  return nextRuntime;
28
28
  }
29
29
  installSuperDocV2BrowserRuntime();
@@ -258,7 +258,7 @@ var v_click_outside_default = {
258
258
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
259
259
  function getSuperdocVersion() {
260
260
  try {
261
- return "2.29.0-next.13";
261
+ return "2.29.0-next.17";
262
262
  } catch {
263
263
  return "unknown";
264
264
  }
@@ -5874,7 +5874,7 @@ var getCommentIndex = (yArray, comment) => {
5874
5874
  //#endregion
5875
5875
  //#region src/core/collaboration/helpers.ts
5876
5876
  var isPropertyBag = (value) => typeof value === "object" && value !== null || typeof value === "function";
5877
- var readCommentsStore = (superdoc) => superdoc["commentsStore"];
5877
+ var readCommentsStore$1 = (superdoc) => superdoc["commentsStore"];
5878
5878
  var isV2ReviewRuntimeActive = (superdoc) => superdoc.activeEditor?.editorVersion === 2 || superdoc.editorVersion === 2;
5879
5879
  var commentKey = (comment) => {
5880
5880
  const key = comment.commentId ?? comment.importedId;
@@ -5893,7 +5893,7 @@ var preserveLocalV2TrackedChangeRows = (superdoc, commentsStore, incomingComment
5893
5893
  };
5894
5894
  var loadCommentsFromYdoc = (superdoc) => {
5895
5895
  if (!superdoc?.ydoc) return false;
5896
- const commentsStore = readCommentsStore(superdoc);
5896
+ const commentsStore = readCommentsStore$1(superdoc);
5897
5897
  if (!commentsStore) return false;
5898
5898
  const comments = superdoc.ydoc.getArray("comments").toJSON();
5899
5899
  const seenCommentIdByKey = /* @__PURE__ */ new Map();
@@ -5939,7 +5939,7 @@ var initCollaborationComments = (superdoc) => {
5939
5939
  const updateCommentsStore = () => loadCommentsFromYdoc(superdoc);
5940
5940
  const onSuperDocYdocSynced = () => {
5941
5941
  if (!updateCommentsStore()) setTimeout(updateCommentsStore, 0);
5942
- const commentsStore = readCommentsStore(superdoc);
5942
+ const commentsStore = readCommentsStore$1(superdoc);
5943
5943
  if (commentsStore) commentsStore.hasSyncedCollaborationComments = true;
5944
5944
  const currentProvider = superdoc.provider;
5945
5945
  if (!currentProvider) throw new TypeError("initCollaborationComments requires superdoc.provider");
@@ -5951,7 +5951,7 @@ var initCollaborationComments = (superdoc) => {
5951
5951
  provider.on("synced", onSuperDocYdocSynced);
5952
5952
  if (!updateCommentsStore()) setTimeout(updateCommentsStore, 0);
5953
5953
  commentsArray.observe((event) => {
5954
- if (!readCommentsStore(superdoc)) return;
5954
+ if (!readCommentsStore$1(superdoc)) return;
5955
5955
  const currentUser = superdoc.config.user;
5956
5956
  const origin = event?.transaction?.origin;
5957
5957
  const originUser = isPropertyBag(origin) ? origin.user : null;
@@ -6890,23 +6890,76 @@ var buildFloatingCommentInstances = ({ comment, positionKey, positionEntry, fall
6890
6890
  })];
6891
6891
  };
6892
6892
  //#endregion
6893
- //#region src/components/CommentsLayer/tracked-change-threading.js
6893
+ //#region src/stores/helpers/comment-document-scope.ts
6894
+ var getCommentDocumentId = (comment) => {
6895
+ if (!comment) return null;
6896
+ if (comment.fileId != null) return String(comment.fileId);
6897
+ if (comment.documentId != null) return String(comment.documentId);
6898
+ if (comment.selection?.documentId != null) return String(comment.selection.documentId);
6899
+ return null;
6900
+ };
6901
+ var createCommentDocumentScope = (readOpenDocuments) => {
6902
+ const getOpenDocuments = () => {
6903
+ const source = readOpenDocuments();
6904
+ const docs = Array.isArray(source) ? source : source?.value;
6905
+ return Array.isArray(docs) ? docs : [];
6906
+ };
6907
+ const getSingleOpenDocumentId = () => {
6908
+ const docs = getOpenDocuments();
6909
+ if (docs.length !== 1) return null;
6910
+ return docs[0]?.id != null ? String(docs[0].id) : null;
6911
+ };
6912
+ const belongsToDocument = (comment, activeDocumentId, options = {}) => {
6913
+ const { allowSingleDocumentMismatch = false } = options;
6914
+ if (!activeDocumentId) return false;
6915
+ const commentDocumentId = getCommentDocumentId(comment);
6916
+ if (commentDocumentId) {
6917
+ if (commentDocumentId === activeDocumentId) return true;
6918
+ const singleOpenDocumentId = getSingleOpenDocumentId();
6919
+ return allowSingleDocumentMismatch && singleOpenDocumentId === activeDocumentId;
6920
+ }
6921
+ return getSingleOpenDocumentId() === activeDocumentId;
6922
+ };
6923
+ const belongsToTrackedChangeSyncDocument = (comment, activeDocumentId) => belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true });
6924
+ return {
6925
+ belongsToDocument,
6926
+ belongsToTrackedChangeSyncDocument
6927
+ };
6928
+ };
6929
+ //#endregion
6930
+ //#region src/stores/helpers/pending-selection-snapshot.ts
6931
+ var isThenable = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
6932
+ var getPendingSelectionSnapshot = (superdoc, activeSelection) => {
6933
+ if (activeSelection?.source !== "document-editor") return null;
6934
+ const selectionDocumentId = activeSelection?.documentId ?? null;
6935
+ const editorDocumentId = superdoc?.activeEditor?.options?.documentId ?? null;
6936
+ if (!selectionDocumentId || !editorDocumentId || selectionDocumentId !== editorDocumentId) return null;
6937
+ let currentSelection;
6938
+ try {
6939
+ currentSelection = superdoc?.activeEditor?.doc?.selection?.current;
6940
+ } catch {
6941
+ return null;
6942
+ }
6943
+ if (typeof currentSelection !== "function") return null;
6944
+ try {
6945
+ const snapshot = currentSelection();
6946
+ return isThenable(snapshot) ? Promise.resolve(snapshot).catch(() => null) : snapshot;
6947
+ } catch {
6948
+ return null;
6949
+ }
6950
+ };
6951
+ //#endregion
6952
+ //#region src/components/CommentsLayer/tracked-change-threading.ts
6894
6953
  /**
6895
6954
  * Legacy comment payloads predate explicit tracked-change thread provenance.
6896
6955
  * These fields distinguish a true legacy review child from a v2 comment whose
6897
6956
  * anchor merely overlaps tracked content.
6898
- *
6899
- * @param {Record<string, any> | null | undefined} comment
6900
- * @returns {boolean}
6901
6957
  */
6902
6958
  var hasLegacyTrackedChangeThreadSignal = (comment) => Boolean(comment?.trackedChangeLink) || Boolean(comment?.trackedChangeType) || Boolean(comment?.trackedChangeDisplayType) || Boolean(comment?.trackedChangeText) || Boolean(comment?.deletedText) || comment?.trackedChange === true;
6903
6959
  /**
6904
6960
  * Resolve explicit thread provenance first, then the guarded legacy fallback.
6905
6961
  * Spatial-only v2 comments carry neither the explicit field nor a legacy
6906
6962
  * review signal and therefore remain standalone.
6907
- *
6908
- * @param {Record<string, any> | null | undefined} comment
6909
- * @returns {string | number | null}
6910
6963
  */
6911
6964
  var trackedChangeThreadParentIdForComment$1 = (comment) => {
6912
6965
  if (comment?.trackedChangeThreadParentId != null) return comment.trackedChangeThreadParentId;
@@ -7185,7 +7238,6 @@ function createDefaultV2Integration() {
7185
7238
  //#region src/helpers/interaction-trace.ts
7186
7239
  var isStartSpan = (value) => typeof value === "function";
7187
7240
  var isEndSpan = (value) => typeof value === "function";
7188
- var isThenable$3 = (value) => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
7189
7241
  function safeTraceCollector() {
7190
7242
  try {
7191
7243
  const collector = Reflect.get(globalThis, "__superdocInteractionTrace");
@@ -7216,7 +7268,7 @@ function withInteractionSpan(stage, branch, meta, fn) {
7216
7268
  if (!span) return fn();
7217
7269
  try {
7218
7270
  const result = fn();
7219
- if (isThenable$3(result)) return result.then((value) => {
7271
+ if (isThenable$1(result)) return result.then((value) => {
7220
7272
  endInteractionSpan(span);
7221
7273
  return value;
7222
7274
  }, (error) => {
@@ -7231,6 +7283,81 @@ function withInteractionSpan(stage, branch, meta, fn) {
7231
7283
  }
7232
7284
  }
7233
7285
  //#endregion
7286
+ //#region src/stores/helpers/tracked-change-decision.ts
7287
+ var normalizeTrackedChangeDecisionType = (value) => {
7288
+ const lower = typeof value === "string" ? value.toLowerCase() : "";
7289
+ if (!lower) return null;
7290
+ if (lower === "insert" || lower === "insertion" || lower === "trackinsert" || lower === "tableinsert" || lower === "paragraphsplit") return "insertion";
7291
+ if (lower === "delete" || lower === "deletion" || lower === "trackdelete" || lower === "tabledelete") return "deletion";
7292
+ return lower;
7293
+ };
7294
+ var trackedChangeDecisionKeepsCommentAnchor = ({ comment, decision } = {}) => {
7295
+ const normalizedDecision = decision === "accept" || decision === "reject" ? decision : null;
7296
+ if (!normalizedDecision) return false;
7297
+ const type = normalizeTrackedChangeDecisionType(comment?.trackedChangeDisplayType) ?? normalizeTrackedChangeDecisionType(comment?.trackedChangeType);
7298
+ return normalizedDecision === "accept" && type === "insertion" || normalizedDecision === "reject" && type === "deletion";
7299
+ };
7300
+ var collectTrackedChangeDecisionIdsWithAliases = (comment, aliasIds) => {
7301
+ const trackedChangeIds = new Set(aliasIds);
7302
+ if (comment?.trackedChangeCanonicalId != null) trackedChangeIds.add(String(comment.trackedChangeCanonicalId));
7303
+ const anchorKey = comment?.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
7304
+ if (anchorKey) {
7305
+ trackedChangeIds.add(anchorKey);
7306
+ if (anchorKey.startsWith("tc::")) {
7307
+ const rawId = anchorKey.slice(anchorKey.lastIndexOf("::") + 2);
7308
+ if (rawId) trackedChangeIds.add(rawId);
7309
+ }
7310
+ }
7311
+ return trackedChangeIds;
7312
+ };
7313
+ var collectTrackedChangeEntityIdsFromReceipt = (receipt) => {
7314
+ const record = receipt && typeof receipt === "object" ? receipt : null;
7315
+ if (!record?.success) return /* @__PURE__ */ new Set();
7316
+ const ids = /* @__PURE__ */ new Set();
7317
+ const collect = (entry) => {
7318
+ const ref = entry && typeof entry === "object" ? entry : null;
7319
+ if (ref?.kind !== "entity" || ref.entityType !== "trackedChange") return;
7320
+ if (ref.entityId != null && String(ref.entityId).length > 0) ids.add(String(ref.entityId));
7321
+ };
7322
+ if (Array.isArray(record.removed)) record.removed.forEach(collect);
7323
+ if (Array.isArray(record.invalidatedRefs)) record.invalidatedRefs.forEach(collect);
7324
+ return ids;
7325
+ };
7326
+ var collectReliableDecidedTrackedChangeIds = (outcome) => {
7327
+ const ids = /* @__PURE__ */ new Set();
7328
+ if (outcome?.decidedId != null && String(outcome.decidedId).length > 0) ids.add(String(outcome.decidedId));
7329
+ if (Array.isArray(outcome?.decidedIds)) outcome.decidedIds.forEach((id) => {
7330
+ if (id != null && String(id).length > 0) ids.add(String(id));
7331
+ });
7332
+ collectTrackedChangeEntityIdsFromReceipt(outcome?.receipt).forEach((id) => ids.add(id));
7333
+ return ids;
7334
+ };
7335
+ var clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
7336
+ if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
7337
+ try {
7338
+ adapter.clearActiveTrackedChangeTargetIfMatches(decidedId);
7339
+ } catch {}
7340
+ };
7341
+ var waitForTrackedDecisionCanonicalPaint = async ({ superdoc, receipt } = {}) => {
7342
+ const readiness = superdoc?.activeEditor?.documentMutationReadiness;
7343
+ if (receipt?.success !== true || typeof receipt?.txId !== "string" || !receipt.txId || typeof readiness?.whenPainted !== "function") return;
7344
+ try {
7345
+ await readiness.whenPainted(receipt);
7346
+ const requestFrame = globalThis.requestAnimationFrame;
7347
+ if (typeof requestFrame === "function") await new Promise((resolve) => {
7348
+ let settled = false;
7349
+ const finish = () => {
7350
+ if (settled) return;
7351
+ settled = true;
7352
+ clearTimeout(fallback);
7353
+ resolve();
7354
+ };
7355
+ const fallback = setTimeout(finish, 250);
7356
+ requestFrame(() => requestFrame(() => setTimeout(finish, 0)));
7357
+ });
7358
+ } catch {}
7359
+ };
7360
+ //#endregion
7234
7361
  //#region src/stores/helpers/comment-draft-text.ts
7235
7362
  var COMMENT_DRAFT_BR_TAG = /<br(?:\s[^>]*)?\s*\/?>/gi;
7236
7363
  var COMMENT_DRAFT_BLOCK_BOUNDARY = /(?:<\/(?:p|div|li|blockquote|pre|h[1-6])\s*>\s*)+(?:<(?:p|div|li|blockquote|pre|h[1-6])(?:\s[^>]*)?\s*\/?>)+/gi;
@@ -7603,6 +7730,82 @@ var cloneV2TrackedChangeStory = (story) => {
7603
7730
  };
7604
7731
  };
7605
7732
  //#endregion
7733
+ //#region src/stores/helpers/tracked-change-compaction.ts
7734
+ var isPresentId = (id) => Boolean(id);
7735
+ var getBodyTrackedChangeIdentityIds = (comment) => {
7736
+ return [normalizeCommentId(comment.commentId), ...!normalizeCommentId(comment.trackedChangeCanonicalId) ? [
7737
+ comment.importedId,
7738
+ comment.trackedChangeAnchorKey,
7739
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
7740
+ ] : []].map((id) => normalizeCommentId(id)).filter(isPresentId);
7741
+ };
7742
+ var groupBodyTrackedChangeCommentsByIdentity = (comments) => {
7743
+ const parents = comments.map((_, index) => index);
7744
+ const findRoot = (index) => {
7745
+ let root = index;
7746
+ while (parents[root] !== root) root = parents[root];
7747
+ while (parents[index] !== index) {
7748
+ const next = parents[index];
7749
+ parents[index] = root;
7750
+ index = next;
7751
+ }
7752
+ return root;
7753
+ };
7754
+ const join = (left, right) => {
7755
+ const leftRoot = findRoot(left);
7756
+ const rightRoot = findRoot(right);
7757
+ if (leftRoot === rightRoot) return;
7758
+ parents[Math.max(leftRoot, rightRoot)] = Math.min(leftRoot, rightRoot);
7759
+ };
7760
+ const identityOwner = /* @__PURE__ */ new Map();
7761
+ comments.forEach((comment, index) => {
7762
+ getBodyTrackedChangeIdentityIds(comment).forEach((identityId) => {
7763
+ const owner = identityOwner.get(identityId);
7764
+ if (owner === void 0) identityOwner.set(identityId, index);
7765
+ else join(index, owner);
7766
+ });
7767
+ });
7768
+ const groups = /* @__PURE__ */ new Map();
7769
+ comments.forEach((comment, index) => {
7770
+ const root = findRoot(index);
7771
+ const group = groups.get(root) ?? [];
7772
+ group.push(comment);
7773
+ groups.set(root, group);
7774
+ });
7775
+ return groups;
7776
+ };
7777
+ var mergeDuplicateBodyTrackedChangeComments = (groups) => {
7778
+ const duplicates = /* @__PURE__ */ new Map();
7779
+ groups.forEach(([survivor, ...duplicateRows]) => {
7780
+ if (!survivor || duplicateRows.length === 0) return;
7781
+ const resolvedDuplicate = duplicateRows.find((comment) => comment.resolvedTime != null);
7782
+ if (survivor.resolvedTime == null && resolvedDuplicate) {
7783
+ survivor.resolvedTime = resolvedDuplicate.resolvedTime;
7784
+ survivor.resolvedById = resolvedDuplicate.resolvedById;
7785
+ survivor.resolvedByEmail = resolvedDuplicate.resolvedByEmail;
7786
+ survivor.resolvedByName = resolvedDuplicate.resolvedByName;
7787
+ survivor.trackedChangeDecision = resolvedDuplicate.trackedChangeDecision;
7788
+ }
7789
+ survivor.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...normalizeTrackedChangePositionAliases(survivor.trackedChangePositionAliases), ...duplicateRows.flatMap((comment) => [
7790
+ comment.commentId,
7791
+ comment.importedId,
7792
+ comment.trackedChangeCanonicalId,
7793
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
7794
+ ])]);
7795
+ duplicateRows.forEach((comment) => duplicates.set(comment, survivor));
7796
+ });
7797
+ return duplicates;
7798
+ };
7799
+ var createDroppedCommentIdMap = (duplicates) => {
7800
+ const droppedCommentIds = /* @__PURE__ */ new Map();
7801
+ duplicates.forEach((survivor, duplicate) => {
7802
+ const fromId = normalizeCommentId(duplicate.commentId);
7803
+ const toId = normalizeCommentId(survivor.commentId);
7804
+ if (fromId && toId) droppedCommentIds.set(fromId, toId);
7805
+ });
7806
+ return droppedCommentIds;
7807
+ };
7808
+ //#endregion
7606
7809
  //#region src/stores/comments-store.js
7607
7810
  var useCommentsStore = defineStore("comments", () => {
7608
7811
  const superdocStore = useSuperdocStore();
@@ -8081,25 +8284,6 @@ var useCommentsStore = defineStore("comments", () => {
8081
8284
  delete debounceTimers[commentId];
8082
8285
  }, delay);
8083
8286
  };
8084
- const getPendingSelectionSnapshot = (superdoc, activeSelection) => {
8085
- if (activeSelection?.source !== "document-editor") return null;
8086
- const selectionDocumentId = activeSelection?.documentId ?? null;
8087
- const editorDocumentId = superdoc?.activeEditor?.options?.documentId ?? null;
8088
- if (!selectionDocumentId || !editorDocumentId || selectionDocumentId !== editorDocumentId) return null;
8089
- let currentSelection;
8090
- try {
8091
- currentSelection = superdoc?.activeEditor?.doc?.selection?.current;
8092
- } catch {
8093
- return null;
8094
- }
8095
- if (typeof currentSelection !== "function") return null;
8096
- try {
8097
- const snapshot = currentSelection();
8098
- return typeof snapshot?.then === "function" ? Promise.resolve(snapshot).catch(() => null) : snapshot;
8099
- } catch {
8100
- return null;
8101
- }
8102
- };
8103
8287
  const showAddComment = (superdoc, targetClientY = null) => {
8104
8288
  const request = ++pendingCommentRequest;
8105
8289
  const editor = superdoc?.activeEditor;
@@ -9623,122 +9807,7 @@ var useCommentsStore = defineStore("comments", () => {
9623
9807
  const activeCommentId = activeComment.value != null ? String(activeComment.value) : null;
9624
9808
  if (activeCommentId && removedAliasIds.has(activeCommentId)) clearActiveCommentSelection();
9625
9809
  }
9626
- const getCommentDocumentId = (comment) => {
9627
- if (!comment) return null;
9628
- if (comment.fileId != null) return String(comment.fileId);
9629
- if (comment.documentId != null) return String(comment.documentId);
9630
- if (comment.selection?.documentId != null) return String(comment.selection.documentId);
9631
- return null;
9632
- };
9633
- const getOpenDocuments = () => {
9634
- const docs = Array.isArray(superdocStore.documents) ? superdocStore.documents : superdocStore.documents?.value;
9635
- return Array.isArray(docs) ? docs : [];
9636
- };
9637
- const getSingleOpenDocumentId = () => {
9638
- const docs = getOpenDocuments();
9639
- if (docs.length !== 1) return null;
9640
- return docs[0]?.id != null ? String(docs[0].id) : null;
9641
- };
9642
- const belongsToDocument = (comment, activeDocumentId, options = {}) => {
9643
- const { allowSingleDocumentMismatch = false } = options;
9644
- if (!activeDocumentId) return false;
9645
- const commentDocumentId = getCommentDocumentId(comment);
9646
- if (commentDocumentId) {
9647
- if (commentDocumentId === activeDocumentId) return true;
9648
- const singleOpenDocumentId = getSingleOpenDocumentId();
9649
- return allowSingleDocumentMismatch && singleOpenDocumentId === activeDocumentId;
9650
- }
9651
- return getSingleOpenDocumentId() === activeDocumentId;
9652
- };
9653
- const belongsToTrackedChangeSyncDocument = (comment, activeDocumentId) => {
9654
- return belongsToDocument(comment, activeDocumentId, { allowSingleDocumentMismatch: true });
9655
- };
9656
- const normalizeTrackedChangeDecisionType = (value) => {
9657
- const lower = typeof value === "string" ? value.toLowerCase() : "";
9658
- if (!lower) return null;
9659
- if (lower === "insert" || lower === "insertion" || lower === "trackinsert" || lower === "tableinsert" || lower === "paragraphsplit") return "insertion";
9660
- if (lower === "delete" || lower === "deletion" || lower === "trackdelete" || lower === "tabledelete") return "deletion";
9661
- return lower;
9662
- };
9663
- const trackedChangeDecisionKeepsCommentAnchor = ({ comment, decision } = {}) => {
9664
- const normalizedDecision = decision === "accept" || decision === "reject" ? decision : null;
9665
- if (!normalizedDecision) return false;
9666
- const type = normalizeTrackedChangeDecisionType(comment?.trackedChangeDisplayType) ?? normalizeTrackedChangeDecisionType(comment?.trackedChangeType);
9667
- return normalizedDecision === "accept" && type === "insertion" || normalizedDecision === "reject" && type === "deletion";
9668
- };
9669
- const getBodyTrackedChangeIdentityIds = (comment) => {
9670
- return [normalizeCommentId(comment.commentId), ...!normalizeCommentId(comment.trackedChangeCanonicalId) ? [
9671
- comment.importedId,
9672
- comment.trackedChangeAnchorKey,
9673
- ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
9674
- ] : []].map((id) => normalizeCommentId(id)).filter(Boolean);
9675
- };
9676
- const groupBodyTrackedChangeCommentsByIdentity = (comments) => {
9677
- const parents = comments.map((_, index) => index);
9678
- const findRoot = (index) => {
9679
- let root = index;
9680
- while (parents[root] !== root) root = parents[root];
9681
- while (parents[index] !== index) {
9682
- const next = parents[index];
9683
- parents[index] = root;
9684
- index = next;
9685
- }
9686
- return root;
9687
- };
9688
- const join = (left, right) => {
9689
- const leftRoot = findRoot(left);
9690
- const rightRoot = findRoot(right);
9691
- if (leftRoot === rightRoot) return;
9692
- parents[Math.max(leftRoot, rightRoot)] = Math.min(leftRoot, rightRoot);
9693
- };
9694
- const identityOwner = /* @__PURE__ */ new Map();
9695
- comments.forEach((comment, index) => {
9696
- getBodyTrackedChangeIdentityIds(comment).forEach((identityId) => {
9697
- const owner = identityOwner.get(identityId);
9698
- if (owner === void 0) identityOwner.set(identityId, index);
9699
- else join(index, owner);
9700
- });
9701
- });
9702
- const groups = /* @__PURE__ */ new Map();
9703
- comments.forEach((comment, index) => {
9704
- const root = findRoot(index);
9705
- const group = groups.get(root) ?? [];
9706
- group.push(comment);
9707
- groups.set(root, group);
9708
- });
9709
- return groups;
9710
- };
9711
- const mergeDuplicateBodyTrackedChangeComments = (groups) => {
9712
- const duplicates = /* @__PURE__ */ new Map();
9713
- groups.forEach(([survivor, ...duplicateRows]) => {
9714
- if (!survivor || duplicateRows.length === 0) return;
9715
- const resolvedDuplicate = duplicateRows.find((comment) => comment.resolvedTime != null);
9716
- if (survivor.resolvedTime == null && resolvedDuplicate) {
9717
- survivor.resolvedTime = resolvedDuplicate.resolvedTime;
9718
- survivor.resolvedById = resolvedDuplicate.resolvedById;
9719
- survivor.resolvedByEmail = resolvedDuplicate.resolvedByEmail;
9720
- survivor.resolvedByName = resolvedDuplicate.resolvedByName;
9721
- survivor.trackedChangeDecision = resolvedDuplicate.trackedChangeDecision;
9722
- }
9723
- survivor.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...normalizeTrackedChangePositionAliases(survivor.trackedChangePositionAliases), ...duplicateRows.flatMap((comment) => [
9724
- comment.commentId,
9725
- comment.importedId,
9726
- comment.trackedChangeCanonicalId,
9727
- ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
9728
- ])]);
9729
- duplicateRows.forEach((comment) => duplicates.set(comment, survivor));
9730
- });
9731
- return duplicates;
9732
- };
9733
- const createDroppedCommentIdMap = (duplicates) => {
9734
- const droppedCommentIds = /* @__PURE__ */ new Map();
9735
- duplicates.forEach((survivor, duplicate) => {
9736
- const fromId = normalizeCommentId(duplicate.commentId);
9737
- const toId = normalizeCommentId(survivor.commentId);
9738
- if (fromId && toId) droppedCommentIds.set(fromId, toId);
9739
- });
9740
- return droppedCommentIds;
9741
- };
9810
+ const { belongsToDocument, belongsToTrackedChangeSyncDocument } = createCommentDocumentScope(() => superdocStore.documents);
9742
9811
  const remapTrackedChangeReferences = (droppedCommentIds, activeDocumentId) => {
9743
9812
  const remapSelection = (selection) => {
9744
9813
  const selectedId = normalizeCommentId(selection.value);
@@ -9764,9 +9833,7 @@ var useCommentsStore = defineStore("comments", () => {
9764
9833
  });
9765
9834
  };
9766
9835
  const compactDuplicateBodyTrackedChangeComments = (activeDocumentId) => {
9767
- const candidates = commentsList.value.filter((comment) => isBodyTrackedChangeComment(comment) && belongsToTrackedChangeSyncDocument(comment, activeDocumentId));
9768
- const groups = groupBodyTrackedChangeCommentsByIdentity(candidates);
9769
- const duplicates = mergeDuplicateBodyTrackedChangeComments(groups);
9836
+ const duplicates = mergeDuplicateBodyTrackedChangeComments(groupBodyTrackedChangeCommentsByIdentity(commentsList.value.filter((comment) => isBodyTrackedChangeComment(comment) && belongsToTrackedChangeSyncDocument(comment, activeDocumentId))));
9770
9837
  if (!duplicates.size) return 0;
9771
9838
  commentsList.value = commentsList.value.filter((comment) => !duplicates.has(comment));
9772
9839
  remapTrackedChangeReferences(createDroppedCommentIdMap(duplicates), activeDocumentId);
@@ -9907,19 +9974,7 @@ var useCommentsStore = defineStore("comments", () => {
9907
9974
  });
9908
9975
  return resolvedCount;
9909
9976
  };
9910
- const collectTrackedChangeDecisionIds = (comment) => {
9911
- const trackedChangeIds = new Set(getCommentAliasIds(comment));
9912
- if (comment?.trackedChangeCanonicalId != null) trackedChangeIds.add(String(comment.trackedChangeCanonicalId));
9913
- const anchorKey = comment?.trackedChangeAnchorKey != null ? String(comment.trackedChangeAnchorKey) : null;
9914
- if (anchorKey) {
9915
- trackedChangeIds.add(anchorKey);
9916
- if (anchorKey.startsWith("tc::")) {
9917
- const rawId = anchorKey.slice(anchorKey.lastIndexOf("::") + 2);
9918
- if (rawId) trackedChangeIds.add(rawId);
9919
- }
9920
- }
9921
- return trackedChangeIds;
9922
- };
9977
+ const collectTrackedChangeDecisionIds = (comment) => collectTrackedChangeDecisionIdsWithAliases(comment, getCommentAliasIds(comment));
9923
9978
  const getTrackedChangeDecisionLinks = (comment) => {
9924
9979
  const linked = [];
9925
9980
  const seen = /* @__PURE__ */ new Set();
@@ -9930,28 +9985,6 @@ var useCommentsStore = defineStore("comments", () => {
9930
9985
  }
9931
9986
  return linked;
9932
9987
  };
9933
- const collectTrackedChangeEntityIdsFromReceipt = (receipt) => {
9934
- const record = receipt && typeof receipt === "object" ? receipt : null;
9935
- if (!record?.success) return /* @__PURE__ */ new Set();
9936
- const ids = /* @__PURE__ */ new Set();
9937
- const collect = (entry) => {
9938
- const ref = entry && typeof entry === "object" ? entry : null;
9939
- if (ref?.kind !== "entity" || ref.entityType !== "trackedChange") return;
9940
- if (ref.entityId != null && String(ref.entityId).length > 0) ids.add(String(ref.entityId));
9941
- };
9942
- if (Array.isArray(record.removed)) record.removed.forEach(collect);
9943
- if (Array.isArray(record.invalidatedRefs)) record.invalidatedRefs.forEach(collect);
9944
- return ids;
9945
- };
9946
- const collectReliableDecidedTrackedChangeIds = (outcome) => {
9947
- const ids = /* @__PURE__ */ new Set();
9948
- if (outcome?.decidedId != null && String(outcome.decidedId).length > 0) ids.add(String(outcome.decidedId));
9949
- if (Array.isArray(outcome?.decidedIds)) outcome.decidedIds.forEach((id) => {
9950
- if (id != null && String(id).length > 0) ids.add(String(id));
9951
- });
9952
- collectTrackedChangeEntityIdsFromReceipt(outcome?.receipt).forEach((id) => ids.add(id));
9953
- return ids;
9954
- };
9955
9988
  const detachLinkedCommentsForTrackedChangeDecision = ({ comment, decision } = {}) => {
9956
9989
  if (!comment?.trackedChange) return 0;
9957
9990
  if (!trackedChangeDecisionKeepsCommentAnchor({
@@ -10127,31 +10160,6 @@ var useCommentsStore = defineStore("comments", () => {
10127
10160
  removedIds
10128
10161
  };
10129
10162
  };
10130
- const clearV2ActiveTrackedChangeTarget = (adapter, decidedId) => {
10131
- if (!decidedId || typeof adapter?.clearActiveTrackedChangeTargetIfMatches !== "function") return;
10132
- try {
10133
- adapter.clearActiveTrackedChangeTargetIfMatches(decidedId);
10134
- } catch {}
10135
- };
10136
- const waitForTrackedDecisionCanonicalPaint = async ({ superdoc, receipt } = {}) => {
10137
- const readiness = superdoc?.activeEditor?.documentMutationReadiness;
10138
- if (receipt?.success !== true || typeof receipt?.txId !== "string" || !receipt.txId || typeof readiness?.whenPainted !== "function") return;
10139
- try {
10140
- await readiness.whenPainted(receipt);
10141
- const requestFrame = globalThis.requestAnimationFrame;
10142
- if (typeof requestFrame === "function") await new Promise((resolve) => {
10143
- let settled = false;
10144
- const finish = () => {
10145
- if (settled) return;
10146
- settled = true;
10147
- clearTimeout(fallback);
10148
- resolve();
10149
- };
10150
- const fallback = setTimeout(finish, 250);
10151
- requestFrame(() => requestFrame(() => setTimeout(finish, 0)));
10152
- });
10153
- } catch {}
10154
- };
10155
10163
  /**
10156
10164
  * Accept or reject the tracked change behind a sidebar row.
10157
10165
  *
@@ -11074,12 +11082,9 @@ var InternalDropdown_default = /* @__PURE__ */ _plugin_vue_export_helper_default
11074
11082
  }
11075
11083
  }), [["__scopeId", "data-v-026f5d66"]]);
11076
11084
  //#endregion
11077
- //#region src/components/CommentsLayer/helpers.js
11085
+ //#region src/components/CommentsLayer/helpers.ts
11078
11086
  /**
11079
11087
  * Comments helper to format dates from timestamp
11080
- *
11081
- * @param {Number} timestamp The timestamp to format
11082
- * @returns {String} The formatted date
11083
11088
  */
11084
11089
  function formatDate(timestamp) {
11085
11090
  const date = new Date(timestamp);
@@ -11677,7 +11682,7 @@ var CommentInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/*
11677
11682
  }
11678
11683
  }), [["__scopeId", "data-v-aa97de44"]]);
11679
11684
  //#endregion
11680
- //#region src/internal/toolbar/built-in/url-safety.js
11685
+ //#region src/internal/toolbar/built-in/url-safety.ts
11681
11686
  /**
11682
11687
  * Minimal href sanitizer for the built-in link popover.
11683
11688
  *
@@ -11693,8 +11698,6 @@ var DANGEROUS_SCHEME = /^(javascript|data|vbscript):/i;
11693
11698
  var HAS_SCHEME = /^[a-z][a-z0-9+.-]*:/i;
11694
11699
  /**
11695
11700
  * Validate and normalize an href. Returns `{ href }` for safe values, or `null`.
11696
- * @param {string} value
11697
- * @returns {{ href: string }|null}
11698
11701
  */
11699
11702
  function sanitizeHref(value) {
11700
11703
  if (typeof value !== "string") return null;
@@ -11706,7 +11709,7 @@ function sanitizeHref(value) {
11706
11709
  return { href: trimmed };
11707
11710
  }
11708
11711
  //#endregion
11709
- //#region src/components/CommentsLayer/comment-urls.js
11712
+ //#region src/components/CommentsLayer/comment-urls.ts
11710
11713
  function isAbsoluteWebUrl(value) {
11711
11714
  if (!/^https?:\/\/[^\s/?#\\]+/i.test(value) || /[\s\\]/u.test(value)) return false;
11712
11715
  try {
@@ -11730,7 +11733,7 @@ function trimUrlPunctuation(value) {
11730
11733
  for (const character of value) {
11731
11734
  const close = closingDelimiter[character];
11732
11735
  if (close) balance[close] += 1;
11733
- else if (Object.hasOwn(balance, character)) balance[character] -= 1;
11736
+ else if (Object.prototype.hasOwnProperty.call(balance, character)) balance[character] -= 1;
11734
11737
  }
11735
11738
  let end = value.length;
11736
11739
  while (end > 0) {
@@ -11754,17 +11757,18 @@ function renderCommentHtml(value) {
11754
11757
  if (typeof document === "undefined") return value;
11755
11758
  const template = document.createElement("template");
11756
11759
  template.innerHTML = value;
11757
- for (const link of template.content.querySelectorAll("a")) {
11758
- const safe = sanitizeHref(link.getAttribute("href"));
11760
+ for (const link of Array.from(template.content.querySelectorAll("a"))) {
11761
+ const rawHref = link.getAttribute("href");
11762
+ const safe = rawHref === null ? null : sanitizeHref(rawHref);
11759
11763
  if (safe && (isAbsoluteWebUrl(safe.href) || /^(mailto|tel):\S+$/i.test(safe.href))) configureLink(link, safe.href);
11760
- else link.replaceWith(...link.childNodes);
11764
+ else link.replaceWith(...Array.from(link.childNodes));
11761
11765
  }
11762
11766
  const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
11763
11767
  const textNodes = [];
11764
- while (walker.nextNode()) textNodes.push(walker.currentNode);
11768
+ while (walker.nextNode()) if (walker.currentNode instanceof Text) textNodes.push(walker.currentNode);
11765
11769
  for (const node of textNodes) {
11766
11770
  if (node.parentElement?.closest("a, script, style, textarea, code, pre")) continue;
11767
- const text = node.textContent;
11771
+ const text = node.data;
11768
11772
  const fragment = document.createDocumentFragment();
11769
11773
  let end = 0;
11770
11774
  for (const match of text.matchAll(/(^|[\s([{])(https?:\/\/[^\s<>"']+)/gi)) {
@@ -13445,21 +13449,25 @@ var commentsList_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/*
13445
13449
  }
13446
13450
  }), [["__scopeId", "data-v-8eca48e1"]]);
13447
13451
  //#endregion
13448
- //#region src/components/CommentsLayer/commentsList/super-comments-list.js
13452
+ //#region src/components/CommentsLayer/commentsList/super-comments-list.ts
13453
+ var isReviewDirectoryStore = (value) => isPlainObject$1(value) && typeof value.setReviewDirectoryFromV2 === "function" && typeof value.clearReviewDirectory === "function";
13454
+ var readCommentsStore = (superdoc) => {
13455
+ const store = superdoc?.["commentsStore"];
13456
+ return isReviewDirectoryStore(store) ? store : void 0;
13457
+ };
13449
13458
  /**
13450
13459
  * Comments list renderer (not floating comments)
13451
13460
  *
13452
13461
  * This renders a list of comments into an element, connected to main SuperDoc instance
13453
13462
  */
13454
13463
  var SuperComments = class extends import_eventemitter3.default {
13455
- element;
13456
- config = {
13457
- comments: [],
13458
- element: null,
13459
- commentsStore: null
13460
- };
13461
13464
  constructor(options, superdoc) {
13462
13465
  super();
13466
+ this.config = {
13467
+ comments: [],
13468
+ element: null,
13469
+ commentsStore: null
13470
+ };
13463
13471
  this.config = {
13464
13472
  ...this.config,
13465
13473
  ...options
@@ -13480,7 +13488,7 @@ var SuperComments = class extends import_eventemitter3.default {
13480
13488
  this.open();
13481
13489
  }
13482
13490
  syncDirectory() {
13483
- const store = this.superdoc?.commentsStore;
13491
+ const store = readCommentsStore(this.superdoc);
13484
13492
  if (!store) return;
13485
13493
  const comments = this.directorySnapshots.comments;
13486
13494
  const trackChanges = this.directorySnapshots.trackChanges;
@@ -13498,12 +13506,14 @@ var SuperComments = class extends import_eventemitter3.default {
13498
13506
  const acceptDirectorySnapshot = (snapshot) => {
13499
13507
  if (generation !== this.directoryGeneration) return;
13500
13508
  if ((snapshot?.listStatus ?? snapshot?.status) !== "ready") {
13501
- if (this.superdoc?.commentsStore) this.superdoc.commentsStore.isReviewDirectoryLoading = true;
13509
+ const store = readCommentsStore(this.superdoc);
13510
+ if (store) store.isReviewDirectoryLoading = true;
13502
13511
  return;
13503
13512
  }
13504
13513
  const items = Array.isArray(snapshot.items) ? snapshot.items : [];
13505
13514
  if (this.directoryItemRefs[family] === items) {
13506
- if (this.superdoc?.commentsStore) this.superdoc.commentsStore.isReviewDirectoryLoading = this.directorySnapshots.comments == null || this.directorySnapshots.trackChanges == null;
13515
+ const store = readCommentsStore(this.superdoc);
13516
+ if (store) store.isReviewDirectoryLoading = this.directorySnapshots.comments == null || this.directorySnapshots.trackChanges == null;
13507
13517
  return;
13508
13518
  }
13509
13519
  this.directoryItemRefs[family] = items;
@@ -13520,15 +13530,16 @@ var SuperComments = class extends import_eventemitter3.default {
13520
13530
  };
13521
13531
  const ui = this.superdoc?.ui;
13522
13532
  if (!ui) return;
13523
- if (this.superdoc?.commentsStore) {
13524
- this.superdoc.commentsStore.isReviewDirectoryActive = true;
13525
- this.superdoc.commentsStore.isReviewDirectoryLoading = true;
13533
+ const store = readCommentsStore(this.superdoc);
13534
+ if (store) {
13535
+ store.isReviewDirectoryActive = true;
13536
+ store.isReviewDirectoryLoading = true;
13526
13537
  }
13527
13538
  this.stopDirectoryObservers = [subscribe(ui.comments, "comments"), subscribe(ui.trackChanges, "trackChanges")];
13528
13539
  }
13529
13540
  createVueApp() {
13530
13541
  this.app = createApp(commentsList_default);
13531
- const parentProvides = this.superdoc?.app?._context?.provides;
13542
+ const parentProvides = this.superdoc?.["app"]?._context?.provides;
13532
13543
  if (parentProvides && this.app?._context?.provides) Object.setPrototypeOf(this.app._context.provides, parentProvides);
13533
13544
  if (this.superdoc?.pinia) {
13534
13545
  setActivePinia(this.superdoc.pinia);
@@ -13552,10 +13563,11 @@ var SuperComments = class extends import_eventemitter3.default {
13552
13563
  comments: null,
13553
13564
  trackChanges: null
13554
13565
  };
13555
- if (this.superdoc?.commentsStore) {
13556
- this.superdoc.commentsStore.clearReviewDirectory();
13557
- this.superdoc.commentsStore.isReviewDirectoryActive = false;
13558
- this.superdoc.commentsStore.isReviewDirectoryLoading = false;
13566
+ const store = readCommentsStore(this.superdoc);
13567
+ if (store) {
13568
+ store.clearReviewDirectory();
13569
+ store.isReviewDirectoryActive = false;
13570
+ store.isReviewDirectoryLoading = false;
13559
13571
  }
13560
13572
  if (this.app) {
13561
13573
  this.app.unmount();
@@ -15481,7 +15493,7 @@ var WhiteboardPage_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/
15481
15493
  }, null, 44, _hoisted_1$21);
15482
15494
  };
15483
15495
  }
15484
- }), [["__scopeId", "data-v-f730b33d"]]);
15496
+ }), [["__scopeId", "data-v-fdae8749"]]);
15485
15497
  //#endregion
15486
15498
  //#region src/components/Whiteboard/WhiteboardLayer.vue
15487
15499
  var WhiteboardLayer_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -15552,16 +15564,11 @@ var WhiteboardLayer_default = /* @__PURE__ */ _plugin_vue_export_helper_default(
15552
15564
  }), 128))], 4);
15553
15565
  };
15554
15566
  }
15555
- }), [["__scopeId", "data-v-980e1f94"]]);
15567
+ }), [["__scopeId", "data-v-800e1970"]]);
15556
15568
  //#endregion
15557
- //#region src/components/CommentsLayer/collect-removed-comment-ids.js
15569
+ //#region src/components/CommentsLayer/collect-removed-comment-ids.ts
15558
15570
  /**
15559
15571
  * Expand deleted comment ids through comment and tracked-change descendants.
15560
- *
15561
- * @param {ReadonlyArray<Record<string, any>>} comments
15562
- * @param {ReadonlyArray<string>} targetIds
15563
- * @param {(comment: Record<string, any>) => boolean} [isInScope]
15564
- * @returns {Set<string>}
15565
15572
  */
15566
15573
  var collectRemovedCommentIds = (comments, targetIds, isInScope = () => true) => {
15567
15574
  const targets = new Set(targetIds.map(String));
@@ -16531,7 +16538,7 @@ function usePasswordPrompt({ getSurfaceManager, getPasswordPromptConfig, onUnhan
16531
16538
  })
16532
16539
  });
16533
16540
  } else {
16534
- const mod = await import("./chunks/PasswordPromptSurface-6mF6Azda.es.js");
16541
+ const mod = await import("./chunks/PasswordPromptSurface-CZqhDQQ1.es.js");
16535
16542
  const surfaceId = `password-prompt-${doc.id}`;
16536
16543
  handle = manager.open({
16537
16544
  id: surfaceId,
@@ -16633,9 +16640,6 @@ function createReplaceContinuation(session, { getCurrentSession, applySlice, onS
16633
16640
  }
16634
16641
  //#endregion
16635
16642
  //#region src/composables/use-find-replace.ts
16636
- function isThenable$2(value) {
16637
- return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
16638
- }
16639
16643
  var DEFAULT_TEXTS = {
16640
16644
  findPlaceholder: "Find",
16641
16645
  findAriaLabel: "Find text",
@@ -16810,7 +16814,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
16810
16814
  try {
16811
16815
  result = search.replace(replaceText.value);
16812
16816
  } catch {}
16813
- if (isThenable$2(result)) Promise.resolve(result).then(finish, finish);
16817
+ if (isThenable$1(result)) Promise.resolve(result).then(finish, finish);
16814
16818
  else finish();
16815
16819
  }
16816
16820
  function replaceAll() {
@@ -16832,7 +16836,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
16832
16836
  try {
16833
16837
  result = search.replaceAll(replaceText.value);
16834
16838
  } catch {}
16835
- if (isThenable$2(result)) Promise.resolve(result).then(finish, finish);
16839
+ if (isThenable$1(result)) Promise.resolve(result).then(finish, finish);
16836
16840
  else finish();
16837
16841
  }
16838
16842
  function syncFromSearchSession() {
@@ -17194,7 +17198,7 @@ function useFindReplace({ getSurfaceManager, getActiveEditor, activeEditorRef, g
17194
17198
  } else {
17195
17199
  let FindReplaceSurface;
17196
17200
  try {
17197
- FindReplaceSurface = (await import("./chunks/FindReplaceSurface-BKVHzhQ4.es.js")).default;
17201
+ FindReplaceSurface = (await import("./chunks/FindReplaceSurface-B_5ggdWg.es.js")).default;
17198
17202
  } catch {
17199
17203
  opening = false;
17200
17204
  return;
@@ -17461,7 +17465,7 @@ var plus_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0
17461
17465
  //#region ../../shared/common/icons/trash-can-solid.svg?raw
17462
17466
  var trash_can_solid_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 448 512\"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d=\"M135.2 17.7C140.6 6.8 151.7 0 163.8 0L284.2 0c12.1 0 23.2 6.8 28.6 17.7L320 32l96 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 96C14.3 96 0 81.7 0 64S14.3 32 32 32l96 0 7.2-14.3zM32 128l384 0 0 320c0 35.3-28.7 64-64 64L96 512c-35.3 0-64-28.7-64-64l0-320zm96 64c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16zm96 0c-8.8 0-16 7.2-16 16l0 224c0 8.8 7.2 16 16 16s16-7.2 16-16l0-224c0-8.8-7.2-16-16-16z\"/></svg>";
17463
17467
  //#endregion
17464
- //#region src/internal/toolbar/built-in/toolbarIcons.js
17468
+ //#region src/internal/toolbar/built-in/toolbarIcons.ts
17465
17469
  var toolbarIcons = {
17466
17470
  undo: rotate_left_solid_default,
17467
17471
  redo: rotate_right_solid_default,
@@ -17854,7 +17858,7 @@ var LinkInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__
17854
17858
  }
17855
17859
  }), [["__scopeId", "data-v-172107e4"]]);
17856
17860
  //#endregion
17857
- //#region src/internal/toolbar/built-in/scroll-helpers.js
17861
+ //#region src/internal/toolbar/built-in/scroll-helpers.ts
17858
17862
  function getScrollableParent(element) {
17859
17863
  let currentElement = element;
17860
17864
  while (currentElement) {
@@ -17887,7 +17891,6 @@ function scrollToElement(targetElement, options = {
17887
17891
  var FLOATING_SURFACE_ID = "link-popover";
17888
17892
  var RECENT_OUTSIDE_CLOSE_MS = 500;
17889
17893
  var MAX_ANCHOR_NAVIGATION_STEPS = 4;
17890
- var isThenable$1 = (value) => Boolean(value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function");
17891
17894
  function isLinkPopoverDocumentApi(value) {
17892
17895
  return isPlainObject$1(value) || typeof value === "function";
17893
17896
  }
@@ -20457,7 +20460,7 @@ var SuperDoc_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__P
20457
20460
  __name: "SuperDoc",
20458
20461
  emits: ["selection-update"],
20459
20462
  setup(__props, { emit: __emit }) {
20460
- const PdfViewer = defineAsyncComponent(() => import("./chunks/PdfViewer-aOWhUVI7.es.js"));
20463
+ const PdfViewer = defineAsyncComponent(() => import("./chunks/PdfViewer-CW09MNrB.es.js"));
20461
20464
  const getDocumentLoadPassword = (doc) => doc.password ?? proxy.$superdoc.config.password;
20462
20465
  const resolveDocumentV2Collaboration = (doc) => {
20463
20466
  const rawConfig = doc?.v2Collaboration;
@@ -25859,23 +25862,21 @@ function resolveBuiltInItemCommandId(name) {
25859
25862
  return resolveToolbarCommandId(name) ?? UNCATALOGED_ITEM_COMMAND_IDS[name] ?? null;
25860
25863
  }
25861
25864
  //#endregion
25862
- //#region src/internal/toolbar/built-in/helpers.js
25865
+ //#region src/internal/toolbar/built-in/helpers.ts
25863
25866
  var sanitizeNumber = (value, defaultNumber) => {
25864
- let sanitized = value.replace(/[^0-9.]/g, "");
25865
- sanitized = parseFloat(sanitized);
25866
- if (isNaN(sanitized)) sanitized = defaultNumber;
25867
- sanitized = parseFloat(sanitized);
25868
- return sanitized;
25869
- };
25870
- var throttle = (func, wait, options) => {
25871
- let timeout, args, result;
25867
+ const parsed = parseFloat(String(value ?? "").replace(/[^0-9.]/g, ""));
25868
+ return isNaN(parsed) ? defaultNumber : parsed;
25869
+ };
25870
+ var throttle = (func, wait, options = {}) => {
25871
+ let timeout;
25872
+ let args;
25873
+ let result;
25872
25874
  let previous = 0;
25873
- if (!options) options = {};
25874
25875
  const later = () => {
25875
25876
  previous = options.leading === false ? 0 : Date.now();
25876
- timeout = null;
25877
- result = func(...args);
25878
- if (!timeout) args = null;
25877
+ timeout = void 0;
25878
+ if (args) result = func(...args);
25879
+ if (!timeout) args = void 0;
25879
25880
  };
25880
25881
  const throttled = (...callArgs) => {
25881
25882
  const _now = Date.now();
@@ -25885,18 +25886,18 @@ var throttle = (func, wait, options) => {
25885
25886
  if (remaining <= 0 || remaining > wait) {
25886
25887
  if (timeout) {
25887
25888
  clearTimeout(timeout);
25888
- timeout = null;
25889
+ timeout = void 0;
25889
25890
  }
25890
25891
  previous = _now;
25891
25892
  result = func(...callArgs);
25892
- if (!timeout) args = null;
25893
+ if (!timeout) args = void 0;
25893
25894
  } else if (!timeout && options.trailing !== false) timeout = setTimeout(later, remaining);
25894
25895
  return result;
25895
25896
  };
25896
25897
  throttled.cancel = function() {
25897
25898
  clearTimeout(timeout);
25898
25899
  previous = 0;
25899
- timeout = args = null;
25900
+ timeout = args = void 0;
25900
25901
  };
25901
25902
  return throttled;
25902
25903
  };
@@ -26795,24 +26796,11 @@ var OverflowMenu_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/*
26795
26796
  }
26796
26797
  }), [["__scopeId", "data-v-d2e189fd"]]);
26797
26798
  //#endregion
26798
- //#region src/internal/toolbar/built-in/font-typeahead.js
26799
- /**
26800
- * Pure typeahead/autocomplete helpers for the font comboboxes (family + size).
26801
- *
26802
- * Matching is case-insensitive prefix matching on the logical font labels.
26803
- * Space is a normal query character, so the query is never split on spaces;
26804
- * only the outer whitespace is ignored when comparing.
26805
- *
26806
- * These functions hold no Vue or DOM state so CI can unit-test them in isolation.
26807
- */
26799
+ //#region src/internal/toolbar/built-in/font-typeahead.ts
26808
26800
  var normalize = (value) => String(value ?? "").trim().toLowerCase();
26809
26801
  /**
26810
26802
  * Index of the first label that starts with `query` (case-insensitive).
26811
- * An empty/whitespace query never matches.
26812
- *
26813
- * @param {string} query
26814
- * @param {ReadonlyArray<string>} labels
26815
- * @returns {number} matching index or -1
26803
+ * An empty/whitespace query never matches. Returns the matching index or -1.
26816
26804
  */
26817
26805
  var findPrefixMatchIndex = (query, labels) => {
26818
26806
  const q = normalize(query);
@@ -26826,12 +26814,7 @@ var findPrefixMatchIndex = (query, labels) => {
26826
26814
  * When `autocomplete` is true and a prefix match exists that is longer than the
26827
26815
  * typed query, the completion is shown with the suffix selected so the next
26828
26816
  * keystroke replaces it. When false (deletion) or no match exists, the raw
26829
- * query is shown with the caret at its end.
26830
- *
26831
- * @param {string} query - the user-typed portion
26832
- * @param {ReadonlyArray<string>} labels
26833
- * @param {{ autocomplete?: boolean }} [options]
26834
- * @returns {{ matchIndex: number, display: string, selectionStart: number, selectionEnd: number }}
26817
+ * query is shown with the caret at its end. `query` is the user-typed portion.
26835
26818
  */
26836
26819
  var computeTypeahead = (query, labels, { autocomplete = true } = {}) => {
26837
26820
  const typed = String(query ?? "");
@@ -26883,9 +26866,6 @@ var MAX_FONT_SIZE = 1638;
26883
26866
  * the nearest half point (DOCX/Word support half points such as 10.5), and clamps
26884
26867
  * to the supported range. Returns '' when nothing usable was typed, including
26885
26868
  * negative or sub-minimum values.
26886
- *
26887
- * @param {string} value
26888
- * @returns {string} point size (whole or half), or '' when empty/invalid
26889
26869
  */
26890
26870
  var normalizeCustomFontSize = (value) => {
26891
26871
  const cleaned = String(value ?? "").replace(/[^0-9.-]/g, "");
@@ -28576,7 +28556,7 @@ var Toolbar_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/* @__PU
28576
28556
  }
28577
28557
  }), [["__scopeId", "data-v-bce7c04a"]]);
28578
28558
  //#endregion
28579
- //#region src/internal/toolbar/built-in/font-options.js
28559
+ //#region src/internal/toolbar/built-in/font-options.ts
28580
28560
  /**
28581
28561
  * Normalize a font dropdown option so each row renders in its own typeface.
28582
28562
  *
@@ -28932,7 +28912,7 @@ var StyleButtonsList_default = /* @__PURE__ */ _plugin_vue_export_helper_default
28932
28912
  }
28933
28913
  }), [["__scopeId", "data-v-539d0995"]]);
28934
28914
  //#endregion
28935
- //#region src/internal/toolbar/built-in/list-style-buttons.js
28915
+ //#region src/internal/toolbar/built-in/list-style-buttons.ts
28936
28916
  var bulletStyleButtons = [
28937
28917
  {
28938
28918
  key: "disc",
@@ -30243,7 +30223,7 @@ var PageNumberMenu_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/
30243
30223
  onClick: ($event) => selectTile(tile),
30244
30224
  onDblclick: applyPageNumbers,
30245
30225
  onKeydown: onTileKeydown
30246
- }, [(openBlock(), createElementBlock("svg", _hoisted_5, [_cache[4] || (_cache[4] = createStaticVNode("<rect class=\"sd-page-number-menu__sheet\" x=\"0.75\" y=\"0.75\" width=\"34.5\" height=\"44.5\" rx=\"2.5\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"14\" width=\"22\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"19\" width=\"18\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"24\" width=\"22\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"29\" width=\"14\" height=\"2\" rx=\"1\" data-v-a6c124c0></rect>", 5)), createElementVNode("rect", {
30226
+ }, [(openBlock(), createElementBlock("svg", _hoisted_5, [_cache[4] || (_cache[4] = createStaticVNode("<rect class=\"sd-page-number-menu__sheet\" x=\"0.75\" y=\"0.75\" width=\"34.5\" height=\"44.5\" rx=\"2.5\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"14\" width=\"22\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"19\" width=\"18\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"24\" width=\"22\" height=\"2\" rx=\"1\" data-v-e3105afd></rect><rect class=\"sd-page-number-menu__line\" x=\"7\" y=\"29\" width=\"14\" height=\"2\" rx=\"1\" data-v-e3105afd></rect>", 5)), createElementVNode("rect", {
30247
30227
  class: "sd-page-number-menu__chip",
30248
30228
  x: CHIP_X[tile.alignment],
30249
30229
  y: CHIP_Y[tile.position],
@@ -30323,23 +30303,21 @@ var PageNumberMenu_default = /* @__PURE__ */ _plugin_vue_export_helper_default(/
30323
30303
  ], 10, _hoisted_1);
30324
30304
  };
30325
30305
  }
30326
- }), [["__scopeId", "data-v-a6c124c0"]]);
30306
+ }), [["__scopeId", "data-v-e3105afd"]]);
30327
30307
  //#endregion
30328
- //#region src/internal/toolbar/built-in/page-number-feedback.js
30308
+ //#region src/internal/toolbar/built-in/page-number-feedback.ts
30329
30309
  var FLASH_CLASS = "sd-page-number-flash";
30330
30310
  var FLASH_MS = 1400;
30331
30311
  var nextFrame = (view) => new Promise((resolve) => {
30332
- if (typeof view?.requestAnimationFrame === "function") view.requestAnimationFrame(() => resolve());
30312
+ if (typeof view.requestAnimationFrame === "function") view.requestAnimationFrame(() => resolve());
30333
30313
  else setTimeout(resolve, 16);
30334
30314
  });
30335
30315
  /**
30336
30316
  * Briefly highlight the painted header or footer regions that are on screen,
30337
30317
  * so the user sees where page numbers landed without the caret leaving the
30338
30318
  * body. Regions are read after the repaint that follows the mutation; nothing
30339
- * happens when none is visible or the host is unavailable.
30340
- *
30341
- * @param {HTMLElement | null | undefined} host Document viewport host element.
30342
- * @param {'header' | 'footer'} kind
30319
+ * happens when none is visible or the host is unavailable. `host` is the
30320
+ * document viewport host element.
30343
30321
  */
30344
30322
  async function flashPageNumberRegions(host, kind) {
30345
30323
  const view = host?.ownerDocument?.defaultView;
@@ -30347,7 +30325,7 @@ async function flashPageNumberRegions(host, kind) {
30347
30325
  await nextFrame(view);
30348
30326
  await nextFrame(view);
30349
30327
  const viewportHeight = view.innerHeight;
30350
- const regions = [...host.querySelectorAll(`[data-sd-headerfooter-kind="${kind}"]`)].filter((region) => {
30328
+ const regions = Array.from(host.querySelectorAll(`[data-sd-headerfooter-kind="${kind}"]`)).filter((region) => {
30351
30329
  const rect = region.getBoundingClientRect();
30352
30330
  return rect.height > 0 && rect.bottom > 0 && rect.top < viewportHeight;
30353
30331
  });
@@ -31695,7 +31673,7 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
31695
31673
  };
31696
31674
  };
31697
31675
  //#endregion
31698
- //#region src/internal/toolbar/built-in/general.js
31676
+ //#region src/internal/toolbar/built-in/general.ts
31699
31677
  /**
31700
31678
  * Minimal DOM helpers for the built-in toolbar shell.
31701
31679
  *
@@ -31706,8 +31684,6 @@ var makeDefaultItems = ({ superToolbar, toolbarIcons: configuredIcons, toolbarTe
31706
31684
  */
31707
31685
  /**
31708
31686
  * Resolve a toolbar mount target from a selector string or element id.
31709
- * @param {string|HTMLElement|null|undefined} selector
31710
- * @returns {HTMLElement|null}
31711
31687
  */
31712
31688
  var findElementBySelector = (selector) => {
31713
31689
  if (!selector) return null;
@@ -31747,9 +31723,6 @@ function toSelectedValue(value) {
31747
31723
  function nonEmptyString(value) {
31748
31724
  return typeof value === "string" && value ? value : void 0;
31749
31725
  }
31750
- function isThenable(value) {
31751
- return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
31752
- }
31753
31726
  function isToolbarCommandCallback(value) {
31754
31727
  return typeof value === "function";
31755
31728
  }
@@ -31772,7 +31745,7 @@ function executeCommand(ui, commandId, argument, options = {}) {
31772
31745
  if (!options.reportUnhandled || settled !== false) return;
31773
31746
  options.onError?.(/* @__PURE__ */ new Error(`[superdoc toolbar] Command "${commandId}" did not run. Check that it is enabled and has the required input.`));
31774
31747
  };
31775
- if (isThenable(result)) Promise.resolve(result).then((settled) => {
31748
+ if (isThenable$1(result)) Promise.resolve(result).then((settled) => {
31776
31749
  reportFailure(settled);
31777
31750
  options.onSettled?.();
31778
31751
  }, (error) => {
@@ -32124,7 +32097,7 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
32124
32097
  argument: payload.argument,
32125
32098
  option: payload.option
32126
32099
  });
32127
- if (isThenable(result)) return Promise.resolve(result).catch((error) => {
32100
+ if (isThenable$1(result)) return Promise.resolve(result).catch((error) => {
32128
32101
  this.#emitCommandException(error, config.name);
32129
32102
  return false;
32130
32103
  });
@@ -32601,7 +32574,7 @@ var BuiltInToolbar = class extends import_eventemitter3.default {
32601
32574
  ui: this.ui,
32602
32575
  superdoc: this.superdoc
32603
32576
  });
32604
- if (isThenable(result)) Promise.resolve(result).catch((error) => this.#emitCommandException(error, name));
32577
+ if (isThenable$1(result)) Promise.resolve(result).catch((error) => this.#emitCommandException(error, name));
32605
32578
  }
32606
32579
  this.updateToolbarState();
32607
32580
  return;
@@ -33171,7 +33144,7 @@ var SuperDoc = class extends import_eventemitter3.default {
33171
33144
  }
33172
33145
  this.userColorMap = /* @__PURE__ */ new Map();
33173
33146
  this.colorIndex = 0;
33174
- this.version = "2.29.0-next.13";
33147
+ this.version = "2.29.0-next.17";
33175
33148
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
33176
33149
  this.superdocId = config.superdocId || v4();
33177
33150
  this.colors = this.config.colors ?? [];