superdoc 2.12.0-next.1 → 2.12.0-next.11

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 (31) hide show
  1. package/dist/collaboration-upgrade-engine.cjs +1 -1
  2. package/dist/collaboration-upgrade-engine.es.js +1 -1
  3. package/dist/layout-engine/contracts/src/index.d.ts +1 -1
  4. package/dist/layout-engine/contracts/src/run-helpers.d.ts +8 -0
  5. package/dist/layout-engine/layout-bridge/src/cache.d.ts +5 -4
  6. package/dist/layout-engine/layout-bridge/src/incrementalLayout.d.ts +4 -1
  7. package/dist/layout-engine/layout-bridge/src/note-marker-measure-key.d.ts +3 -0
  8. package/dist/layout-engine/layout-bridge/src/remeasure.d.ts +2 -1
  9. package/dist/public/ui-react.cjs +38 -9
  10. package/dist/public/ui-react.es.js +38 -9
  11. package/dist/shared/font-system/src/index.d.ts +3 -1
  12. package/dist/shared/font-system/src/natural-line-metrics.d.ts +11 -0
  13. package/dist/shared/font-system/src/resolver.d.ts +14 -0
  14. package/dist/style.css +25 -25
  15. package/dist/style.layered.css +25 -25
  16. package/dist/superdoc/src/core/types/index.d.ts +15 -0
  17. package/dist/superdoc/src/public/index.d.cts +2 -0
  18. package/dist/superdoc/src/public/index.d.ts +1 -0
  19. package/dist/superdoc/src/public/ui/react.d.ts +10 -3
  20. package/dist/superdoc/src/public/ui/types.d.ts +14 -12
  21. package/dist/superdoc/src/public/ui/vue.d.ts +2 -2
  22. package/dist/superdoc/src/public/ui-react.d.cts +2 -0
  23. package/dist/superdoc/src/public/ui-react.d.ts +1 -1
  24. package/dist/superdoc/src/public/ui.d.cts +2 -0
  25. package/dist/superdoc/src/public/ui.d.ts +1 -1
  26. package/dist/superdoc.cjs +149 -9
  27. package/dist/superdoc.es.js +149 -9
  28. package/dist-cdn/style.layered.css +1 -1
  29. package/dist-cdn/superdoc.min.css +1 -1
  30. package/dist-cdn/superdoc.min.js +21 -21
  31. package/package.json +2 -2
@@ -195,6 +195,7 @@ import type { SuperDocVisualApi as __Cjs_SuperDocVisualApi } from './index.js' w
195
195
  import type { SuperDocVisualHandle as __Cjs_SuperDocVisualHandle } from './index.js' with { "resolution-mode": "import" };
196
196
  import type { SuperDocVisualOptions as __Cjs_SuperDocVisualOptions } from './index.js' with { "resolution-mode": "import" };
197
197
  import type { SuperDocVisualTarget as __Cjs_SuperDocVisualTarget } from './index.js' with { "resolution-mode": "import" };
198
+ import type { SuperDocWorkerFailureDetail as __Cjs_SuperDocWorkerFailureDetail } from './index.js' with { "resolution-mode": "import" };
198
199
  import type { SuperDocZoomConfig as __Cjs_SuperDocZoomConfig } from './index.js' with { "resolution-mode": "import" };
199
200
  import type { SuperDocZoomMode as __Cjs_SuperDocZoomMode } from './index.js' with { "resolution-mode": "import" };
200
201
  import type { SuperDocZoomPayload as __Cjs_SuperDocZoomPayload } from './index.js' with { "resolution-mode": "import" };
@@ -459,6 +460,7 @@ export type { __Cjs_SuperDocVisualApi as SuperDocVisualApi };
459
460
  export type { __Cjs_SuperDocVisualHandle as SuperDocVisualHandle };
460
461
  export type { __Cjs_SuperDocVisualOptions as SuperDocVisualOptions };
461
462
  export type { __Cjs_SuperDocVisualTarget as SuperDocVisualTarget };
463
+ export type { __Cjs_SuperDocWorkerFailureDetail as SuperDocWorkerFailureDetail };
462
464
  export type { __Cjs_SuperDocZoomConfig as SuperDocZoomConfig };
463
465
  export type { __Cjs_SuperDocZoomMode as SuperDocZoomMode };
464
466
  export type { __Cjs_SuperDocZoomPayload as SuperDocZoomPayload };
@@ -82,6 +82,7 @@ export type { SuperDocDocumentModeChangePayload } from '../core/types/index.js';
82
82
  export type { SuperDocEditorPayload } from '../core/types/index.js';
