superdoc 2.28.0-next.9 → 2.29.0-next.1

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 (94) hide show
  1. package/dist/chunks/{FindReplaceSurface-8V8AjgR4.cjs → FindReplaceSurface-BRs3JrCq.cjs} +1 -1
  2. package/dist/chunks/{FindReplaceSurface-RUiTFDt3.es.js → FindReplaceSurface-Dm043CZP.es.js} +1 -1
  3. package/dist/chunks/{PasswordPromptSurface-B5DHV6qr.cjs → PasswordPromptSurface-BpqP4pUa.cjs} +1 -1
  4. package/dist/chunks/{PasswordPromptSurface-BDpxqdzp.es.js → PasswordPromptSurface-DGjmN7A-.es.js} +1 -1
  5. package/dist/chunks/{PdfViewer-DjdsIh6n.es.js → PdfViewer-D4lVeOJu.es.js} +4 -3
  6. package/dist/chunks/{PdfViewer-omriDChK.cjs → PdfViewer-boENOZdF.cjs} +4 -3
  7. package/dist/chunks/{_plugin-vue_export-helper-BUdjGKyl.cjs → _plugin-vue_export-helper-6MBoygIY.cjs} +9 -0
  8. package/dist/chunks/{_plugin-vue_export-helper-7ZiLY07t.es.js → _plugin-vue_export-helper-CsJQtMvr.es.js} +4 -1
  9. package/dist/chunks/{create-super-doc-ui-B4c55pFy.cjs → create-super-doc-ui-0OA8hCNb.cjs} +390 -44
  10. package/dist/chunks/{create-super-doc-ui-C4Ka5Ph3.es.js → create-super-doc-ui-Duf65d0b.es.js} +357 -41
  11. package/dist/chunks/is-finite-number-BEXgTRgc.cjs +11 -0
  12. package/dist/chunks/is-finite-number-BpL4F38c.es.js +6 -0
  13. package/dist/collaboration-upgrade-engine.cjs +1 -1
  14. package/dist/collaboration-upgrade-engine.es.js +1 -1
  15. package/dist/document-api/src/capabilities/html-markdown-support.d.ts +3 -3
  16. package/dist/document-api/src/contract/operation-definitions.d.ts +2 -2
  17. package/dist/document-api/src/index.d.ts +1 -1
  18. package/dist/document-api/src/lists/lists.d.ts +79 -79
  19. package/dist/document-api/src/lists/lists.types.d.ts +1 -0
  20. package/dist/document-api/src/sections/sections.types.d.ts +5 -1
  21. package/dist/document-api/src/types/clipboard.d.ts +5 -1
  22. package/dist/document-api/src/types/receipt.d.ts +2 -1
  23. package/dist/document-api/src/write/write.d.ts +10 -9
  24. package/dist/layout-engine/contracts/src/index.d.ts +5 -1
  25. package/dist/layout-engine/contracts/src/run-helpers.d.ts +1 -0
  26. package/dist/layout-engine/layout-bridge/src/index.d.ts +1 -0
  27. package/dist/layout-engine/layout-bridge/src/place-inline-drawings.d.ts +9 -0
  28. package/dist/layout-engine/layout-engine/src/layout-drawing.d.ts +2 -1
  29. package/dist/layout-engine/layout-engine/src/paginator.d.ts +1 -0
  30. package/dist/layout-engine/painters/dom/src/page-content.d.ts +1 -1
  31. package/dist/layout-engine/painters/dom/src/persistent-page-surface.d.ts +2 -0
  32. package/dist/layout-engine/style-engine/src/ooxml/index.d.ts +1 -1
  33. package/dist/public/ui-react.cjs +1 -1
  34. package/dist/public/ui-react.es.js +1 -1
  35. package/dist/public/ui-vue.cjs +1 -1
  36. package/dist/public/ui-vue.es.js +1 -1
  37. package/dist/public/ui.cjs +3 -2
  38. package/dist/public/ui.es.js +3 -2
  39. package/dist/shared/font-system/src/resolver.d.ts +3 -3
  40. package/dist/style.css +1 -1
  41. package/dist/style.layered.css +1 -1
  42. package/dist/superdoc/src/SuperDoc.vue.d.ts +5 -3
  43. package/dist/superdoc/src/components/CommentsLayer/CommentDialog.vue.d.ts +1670 -24
  44. package/dist/superdoc/src/components/CommentsLayer/CommentHeader.vue.d.ts +2 -2
  45. package/dist/superdoc/src/components/CommentsLayer/CommentInput.vue.d.ts +2 -2
  46. package/dist/superdoc/src/components/CommentsLayer/FloatingComments.vue.d.ts +24 -0
  47. package/dist/superdoc/src/components/CommentsLayer/PdfCommentsLayer.vue.d.ts +4 -0
  48. package/dist/superdoc/src/components/general/Avatar.vue.d.ts +7 -0
  49. package/dist/superdoc/src/components/surfaces/SurfaceDialog.vue.d.ts +27 -9
  50. package/dist/superdoc/src/components/surfaces/SurfaceExternalMount.vue.d.ts +53 -16
  51. package/dist/superdoc/src/composables/use-high-contrast-mode.d.ts +8 -4
  52. package/dist/superdoc/src/composables/use-link-popover.d.ts +3 -3
  53. package/dist/superdoc/src/composables/use-superdoc-instance.d.ts +10 -0
  54. package/dist/superdoc/src/core/SuperDoc.d.ts +2 -6
  55. package/dist/superdoc/src/core/collaboration/helpers.d.ts +0 -5
  56. package/dist/superdoc/src/core/collaboration/permissions.d.ts +1 -0
  57. package/dist/superdoc/src/core/collaboration/resolve-v2-collaboration-target.d.ts +2 -1
  58. package/dist/superdoc/src/core/create-app.d.ts +2 -6
  59. package/dist/superdoc/src/core/editor-runtime/types.d.ts +2 -0
  60. package/dist/superdoc/src/core/editor-runtime/v2/v2-editor-runtime-adapter.d.ts +2 -0
  61. package/dist/superdoc/src/core/types/index.d.ts +10 -4
  62. package/dist/superdoc/src/core/v2-integration/internal-vue-runtime.d.ts +1 -0
  63. package/dist/superdoc/src/core/v2-integration/v2-integration.d.ts +104 -84
  64. package/dist/superdoc/src/helpers/is-finite-number.d.ts +1 -0
  65. package/dist/superdoc/src/helpers/v2-review-mutation-impact.d.ts +2 -0
  66. package/dist/superdoc/src/internal/diagnostics/diagnostic-dedupe.d.ts +2 -2
  67. package/dist/superdoc/src/internal/diagnostics/translate-diagnostic.d.ts +5 -0
  68. package/dist/superdoc/src/internal/toolbar/built-in/AIWriter.vue.d.ts +2 -2
  69. package/dist/superdoc/src/internal/toolbar/built-in/LinkInput.vue.d.ts +181 -36
  70. package/dist/superdoc/src/internal/toolbar/built-in/LinkedStyle.vue.d.ts +39 -10
  71. package/dist/superdoc/src/internal/toolbar/built-in/PageNumberMenu.vue.d.ts +133 -22
  72. package/dist/superdoc/src/internal/toolbar/built-in/SdTooltip.vue.d.ts +62 -23
  73. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButton.vue.d.ts +101 -16
  74. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarButtonIcon.vue.d.ts +31 -10
  75. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarComboBox.vue.d.ts +82 -11
  76. package/dist/superdoc/src/internal/toolbar/built-in/ToolbarDropdown.vue.d.ts +122 -33
  77. package/dist/superdoc/src/internal/toolbar/built-in/constants.d.ts +0 -48
  78. package/dist/superdoc/src/internal/toolbar/built-in/use-toolbar-item.d.ts +0 -1
  79. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +4 -1
  80. package/dist/superdoc/src/internal/toolbar/compatibility-catalog.d.ts +16 -0
  81. package/dist/superdoc/src/public/ui/types.d.ts +39 -1
  82. package/dist/superdoc/src/public/ui.d.cts +12 -0
  83. package/dist/superdoc/src/public/ui.d.ts +1 -1
  84. package/dist/superdoc/src/stores/comments-store.d.ts +158 -125
  85. package/dist/superdoc/src/stores/superdoc-store.d.ts +475 -376
  86. package/dist/superdoc.cjs +561 -1843
  87. package/dist/superdoc.es.js +766 -13144
  88. package/dist-cdn/style.layered.css +1 -1
  89. package/dist-cdn/superdoc.min.css +1 -1
  90. package/dist-cdn/superdoc.min.js +42 -42
  91. package/package.json +4 -3
  92. package/dist/superdoc/src/core/collaboration/collaboration.d.ts +0 -18
  93. package/dist/superdoc/src/helpers/group-changes.d.ts +0 -1
  94. package/dist/superdoc/src/internal/toolbar/built-in/OverflowMenu.vue.d.ts +0 -104
