superdoc 2.28.0-next.6 → 2.28.0-next.8

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 (53) hide show
  1. package/dist/chunks/{create-super-doc-ui-D1eOhAjv.cjs → create-super-doc-ui-B4c55pFy.cjs} +420 -84
  2. package/dist/chunks/{create-super-doc-ui-B29zw5qD.es.js → create-super-doc-ui-C4Ka5Ph3.es.js} +415 -85
  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/content-controls/content-controls.types.d.ts +11 -0
  6. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  7. package/dist/document-api/src/contract/operation-definitions.d.ts +33 -33
  8. package/dist/document-api/src/contract/operation-registry.d.ts +4 -0
  9. package/dist/document-api/src/export/export.d.ts +3 -1
  10. package/dist/document-api/src/export/export.types.d.ts +8 -0
  11. package/dist/document-api/src/get-node/get-node.d.ts +10 -4
  12. package/dist/document-api/src/hyperlinks/hyperlinks.types.d.ts +2 -0
  13. package/dist/document-api/src/index.d.ts +1 -0
  14. package/dist/document-api/src/types/track-changes.types.d.ts +10 -2
  15. package/dist/layout-engine/contracts/src/index.d.ts +2 -0
  16. package/dist/layout-engine/contracts/src/resolved-layout.d.ts +1 -0
  17. package/dist/public/ui-react.cjs +1 -1
  18. package/dist/public/ui-react.es.js +1 -1
  19. package/dist/public/ui-vue.cjs +1 -1
  20. package/dist/public/ui-vue.es.js +1 -1
  21. package/dist/public/ui.cjs +1 -1
  22. package/dist/public/ui.es.js +1 -1
  23. package/dist/shared/common/list-marker-utils.d.ts +3 -0
  24. package/dist/style.css +1 -1
  25. package/dist/style.layered.css +1 -1
  26. package/dist/superdoc/src/core/SuperDoc.d.ts +2 -6
  27. package/dist/superdoc/src/core/config/normalize-ui-config.d.ts +1 -0
  28. package/dist/superdoc/src/core/editor-runtime/types.d.ts +1 -0
  29. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -2
  30. package/dist/superdoc/src/core/extensions/types.d.ts +14 -3
  31. package/dist/superdoc/src/core/helpers/resolve-docx-export.d.ts +6 -0
  32. package/dist/superdoc/src/core/types/index.d.ts +12 -1
  33. package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +0 -8
  34. package/dist/superdoc/src/internal/toolbar/built-in/color-dropdown-helpers.d.ts +0 -1
  35. package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +0 -2
  36. package/dist/superdoc/src/public/export-types.d.ts +3 -0
  37. package/dist/superdoc/src/public/ui/entity-at.d.ts +1 -0
  38. package/dist/superdoc/src/public/ui/format-painter-helpers.d.ts +0 -13
  39. package/dist/superdoc/src/public/ui/types.d.ts +16 -2
  40. package/dist/superdoc/src/public/ui.d.cts +14 -0
  41. package/dist/superdoc/src/public/ui.d.ts +1 -1
  42. package/dist/superdoc/src/stores/comments-store.d.ts +3 -57
  43. package/dist/superdoc/src/stores/superdoc-store.d.ts +9 -171
  44. package/dist/superdoc.cjs +224 -59
  45. package/dist/superdoc.es.js +224 -59
  46. package/dist/word-layout/src/types.d.ts +1 -0
  47. package/dist-cdn/style.layered.css +1 -1
  48. package/dist-cdn/superdoc.min.css +1 -1
  49. package/dist-cdn/superdoc.min.js +42 -42
  50. package/package.json +2 -2
  51. package/dist/superdoc/src/helpers/floor.d.ts +0 -1
  52. package/dist/superdoc/src/index.d.cts +0 -18
  53. package/dist/superdoc/src/index.d.ts +0 -14
@@ -1,6 +1,6 @@
1
1
  import { i as __toESM$2 } from "./chunks/rolldown-runtime-0pSA04fp.es.js";
2
2
  import { t as blank_default } from "./chunks/blank-docx-DzQccOlW.es.js";