83
83
  export type { SuperDocExceptionDiagnosticPayload } from '../core/types/index.js';
84
84
  export type { SuperDocExceptionEditorPayload } from '../core/types/index.js';
85
+ export type { SuperDocWorkerFailureDetail } from '../core/types/index.js';
85
86
  export type { SuperDocExceptionHyperlinkPayload } from '../core/types/index.js';
86
87
  export type { SuperDocExceptionToolbarPayload } from '../core/types/index.js';
87
88
  export type { SuperDocExceptionPayload } from '../core/types/index.js';
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { toSliceSource, SliceSource } from './slice-source.js';
3
- import { BorrowedSuperDocUI, CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
3
+ import { BorrowedSuperDocUI, CommandExecutionResult, CommandId, CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
4
4
  /** The raw SuperDoc instance (or host stub) handed to the provider. */
5
5
  export type SuperDocHost = SuperDocLike;
6
6
  /** Props accepted by {@link SuperDocUIProvider}. */
@@ -50,8 +50,15 @@ export declare function useSuperDocContentControls(): ContentControlsSlice;
50
50
  export declare function useSuperDocTrackChanges(): TrackChangesSlice;
51
51
  /** Subscribe to the toolbar snapshot slice. */
52
52
  export declare function useSuperDocToolbar(): ToolbarSnapshotSlice;
53
- /** Subscribe to a single command's enable/active state. */
54
- export declare function useSuperDocCommand(id: string): CommandState;
53
+ /** Reactive state and execution methods for one SuperDoc command. */
54
+ export interface UseSuperDocCommandResult extends CommandState {
55
+ /** Run the command against the currently bound Editor. */
56
+ execute(payload?: unknown): CommandExecutionResult;
57
+ /** Run the command and await the routed operation's settled result. */
58
+ executeAsync(payload?: unknown): Promise<CommandExecutionResult>;
59
+ }
60
+ /** Subscribe to and execute one SuperDoc command. */
61
+ export declare function useSuperDocCommand(id: CommandId): UseSuperDocCommandResult;
55
62
  /** Subscribe to the document slice. */
56
63
  export declare function useSuperDocDocument(): DocumentSlice;
57
64
  /** Subscribe to available font-family options. */
@@ -184,6 +184,10 @@ export interface CommandState {
184
184
  */
185
185
  reason?: SuperDocUIReason;
186
186
  }
187
+ /** A built-in command id, or an application id registered through `ui.commands.register()`. */
188
+ export type CommandId = BuiltInCommandId | (string & {});
189
+ /** Command id accepted by toolbar APIs. Equivalent to {@link CommandId}. */
190
+ export type ToolbarCommandId = CommandId;
187
191
  /**
188
192
  * Failure code carried by a receipt that the UI controller mints itself
189
193
  * (rather than relaying from the Document API). Extends the Document API's
@@ -317,7 +321,7 @@ export type SelectionRestoreResult = {
317
321
  * Document API / SuperDoc instance; `getState` reflects the live enable/active
318
322
  * snapshot; `observe` notifies on state change.
319
323
  */
320
- export interface CommandHandle<Id extends string = string> {
324
+ export interface CommandHandle<Id extends CommandId = CommandId> {
321
325
  /** The command id this handle wraps. */
322
326
  readonly id: Id;
323
327
  /** Current enable/active state. */
@@ -437,9 +441,9 @@ export interface CustomCommandContext<TPayload = unknown> {
437
441
  */
438
442
  ui: BorrowedSuperDocUI;
439
443
  /** Run a catalog command id through the shared controller. */
440
- execute(id: string, payload?: unknown): CommandExecutionResult;
444
+ execute(id: CommandId, payload?: unknown): CommandExecutionResult;
441
445
  /** Run a catalog command id and await its settled result. */
442
- executeAsync(id: string, payload?: unknown): Promise<CommandExecutionResult>;
446
+ executeAsync(id: CommandId, payload?: unknown): Promise<CommandExecutionResult>;
443
447
  /**
444
448
  * The host's browser Document API facade (read-only-guarded, async-capable),
445
449
  * or `null` when unavailable.
@@ -469,7 +473,7 @@ export interface CustomCommandContext<TPayload = unknown> {
469
473
  }
470
474
  export interface CustomCommandRegistration<TPayload = unknown, TValue = unknown> {
471
475
  /** Unique command id. */
472
- id: string;
476
+ id: CommandId;
473
477
  /** Implementation invoked when the command runs. */
474
478
  execute(context: CustomCommandContext<TPayload>): unknown;
475
479
  /** Optional live-state provider. */
@@ -484,7 +488,7 @@ export interface CustomCommandRegistration<TPayload = unknown, TValue = unknown>
484
488
  when?(context: ViewportContext): boolean;
485
489
  };
486
490
  }
487
- export interface CustomCommandHandle<TPayload = unknown, TValue = unknown> extends Omit<CommandHandle<string>, 'execute' | 'executeAsync' | 'getState' | 'observe'> {
491
+ export interface CustomCommandHandle<TPayload = unknown, TValue = unknown> extends Omit<CommandHandle<CommandId>, 'execute' | 'executeAsync' | 'getState' | 'observe'> {
488
492
  /** Current custom-command state. */
489
493
  getState(): CustomCommandHandleState<TValue>;
490
494
  /** Subscribe to custom-command state changes; returns an unsubscribe function. */
@@ -501,15 +505,15 @@ export type CustomCommandRegistrationResult<TPayload = unknown, TValue = unknown
501
505
  /** Aggregate command surface. */
502
506
  export interface CommandsHandle {
503
507
  /** All known command ids (built-in plus registered). */
504
- readonly ids: readonly string[];
508
+ readonly ids: readonly CommandId[];
505
509
  /** Whether a command id is known to the controller. */
506
- has(id: string): boolean;
510
+ has(id: CommandId): boolean;
507
511
  /** Resolve a handle for a command id. */
508
- get<Id extends string = string>(id: Id): CommandHandle<Id>;
512
+ get<Id extends CommandId = CommandId>(id: Id): CommandHandle<Id>;
509
513
  /** Execute a command by id. */
510
- execute(id: string, payload?: unknown): CommandExecutionResult;
514
+ execute(id: CommandId, payload?: unknown): CommandExecutionResult;
511
515
  /** Execute a command by id and resolve once the routed work has settled. */
512
- executeAsync(id: string, payload?: unknown): Promise<CommandExecutionResult>;
516
+ executeAsync(id: CommandId, payload?: unknown): Promise<CommandExecutionResult>;
513
517
  /** Register a consumer-defined command; returns an unregister function. */
514
518
  register<TPayload = unknown, TValue = unknown>(registration: CustomCommandRegistration<TPayload, TValue>): CustomCommandRegistrationResult<TPayload, TValue>;
515
519
  /** Resolve context-menu contributions for a viewport context. */
@@ -1081,8 +1085,6 @@ export interface FontsHandle extends SnapshotSubscribable<FontsSlice> {
1081
1085
  /** Available font size options. */
1082
1086
  getSizeOptions(): readonly FontSizeOption[];
1083
1087
  }
1084
- /** A built-in command id, or an id registered through `ui.commands.register()`. */
1085
- export type ToolbarCommandId = BuiltInCommandId | (string & {});
1086
1088
  /** Toolbar handle. */
1087
1089
  export interface ToolbarHandle extends SnapshotSubscribable<ToolbarSnapshotSlice> {
1088
1090
  /** Read the current toolbar snapshot. */
@@ -1,6 +1,6 @@
1
1
  import { ComputedRef, MaybeRefOrGetter, ShallowRef } from 'vue';
2
2
  import { SliceSource } from './slice-source.js';
3
- import { BorrowedSuperDocUI, CommandExecutionResult, CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
3
+ import { BorrowedSuperDocUI, CommandExecutionResult, CommandId, CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
4
4
  /** The raw SuperDoc instance (or host stub) handed to the provider. */
5
5
  export type SuperDocHost = SuperDocLike;
6
6
  /**
@@ -111,7 +111,7 @@ export interface UseSuperDocCommandResult {
111
111
  * Subscribe to and execute a single command. Accepts a plain id, a ref, or a
112
112
  * getter; a reactive id re-subscribes and routes execution to the new command.
113
113
  */
114
- export declare function useSuperDocCommand(id: MaybeRefOrGetter<string>): UseSuperDocCommandResult;
114
+ export declare function useSuperDocCommand(id: MaybeRefOrGetter<CommandId>): UseSuperDocCommandResult;
115
115
  /** Subscribe to the document slice. */
116
116
  export declare function useSuperDocDocument(): Readonly<ShallowRef<DocumentSlice>>;
117
117
  /** Subscribe to available font-family options. */
@@ -1,11 +1,13 @@
1
1
  // Generated by scripts/ensure-types.cjs. Do not edit by hand.
2
2
  import type { SuperDocHost as __Cjs_SuperDocHost } from './ui-react.js' with { "resolution-mode": "import" };
3
3
  import type { SuperDocUIProviderProps as __Cjs_SuperDocUIProviderProps } from './ui-react.js' with { "resolution-mode": "import" };
4
+ import type { UseSuperDocCommandResult as __Cjs_UseSuperDocCommandResult } from './ui-react.js' with { "resolution-mode": "import" };
4
5
  export type { __Cjs_SuperDocHost as SuperDocHost };
5
6
  export declare const SuperDocUIProvider: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).SuperDocUIProvider;
6
7
  export type { __Cjs_SuperDocUIProviderProps as SuperDocUIProviderProps };
7
8
  export declare const useSetSuperDoc: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).useSetSuperDoc;
8
9
  export declare const useSuperDocCommand: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).useSuperDocCommand;
10
+ export type { __Cjs_UseSuperDocCommandResult as UseSuperDocCommandResult };
9
11
  export declare const useSuperDocComments: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).useSuperDocComments;
10
12
  export declare const useSuperDocContentControls: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).useSuperDocContentControls;
11
13
  export declare const useSuperDocDocument: typeof import('./ui-react.js', { with: { "resolution-mode": "import" } }).useSuperDocDocument;
@@ -17,4 +17,4 @@
17
17
  * the emitted declarations expose exactly these named exports.
18
18
  */
19
19
  export { SuperDocUIProvider, useSuperDocUI, useSuperDocHost, useSetSuperDoc, useSuperDocSlice, useSuperDocSelection, useSuperDocComments, useSuperDocContentControls, useSuperDocTrackChanges, useSuperDocToolbar, useSuperDocCommand, useSuperDocDocument, useSuperDocFontOptions, useSuperDocFontSizeOptions, useSuperDocZoom, } from './ui/react.js';
20
- export type { SuperDocHost, SuperDocUIProviderProps } from './ui/react.js';
20
+ export type { SuperDocHost, SuperDocUIProviderProps, UseSuperDocCommandResult } from './ui/react.js';
@@ -5,6 +5,7 @@ import type { BrowserDocumentApi as __Cjs_BrowserDocumentApi } from './ui.js' wi
5
5
  import type { BuiltInCommandId as __Cjs_BuiltInCommandId } from './ui.js' with { "resolution-mode": "import" };
6
6
  import type { CommandExecutionResult as __Cjs_CommandExecutionResult } from './ui.js' with { "resolution-mode": "import" };
7
7
  import type { CommandHandle as __Cjs_CommandHandle } from './ui.js' with { "resolution-mode": "import" };
8
+ import type { CommandId as __Cjs_CommandId } from './ui.js' with { "resolution-mode": "import" };
8
9
  import type { CommandsHandle as __Cjs_CommandsHandle } from './ui.js' with { "resolution-mode": "import" };
9
10
  import type { CommandState as __Cjs_CommandState } from './ui.js' with { "resolution-mode": "import" };
10
11
  import type { CommentAddress as __Cjs_CommentAddress } from './ui.js' with { "resolution-mode": "import" };
@@ -111,6 +112,7 @@ export declare const BUILT_IN_COMMAND_IDS: typeof import('./ui.js', { with: { "r
111
112
  export type { __Cjs_BuiltInCommandId as BuiltInCommandId };
112
113
  export type { __Cjs_CommandExecutionResult as CommandExecutionResult };
113
114
  export type { __Cjs_CommandHandle as CommandHandle };
115
+ export type { __Cjs_CommandId as CommandId };
114
116
  export type { __Cjs_CommandsHandle as CommandsHandle };
115
117
  export type { __Cjs_CommandState as CommandState };
116
118
  export type { __Cjs_CommentAddress as CommentAddress };
@@ -26,4 +26,4 @@
26
26
  export { createSuperDocUI } from './ui/create-super-doc-ui.js';
27
27
  export { shallowEqual } from './ui/equality.js';
28
28
  export { BUILT_IN_COMMAND_IDS } from './ui/commands.js';
29
- export type { EqualityFn, SelectorFn, Subscribable, SuperDocUI, BorrowedSuperDocUI, SuperDocUIOptions, SuperDocUIState, SuperDocUIScope, SuperDocLike, SuperDocEditorLike, CommandHandle, CommandState, CommandExecutionResult, WorkflowReceipt, WorkflowActionResult, WorkflowScrollResult, SelectionRestoreResult, SuperDocUIReason, CommandsHandle, ContextMenuItem, ContextMenuHandle, SearchController, SearchHandle, SearchQueryOptions, CustomCommandContext, CustomCommandHandle, CustomCommandHandleState, CustomCommandRegistration, CustomCommandRegistrationResult, MetadataHandle, SelectionHandle, ToolbarHandle, BuiltInCommandId, ToolbarCommandId, CommentsHandle, TrackChangesHandle, ContentControlsHandle, ContentControlFocusResult, FontsHandle, ZoomHandle, DocumentHandle, ViewportHandle, StylesHandle, ActiveParagraphStyle, SliceStatus, SelectionSlice, SelectionCapture, CommentAnchorCapture, ToolbarSnapshotSlice, CommentsSlice, TrackChangesSlice, ContentControlsSlice, FontsSlice, ZoomSlice, DocumentSlice, StylesSlice, SearchSnapshot, SearchSlice, StyleCatalogView, StyleCatalogItemType, StyleCatalogFilterType, StyleProvenance, StyleCatalogItemVisibility, StyleCatalogItemUsage, StyleCatalogItemPreview, StyleCatalogItem, StyleCatalogDefaults, StyleCatalogDiagnostic, StyleCatalogSourceStatus, StylesGetCatalogInput, StylesGetCatalogResult, CommentInfo, CommentsListQuery, TrackChangeInfo, TrackChangePointHit, TrackChangesItem, FontFamilyOption, FontSizeOption, CommentAddress, TrackedChangeAddress, ContentControlViewportAddress, ViewportEntityAddress, ViewportEntityHit, ViewportContext, ViewportRect, ViewportGetRectInput, ViewportRectResult, BrowserDocumentApi, PartialBrowserDocumentApi, DocumentApi, Receipt, SelectionInfo, SelectionTarget, SelectionPoint, TextTarget, TextAddress, ScrollIntoViewInput, ScrollIntoViewOutput, EntityAddress, CommentsListResult, TrackChangesListResult, ContentControlsListResult, ContentControlInfo, RichContentInsertInput, SDHtmlMarkdownSupportCheckResult, } from './ui/types.js';
29
+ export type { EqualityFn, SelectorFn, Subscribable, SuperDocUI, BorrowedSuperDocUI, SuperDocUIOptions, SuperDocUIState, SuperDocUIScope, SuperDocLike, SuperDocEditorLike, CommandHandle, CommandState, CommandExecutionResult, WorkflowReceipt, WorkflowActionResult, WorkflowScrollResult, SelectionRestoreResult, SuperDocUIReason, CommandId, CommandsHandle, ContextMenuItem, ContextMenuHandle, SearchController, SearchHandle, SearchQueryOptions, CustomCommandContext, CustomCommandHandle, CustomCommandHandleState, CustomCommandRegistration, CustomCommandRegistrationResult, MetadataHandle, SelectionHandle, ToolbarHandle, BuiltInCommandId, ToolbarCommandId, CommentsHandle, TrackChangesHandle, ContentControlsHandle, ContentControlFocusResult, FontsHandle, ZoomHandle, DocumentHandle, ViewportHandle, StylesHandle, ActiveParagraphStyle, SliceStatus, SelectionSlice, SelectionCapture, CommentAnchorCapture, ToolbarSnapshotSlice, CommentsSlice, TrackChangesSlice, ContentControlsSlice, FontsSlice, ZoomSlice, DocumentSlice, StylesSlice, SearchSnapshot, SearchSlice, StyleCatalogView, StyleCatalogItemType, StyleCatalogFilterType, StyleProvenance, StyleCatalogItemVisibility, StyleCatalogItemUsage, StyleCatalogItemPreview, StyleCatalogItem, StyleCatalogDefaults, StyleCatalogDiagnostic, StyleCatalogSourceStatus, StylesGetCatalogInput, StylesGetCatalogResult, CommentInfo, CommentsListQuery, TrackChangeInfo, TrackChangePointHit, TrackChangesItem, FontFamilyOption, FontSizeOption, CommentAddress, TrackedChangeAddress, ContentControlViewportAddress, ViewportEntityAddress, ViewportEntityHit, ViewportContext, ViewportRect, ViewportGetRectInput, ViewportRectResult, BrowserDocumentApi, PartialBrowserDocumentApi, DocumentApi, Receipt, SelectionInfo, SelectionTarget, SelectionPoint, TextTarget, TextAddress, ScrollIntoViewInput, ScrollIntoViewOutput, EntityAddress, CommentsListResult, TrackChangesListResult, ContentControlsListResult, ContentControlInfo, RichContentInsertInput, SDHtmlMarkdownSupportCheckResult, } from './ui/types.js';
package/dist/superdoc.cjs CHANGED
@@ -316,7 +316,7 @@ var shuffleArray = (array) => {
316
316
  var DEFAULT_ENDPOINT = "https://ingest.superdoc.dev/v1/collect";
317
317
  function getSuperdocVersion() {
318
318
  try {
319
- return "2.12.0-next.1";
319
+ return "2.12.0-next.11";
320
320
  } catch {
321
321
  return "unknown";
322
322
  }
@@ -10188,6 +10188,115 @@ var useCommentsStore = defineStore("comments", () => {
10188
10188
  const type = normalizeTrackedChangeDecisionType(comment?.trackedChangeDisplayType) ?? normalizeTrackedChangeDecisionType(comment?.trackedChangeType);
10189
10189
  return normalizedDecision === "accept" && type === "insertion" || normalizedDecision === "reject" && type === "deletion";
10190
10190
  };
10191
+ const getBodyTrackedChangeIdentityIds = (comment) => {
10192
+ const commentId = normalizeCommentId(comment.commentId);
10193
+ const canonicalId = normalizeCommentId(comment.trackedChangeCanonicalId);
10194
+ return [commentId, ...!(canonicalId && canonicalId !== commentId) ? [
10195
+ comment.importedId,
10196
+ canonicalId,
10197
+ comment.trackedChangeAnchorKey,
10198
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
10199
+ ] : []].map((id) => normalizeCommentId(id)).filter(Boolean);
10200
+ };
10201
+ const groupBodyTrackedChangeCommentsByIdentity = (comments) => {
10202
+ const parents = comments.map((_, index) => index);
10203
+ const findRoot = (index) => {
10204
+ let root = index;
10205
+ while (parents[root] !== root) root = parents[root];
10206
+ while (parents[index] !== index) {
10207
+ const next = parents[index];
10208
+ parents[index] = root;
10209
+ index = next;
10210
+ }
10211
+ return root;
10212
+ };
10213
+ const join = (left, right) => {
10214
+ const leftRoot = findRoot(left);
10215
+ const rightRoot = findRoot(right);
10216
+ if (leftRoot === rightRoot) return;
10217
+ parents[Math.max(leftRoot, rightRoot)] = Math.min(leftRoot, rightRoot);
10218
+ };
10219
+ const identityOwner = /* @__PURE__ */ new Map();
10220
+ comments.forEach((comment, index) => {
10221
+ getBodyTrackedChangeIdentityIds(comment).forEach((identityId) => {
10222
+ const owner = identityOwner.get(identityId);
10223
+ if (owner === void 0) identityOwner.set(identityId, index);
10224
+ else join(index, owner);
10225
+ });
10226
+ });
10227
+ const groups = /* @__PURE__ */ new Map();
10228
+ comments.forEach((comment, index) => {
10229
+ const root = findRoot(index);
10230
+ const group = groups.get(root) ?? [];
10231
+ group.push(comment);
10232
+ groups.set(root, group);
10233
+ });
10234
+ return groups;
10235
+ };
10236
+ const mergeDuplicateBodyTrackedChangeComments = (groups) => {
10237
+ const duplicates = /* @__PURE__ */ new Map();
10238
+ groups.forEach(([survivor, ...duplicateRows]) => {
10239
+ if (!survivor || duplicateRows.length === 0) return;
10240
+ const resolvedDuplicate = duplicateRows.find((comment) => comment.resolvedTime != null);
10241
+ if (survivor.resolvedTime == null && resolvedDuplicate) {
10242
+ survivor.resolvedTime = resolvedDuplicate.resolvedTime;
10243
+ survivor.resolvedById = resolvedDuplicate.resolvedById;
10244
+ survivor.resolvedByEmail = resolvedDuplicate.resolvedByEmail;
10245
+ survivor.resolvedByName = resolvedDuplicate.resolvedByName;
10246
+ survivor.trackedChangeDecision = resolvedDuplicate.trackedChangeDecision;
10247
+ }
10248
+ survivor.trackedChangePositionAliases = normalizeTrackedChangePositionAliases([...normalizeTrackedChangePositionAliases(survivor.trackedChangePositionAliases), ...duplicateRows.flatMap((comment) => [
10249
+ comment.commentId,
10250
+ comment.importedId,
10251
+ comment.trackedChangeCanonicalId,
10252
+ ...normalizeTrackedChangePositionAliases(comment.trackedChangePositionAliases)
10253
+ ])]);
10254
+ duplicateRows.forEach((comment) => duplicates.set(comment, survivor));
10255
+ });
10256
+ return duplicates;
10257
+ };
10258
+ const createDroppedCommentIdMap = (duplicates) => {
10259
+ const droppedCommentIds = /* @__PURE__ */ new Map();
10260
+ duplicates.forEach((survivor, duplicate) => {
10261
+ const fromId = normalizeCommentId(duplicate.commentId);
10262
+ const toId = normalizeCommentId(survivor.commentId);
10263
+ if (fromId && toId) droppedCommentIds.set(fromId, toId);
10264
+ });
10265
+ return droppedCommentIds;
10266
+ };
10267
+ const remapTrackedChangeReferences = (droppedCommentIds, activeDocumentId) => {
10268
+ const remapSelection = (selection) => {
10269
+ const selectedId = normalizeCommentId(selection.value);
10270
+ if (selectedId && droppedCommentIds.has(selectedId)) selection.value = droppedCommentIds.get(selectedId);
10271
+ };
10272
+ remapSelection(activeComment);
10273
+ remapSelection(activeFloatingCommentInstanceId);
10274
+ commentsList.value.forEach((row) => {
10275
+ if (!belongsToTrackedChangeSyncDocument(row, activeDocumentId)) return;
10276
+ const rowIdentityUpdates = {};
10277
+ for (const field of [
10278
+ "trackedChangeThreadParentId",
10279
+ "trackedChangeParentId",
10280
+ "threadingParentCommentId",
10281
+ "parentCommentId"
10282
+ ]) {
10283
+ const replacementId = droppedCommentIds.get(normalizeCommentId(row?.[field]));
10284
+ if (!replacementId) continue;
10285
+ row[field] = replacementId;
10286
+ rowIdentityUpdates[field] = replacementId;
10287
+ }
10288
+ if (Object.keys(rowIdentityUpdates).length && typeof row.updateIdentityValues === "function") row.updateIdentityValues(rowIdentityUpdates);
10289
+ });
10290
+ };
10291
+ const compactDuplicateBodyTrackedChangeComments = (activeDocumentId) => {
10292
+ const candidates = commentsList.value.filter((comment) => isBodyTrackedChangeComment(comment) && belongsToTrackedChangeSyncDocument(comment, activeDocumentId));
10293
+ const groups = groupBodyTrackedChangeCommentsByIdentity(candidates);
10294
+ const duplicates = mergeDuplicateBodyTrackedChangeComments(groups);
10295
+ if (!duplicates.size) return 0;
10296
+ commentsList.value = commentsList.value.filter((comment) => !duplicates.has(comment));
10297
+ remapTrackedChangeReferences(createDroppedCommentIdMap(duplicates), activeDocumentId);
10298
+ return duplicates.size;
10299
+ };
10191
10300
  /**
10192
10301
  * Remove tracked-change comments that no longer have a corresponding mark in the editor.
10193
10302
  * Also removes any replies linked to those removed tracked-change threads.
@@ -10233,7 +10342,9 @@ var useCommentsStore = defineStore("comments", () => {
10233
10342
  if (importedId) removedIds.add(importedId);
10234
10343
  return false;
10235
10344
  });
10345
+ compactDuplicateBodyTrackedChangeComments(activeDocumentId);
10236
10346
  restoredComments.forEach((comment) => {
10347
+ if (!commentsList.value.includes(comment)) return;
10237
10348
  const payload = getCommentEventPayload(comment);
10238
10349
  const event = {
10239
10350
  type: COMMENT_EVENTS.UPDATE,
@@ -10823,11 +10934,14 @@ var useCommentsStore = defineStore("comments", () => {
10823
10934
  } finally {
10824
10935
  endInteractionSpan(identitySpan, trackedChangeIdentityIndex.work());
10825
10936
  }
10826
- if (!effectiveDocumentId || !pruneStale) return {
10827
- liveIds,
10828
- liveAnchorKeys,
10829
- appliedCount
10830
- };
10937
+ if (!effectiveDocumentId || !pruneStale) {
10938
+ if (effectiveDocumentId) compactDuplicateBodyTrackedChangeComments(String(effectiveDocumentId));
10939
+ return {
10940
+ liveIds,
10941
+ liveAnchorKeys,
10942
+ appliedCount
10943
+ };
10944
+ }
10831
10945
  pruneStaleTrackedChangeComments(liveIds, liveAnchorKeys, String(effectiveDocumentId), superdoc, { broadcastChanges: false });
10832
10946
  return {
10833
10947
  liveIds,
@@ -16137,6 +16251,8 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
16137
16251
  const isCompactCommentsMode = (0, vue.ref)(false);
16138
16252
  let commentsContainerResizeObserver = null;
16139
16253
  let compactMeasurementTarget = null;
16254
+ let documentWidthResizeObserver = null;
16255
+ let documentWidthTargets = [];
16140
16256
  const isValidMeasurementTarget = (element) => {
16141
16257
  if (!(element instanceof HTMLElement)) return false;
16142
16258
  if ((typeof window !== "undefined" ? window.getComputedStyle(element) : null)?.display === "contents") return false;
@@ -16190,7 +16306,25 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
16190
16306
  if (Number.isFinite(rectWidth) && rectWidth > 0) return rectWidth;
16191
16307
  return 0;
16192
16308
  };
16309
+ const ensureDocumentWidthObserver = () => {
16310
+ const ResizeObserverClass = typeof window !== "undefined" ? window.ResizeObserver : void 0;
16311
+ if (typeof ResizeObserverClass === "undefined") return;
16312
+ const documentElement = superdocRoot.value?.querySelector?.(SUPERDOC_DOCUMENT_SELECTOR) ?? null;
16313
+ const nextTargets = [layers.value, documentElement].filter((el, index, all) => el instanceof HTMLElement && all.indexOf(el) === index);
16314
+ if (nextTargets.length === documentWidthTargets.length && nextTargets.every((el, index) => el === documentWidthTargets[index])) return;
16315
+ if (documentWidthResizeObserver) {
16316
+ documentWidthResizeObserver.disconnect();
16317
+ documentWidthResizeObserver = null;
16318
+ }
16319
+ documentWidthTargets = nextTargets;
16320
+ if (!nextTargets.length) return;
16321
+ documentWidthResizeObserver = new ResizeObserverClass(() => {
16322
+ recalculateCompactCommentsMode();
16323
+ });
16324
+ nextTargets.forEach((el) => documentWidthResizeObserver.observe(el));
16325
+ };
16193
16326
  const getMeasuredDocumentWidth = () => {
16327
+ ensureDocumentWidthObserver();
16194
16328
  const documentElement = superdocRoot.value?.querySelector?.(SUPERDOC_DOCUMENT_SELECTOR);
16195
16329
  const layersElement = layers.value;
16196
16330
  const measuredFromDocument = Number(documentElement?.clientWidth ?? documentElement?.getBoundingClientRect?.().width ?? 0);
@@ -16229,6 +16363,11 @@ function useCommentSmallScreen({ commentsModuleConfig, superdocRoot, layers }) {
16229
16363
  commentsContainerResizeObserver = null;
16230
16364
  }
16231
16365
  compactMeasurementTarget = null;
16366
+ if (documentWidthResizeObserver) {
16367
+ documentWidthResizeObserver.disconnect();
16368
+ documentWidthResizeObserver = null;
16369
+ }
16370
+ documentWidthTargets = [];
16232
16371
  });
16233
16372
  return {
16234
16373
  superdocContainerWidth,
@@ -22789,7 +22928,8 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
22789
22928
  error: new Error(message),
22790
22929
  code: reason,
22791
22930
  ...documentId ? { documentId } : {},
22792
- editor: null
22931
+ editor: null,
22932
+ ...workerFailure ? { workerFailure } : {}
22793
22933
  });
22794
22934
  const bootDiagnostic = translateBootFailureReason(reason, detail, {
22795
22935
  documentId,
@@ -23992,7 +24132,7 @@ var SuperDoc_default = /*#__PURE__*/ require__plugin_vue_export_helper._plugin_v
23992
24132
  ], 38);
23993
24133
  };
23994
24134
  }
23995
- }, [["__scopeId", "data-v-01062725"]]);
24135
+ }, [["__scopeId", "data-v-770204b4"]]);
23996
24136
  //#endregion
23997
24137
  //#region src/core/create-app.js
23998
24138
  var PINIA_DEVTOOLS_SETUP_EVENT = "devtools-plugin:setup";
@@ -45188,7 +45328,7 @@ var SuperDoc = class extends require_eventemitter3.import_eventemitter3.default
45188
45328
  this.config.colors = shuffleArray(this.config.colors);
45189
45329
  this.userColorMap = /* @__PURE__ */ new Map();
45190
45330
  this.colorIndex = 0;
45191
- this.version = "2.12.0-next.1";
45331
+ this.version = "2.12.0-next.11";
45192
45332
  this.#log("🦋 [superdoc] Using SuperDoc version:", this.version);
45193
45333
  this.superdocId = config.superdocId || require_uuid.v4();
45194
45334
  this.colors = this.config.colors ?? [];