@@ -1,4 +1,5 @@
1
- const require__plugin_vue_export_helper = require("./_plugin-vue_export-helper-BUdjGKyl.cjs");
1
+ const require__plugin_vue_export_helper = require("./_plugin-vue_export-helper-6MBoygIY.cjs");
2
+ const require_is_finite_number = require("./is-finite-number-BEXgTRgc.cjs");
2
3
  //#region src/internal/diagnostics/workflow-recording.ts
3
4
  var fields$1 = /* @__PURE__ */ new Set([
4
5
  "documentId",
@@ -1087,6 +1088,172 @@ function isSyntheticTrackedChangeCommentLaneItem(item) {
1087
1088
  return typeof itemId === "string" && itemId.startsWith(TRACKED_CHANGE_COMMENT_LANE_ID_PREFIX);
1088
1089
  }
1089
1090
  //#endregion
1091
+ //#region src/helpers/object-guards.js
1092
+ /**
1093
+ * @param {unknown} value
1094
+ * @returns {value is Record<string, unknown>}
1095
+ */
1096
+ function isPlainObject(value) {
1097
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1098
+ }
1099
+ //#endregion
1100
+ //#region src/core/collaboration/permissions.js
1101
+ var PERMISSIONS = Object.freeze({
1102
+ RESOLVE_OWN: "RESOLVE_OWN",
1103
+ RESOLVE_OTHER: "RESOLVE_OTHER",
1104
+ REJECT_OWN: "REJECT_OWN",
1105
+ REJECT_OTHER: "REJECT_OTHER",
1106
+ COMMENTS_OVERFLOW_OWN: "COMMENTS_OVERFLOW",
1107
+ COMMENTS_OVERFLOW_OTHER: "COMMENTS_OVERFLOW_OTHER",
1108
+ COMMENTS_DELETE_OWN: "COMMENTS_DELETE_OWN",
1109
+ COMMENTS_DELETE_OTHER: "COMMENTS_DELETE_OTHER",
1110
+ UPLOAD_VERSION: "UPLOAD_VERSION",
1111
+ VERSION_HISTORY: "VERSION_HISTORY"
1112
+ });
1113
+ var ROLES = Object.freeze({
1114
+ EDITOR: "editor",
1115
+ SUGGESTER: "suggester",
1116
+ VIEWER: "viewer"
1117
+ });
1118
+ var PERMISSION_MATRIX = Object.freeze({
1119
+ [PERMISSIONS.RESOLVE_OWN]: {
1120
+ internal: [ROLES.EDITOR],
1121
+ external: [ROLES.EDITOR]
1122
+ },
1123
+ [PERMISSIONS.RESOLVE_OTHER]: {
1124
+ internal: [ROLES.EDITOR],
1125
+ external: [ROLES.EDITOR]
1126
+ },
1127
+ [PERMISSIONS.REJECT_OWN]: {
1128
+ internal: [ROLES.EDITOR, ROLES.SUGGESTER],
1129
+ external: [ROLES.EDITOR, ROLES.SUGGESTER]
1130
+ },
1131
+ [PERMISSIONS.REJECT_OTHER]: {
1132
+ internal: [ROLES.EDITOR],
1133
+ external: [ROLES.EDITOR]
1134
+ },
1135
+ [PERMISSIONS.COMMENTS_OVERFLOW_OWN]: {
1136
+ internal: [ROLES.EDITOR, ROLES.SUGGESTER],
1137
+ external: [ROLES.EDITOR, ROLES.SUGGESTER]
1138
+ },
1139
+ [PERMISSIONS.COMMENTS_OVERFLOW_OTHER]: {
1140
+ internal: [ROLES.EDITOR],
1141
+ external: [ROLES.EDITOR]
1142
+ },
1143
+ [PERMISSIONS.COMMENTS_DELETE_OWN]: {
1144
+ internal: [ROLES.EDITOR, ROLES.SUGGESTER],
1145
+ external: [ROLES.EDITOR, ROLES.SUGGESTER]
1146
+ },
1147
+ [PERMISSIONS.COMMENTS_DELETE_OTHER]: {
1148
+ internal: [ROLES.EDITOR],
1149
+ external: [ROLES.EDITOR]
1150
+ },
1151
+ [PERMISSIONS.UPLOAD_VERSION]: {
1152
+ internal: [ROLES.EDITOR],
1153
+ external: []
1154
+ },
1155
+ [PERMISSIONS.VERSION_HISTORY]: {
1156
+ internal: [ROLES.EDITOR],
1157
+ external: []
1158
+ }
1159
+ });
1160
+ var pickResolver = (context = {}) => {
1161
+ if (typeof context.permissionResolver === "function") return context.permissionResolver;
1162
+ if (typeof context.superdoc?.config?.permissionResolver === "function") return context.superdoc.config.permissionResolver;
1163
+ const deprecatedResolver = context.superdoc?.config?.modules?.comments?.permissionResolver;
1164
+ if (typeof deprecatedResolver === "function") return deprecatedResolver;
1165
+ return null;
1166
+ };
1167
+ var BUILT_IN_PERMISSION_METHOD = Symbol.for("superdoc.internal.permission-method.builtin");
1168
+ var BUILT_IN_PERMISSION_RESOLVER = Symbol.for("superdoc.internal.permission-resolver.builtin");
1169
+ /** Create the shell's internal, live tracked-change permission shim. */
1170
+ var createTrackedChangePermissionResolver = (superdoc) => {
1171
+ const isBuiltInPolicy = () => superdoc.canPerformPermission?.[BUILT_IN_PERMISSION_METHOD] === true && pickResolver({ superdoc }) === null;
1172
+ const resolver = (payload = {}) => isBuiltInPolicy() ? defaultDecisionFor(payload.permission, superdoc.config.role, superdoc.config.isInternal) : superdoc.canPerformPermission({
1173
+ ...payload,
1174
+ role: superdoc.config.role,
1175
+ isInternal: superdoc.config.isInternal
1176
+ });
1177
+ Object.defineProperty(resolver, BUILT_IN_PERMISSION_RESOLVER, { value: isBuiltInPolicy });
1178
+ return resolver;
1179
+ };
1180
+ var defaultDecisionFor = (permission, role, isInternal) => {
1181
+ const internalExternal = isInternal ? "internal" : "external";
1182
+ return PERMISSION_MATRIX[permission]?.[internalExternal]?.includes(role) ?? false;
1183
+ };
1184
+ var NON_DATA_PERMISSION_PROPERTY = Symbol();
1185
+ var readPermissionDataProperty = (source, key) => {
1186
+ if (source == null) return void 0;
1187
+ if (typeof source !== "object" && typeof source !== "function") return NON_DATA_PERMISSION_PROPERTY;
1188
+ for (let owner = source; owner !== null; owner = Object.getPrototypeOf(owner)) {
1189
+ const descriptor = Object.getOwnPropertyDescriptor(owner, key);
1190
+ if (descriptor) return "value" in descriptor ? descriptor.value : NON_DATA_PERMISSION_PROPERTY;
1191
+ }
1192
+ };
1193
+ var readBuiltInTrackedChangePermissionDecision = (superdoc, canPerform, permission, trackedChange) => {
1194
+ try {
1195
+ if (readPermissionDataProperty(superdoc, "canPerformPermission") !== canPerform || readPermissionDataProperty(canPerform, BUILT_IN_PERMISSION_METHOD) !== true) return null;
1196
+ const config = readPermissionDataProperty(superdoc, "config");
1197
+ if (!config || typeof config !== "object") return null;
1198
+ const role = readPermissionDataProperty(config, "role");
1199
+ const isInternal = readPermissionDataProperty(config, "isInternal");
1200
+ const user = readPermissionDataProperty(config, "user");
1201
+ const resolver = readPermissionDataProperty(config, "permissionResolver");
1202
+ const modules = readPermissionDataProperty(config, "modules");
1203
+ const comments = readPermissionDataProperty(modules, "comments");
1204
+ const deprecatedResolver = readPermissionDataProperty(comments, "permissionResolver");
1205
+ const commentsStore = readPermissionDataProperty(superdoc, "commentsStore");
1206
+ if ([
1207
+ role,
1208
+ isInternal,
1209
+ user,
1210
+ resolver,
1211
+ modules,
1212
+ comments,
1213
+ deprecatedResolver,
1214
+ commentsStore,
1215
+ readPermissionDataProperty(commentsStore, "getComment"),
1216
+ readPermissionDataProperty(trackedChange, "comment"),
1217
+ readPermissionDataProperty(trackedChange, "commentId"),
1218
+ readPermissionDataProperty(trackedChange, "id")
1219
+ ].includes(NON_DATA_PERMISSION_PROPERTY) || typeof resolver === "function" || typeof deprecatedResolver === "function") return null;
1220
+ return defaultDecisionFor(permission, role, isInternal);
1221
+ } catch {
1222
+ return null;
1223
+ }
1224
+ };
1225
+ /**
1226
+ * Resolve a client-side permission through the built-in matrix and optional
1227
+ * resolver.
1228
+ *
1229
+ * @param {string} permission The permission to check
1230
+ * @param {string} role The role to check
1231
+ * @param {boolean} isInternal The internal/external flag
1232
+ * @param {object} [context] Context passed to the permission resolver
1233
+ * @param {object | null} [context.comment] The comment/tracked change being evaluated
1234
+ * @param {object | null} [context.superdoc] The SuperDoc instance
1235
+ * @param {object | null} [context.currentUser] The active user object performing the action
1236
+ * @param {Function} [context.permissionResolver] Explicit resolver override
1237
+ * @param {object | null} [context.trackedChange] Tracked change metadata (for tracked-change permissions)
1238
+ * @returns {boolean} Whether the permission is allowed
1239
+ */
1240
+ var isAllowed = (permission, role, isInternal, context = {}) => {
1241
+ const defaultDecision = defaultDecisionFor(permission, role, isInternal);
1242
+ const resolver = pickResolver(context);
1243
+ if (typeof resolver !== "function") return defaultDecision;
1244
+ const decision = resolver({
1245
+ permission,
1246
+ role,
1247
+ isInternal,
1248
+ defaultDecision,
1249
+ comment: context.comment ?? null,
1250
+ currentUser: context.currentUser ?? context.superdoc?.config?.user ?? null,
1251
+ superdoc: context.superdoc ?? null,
1252
+ trackedChange: context.trackedChange ?? null
1253
+ });
1254
+ return typeof decision === "boolean" ? decision : defaultDecision;
1255
+ };
1256
+ //#endregion
1090
1257
  //#region src/public/ui/viewport-batch.ts
1091
1258
  /** No rendering or scrolling: read only geometry already acknowledged by the host. */
1092
1259
  async function readViewportBatch(input, read, generation, disposed) {
@@ -2487,7 +2654,7 @@ function toStyleValue(key, value) {
2487
2654
  case "italic": return value === true;
2488
2655
  case "underline": return underlineValue(value);
2489
2656
  case "color": return typeof value === "string" && value.length > 0 ? { val: value.replace(/^#/, "") } : null;
2490
- case "fontSize": return typeof value === "number" && Number.isFinite(value) ? Math.round(value * 2) : null;
2657
+ case "fontSize": return require_is_finite_number.isFiniteNumber(value) ? Math.round(value * 2) : null;
2491
2658
  case "rFonts": return fontsValue(value);
2492
2659
  default: return null;
2493
2660
  }
@@ -2641,16 +2808,17 @@ function selectionKey(selection) {
2641
2808
  }
2642
2809
  }
2643
2810
  //#endregion
2644
- //#region src/helpers/object-guards.js
2645
- /**
2646
- * @param {unknown} value
2647
- * @returns {value is Record<string, unknown>}
2648
- */
2649
- function isPlainObject(value) {
2650
- return typeof value === "object" && value !== null && !Array.isArray(value);
2651
- }
2652
- //#endregion
2653
2811
  //#region src/helpers/v2-review-mutation-impact.ts
2812
+ function mutationCommittedEventChangedVisibleContent(event) {
2813
+ if (event.dryRun === true) return false;
2814
+ if (isPlainObject(event.result) && event.result.noop === true) return false;
2815
+ const receipt = isPlainObject(event.receipt) ? event.receipt : null;
2816
+ if (receipt?.changed === false || receipt?.noop === true || receipt?.status === "NO_OP") return false;
2817
+ return true;
2818
+ }
2819
+ function mutationCommittedEventChangedDocument(event) {
2820
+ return event.cause !== "preview" && mutationCommittedEventChangedVisibleContent(event);
2821
+ }
2654
2822
  /**
2655
2823
  * Classify the tracked-change identities carried by a v2 mutation event.
2656
2824
  *
@@ -2978,7 +3146,7 @@ function normalizeZoomPayload(payload) {
2978
3146
  if (!Number.isFinite(parsed)) return payload;
2979
3147
  return normalizeNumber(parsed, isPercent);
2980
3148
  }
2981
- if (typeof payload === "number" && Number.isFinite(payload)) return normalizeNumber(payload, false);
3149
+ if (require_is_finite_number.isFiniteNumber(payload)) return normalizeNumber(payload, false);
2982
3150
  return payload;
2983
3151
  }
2984
3152
  /**
@@ -5348,9 +5516,6 @@ var PARAGRAPH_INDENT_STEP_TWIPS = 720;
5348
5516
  function pointsToTwips(value) {
5349
5517
  return Math.round(value * 20);
5350
5518
  }
5351
- function isFiniteNumber(value) {
5352
- return typeof value === "number" && Number.isFinite(value);
5353
- }
5354
5519
  function readParagraphIndentationFromResult(result) {
5355
5520
  if (!result || typeof result !== "object") return null;
5356
5521
  const node = result.node;
@@ -5361,10 +5526,10 @@ function readParagraphIndentationFromResult(result) {
5361
5526
  const props = paragraphPayload.props;
5362
5527
  const indent = resolved?.indent ?? props?.indent;
5363
5528
  if (!indent || typeof indent !== "object") return null;
5364
- const left = isFiniteNumber(indent.left) ? pointsToTwips(indent.left) : isFiniteNumber(indent.start) ? pointsToTwips(indent.start) : void 0;
5365
- const right = isFiniteNumber(indent.right) ? pointsToTwips(indent.right) : isFiniteNumber(indent.end) ? pointsToTwips(indent.end) : void 0;
5366
- const firstLine = isFiniteNumber(indent.firstLine) ? pointsToTwips(indent.firstLine) : void 0;
5367
- const hanging = isFiniteNumber(indent.hanging) ? pointsToTwips(indent.hanging) : void 0;
5529
+ const left = require_is_finite_number.isFiniteNumber(indent.left) ? pointsToTwips(indent.left) : require_is_finite_number.isFiniteNumber(indent.start) ? pointsToTwips(indent.start) : void 0;
5530
+ const right = require_is_finite_number.isFiniteNumber(indent.right) ? pointsToTwips(indent.right) : require_is_finite_number.isFiniteNumber(indent.end) ? pointsToTwips(indent.end) : void 0;
5531
+ const firstLine = require_is_finite_number.isFiniteNumber(indent.firstLine) ? pointsToTwips(indent.firstLine) : void 0;
5532
+ const hanging = require_is_finite_number.isFiniteNumber(indent.hanging) ? pointsToTwips(indent.hanging) : void 0;
5368
5533
  if (left == null && right == null && firstLine == null && hanging == null) return null;
5369
5534
  return {
5370
5535
  ...left != null ? { left } : {},
@@ -5654,7 +5819,7 @@ function normalizeLayoutFontFamily(value) {
5654
5819
  }
5655
5820
  /** Convert a resolved run font size in CSS px to the toolbar's point value (SD-3652). */
5656
5821
  function normalizeLayoutFontSizePt(value) {
5657
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
5822
+ if (!require_is_finite_number.isFiniteNumber(value) || value <= 0) return void 0;
5658
5823
  const pt = Math.round(value * .75 * 2) / 2;
5659
5824
  if (pt <= 0) return void 0;
5660
5825
  return String(pt);
@@ -5763,17 +5928,42 @@ function commandResultFromOperationResult(result) {
5763
5928
  function isSuccessfulReceipt(result) {
5764
5929
  return Boolean(result) && typeof result === "object" && result.success === true;
5765
5930
  }
5766
- /**
5767
- * The host also emits `mutation:committed` for previews and no-op receipts;
5768
- * those events must not mark the document as having unsaved edits.
5769
- */
5770
- function mutationCommittedEventChangedDocument(event) {
5771
- if (event.dryRun === true) return false;
5772
- const receipt = event.receipt;
5773
- if (receipt && typeof receipt === "object" && receipt.changed === false) return false;
5774
- if (receipt && typeof receipt === "object" && receipt.noop === true) return false;
5775
- if (receipt && typeof receipt === "object" && receipt.status === "NO_OP") return false;
5776
- return true;
5931
+ function readTxId(value) {
5932
+ return typeof value === "string" && value.length > 0 ? value : null;
5933
+ }
5934
+ function documentChangeScope(stories) {
5935
+ return Array.isArray(stories) && stories.length > 0 ? {
5936
+ kind: "known",
5937
+ stories
5938
+ } : { kind: "unknown" };
5939
+ }
5940
+ function documentChangeFromHostEvent(event) {
5941
+ if (event.type === "collaboration:remote-changed") return {
5942
+ cause: "remote",
5943
+ changeTag: null,
5944
+ txId: null,
5945
+ scope: { kind: "unknown" }
5946
+ };
5947
+ if (event.type !== "mutation:committed") return null;
5948
+ if (event.origin === "history") {
5949
+ const result = isPlainObject(event.result) ? event.result : null;
5950
+ if (!result || result.noop === true) return null;
5951
+ const history = isPlainObject(result.history) ? result.history : null;
5952
+ return {
5953
+ cause: event.direction === "redo" ? "redo" : "undo",
5954
+ changeTag: null,
5955
+ txId: readTxId(history?.txId),
5956
+ scope: documentChangeScope(result.affectedStories)
5957
+ };
5958
+ }
5959
+ if (!mutationCommittedEventChangedDocument(event)) return null;
5960
+ const receipt = isPlainObject(event.receipt) ? event.receipt : {};
5961
+ return {
5962
+ cause: event.cause === "user" ? "user" : "api",
5963
+ changeTag: typeof receipt.changeTag === "string" ? receipt.changeTag : null,
5964
+ txId: readTxId(receipt.txId),
5965
+ scope: documentChangeScope(receipt.affectedStories)
5966
+ };
5777
5967
  }
5778
5968
  function commandResultSucceeded(result) {
5779
5969
  if (result === false) return false;
@@ -6367,7 +6557,7 @@ function createSuperDocUI(options) {
6367
6557
  if (!pending || !(method in pending)) return void 0;
6368
6558
  const value = pending[method];
6369
6559
  if (typeof value === "string" && value !== "") return value;
6370
- if (typeof value === "number" && Number.isFinite(value)) return String(value);
6560
+ if (require_is_finite_number.isFiniteNumber(value)) return String(value);
6371
6561
  };
6372
6562
  /** Record / clear the stored inline mark for a collapsed-caret pick (SD-3654/SD-3652). */
6373
6563
  const setPendingInlineFormatOnHost = (method, value) => {
@@ -6682,9 +6872,19 @@ function createSuperDocUI(options) {
6682
6872
  if (seeded > 0) dirtyHosts.add(host);
6683
6873
  else if (revision === 0) dirtyHosts.delete(host);
6684
6874
  };
6685
- const hasLocalDocumentMutation = () => {
6875
+ const savedPoint = () => {
6686
6876
  const host = getHost();
6877
+ return {
6878
+ host,
6879
+ isDirty: hostMethod(host, "isDirty"),
6880
+ getDocumentVersion: hostMethod(host, "getDocumentVersion"),
6881
+ markSaved: hostMethod(host, "markSaved")
6882
+ };
6883
+ };
6884
+ const hasLocalDocumentMutation = () => {
6885
+ const { host, isDirty } = savedPoint();
6687
6886
  if (!host) return false;
6887
+ if (isDirty) return Boolean(safeCall(() => isDirty(), false));
6688
6888
  seedLocalDocumentMutation(host);
6689
6889
  return dirtyHosts.has(host);
6690
6890
  };
@@ -8095,6 +8295,33 @@ function createSuperDocUI(options) {
8095
8295
  sizeOptions: DEFAULT_FONT_SIZE_OPTIONS
8096
8296
  };
8097
8297
  };
8298
+ const EMPTY_HISTORY = {
8299
+ canUndo: false,
8300
+ canRedo: false,
8301
+ undoDepth: 0,
8302
+ redoDepth: 0
8303
+ };
8304
+ let historySlice = EMPTY_HISTORY;
8305
+ let historySource = null;
8306
+ const computeHistory = () => {
8307
+ const source = getEditCommands();
8308
+ if (source !== historySource) {
8309
+ historySource = source;
8310
+ historySlice = EMPTY_HISTORY;
8311
+ }
8312
+ const getSnapshot = hostMethod(source, "getSnapshot");
8313
+ const snapshot = getSnapshot ? safeCall(() => getSnapshot(), null) : null;
8314
+ const { undoDepth, redoDepth } = (isPlainObject(snapshot) && isPlainObject(snapshot.history) ? snapshot.history : null) ?? {};
8315
+ if (typeof undoDepth !== "number" || typeof redoDepth !== "number") return historySlice;
8316
+ const next = {
8317
+ canUndo: undoDepth > 0,
8318
+ canRedo: redoDepth > 0,
8319
+ undoDepth,
8320
+ redoDepth
8321
+ };
8322
+ if (!shallowEqual(next, historySlice)) historySlice = next;
8323
+ return historySlice;
8324
+ };
8098
8325
  let zoomFitWidth;
8099
8326
  const computeZoom = () => {
8100
8327
  const getZoomState = hostMethod(superdoc, "getZoomState");
@@ -8728,9 +8955,10 @@ function createSuperDocUI(options) {
8728
8955
  for (const candidate of permissions) {
8729
8956
  let allowed;
8730
8957
  try {
8731
- allowed = canPerform.call(superdoc, {
8958
+ const permissionChange = trackedChange ?? { id };
8959
+ allowed = readBuiltInTrackedChangePermissionDecision(superdoc, canPerform, candidate, permissionChange) ?? canPerform.call(superdoc, {
8732
8960
  permission: candidate,
8733
- trackedChange: trackedChange ?? { id },
8961
+ trackedChange: permissionChange,
8734
8962
  comment: null
8735
8963
  });
8736
8964
  } catch {
@@ -9623,7 +9851,7 @@ function createSuperDocUI(options) {
9623
9851
  };
9624
9852
  /** Validate normalized payloads before invoking public SuperDoc-instance methods. */
9625
9853
  const instanceCommandPayloadIsValid = (descriptor, payload) => {
9626
- if (descriptor.id === "zoom") return typeof payload === "number" && Number.isFinite(payload) && payload > 0;
9854
+ if (descriptor.id === "zoom") return require_is_finite_number.isFiniteNumber(payload) && payload > 0;
9627
9855
  if (descriptor.id === "document-mode") return payload === "editing" || payload === "suggesting" || payload === "viewing";
9628
9856
  if (descriptor.id === "measurement-unit") return payload === "in" || payload === "cm";
9629
9857
  return true;
@@ -9907,6 +10135,7 @@ function createSuperDocUI(options) {
9907
10135
  trackChanges: measure("trackChanges", () => computeTrackChanges(selection)),
9908
10136
  contentControls: measure("contentControls", () => computeContentControls(selection)),
9909
10137
  zoom: measure("zoom", computeZoom),
10138
+ history: measure("history", computeHistory),
9910
10139
  fonts: measure("fonts", computeFonts),
9911
10140
  styles: measure("styles", () => computeStyles(selection))
9912
10141
  };
@@ -10010,7 +10239,7 @@ function createSuperDocUI(options) {
10010
10239
  const familyValue = state.toolbar.commands["font-family"]?.value;
10011
10240
  const sizeValue = state.toolbar.commands["font-size"]?.value;
10012
10241
  const hadFamily = typeof familyValue === "string" && familyValue.length > 0;
10013
- const hadSize = typeof sizeValue === "string" && sizeValue.length > 0 || typeof sizeValue === "number" && Number.isFinite(sizeValue);
10242
+ const hadSize = typeof sizeValue === "string" && sizeValue.length > 0 || require_is_finite_number.isFiniteNumber(sizeValue);
10014
10243
  return hadFamily && projected.fontFamily === void 0 || hadSize && projected.fontSize === void 0;
10015
10244
  };
10016
10245
  const syncHostSelectionSubscription = () => {
@@ -10196,6 +10425,41 @@ function createSuperDocUI(options) {
10196
10425
  state = computeState("initial");
10197
10426
  lastOptimisticInlineSelectionSignature = selectionInlineValueSignature(state.selection);
10198
10427
  let scheduleActiveSearchRefresh = () => {};
10428
+ const documentChangeListeners = /* @__PURE__ */ new Set();
10429
+ const documentChangeCounters = /* @__PURE__ */ new WeakMap();
10430
+ let documentEpochCount = 0;
10431
+ const readDocumentReplacement = (host) => safeCall(() => hostMethod(host, "getDocumentReplacementVersion")?.(), null);
10432
+ const startDocumentChangeEpoch = (host) => {
10433
+ documentEpochCount += 1;
10434
+ const counter = {
10435
+ epoch: `document-${documentEpochCount}`,
10436
+ seq: 0,
10437
+ replacement: readDocumentReplacement(host)
10438
+ };
10439
+ documentChangeCounters.set(host, counter);
10440
+ return counter;
10441
+ };
10442
+ const currentDocumentChangeCounter = (host) => {
10443
+ const counter = documentChangeCounters.get(host);
10444
+ return counter && counter.replacement === readDocumentReplacement(host) ? counter : startDocumentChangeEpoch(host);
10445
+ };
10446
+ const publishDocumentChange = (host, event) => {
10447
+ if (event.type === "collaboration:document-replaced" || event.documentReplaced === true) {
10448
+ startDocumentChangeEpoch(host);
10449
+ return;
10450
+ }
10451
+ if (documentChangeListeners.size === 0) return;
10452
+ const facts = documentChangeFromHostEvent(event);
10453
+ if (!facts) return;
10454
+ const counter = currentDocumentChangeCounter(host);
10455
+ counter.seq += 1;
10456
+ const change = {
10457
+ documentEpoch: counter.epoch,
10458
+ seq: counter.seq,
10459
+ ...facts
10460
+ };
10461
+ for (const listener of Array.from(documentChangeListeners)) safeCall(() => listener(change), void 0);
10462
+ };
10199
10463
  const syncHostEventsSubscription = () => {
10200
10464
  const host = getEditor()?.host;
10201
10465
  const events = host?.events;
@@ -10214,15 +10478,19 @@ function createSuperDocUI(options) {
10214
10478
  try {
10215
10479
  const off = hostMethod(next, "subscribe")?.((event) => {
10216
10480
  const type = event?.type;
10481
+ if (host) publishDocumentChange(host, event);
10217
10482
  const isStandaloneDocumentMutation = type === "document:mutated" && event.hasCommitEvent !== true;
10218
- if (type === "collaboration:document-replaced" || isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedDocument(event) || type === "collaboration:remote-changed") {
10483
+ if (type === "collaboration:document-replaced" || isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedVisibleContent(event) || type === "collaboration:remote-changed") {
10219
10484
  for (const [commandId, optimistic] of optimisticInlineToggles) if (optimistic.settled || type === "collaboration:document-replaced") optimisticInlineToggles.delete(commandId);
10220
10485
  }
10221
- if (isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedDocument(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0) scheduleActiveSearchRefresh();
10222
- if ((type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event)) && host && !dirtyHosts.has(host)) {
10486
+ if (isStandaloneDocumentMutation || type === "mutation:committed" && mutationCommittedEventChangedVisibleContent(event) || type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0) scheduleActiveSearchRefresh();
10487
+ const documentEdited = type === "document:mutated" || type === "mutation:committed" && mutationCommittedEventChangedDocument(event);
10488
+ if (documentEdited && host && hostMethod(host, "isDirty")) recompute("document-dirty");
10489
+ else if (documentEdited && host && !dirtyHosts.has(host)) {
10223
10490
  dirtyHosts.add(host);
10224
10491
  recompute("document-dirty");
10225
10492
  }
10493
+ if (type === "document:saved-point-changed") recompute("document-dirty");
10226
10494
  if (type === "collaboration:document-replaced" && host) {
10227
10495
  dirtyHosts.delete(host);
10228
10496
  hostSeededMutationRevision.delete(host);
@@ -10254,6 +10522,7 @@ function createSuperDocUI(options) {
10254
10522
  if (impact?.allResolved) {
10255
10523
  replaceTrackedChangeItemsInCache([]);
10256
10524
  publishAllTrackedChangesResolved(event.receipt);
10525
+ if (event.cause === "preview") invalidateDocumentContent();
10257
10526
  return;
10258
10527
  }
10259
10528
  if (impact?.removedIds.size) markPostDecisionTrackChanges(new Set(impact.removedIds), event.receipt);
@@ -10263,7 +10532,10 @@ function createSuperDocUI(options) {
10263
10532
  scheduleTypingDocumentContentInvalidation();
10264
10533
  return;
10265
10534
  }
10266
- if (impact?.removedIds.size && impact.upsertIds.size === 0) return;
10535
+ if (impact?.removedIds.size && impact.upsertIds.size === 0) {
10536
+ if (event.cause === "preview") invalidateDocumentContent();
10537
+ return;
10538
+ }
10267
10539
  if (isStandaloneDocumentMutation || type === "collaboration:remote-changed" || type === "mutation:committed" && !isTypingBurst) schedulePostPaintContentRefresh();
10268
10540
  const remoteCommentsPartChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedPartUris) && event.changedPartUris.some((partUri) => typeof partUri === "string" && COMMENTS_CATALOG_PART_URIS.has(partUri));
10269
10541
  const loadedCommentAnchorsMayHaveChanged = type === "collaboration:remote-changed" && Array.isArray(event.changedStoryIds) && event.changedStoryIds.length > 0 && commentsCatalogMayHaveRows();
@@ -12172,6 +12444,16 @@ function createSuperDocUI(options) {
12172
12444
  mixedInlineKeys.add(patchKey);
12173
12445
  }
12174
12446
  }
12447
+ const fontFamily = effective?.fontFamily;
12448
+ if (fontFamily?.state === "uniform" && typeof fontFamily.value === "string") {
12449
+ inlinePatch.fontFamily = fontFamily.value;
12450
+ mixedInlineKeys.delete("fontFamily");
12451
+ } else if (fontFamily) {
12452
+ delete inlinePatch.fontFamily;
12453
+ delete inlinePatch.rFonts;
12454
+ mixedInlineKeys.add("fontFamily");
12455
+ mixedInlineKeys.add("rFonts");
12456
+ }
12175
12457
  const highlight = effective?.highlight;
12176
12458
  if (highlight?.state === "uniform") {
12177
12459
  inlinePatch.highlight = highlight.value;
@@ -12354,7 +12636,11 @@ function createSuperDocUI(options) {
12354
12636
  const node = (await readBlockNode(paragraphTarget(segment.blockId, targetStory)))?.node;
12355
12637
  const para = node ? getParagraphLikeData(node) : null;
12356
12638
  const runs = Array.isArray(para?.inlines) ? para.inlines : [];
12357
- for (const props of sliceRunProps(runs, segment.range)) for (const key of Object.keys(sdRunPropsToInlineRunPatch(props))) if (!(key in inline) && !snap.mixedInlineKeys.includes(key)) inline[key] = FORMAT_PAINTER_BOOLEAN_KEYS.has(key) ? false : null;
12639
+ for (const props of sliceRunProps(runs, segment.range)) for (const key of Object.keys(sdRunPropsToInlineRunPatch(props))) {
12640
+ const fontAlias = key === "rFonts" ? "fontFamily" : key === "fontFamily" ? "rFonts" : null;
12641
+ const capturedFontAlias = fontAlias && (fontAlias in inline || snap.mixedInlineKeys.includes(fontAlias));
12642
+ if (!(key in inline) && !snap.mixedInlineKeys.includes(key) && !capturedFontAlias) inline[key] = FORMAT_PAINTER_BOOLEAN_KEYS.has(key) ? false : null;
12643
+ }
12358
12644
  }
12359
12645
  if (disposed || painter.snapshot !== snap || getEditor() !== ownerEditor || ownerEditor?.doc !== ownerDoc || readDocumentMode() !== ownerMode) return;
12360
12646
  }
@@ -13695,6 +13981,7 @@ function createSuperDocUI(options) {
13695
13981
  getFamilyOptions: () => state.fonts.options,
13696
13982
  getSizeOptions: () => state.fonts.sizeOptions
13697
13983
  };
13984
+ const history = snapshotHandle(sliceHandle((s) => s.history));
13698
13985
  const zoomSnap = snapshotHandle(sliceHandle((s) => s.zoom));
13699
13986
  const zoom = {
13700
13987
  get: zoomSnap.get,
@@ -13755,6 +14042,28 @@ function createSuperDocUI(options) {
13755
14042
  } catch {
13756
14043
  return;
13757
14044
  }
14045
+ },
14046
+ onChange: (listener) => {
14047
+ if (disposed) return () => {};
14048
+ documentChangeListeners.add(listener);
14049
+ return () => documentChangeListeners.delete(listener);
14050
+ },
14051
+ getVersion: () => {
14052
+ const { getDocumentVersion } = savedPoint();
14053
+ const version = getDocumentVersion ? safeCall(() => getDocumentVersion(), null) : null;
14054
+ return typeof version === "string" ? version : null;
14055
+ },
14056
+ markClean: (version) => {
14057
+ const { markSaved } = savedPoint();
14058
+ if (!markSaved) return {
14059
+ ok: false,
14060
+ reason: "unavailable"
14061
+ };
14062
+ const result = safeCall(() => markSaved(version), null);
14063
+ return isPlainObject(result) && result.ok === true ? { ok: true } : {
14064
+ ok: false,
14065
+ reason: isPlainObject(result) && result.reason === "document-changed" ? "document-changed" : "unavailable"
14066
+ };
13758
14067
  }
13759
14068
  };
13760
14069
  const resolveVisibleHost = () => {
@@ -13766,7 +14075,7 @@ function createSuperDocUI(options) {
13766
14075
  return null;
13767
14076
  };
13768
14077
  const pointHitElements = (x, y) => {
13769
- if (typeof x !== "number" || typeof y !== "number" || !Number.isFinite(x) || !Number.isFinite(y)) return null;
14078
+ if (!require_is_finite_number.isFiniteNumber(x) || !require_is_finite_number.isFiniteNumber(y)) return null;
13770
14079
  const dom = globalThis.document;
13771
14080
  if (!dom || typeof dom.elementFromPoint !== "function") return null;
13772
14081
  const container = resolveVisibleHost();
@@ -14544,7 +14853,7 @@ function createSuperDocUI(options) {
14544
14853
  const record = result && typeof result === "object" ? result : null;
14545
14854
  if (!record) return null;
14546
14855
  const matches = Array.isArray(record.matches) ? record.matches : [];
14547
- const total = typeof record.total === "number" && Number.isFinite(record.total) ? record.total : matches.length;
14856
+ const total = require_is_finite_number.isFiniteNumber(record.total) ? record.total : matches.length;
14548
14857
  const activeIndex = typeof record.activeMatchIndex === "number" ? record.activeMatchIndex : typeof record.activeIndex === "number" ? record.activeIndex : -1;
14549
14858
  const canReplace = record.canReplace === true || fallbackCanReplace;
14550
14859
  return {
@@ -15237,6 +15546,11 @@ function createSuperDocUI(options) {
15237
15546
  const scopeUnsubs = [];
15238
15547
  return {
15239
15548
  decorations: createDecorationsHandle((handle) => scopeUnsubs.push(() => handle.dispose())),
15549
+ document: { onChange: (listener) => {
15550
+ const unsub = documentHandle.onChange(listener);
15551
+ scopeUnsubs.push(unsub);
15552
+ return unsub;
15553
+ } },
15240
15554
  select: (selector, equality) => {
15241
15555
  const sub = select(selector, equality);
15242
15556
  return {
@@ -15323,6 +15637,7 @@ function createSuperDocUI(options) {
15323
15637
  painterCaptureEpoch += 1;
15324
15638
  painterCommandDoc = null;
15325
15639
  painterModeListeners.clear();
15640
+ documentChangeListeners.clear();
15326
15641
  searchRequestGeneration += 1;
15327
15642
  customCommands.clear();
15328
15643
  };
@@ -15340,6 +15655,7 @@ function createSuperDocUI(options) {
15340
15655
  bookmarks,
15341
15656
  fonts,
15342
15657
  zoom,
15658
+ history,
15343
15659
  document: documentHandle,
15344
15660
  viewport,
15345
15661
  decorations,
@@ -15573,6 +15889,12 @@ Object.defineProperty(exports, "DOM_CLASS_NAMES", {
15573
15889
  return DOM_CLASS_NAMES;
15574
15890
  }
15575
15891
  });
15892
+ Object.defineProperty(exports, "PERMISSIONS", {
15893
+ enumerable: true,
15894
+ get: function() {
15895
+ return PERMISSIONS;
15896
+ }
15897
+ });
15576
15898
  Object.defineProperty(exports, "applyV2CommentInvalidationFromMutation", {
15577
15899
  enumerable: true,
15578
15900
  get: function() {
@@ -15603,6 +15925,12 @@ Object.defineProperty(exports, "createSuperDocUI", {
15603
15925
  return createSuperDocUI;
15604
15926
  }
15605
15927
  });
15928
+ Object.defineProperty(exports, "createTrackedChangePermissionResolver", {
15929
+ enumerable: true,
15930
+ get: function() {
15931
+ return createTrackedChangePermissionResolver;
15932
+ }
15933
+ });
15606
15934
  Object.defineProperty(exports, "executeFirstPartyCommandAsync", {
15607
15935
  enumerable: true,
15608
15936
  get: function() {
@@ -15615,6 +15943,12 @@ Object.defineProperty(exports, "executeFirstPartyShortcutAsync", {
15615
15943
  return executeFirstPartyShortcutAsync;
15616
15944
  }
15617
15945
  });
15946
+ Object.defineProperty(exports, "getCommandDescriptor", {
15947
+ enumerable: true,
15948
+ get: function() {
15949
+ return getCommandDescriptor;
15950
+ }
15951
+ });
15618
15952
  Object.defineProperty(exports, "getV2TrackedChangeMutationImpact", {
15619
15953
  enumerable: true,
15620
15954
  get: function() {
@@ -15627,6 +15961,12 @@ Object.defineProperty(exports, "getWorkflowRecording", {
15627
15961
  return getWorkflowRecording;
15628
15962
  }
15629
15963
  });
15964
+ Object.defineProperty(exports, "isAllowed", {
15965
+ enumerable: true,
15966
+ get: function() {
15967
+ return isAllowed;
15968
+ }
15969
+ });
15630
15970
  Object.defineProperty(exports, "isPlainObject", {
15631
15971
  enumerable: true,
15632
15972
  get: function() {
@@ -15651,6 +15991,12 @@ Object.defineProperty(exports, "isWorkflowRecordingEnabled", {
15651
15991
  return isWorkflowRecordingEnabled;
15652
15992
  }
15653
15993
  });
15994
+ Object.defineProperty(exports, "mutationCommittedEventChangedDocument", {
15995
+ enumerable: true,
15996
+ get: function() {
15997
+ return mutationCommittedEventChangedDocument;
15998
+ }
15999
+ });
15654
16000
  Object.defineProperty(exports, "readFirstPartyPageNumbers", {
15655
16001
  enumerable: true,
15656
16002
  get: function() {