3
- import { _ as getWorkflowRecording, a as registerFirstPartyCommandMutation, c as getV2TrackedChangeMutationImpact, d as resolveImageSrc, g as createInteractionHistory, h as closeInteractionHistory, i as readFirstPartyPageNumbers, l as isPlainObject$1, m as DOM_CLASS_NAMES, n as executeFirstPartyCommandAsync, p as isSyntheticTrackedChangeCommentLaneItem, r as executeFirstPartyShortcutAsync, s as applyV2CommentInvalidationFromMutation, t as createSuperDocUI, u as createImageFilePicker, v as isWorkflowRecordingEnabled, y as recordInteraction } from "./chunks/create-super-doc-ui-B29zw5qD.es.js";
3
+ import { _ as createInteractionHistory, a as registerFirstPartyCommandMutation, b as recordInteraction, c as applyV2CommentInvalidationFromMutation, d as createImageFilePicker, f as resolveImageSrc, g as closeInteractionHistory, h as DOM_CLASS_NAMES, i as readFirstPartyPageNumbers, l as getV2TrackedChangeMutationImpact, m as isSyntheticTrackedChangeCommentLaneItem, n as executeFirstPartyCommandAsync, o as isRecord, r as executeFirstPartyShortcutAsync, t as createSuperDocUI, u as isPlainObject$1, v as getWorkflowRecording, y as isWorkflowRecordingEnabled } from "./chunks/create-super-doc-ui-C4Ka5Ph3.es.js";
4
4
  import { t as import_eventemitter3 } from "./chunks/eventemitter3-DEIiXiH2.es.js";
5
5
  import { t as v4 } from "./chunks/uuid-H0Xcmmhy.es.js";
6
6
  import { $ as vModelText, A as onActivated, B as renderSlot, C as isRef$1, D as normalizeClass, E as nextTick, F as openBlock, G as toRaw$2, H as resolveDynamicComponent, I as provide$1, J as unref, K as toRef, L as reactive, M as onDeactivated, N as onMounted, O as normalizeProps, P as onScopeDispose$1, Q as vModelSelect, R as ref, S as isReactive$1, T as mergeProps, U as shallowRef$1, V as resolveDirective, W as toDisplayString, X as useSlots, Y as useAttrs, Z as vModelCheckbox, _ as getCurrentInstance, a as computed$1, b as hasInjectionContext, c as createCommentVNode, d as createStaticVNode, et as watch$1, f as createTextVNode, g as effectScope, h as defineComponent, i as Transition, it as withModifiers, j as onBeforeUnmount, k as normalizeStyle, l as createElementBlock, m as defineAsyncComponent, n as Fragment, nt as withDirectives, o as createApp, p as createVNode, q as toRefs, r as Teleport, rt as withKeys, s as createBlock, t as _plugin_vue_export_helper_default, tt as withCtx, u as createElementVNode, v as getCurrentScope, w as markRaw, x as inject$1, y as h, z as renderList } from "./chunks/_plugin-vue_export-helper-7ZiLY07t.es.js";
@@ -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.28.0-next.6";
261
+ return "2.28.0-next.8";
262
262
  } catch {
263
263
  return "unknown";
264
264
  }
@@ -7186,16 +7186,6 @@ function createDefaultV2Integration() {
7186
7186
  return createStubV2Integration();
7187
7187
  }
7188
7188
  }
7189
- /**
7190
- * Backwards-compatible alias. The v2 branch no longer reads any customer
7191
- * config; the parameter is ignored and retained only so existing call sites do
7192
- * not need to change in lockstep with this internalization.
7193
- *
7194
- * @returns {SuperDocV2Integration}
7195
- */
7196
- function resolveV2Integration() {
7197
- return createDefaultV2Integration();
7198
- }
7199
7189
  //#endregion
7200
7190
  //#region src/helpers/interaction-trace.js
7201
7191
  function safeTraceCollector() {
@@ -7754,6 +7744,7 @@ var useCommentsStore = defineStore("comments", () => {
7754
7744
  const instantSidebarAlignmentInstanceId = ref(null);
7755
7745
  const pendingComment = ref(null);
7756
7746
  const pendingV2CommentTarget = shallowRef$1(null);
7747
+ let pendingCommentRequest = 0;
7757
7748
  const isViewingMode = computed$1(() => viewingVisibility.documentMode === "viewing");
7758
7749
  const shouldRenderReviewInViewing = computed$1(() => {
7759
7750
  if (!isViewingMode.value) return true;
@@ -7761,6 +7752,7 @@ var useCommentsStore = defineStore("comments", () => {
7761
7752
  });
7762
7753
  const v2CommentsAdapter = shallowRef$1(null);
7763
7754
  const setV2CommentsAdapter = (adapter) => {
7755
+ if (v2CommentsAdapter.value !== (adapter ?? null)) pendingCommentRequest += 1;
7764
7756
  v2CommentsAdapter.value = adapter ?? null;
7765
7757
  };
7766
7758
  const getV2CommentsAdapter = (superdoc) => {
@@ -8619,26 +8611,41 @@ var useCommentsStore = defineStore("comments", () => {
8619
8611
  }
8620
8612
  if (typeof currentSelection !== "function") return null;
8621
8613
  try {
8622
- return currentSelection();
8614
+ const snapshot = currentSelection();
8615
+ return typeof snapshot?.then === "function" ? Promise.resolve(snapshot).catch(() => null) : snapshot;
8623
8616
  } catch {
8624
8617
  return null;
8625
8618
  }
8626
8619
  };
8627
8620
  const showAddComment = (superdoc, targetClientY = null) => {
8621
+ const request = ++pendingCommentRequest;
8622
+ const editor = superdoc?.activeEditor;
8628
8623
  const v2Adapter = getV2CommentsAdapter(superdoc);
8629
- const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8630
- const event = {
8631
- type: COMMENT_EVENTS.PENDING,
8632
- pendingSelection
8624
+ const ownsRequest = () => pendingCommentRequest === request;
8625
+ const emitPending = (snapshot) => {
8626
+ if (!ownsRequest()) return;
8627
+ superdoc.emit("comments-update", {
8628
+ type: COMMENT_EVENTS.PENDING,
8629
+ pendingSelection: superdoc?.activeEditor === editor ? snapshot : null
8630
+ });
8633
8631
  };
8634
- superdoc.emit("comments-update", event);
8635
8632
  if (v2Adapter) {
8636
8633
  const cap = v2Adapter.getCapabilityState?.();
8637
8634
  if (cap && cap.canWrite === false) return {
8638
8635
  ok: false,
8639
8636
  reason: cap.reason
8640
8637
  };
8641
- return Promise.resolve(v2Adapter.captureCurrentSelection?.()).then((capture) => {
8638
+ return Promise.resolve(v2Adapter.captureCurrentSelection?.({ beforeReady: (snapshot) => {
8639
+ if (superdoc?.activeEditor === editor && getV2CommentsAdapter(superdoc) === v2Adapter) emitPending(snapshot);
8640
+ } })).then((capture) => {
8641
+ if (!ownsRequest()) return {
8642
+ ok: false,
8643
+ reason: "pending-comment-superseded"
8644
+ };
8645
+ if (superdoc?.activeEditor !== editor || getV2CommentsAdapter(superdoc) !== v2Adapter) return {
8646
+ ok: false,
8647
+ reason: "document-replaced"
8648
+ };
8642
8649
  if (!capture?.ok) return {
8643
8650
  ok: false,
8644
8651
  reason: capture?.reason ?? "editing-range-required",
@@ -8667,25 +8674,52 @@ var useCommentsStore = defineStore("comments", () => {
8667
8674
  detail: err?.message ?? String(err)
8668
8675
  }));
8669
8676
  }
8670
- const selection = { ...superdocStore.activeSelection };
8671
- selection.selectionBounds = { ...selection.selectionBounds };
8672
- if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
8673
- pendingComment.value = getPendingComment({
8674
- selection,
8675
- documentId: selection.documentId,
8676
- parentCommentId: null
8677
- });
8678
- if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8679
- if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8680
- ...pendingComment.value.getValues(),
8681
- commentId: "pending",
8682
- skipEmit: true
8683
- });
8684
- if (pendingComment.value.selection.source === "document-editor" && superdocStore.selectionPosition) superdocStore.selectionPosition.source = DOCUMENT_EDITOR_SELECTION_SOURCE;
8685
- requestInstantSidebarAlignment(targetClientY, "pending");
8686
- setActiveFloatingCommentInstance(null);
8687
- activeComment.value = pendingComment.value.commentId;
8688
- return { ok: true };
8677
+ const pendingSelection = getPendingSelectionSnapshot(superdoc, superdocStore.activeSelection);
8678
+ const asyncSnapshot = typeof pendingSelection?.then === "function";
8679
+ if (!asyncSnapshot) emitPending(pendingSelection);
8680
+ const showLegacyPending = (selection) => {
8681
+ selection.selectionBounds = { ...selection.selectionBounds };
8682
+ if (superdocStore.selectionPosition?.source && superdocStore.selectionPosition.source !== "pdf") superdocStore.selectionPosition.source = null;
8683
+ pendingComment.value = getPendingComment({
8684
+ selection,
8685
+ documentId: selection.documentId,
8686
+ parentCommentId: null
8687
+ });
8688
+ if (!superdoc.config.isInternal) pendingComment.value.isInternal = false;
8689
+ if (superdoc.activeEditor?.commands) superdoc.activeEditor.commands.insertComment({
8690
+ ...pendingComment.value.getValues(),
8691
+ commentId: "pending",
8692
+ skipEmit: true
8693
+ });
8694
+ if (pendingComment.value.selection.source === "document-editor" && superdocStore.selectionPosition) superdocStore.selectionPosition.source = DOCUMENT_EDITOR_SELECTION_SOURCE;
8695
+ requestInstantSidebarAlignment(targetClientY, "pending");
8696
+ setActiveFloatingCommentInstance(null);
8697
+ activeComment.value = pendingComment.value.commentId;
8698
+ return { ok: true };
8699
+ };
8700
+ if (asyncSnapshot) {
8701
+ const selection = { ...superdocStore.activeSelection };
8702
+ selection.selectionBounds = { ...selection.selectionBounds };
8703
+ return pendingSelection.then((snapshot) => {
8704
+ if (!ownsRequest()) return {
8705
+ ok: false,
8706
+ reason: "pending-comment-superseded"
8707
+ };
8708
+ emitPending(snapshot);
8709
+ if (!ownsRequest()) return {
8710
+ ok: false,
8711
+ reason: "pending-comment-superseded"
8712
+ };
8713
+ return superdoc?.activeEditor === editor ? showLegacyPending(selection) : {
8714
+ ok: false,
8715
+ reason: "document-replaced"
8716
+ };
8717
+ });
8718
+ }
8719
+ return ownsRequest() ? showLegacyPending({ ...superdocStore.activeSelection }) : {
8720
+ ok: false,
8721
+ reason: "pending-comment-superseded"
8722
+ };
8689
8723
  };
8690
8724
  /**
8691
8725
  * Get the numeric position value for sorting a comment by document order.
@@ -8840,7 +8874,7 @@ var useCommentsStore = defineStore("comments", () => {
8840
8874
  *
8841
8875
  * @returns {void}
8842
8876
  */
8843
- const removePendingComment = (superdoc) => {
8877
+ const resetPendingCommentState = (superdoc, clearViewingSelection = true) => {
8844
8878
  const hadPending = !!pendingComment.value;
8845
8879
  currentCommentText.value = "";
8846
8880
  currentCommentMentions.value = [];
@@ -8849,13 +8883,17 @@ var useCommentsStore = defineStore("comments", () => {
8849
8883
  superdocStore.selectionPosition = null;
8850
8884
  if (hadPending) clearActiveCommentSelection();
8851
8885
  if (isV2EditorActive(superdoc)) {
8852
- if (hadPending && isViewingMode.value) try {
8886
+ if (hadPending && clearViewingSelection && isViewingMode.value) try {
8853
8887
  superdoc?.activeEditor?.host?.getHandles?.()?.selection?.clear?.();
8854
8888
  } catch {}
8855
8889
  return;
8856
8890
  }
8857
8891
  superdoc?.activeEditor?.commands?.removeComment({ commentId: "pending" });
8858
8892
  };
8893
+ const removePendingComment = (superdoc) => {
8894
+ pendingCommentRequest += 1;
8895
+ resetPendingCommentState(superdoc);
8896
+ };
8859
8897
  const getV2CreatedComment = ({ outcome, reconciled, documentId }) => {
8860
8898
  const createdId = normalizeCommentId(outcome?.createdCommentId);
8861
8899
  if (!createdId) return reconciled?.added ?? null;
@@ -8873,6 +8911,7 @@ var useCommentsStore = defineStore("comments", () => {
8873
8911
  const v2Adapter = !skipEditorUpdate && !isHydration ? getV2CommentsAdapter(superdoc) : null;
8874
8912
  if (v2Adapter && !comment.trackedChange) {
8875
8913
  const submittedPendingComment = pendingComment.value;
8914
+ const submittedPendingRequest = pendingCommentRequest;
8876
8915
  const text = normalizeV2CommentDraftText(submittedPendingComment ? currentCommentText.value : comment.commentText);
8877
8916
  const mentions = pendingComment.value ? currentCommentMentions.value : comment.mentions ?? [];
8878
8917
  const target = pendingComment.value ? pendingV2CommentTarget.value : null;
@@ -8921,9 +8960,11 @@ var useCommentsStore = defineStore("comments", () => {
8921
8960
  documentId: v2Adapter.documentId
8922
8961
  });
8923
8962
  const hadPendingComment = submittedPendingComment != null && pendingComment.value?.commentId === submittedPendingComment.commentId;
8924
- if (hadPendingComment) removePendingComment(superdoc);
8963
+ const ownsSubmittedRequest = pendingCommentRequest === submittedPendingRequest;
8964
+ if (hadPendingComment) if (ownsSubmittedRequest) removePendingComment(superdoc);
8965
+ else resetPendingCommentState(superdoc, false);
8925
8966
  const createdId = created?.commentId ?? null;
8926
- if (hadPendingComment && createdId) {
8967
+ if (hadPendingComment && ownsSubmittedRequest && createdId) {
8927
8968
  setActiveComment(superdoc, createdId);
8928
8969
  setActiveFloatingCommentInstance(createdId);
8929
8970
  }
@@ -13514,6 +13555,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
13514
13555
  };
13515
13556
  };
13516
13557
  const CLICK_OUTSIDE_IGNORED_SELECTORS = [
13558
+ ".superdoc__tools [data-id=\"is-tool\"]",
13517
13559
  ".comments-dropdown__option-label",
13518
13560
  ".comments-dropdown__menu",
13519
13561
  ".comments-dropdown__option",
@@ -14635,7 +14677,7 @@ var CommentDialog_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
14635
14677
  ], 64))], 14, _hoisted_1$26)), [[_directive_click_outside, handleClickOutside]]);
14636
14678
  };
14637
14679
  }
14638
- }, [["__scopeId", "data-v-05d27982"]]);
14680
+ }, [["__scopeId", "data-v-f8b79c74"]]);
14639
14681
  //#endregion
14640
14682
  //#region src/components/CommentsLayer/commentsList/ReviewDirectoryListItem.vue
14641
14683
  var _hoisted_1$25 = [
@@ -15358,6 +15400,80 @@ var composeAuthorColorResolver = (config) => {
15358
15400
  };
15359
15401
  };
15360
15402
  //#endregion
15403
+ //#region ../document-api/src/errors.ts
15404
+ /**
15405
+ * Structured validation error thrown by document-api execute* functions.
15406
+ *
15407
+ * Consumers should prefer checking `error.code` over `instanceof` for resilience
15408
+ * across package boundaries and bundling scenarios.
15409
+ */
15410
+ var DocumentApiValidationError = class DocumentApiValidationError extends Error {
15411
+ constructor(code, message, details) {
15412
+ super(message);
15413
+ this.name = "DocumentApiValidationError";
15414
+ this.code = code;
15415
+ this.details = details;
15416
+ Object.setPrototypeOf(this, DocumentApiValidationError.prototype);
15417
+ }
15418
+ };
15419
+ //#endregion
15420
+ //#region ../document-api/src/export/export.types.ts
15421
+ /** Canonical tracked-change export modes accepted by every public export surface. */
15422
+ var SD_EXPORT_MODES = [
15423
+ "review-preserving",
15424
+ "final",
15425
+ "original"
15426
+ ];
15427
+ /** Default mode for modeful DOCX export. */
15428
+ var DEFAULT_SD_EXPORT_MODE = "review-preserving";
15429
+ var SD_COMMENT_EXPORT_POLICIES = [
15430
+ "preserve",
15431
+ "resolve",
15432
+ "remove"
15433
+ ];
15434
+ var SD_CONTENT_CONTROL_EXPORT_POLICIES = ["preserve", "flatten"];
15435
+ //#endregion
15436
+ //#region ../document-api/src/export/export.ts
15437
+ /**
15438
+ * Export namespace: engine-agnostic public API and adapter contract.
15439
+ *
15440
+ * Validates the requested mode at the public boundary so an invalid mode fails
15441
+ * closed with `INVALID_INPUT` before any document work happens, then delegates
15442
+ * byte production and degradation reporting to the engine adapter.
15443
+ */
15444
+ function resolveMode$1(input) {
15445
+ if (input != null && !isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "export.toDocx input must be an object.");
15446
+ const raw = input?.mode;
15447
+ if (raw === void 0) return DEFAULT_SD_EXPORT_MODE;
15448
+ if (typeof raw !== "string" || !SD_EXPORT_MODES.includes(raw)) throw new DocumentApiValidationError("INVALID_INPUT", `export.toDocx mode must be one of: ${SD_EXPORT_MODES.join(", ")}.`, {
15449
+ mode: raw,
15450
+ allowedModes: [...SD_EXPORT_MODES]
15451
+ });
15452
+ return raw;
15453
+ }
15454
+ function resolveDocxExportPolicies(input = {}) {
15455
+ if (!isRecord(input)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export input must be an object.");
15456
+ const mode = resolveMode$1(input);
15457
+ const policies = input.policies;
15458
+ if (policies !== void 0 && !isRecord(policies)) throw new DocumentApiValidationError("INVALID_INPUT", "DOCX export policies must be an object.");
15459
+ const allowed = {
15460
+ trackedChanges: SD_EXPORT_MODES,
15461
+ comments: SD_COMMENT_EXPORT_POLICIES,
15462
+ contentControls: SD_CONTENT_CONTROL_EXPORT_POLICIES
15463
+ };
15464
+ for (const [key, value] of Object.entries(policies ?? {})) if (!Object.prototype.hasOwnProperty.call(allowed, key) || value !== void 0 && !allowed[key].includes(value)) throw new DocumentApiValidationError("INVALID_INPUT", `Unsupported DOCX export policy: ${key}.`, {
15465
+ policy: key,
15466
+ value
15467
+ });
15468
+ const requested = policies;
15469
+ if (input.mode !== void 0 && requested?.trackedChanges !== void 0 && mode !== requested.trackedChanges) throw new DocumentApiValidationError("INVALID_INPUT", "mode conflicts with policies.trackedChanges.");
15470
+ return {
15471
+ trackedChanges: requested?.trackedChanges ?? mode,
15472
+ comments: requested?.comments ?? "preserve",
15473
+ contentControls: requested?.contentControls ?? "preserve"
15474
+ };
15475
+ }
15476
+ //#endregion
15361
15477
  //#region ../document-api/src/permission-ranges/permission-ranges.ts
15362
15478
  function editorKey(editor) {
15363
15479
  return editor.id?.trim() ? editor.id : editor.email?.trim() || void 0;
@@ -20095,6 +20211,28 @@ function useLinkPopover({ getSurfaceManager, getActiveEditor, getUi, getActivati
20095
20211
  };
20096
20212
  }
20097
20213
  //#endregion
20214
+ //#region src/core/helpers/resolve-docx-export.ts
20215
+ function resolveV2DocxExportOptions(options = {}) {
20216
+ const policies = resolveDocxExportPolicies({ policies: options.policies });
20217
+ if (options.isFinalDoc !== void 0) {
20218
+ if (typeof options.isFinalDoc !== "boolean") throw new DocumentApiValidationError("INVALID_INPUT", "isFinalDoc must be a boolean.");
20219
+ const legacy = options.isFinalDoc ? "final" : "review-preserving";
20220
+ if (options.policies?.trackedChanges !== void 0 && policies.trackedChanges !== legacy) throw new DocumentApiValidationError("INVALID_INPUT", "isFinalDoc conflicts with policies.trackedChanges.");
20221
+ policies.trackedChanges = legacy;
20222
+ }
20223
+ if (options.commentsType !== void 0) {
20224
+ if (options.commentsType !== "external" && options.commentsType !== "clean") throw new DocumentApiValidationError("INVALID_INPUT", "commentsType must be external or clean.");
20225
+ const legacy = options.commentsType === "clean" ? "remove" : "preserve";
20226
+ if (options.policies?.comments !== void 0 && policies.comments !== legacy) throw new DocumentApiValidationError("INVALID_INPUT", "commentsType conflicts with policies.comments.");
20227
+ policies.comments = legacy;
20228
+ }
20229
+ return {
20230
+ mode: policies.trackedChanges,
20231
+ commentExportMode: policies.comments === "remove" ? "strip" : policies.comments,
20232
+ contentControlExportMode: policies.contentControls
20233
+ };
20234
+ }
20235
+ //#endregion
20098
20236
  //#region src/core/editor-runtime/v2/v2-editor-runtime-adapter.ts
20099
20237
  var DEFAULT_V2_LEGACY_PROJECTION = Object.freeze({
20100
20238
  editorVersion: 2,
@@ -20734,7 +20872,7 @@ function createV2EditorRuntimeAdapter(options) {
20734
20872
  save: () => host.save(),
20735
20873
  exportDocx: (options) => host.save({
20736
20874
  format: "docx",
20737
- commentExportMode: options?.commentsType === "clean" ? "strip" : "preserve"
20875
+ ...resolveV2DocxExportOptions(options)
20738
20876
  }),
20739
20877
  async setZoom(percent) {
20740
20878
  const result = host.setZoom(percent);
@@ -21981,7 +22119,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
21981
22119
  const { proxy } = getCurrentInstance();
21982
22120
  commentsStore.proxy = proxy;
21983
22121
  const documentOpenTelemetry = createDocumentOpenTelemetry(proxy.$superdoc.config);
21984
- const resolvedEditorIntegration = resolveV2Integration(proxy.$superdoc.config);
22122
+ const resolvedEditorIntegration = createDefaultV2Integration();
21985
22123
  const V2DocumentEditor = markRaw(resolvedEditorIntegration.EditorComponent);
21986
22124
  const V2Ruler = resolvedEditorIntegration.RulerComponent ? markRaw(resolvedEditorIntegration.RulerComponent) : null;
21987
22125
  const floatingComments = computed$1(() => {
@@ -22127,6 +22265,10 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22127
22265
  return layers.value.getBoundingClientRect().top + top * zoom;
22128
22266
  };
22129
22267
  const handleCommentToolClick = async () => {
22268
+ if (isV2Mode.value) {
22269
+ cancelScheduledV2DomSelectionSync();
22270
+ if (applyCurrentV2DomSelection()?.ok === false) return;
22271
+ }
22130
22272
  if ((await showAddComment(proxy.$superdoc, getPendingCommentTargetClientY()))?.ok === false) return;
22131
22273
  if (!isV2Mode.value) return;
22132
22274
  const pendingPosition = buildV2PendingPositionEntry();
@@ -22399,10 +22541,9 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22399
22541
  return host.save(saveOptions);
22400
22542
  });
22401
22543
  const exportV2Docx = async (options = {}) => {
22402
- const commentExportMode = options?.commentsType === "clean" ? "strip" : "preserve";
22403
22544
  const bytes = await saveV2Bytes({
22404
22545
  format: "docx",
22405
- commentExportMode
22546
+ ...resolveV2DocxExportOptions(options)
22406
22547
  });
22407
22548
  return new Blob([bytes], { type: DOCX });
22408
22549
  };
@@ -22677,6 +22818,9 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22677
22818
  subscribe: (listener) => v2ReviewWindowController.subscribe?.(listener) ?? (() => void 0)
22678
22819
  },
22679
22820
  extensions: createV2ExtensionsFacet(host),
22821
+ get visuals() {
22822
+ return typeof host?.getHostVisuals === "function" ? host.getHostVisuals() : null;
22823
+ },
22680
22824
  fonts: fonts ?? host?.getFontRuntime?.() ?? null,
22681
22825
  /**
22682
22826
  * The v2 active-editor facade explicitly does NOT carry v1 commands /
@@ -22842,7 +22986,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
22842
22986
  const result = handles?.selection?.applyDomSelection?.(selection);
22843
22987
  if (!result?.ok || result.mode !== "range") {
22844
22988
  clearV2SelectionToolbarState();
22845
- return;
22989
+ return { ok: false };
22846
22990
  }
22847
22991
  v2DomMirroredRange.value = true;
22848
22992
  v2HasRangeSelection.value = true;
@@ -23495,6 +23639,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
23495
23639
  emitCommentPositionsInViewing: isViewingMode() && shouldRenderCommentsInViewing.value,
23496
23640
  enableCommentsInViewing: isViewingCommentsVisible.value,
23497
23641
  contentControlsChrome: proxy.$superdoc.uiConfig.contentControls.options.chrome,
23642
+ commentHighlights: proxy.$superdoc.uiConfig.comments.highlights,
23498
23643
  resolveTrackedChangeColor: composeAuthorColorResolver(proxy.$superdoc.config.modules?.trackChanges?.authorColors)
23499
23644
  } : void 0,
23500
23645
  permissionResolver: createTrackedChangePermissionResolver(proxy.$superdoc)
@@ -24549,7 +24694,7 @@ var SuperDoc_default = /*#__PURE__*/ _plugin_vue_export_helper_default({
24549
24694
  ], 46, _hoisted_1$17);
24550
24695
  };
24551
24696
  }
24552
- }, [["__scopeId", "data-v-2fc1721f"]]);
24697
+ }, [["__scopeId", "data-v-f2db957f"]]);
24553
24698
  //#endregion
24554
24699
  //#region src/core/create-app.js
24555
24700
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -38011,6 +38156,11 @@ var COMMENT_POLICY_FIELDS = Object.freeze([
38011
38156
  "allowResolve",
38012
38157
  "permissionResolver"
38013
38158
  ]);
38159
+ function withoutSwitches(options) {
38160
+ if (!("panel" in options) && !("highlights" in options)) return options;
38161
+ const { panel: _panel, highlights: _highlights, ...rest } = options;
38162
+ return rest;
38163
+ }
38014
38164
  /**
38015
38165
  * Drop policy fields from a presentation options bag.
38016
38166
  */
@@ -38355,8 +38505,9 @@ function normalizeUiConfig(config = {}) {
38355
38505
  }
38356
38506
  },
38357
38507
  comments: {
38358
- enabled: explicit("comments") ?? (!allDisabled && config.modules?.comments !== false),
38359
- options: allDisabled ? {} : normalizeCommentsUiConfig(withoutCommentPolicy(options("comments"))) || {}
38508
+ enabled: (explicit("comments") ?? (!allDisabled && config.modules?.comments !== false)) && options("comments").panel !== false,
38509
+ highlights: options("comments").highlights !== false,
38510
+ options: allDisabled ? {} : normalizeCommentsUiConfig(withoutCommentPolicy(withoutSwitches(options("comments")))) || {}
38360
38511
  },
38361
38512
  contextMenu: {
38362
38513
  enabled: explicit("contextMenu") ?? (!allDisabled && config.disableContextMenu !== true),
@@ -41480,9 +41631,6 @@ var TABLE_ACTION_COMMAND_MAP = {
41480
41631
  fixTables: "table-fix"
41481
41632
  };
41482
41633
  var TABLE_ACTION_COMMAND_IDS = Object.values(TABLE_ACTION_COMMAND_MAP);
41483
- [.../* @__PURE__ */ new Set([...Object.values(HEADLESS_ITEM_MAP), ...TABLE_ACTION_COMMAND_IDS])];
41484
- var NON_HEADLESS_EXECUTE_ITEM_NAMES = /* @__PURE__ */ new Set(["link"]);
41485
- new Set(Object.keys(HEADLESS_ITEM_MAP).filter((itemName) => !NON_HEADLESS_EXECUTE_ITEM_NAMES.has(itemName)));
41486
41634
  //#endregion
41487
41635
  //#region src/internal/toolbar/built-in/Toolbar.vue
41488
41636
  var _hoisted_1$10 = ["data-superdoc-ui-owner"];
@@ -46246,7 +46394,7 @@ var SuperDoc = class extends import_eventemitter3.default {
46246
46394
  }
46247
46395
  this.userColorMap = /* @__PURE__ */ new Map();
46248
46396
  this.colorIndex = 0;
46249
- this.version = "2.28.0-next.6";
46397
+ this.version = "2.28.0-next.8";
46250
46398
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
46251
46399
  this.superdocId = config.superdocId || v4();
46252
46400
  this.colors = this.config.colors ?? [];
@@ -48200,12 +48348,13 @@ var SuperDoc = class extends import_eventemitter3.default {
48200
48348
  * Export the superdoc to a file
48201
48349
  * @param params - Export configuration
48202
48350
  */
48203
- async export({ exportType = ["docx"], commentsType = "external", exportedName, additionalFiles = [], additionalFileNames = [], isFinalDoc = false, triggerDownload = true, fieldsHighlightColor = null } = {}) {
48351
+ async export({ exportType = ["docx"], commentsType, exportedName, additionalFiles = [], additionalFileNames = [], isFinalDoc, policies, triggerDownload = true, fieldsHighlightColor = null } = {}) {
48204
48352
  if (!Array.isArray(exportType) || exportType.length !== 1 || exportType[0] !== "docx") throw new TypeError("SuperDoc.export() only supports exportType: [\"docx\"].");
48205
48353
  const baseFileName = exportedName ? cleanName(exportedName) : cleanName(this.config.title);
48206
48354
  const docxFiles = await this.exportEditorsToDOCX({
48207
48355
  commentsType,
48208
48356
  isFinalDoc,
48357
+ policies,
48209
48358
  fieldsHighlightColor
48210
48359
  });
48211
48360
  const blobsToZip = [...additionalFiles];
@@ -48291,7 +48440,12 @@ var SuperDoc = class extends import_eventemitter3.default {
48291
48440
  * Export editors to DOCX format.
48292
48441
  * @param [options]
48293
48442
  */
48294
- async exportEditorsToDOCX({ commentsType, isFinalDoc, fieldsHighlightColor } = {}) {
48443
+ async exportEditorsToDOCX({ commentsType, isFinalDoc, policies, fieldsHighlightColor } = {}) {
48444
+ if (policies !== void 0) resolveV2DocxExportOptions({
48445
+ policies,
48446
+ commentsType,
48447
+ isFinalDoc
48448
+ });
48295
48449
  const uiStoreHydrated = this.config?.modules?.comments !== false;
48296
48450
  let legacyComments;
48297
48451
  let legacyCommentsComputed = false;
@@ -48311,7 +48465,13 @@ var SuperDoc = class extends import_eventemitter3.default {
48311
48465
  };
48312
48466
  this.on("exception", rememberBridgedExportError);
48313
48467
  try {
48314
- const docxPromises = this.#requireSuperdocStore("exportEditorsToDOCX").documents.map(async (doc) => {
48468
+ const documents = this.#requireSuperdocStore("exportEditorsToDOCX").documents;
48469
+ if (policies !== void 0 && documents.some((doc) => {
48470
+ if (doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return false;
48471
+ const editor = doc.getEditor?.();
48472
+ return editor?.editorVersion !== 2 || typeof editor.exportDocx !== "function";
48473
+ })) throw new Error("Independent DOCX export policies require a mounted V2 exporter for every document.");
48474
+ const docxPromises = documents.map(async (doc) => {
48315
48475
  if (!doc || doc.type !== "application/vnd.openxmlformats-officedocument.wordprocessingml.document") return null;
48316
48476
  const editor = typeof doc.getEditor === "function" ? doc.getEditor() : null;
48317
48477
  const fallbackDocx = () => {
@@ -48328,6 +48488,7 @@ var SuperDoc = class extends import_eventemitter3.default {
48328
48488
  const exported = await editor.exportDocx(isV2Editor ? {
48329
48489
  isFinalDoc,
48330
48490
  commentsType,
48491
+ policies,
48331
48492
  fieldsHighlightColor
48332
48493
  } : {
48333
48494
  isFinalDoc,
@@ -48656,4 +48817,8 @@ function defineSuperDocExtension(extension) {
48656
48817
  return extension;
48657
48818
  }
48658
48819
  //#endregion
48659
- export { blank_default as BlankDOCX, DOCX, DocumentLoadError, HTML, PDF, SuperDoc, buildTheme, compareVersions, createTheme, defineSuperDocExtension, getFileObject, listPermissionRangeEditors, resolvePermissionRangeEditor };
48820
+ //#region src/public/index.ts
48821
+ /** URL to the blank DOCX template. */
48822
+ var BlankDOCX = blank_default;
48823
+ //#endregion
48824
+ export { BlankDOCX, DOCX, DocumentLoadError, HTML, PDF, SuperDoc, buildTheme, compareVersions, createTheme, defineSuperDocExtension, getFileObject, listPermissionRangeEditors, resolvePermissionRangeEditor };
@@ -90,6 +90,7 @@ export type WordListMarkerLayout = {
90
90
  run: ResolvedRunProperties;
91
91
  };
92
92
  export type WordParagraphLayoutOutput = {
93
+ textStartMode?: 'paragraph';
93
94
  indentLeftPx: number;
94
95
  hangingPx: number;
95
96
  firstLinePx?: number;