superdoc 2.0.0-next.44 → 2.0.0-next.46

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 (34) hide show
  1. package/AGENTS.md +15 -8
  2. package/dist/chunks/{create-super-doc-ui-DYky1UEo.cjs → create-super-doc-ui-6FUZ9d-y.cjs} +204 -159
  3. package/dist/chunks/{create-super-doc-ui-BFz0iim0.es.js → create-super-doc-ui-DCFTmVRK.es.js} +205 -160
  4. package/dist/collaboration-upgrade-engine.cjs +1 -1
  5. package/dist/collaboration-upgrade-engine.es.js +1 -1
  6. package/dist/document-api/src/contract/command-catalog.d.ts +1 -1
  7. package/dist/document-api/src/contract/operation-definitions.d.ts +1 -1
  8. package/dist/public/ui-react.cjs +17 -14
  9. package/dist/public/ui-react.es.js +17 -14
  10. package/dist/public/ui.cjs +1 -1
  11. package/dist/public/ui.es.js +1 -1
  12. package/dist/style.css +28 -28
  13. package/dist/style.layered.css +28 -28
  14. package/dist/superdoc/src/components/surfaces/FindReplaceSurface.vue.d.ts +2 -2
  15. package/dist/superdoc/src/components/surfaces/PasswordPromptSurface.vue.d.ts +2 -2
  16. package/dist/superdoc/src/components/surfaces/SurfaceExternalMount.vue.d.ts +2 -2
  17. package/dist/superdoc/src/composables/use-find-replace.d.ts +2 -2
  18. package/dist/superdoc/src/core/SuperDoc.d.ts +41 -0
  19. package/dist/superdoc/src/core/types/index.d.ts +76 -30
  20. package/dist/superdoc/src/internal/toolbar/built-in-toolbar.d.ts +5 -5
  21. package/dist/superdoc/src/public/browser-document-api.d.ts +53 -0
  22. package/dist/superdoc/src/public/index.d.cts +4 -0
  23. package/dist/superdoc/src/public/index.d.ts +2 -0
  24. package/dist/superdoc/src/public/ui/react.d.ts +18 -7
  25. package/dist/superdoc/src/public/ui/types.d.ts +81 -12
  26. package/dist/superdoc/src/public/ui-react.d.ts +4 -3
  27. package/dist/superdoc/src/public/ui.d.cts +8 -0
  28. package/dist/superdoc/src/public/ui.d.ts +1 -1
  29. package/dist/superdoc.cjs +85 -141
  30. package/dist/superdoc.es.js +85 -141
  31. package/dist-cdn/style.layered.css +1 -1
  32. package/dist-cdn/superdoc.min.css +1 -1
  33. package/dist-cdn/superdoc.min.js +36 -36
  34. package/package.json +2 -2
@@ -1,25 +1,13 @@
1
1
  import { Doc as YDoc } from 'yjs';
2
2
  import { HocuspocusProviderWebsocket } from '@hocuspocus/provider';
3
3
  import { Ref, ComputedRef } from 'vue';
4
- import { DocumentApi } from '../../../../document-api/src/index.js';
5
4
  import { DocumentFontOption, FontAssetUrlResolver, FontFamilyOption, FontLoadSummary, FontResolutionRecord } from '../../../../shared/font-system/src/index.js';
6
5
  import { SuperDoc as SuperDocClass } from '../SuperDoc.js';
7
6
  import { SuperDocActiveEditorExtensions, SuperDocExtension } from '../extensions/index.js';
7
+ import { BrowserDocumentApi } from '../../public/browser-document-api.js';
8
8
  export type { DocumentFontOption, FontAssetUrlContext, FontAssetUrlResolver, FontFaceSlot, FontFamilyOption, FontLoadResult, FontLoadStatus, FontLoadSummary, FontResolutionReason, FontResolutionRecord, GlyphException, ResolvedFontEvidence, SubstitutePolicyAction, SubstituteVerdict, } from '../../../../shared/font-system/src/index.js';
9
9
  export type SuperDoc = SuperDocClass;
10
- type MaybePromise<T> = T | Promise<T>;
11
- type BrowserDocumentApiObject<T> = {
12
- [K in keyof T]: BrowserDocumentApiValue<T[K]>;
13
- };
14
- type BrowserDocumentApiValue<T> = T extends (...args: infer Args) => infer Return ? ((...args: Args) => MaybePromise<Awaited<Return>>) & BrowserDocumentApiObject<T> : T extends object ? BrowserDocumentApiObject<T> : T;
15
- /**
16
- * Browser V2 active-editor Document API facade (`superdoc.activeEditor.doc`).
17
- * In the browser this surface is intentionally async-capable: callers must
18
- * tolerate promise-returning reads/writes, including the default
19
- * worker-backed runtime. SDK/headless callers should continue using the
20
- * synchronous `@superdoc/document-api` surface directly.
21
- */
22
- export type BrowserDocumentApi = BrowserDocumentApiObject<DocumentApi>;
10
+ export type { BrowserDocumentApi } from '../../public/browser-document-api.js';
23
11
  export type V2AuthoringSelectionCollapse = 'start' | 'end' | null;
24
12
  export type V2AuthoringResult = {
25
13
  ok: true;
@@ -1639,17 +1627,31 @@ export interface Modules {
1639
1627
  /** Collaboration module configuration. */
1640
1628
  collaboration?: CollaborationConfig;
1641
1629
  /**
1642
- * Toolbar module configuration. Pass `true` to enable the toolbar with
1643
- * defaults (equivalent to an empty object). The `selector`, `groups`,
1644
- * `icons`, and `texts` fields fall back to the top-level `Config.toolbar`,
1645
- * `Config.toolbarGroups`, `Config.toolbarIcons`, and `Config.toolbarTexts`
1646
- * aliases respectively if not set here.
1630
+ * Toolbar module configuration. Pass `true` to configure the toolbar with
1631
+ * defaults (equivalent to an empty object).
1632
+ *
1633
+ * This field configures the toolbar's contents and behavior; it does not by
1634
+ * itself provide a place to render it. A toolbar is only rendered once a
1635
+ * mount target resolves, from either `selector` here or the top-level
1636
+ * `Config.toolbar`. Without one, SuperDoc still creates the
1637
+ * `superdoc.toolbar` handle (item lookup and command routing keep working)
1638
+ * but renders no toolbar UI.
1639
+ *
1640
+ * Fallbacks to the top-level aliases are per field: `selector` falls back to
1641
+ * `Config.toolbar`, `icons` to `Config.toolbarIcons`, and `texts` to
1642
+ * `Config.toolbarTexts`. `Config.toolbarGroups` supplies the group ordering,
1643
+ * not `groups`: the two are different settings. `groups` maps group ids to
1644
+ * item ids (composition) and has no top-level alias, so omitting it uses the
1645
+ * built-in composition. Supplying it also replaces the group ordering with
1646
+ * its own keys.
1647
1647
  */
1648
1648
  toolbar?: boolean | ({
1649
1649
  /**
1650
- * CSS selector (id or class) for the DOM element to render the toolbar
1651
- * into. Must be a string selector, not an `HTMLElement` reference. Falls
1652
- * back to `Config.toolbar` if omitted.
1650
+ * Selector for the DOM element to render the toolbar into: an id
1651
+ * selector (`#toolbar`), a class selector (`.toolbar`), or a bare
1652
+ * element id (`toolbar`). Must be a string, not an `HTMLElement`
1653
+ * reference — pass an element through the top-level `Config.toolbar`.
1654
+ * Falls back to `Config.toolbar` if omitted.
1653
1655
  */
1654
1656
  selector?: string;
1655
1657
  /** Toolbar item ids to hide from the default set. */
@@ -2348,7 +2350,18 @@ export interface Config {
2348
2350
  role?: 'editor' | 'viewer' | 'suggester';
2349
2351
  /**
2350
2352
  * The document to load. If a string, it will be treated as a URL. If a File
2351
- * or Blob, it will be used directly.
2353
+ * or Blob, it will be used directly. For a v2 collaboration room, pass a
2354
+ * structured document carrying `v2Collaboration`.
2355
+ *
2356
+ * Omitting this field and `documents` mounts a blank DOCX, so the Editor
2357
+ * opens a real document rather than an empty surface. The blank document is
2358
+ * a supported v2 source; it is seeded before mount and behaves like any
2359
+ * other opened DOCX, including export.
2360
+ *
2361
+ * Setting the v1 `modules.collaboration` field also suppresses that seeding,
2362
+ * but it is not a supported v2 path: the runtime fails closed with
2363
+ * `collaboration-v1-config-unsupported` and mounts only enough state to
2364
+ * report that error.
2352
2365
  */
2353
2366
  document?: object | string | globalThis.File | globalThis.Blob;
2354
2367
  /** Password for encrypted DOCX files. Forwarded during document load. */
@@ -2371,8 +2384,26 @@ export interface Config {
2371
2384
  modules?: Modules;
2372
2385
  /** Top-level override for permission checks. */
2373
2386
  permissionResolver?: (params: PermissionResolverParams) => boolean | undefined;
2374
- /** Optional DOM element to render the toolbar in. */
2375
- toolbar?: string;
2387
+ /**
2388
+ * Where to render the built-in toolbar. Either an `HTMLElement`, or a
2389
+ * selector string in one of the supported forms: an id selector (`#toolbar`),
2390
+ * a class selector (`.toolbar`), or a bare element id (`toolbar`). Other CSS
2391
+ * selector syntax is not supported — an attribute or descendant selector such
2392
+ * as `[data-toolbar]` resolves to nothing and leaves the toolbar unrendered.
2393
+ *
2394
+ * SuperDoc renders into the resolved element but does not manage its
2395
+ * placement, and never includes it in the `contained` layout calculation.
2396
+ * Where the application puts it therefore decides the space it needs: a
2397
+ * sibling of a 400px `contained` Editor adds its own height alongside it,
2398
+ * while a toolbar placed inside that host consumes part of the 400px and can
2399
+ * overflow it.
2400
+ *
2401
+ * Omitting this field (and `modules.toolbar.selector`) renders no toolbar.
2402
+ * `modules.toolbar: true` on its own does not render one either — it creates
2403
+ * the `superdoc.toolbar` handle without a mount target. See
2404
+ * {@link Modules.toolbar}.
2405
+ */
2406
+ toolbar?: string | HTMLElement;
2376
2407
  /** Toolbar groups to show. */
2377
2408
  toolbarGroups?: string[];
2378
2409
  /** Icons to show in the toolbar. */
@@ -2574,11 +2605,26 @@ export interface Config {
2574
2605
  /** Document view options (OOXML ST_View compatible). */
2575
2606
  viewOptions?: ViewOptions;
2576
2607
  /**
2577
- * Enable contained mode for fixed-height container embedding. When true,
2578
- * SuperDoc propagates height through its DOM tree and adds internal
2579
- * scrolling, so multi-page documents scroll within the consumer's
2580
- * fixed-height container. Default behavior (false) lets the document
2581
- * expand to its natural height.
2608
+ * Enable contained mode for fixed-height container embedding.
2609
+ *
2610
+ * SuperDoc supports two layout modes, and the host element's height
2611
+ * requirement differs between them:
2612
+ *
2613
+ * - Natural (default, `false`): the Editor grows to the document's full
2614
+ * height and the page scrolls. The host needs no height. Setting one does
2615
+ * not constrain the document or enable internal scrolling, because
2616
+ * SuperDoc leaves overflow visible in this mode, though application CSS
2617
+ * on the host can still clip what is drawn.
2618
+ * - Contained (`true`): SuperDoc propagates `height: 100%` through its DOM
2619
+ * tree and scrolls the document internally, so multi-page documents stay
2620
+ * inside the host. This mode requires the host to have a definite height
2621
+ * (for example `height: 400px`); without one there is nothing for the
2622
+ * percentage heights to resolve against.
2623
+ *
2624
+ * A toolbar mounted through `Config.toolbar` or `modules.toolbar.selector` is
2625
+ * never part of this calculation. Placed as a sibling of the host, its height
2626
+ * adds to the host's: a 400px host with a 40px toolbar occupies 440px in
2627
+ * total. Placed inside the host, it consumes part of the 400px instead.
2582
2628
  */
2583
2629
  contained?: boolean;
2584
2630
  /** Content Security Policy nonce for dynamically injected styles. */
@@ -177,14 +177,14 @@ export class BuiltInToolbar extends EventEmitter<string | symbol, any> {
177
177
  _detachFontsChanged: null;
178
178
  /** Active editor compatibility reference (set by `SuperDoc.setActiveEditor`). */
179
179
  activeEditor: any;
180
- /** Live shared command controller (single command-state truth). */
181
- ui: import('../../public/ui.js').SuperDocUI | null;
180
+ /** SuperDoc-owned command controller (single command-state truth). */
181
+ ui: any;
182
182
  /** Latest controller toolbar snapshot. */
183
- snapshot: import('../../public/ui.js').ToolbarSnapshotSlice | null;
183
+ snapshot: any;
184
184
  /** Controller subscription unsubscribe handle. */
185
- _unsubscribeController: (() => void) | null;
185
+ _unsubscribeController: any;
186
186
  /** Format-painter mode subscription unsubscribe handle. */
187
- _detachFormatPainterModeChange: (() => void) | null;
187
+ _detachFormatPainterModeChange: any;
188
188
  /** Registered custom-button command unregister handles. */
189
189
  _customCommandRegs: Map<any, any>;
190
190
  /** Signature of the last-built font options, to skip redundant rebuilds. */
@@ -0,0 +1,53 @@
1
+ import { DocumentApi } from '../../../document-api/src/index.js';
2
+ type MaybePromise<T> = T | Promise<T>;
3
+ type BrowserDocumentApiObject<T> = {
4
+ [K in keyof T]: BrowserDocumentApiValue<T[K]>;
5
+ };
6
+ type BrowserDocumentApiValue<T> = T extends (...args: infer Args) => infer Return ? ((...args: Args) => MaybePromise<Awaited<Return>>) & BrowserDocumentApiObject<T> : T extends object ? BrowserDocumentApiObject<T> : T;
7
+ /**
8
+ * Browser V2 active-editor Document API facade (`superdoc.activeEditor.doc`).
9
+ * In the browser this surface is intentionally async-capable: callers must
10
+ * tolerate promise-returning reads/writes, including the default
11
+ * worker-backed runtime. SDK/headless callers should continue using the
12
+ * synchronous `@superdoc/document-api` surface directly.
13
+ */
14
+ export type BrowserDocumentApi = BrowserDocumentApiObject<DocumentApi>;
15
+ /**
16
+ * Every operation optional, at any depth.
17
+ *
18
+ * A callable member keeps its call signature *and* its properties, mirroring
19
+ * what {@link BrowserDocumentApiValue} does. Parts of the Document API are both:
20
+ * `capabilities` is callable and carries `get()`, so reconstructing only the call
21
+ * signature would make `doc.capabilities.get()` a type error on a value that
22
+ * supports it at runtime.
23
+ *
24
+ * Intersected rather than unioned with the property bag. A union would let a
25
+ * non-callable object stand in for a callable member, which also makes the
26
+ * member type unenforceable: `{ comments: { list: 42 } }` satisfies a
27
+ * props-only alternative and the type stops catching wrong operations at all.
28
+ */
29
+ type DeepPartial<T> = T extends (...args: infer Args) => infer Return ? ((...args: Args) => Return) & {
30
+ [K in keyof T]?: DeepPartial<T[K]>;
31
+ } : T extends object ? {
32
+ [K in keyof T]?: DeepPartial<T[K]>;
33
+ } : T;
34
+ /**
35
+ * What a *host* may supply as `activeEditor.doc`.
36
+ *
37
+ * A host is duck-typed: a custom adapter or a test stub is expected to carry
38
+ * only the operations it actually implements, and the controller resolves
39
+ * operations defensively at runtime rather than assuming any of them exist.
40
+ * Requiring the whole surface here would reject exactly the partial hosts the
41
+ * contract is documented to accept.
42
+ *
43
+ * `CustomCommandContext.doc` uses this same partial type, because that value is
44
+ * the host's own object passed straight through. It can promise no more than the
45
+ * host contract does. {@link BrowserDocumentApi}, the complete facade, is the
46
+ * type of `activeEditor.doc` on a real `Editor`.
47
+ *
48
+ * Partial, not permissive: the operations a host does declare are still
49
+ * checked, so a typo or a wrong member type fails instead of passing as
50
+ * `any`.
51
+ */
52
+ export type PartialBrowserDocumentApi = DeepPartial<BrowserDocumentApi>;
53
+ export {};
@@ -5,6 +5,7 @@ import type { BlockNavigationAddress as __Cjs_BlockNavigationAddress } from './i
5
5
  import type { BlocksListResult as __Cjs_BlocksListResult } from './index.js' with { "resolution-mode": "import" };
6
6
  import type { BookmarkAddress as __Cjs_BookmarkAddress } from './index.js' with { "resolution-mode": "import" };
7
7
  import type { BookmarkInfo as __Cjs_BookmarkInfo } from './index.js' with { "resolution-mode": "import" };
8
+ import type { BorrowedSuperDocUI as __Cjs_BorrowedSuperDocUI } from './index.js' with { "resolution-mode": "import" };
8
9
  import type { CanPerformPermissionParams as __Cjs_CanPerformPermissionParams } from './index.js' with { "resolution-mode": "import" };
9
10
  import type { CollaborationConfig as __Cjs_CollaborationConfig } from './index.js' with { "resolution-mode": "import" };
10
11
  import type { CommentAddress as __Cjs_CommentAddress } from './index.js' with { "resolution-mode": "import" };
@@ -133,6 +134,7 @@ import type { SuperDocStoryLocator as __Cjs_SuperDocStoryLocator } from './index
133
134
  import type { SuperDocTelemetryConfig as __Cjs_SuperDocTelemetryConfig } from './index.js' with { "resolution-mode": "import" };
134
135
  import type { SuperDocTextAddress as __Cjs_SuperDocTextAddress } from './index.js' with { "resolution-mode": "import" };
135
136
  import type { SuperDocTextTarget as __Cjs_SuperDocTextTarget } from './index.js' with { "resolution-mode": "import" };
137
+ import type { SuperDocUI as __Cjs_SuperDocUI } from './index.js' with { "resolution-mode": "import" };
136
138
  import type { SuperDocViewportChangePayload as __Cjs_SuperDocViewportChangePayload } from './index.js' with { "resolution-mode": "import" };
137
139
  import type { SuperDocViewportMetrics as __Cjs_SuperDocViewportMetrics } from './index.js' with { "resolution-mode": "import" };
138
140
  import type { SuperDocVisibleRange as __Cjs_SuperDocVisibleRange } from './index.js' with { "resolution-mode": "import" };
@@ -175,6 +177,7 @@ export type { __Cjs_BlockNavigationAddress as BlockNavigationAddress };
175
177
  export type { __Cjs_BlocksListResult as BlocksListResult };
176
178
  export type { __Cjs_BookmarkAddress as BookmarkAddress };
177
179
  export type { __Cjs_BookmarkInfo as BookmarkInfo };
180
+ export type { __Cjs_BorrowedSuperDocUI as BorrowedSuperDocUI };
178
181
  export declare const buildTheme: typeof import('./index.js', { with: { "resolution-mode": "import" } }).buildTheme;
179
182
  export type { __Cjs_CanPerformPermissionParams as CanPerformPermissionParams };
180
183
  export type { __Cjs_CollaborationConfig as CollaborationConfig };
@@ -312,6 +315,7 @@ export type { __Cjs_SuperDocStoryLocator as SuperDocStoryLocator };
312
315
  export type { __Cjs_SuperDocTelemetryConfig as SuperDocTelemetryConfig };
313
316
  export type { __Cjs_SuperDocTextAddress as SuperDocTextAddress };
314
317
  export type { __Cjs_SuperDocTextTarget as SuperDocTextTarget };
318
+ export type { __Cjs_SuperDocUI as SuperDocUI };
315
319
  export type { __Cjs_SuperDocViewportChangePayload as SuperDocViewportChangePayload };
316
320
  export type { __Cjs_SuperDocViewportMetrics as SuperDocViewportMetrics };
317
321
  export type { __Cjs_SuperDocVisibleRange as SuperDocVisibleRange };
@@ -81,6 +81,8 @@ export type { SuperDocMeasurementUnitChangePayload } from '../core/types/index.j
81
81
  export type { SuperDocReadyPayload } from '../core/types/index.js';
82
82
  export type { SuperDocState } from '../core/types/index.js';
83
83
  export type { SuperDocTelemetryConfig } from '../core/types/index.js';
84
+ export type { BorrowedSuperDocUI } from './ui/types.js';
85
+ export type { SuperDocUI } from './ui/types.js';
84
86
  export type { SuperDocViewportChangePayload } from '../core/types/index.js';
85
87
  export type { SuperDocViewportMetrics } from '../core/types/index.js';
86
88
  export type { SuperDocZoomConfig } from '../core/types/index.js';
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- import { CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, SuperDocUI, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
2
+ import { BorrowedSuperDocUI, CommandState, CommentsSlice, ContentControlsSlice, DocumentSlice, FontFamilyOption, FontSizeOption, SelectionSlice, Subscribable, SuperDocLike, ToolbarSnapshotSlice, TrackChangesSlice, ZoomSlice } from './types.js';
3
3
  /** The raw SuperDoc instance (or host stub) handed to the provider. */
4
4
  export type SuperDocHost = SuperDocLike;
5
5
  /** Props accepted by {@link SuperDocUIProvider}. */
@@ -8,13 +8,24 @@ export interface SuperDocUIProviderProps {
8
8
  children?: ReactNode;
9
9
  }
10
10
  /**
11
- * Root provider. Owns the controller lifecycle: call {@link useSetSuperDoc}
12
- * from your editor-mount component's ready callback to bind a running SuperDoc
13
- * instance; the controller is created then and destroyed on unmount / rebind.
11
+ * Root provider. Call {@link useSetSuperDoc} from your editor-mount
12
+ * component's ready callback to bind a running SuperDoc instance; the hooks
13
+ * below then read that instance's own controller (`superdoc.ui`).
14
+ *
15
+ * The provider is a consumer, not an owner. SuperDoc creates the controller
16
+ * and destroys it in `superdoc.destroy()`, so unmounting or rebinding the
17
+ * provider leaves it running for the built-in toolbar and any other consumer
18
+ * of the same instance. Every React hook therefore observes the same command
19
+ * state the rest of the application sees.
14
20
  */
15
21
  export declare function SuperDocUIProvider(props: SuperDocUIProviderProps): import('react').ReactElement;
16
- /** Read the controller, or `null` until a SuperDoc instance is bound. */
17
- export declare function useSuperDocUI(): SuperDocUI | null;
22
+ /**
23
+ * Read the controller, or `null` until a SuperDoc instance is bound.
24
+ *
25
+ * Borrowed: the bound instance owns teardown, so the returned type omits
26
+ * `destroy()`. A provider-built fallback controller is disposed by the provider.
27
+ */
28
+ export declare function useSuperDocUI(): BorrowedSuperDocUI | null;
18
29
  /** Read the raw bound SuperDoc host, or `null` until one is bound. */
19
30
  export declare function useSuperDocHost(): SuperDocHost | null;
20
31
  /** Get the stable callback used to bind a running SuperDoc instance. */
@@ -46,7 +57,7 @@ export declare function toSliceSource<T>(source: SliceSource<T> | Subscribable<T
46
57
  * normalized via {@link toSliceSource}. `initial` is returned until the
47
58
  * controller is bound.
48
59
  */
49
- export declare function useSuperDocSlice<T>(pick: (ui: SuperDocUI) => SliceSource<T> | Subscribable<T>, initial: T): T;
60
+ export declare function useSuperDocSlice<T>(pick: (ui: BorrowedSuperDocUI) => SliceSource<T> | Subscribable<T>, initial: T): T;
50
61
  /** Subscribe to the selection slice. */
51
62
  export declare function useSuperDocSelection(): SelectionSlice;
52
63
  /** Subscribe to the comments slice. */
@@ -1,4 +1,5 @@
1
1
  import { CommentsListQuery as DocumentApiCommentsListQuery, CommentsListResult, TrackChangesListResult, EntityAddress, TextAddress, TextTarget, ScrollIntoViewInput, ScrollIntoViewOutput, SelectionInfo, SelectionTarget, Receipt, ReceiptFailureCode, ContentControlInfo, StyleCatalogItem, StyleCatalogDiagnostic, StyleCatalogSourceStatus, StylesGetCatalogInput, StylesGetCatalogResult } from '../../../../document-api/src/index.js';
2
+ import { PartialBrowserDocumentApi } from '../browser-document-api.js';
2
3
  import { SuperDocUIReason } from './reasons.js';
3
4
  /**
4
5
  * v2-native `superdoc/ui` controller types.
@@ -26,9 +27,10 @@ import { SuperDocUIReason } from './reasons.js';
26
27
  * (`scripts/ensure-types.cjs` `rewriteDocApiPaths`), so no bare private
27
28
  * specifier leaks into the emitted `.d.ts`.
28
29
  */
29
- export type { Receipt, SelectionInfo, SelectionTarget, SelectionPoint, TextTarget, TextAddress, ScrollIntoViewInput, ScrollIntoViewOutput, EntityAddress, CommentsListQuery as DocumentApiCommentsListQuery, CommentsListResult, TrackChangesListResult, ContentControlsListResult, ContentControlInfo, } from '../../../../document-api/src/index.js';
30
+ export type { Receipt, SelectionInfo, SelectionTarget, SelectionPoint, TextTarget, TextAddress, ScrollIntoViewInput, ScrollIntoViewOutput, DocumentApi, EntityAddress, CommentsListQuery as DocumentApiCommentsListQuery, CommentsListResult, TrackChangesListResult, ContentControlsListResult, ContentControlInfo, } from '../../../../document-api/src/index.js';
30
31
  export type { StyleCatalogView, StyleCatalogItemType, StyleCatalogFilterType, StyleProvenance, StyleCatalogItemVisibility, StyleCatalogItemUsage, StyleCatalogItemPreview, StyleCatalogItem, StyleCatalogDefaults, StyleCatalogDiagnostic, StyleCatalogSourceStatus, StylesGetCatalogInput, StylesGetCatalogResult, } from '../../../../document-api/src/index.js';
31
32
  export type { ListPresetId } from '../../../../document-api/src/index.js';
33
+ export type { BrowserDocumentApi, PartialBrowserDocumentApi } from '../browser-document-api.js';
32
34
  export type { SuperDocUIReason } from './reasons.js';
33
35
  /** Equality predicate used to suppress redundant slice notifications. */
34
36
  export type EqualityFn<T> = (a: T, b: T) => boolean;
@@ -414,14 +416,44 @@ export interface CustomCommandContext<TPayload = unknown> {
414
416
  editor: SuperDocEditorLike | null;
415
417
  superdoc: SuperDocLike;
416
418
  context?: ViewportContext;
417
- /** The live UI controller (shared command-state truth). */
418
- ui: SuperDocUI;
419
+ /**
420
+ * The live UI controller (shared command-state truth).
421
+ *
422
+ * Borrowed: a custom command runs against whichever controller invoked it,
423
+ * which for `superdoc.ui.commands.register(...)` is the instance-owned
424
+ * singleton the built-in toolbar also reads. Typing this as the owned form
425
+ * would let a command callback destroy it, which is the hole the borrowed
426
+ * handle exists to close.
427
+ *
428
+ * Borrowed unconditionally, including for a controller you built with
429
+ * `createSuperDocUI()`. That costs an owner nothing: you necessarily hold the
430
+ * owned reference already, since you called `.commands.register(...)` on it,
431
+ * so tear it down through that instead of through the context. Varying this
432
+ * by ownership would mean `SuperDocUI` and {@link BorrowedSuperDocUI} needing
433
+ * different `commands` handles, and the borrowed form is derived from the
434
+ * owned one precisely so the two cannot drift.
435
+ */
436
+ ui: BorrowedSuperDocUI;
419
437
  /** Run a catalog command id through the shared controller. */
420
438
  execute(id: string, payload?: unknown): CommandExecutionResult;
421
439
  /** Run a catalog command id and await its settled result. */
422
440
  executeAsync(id: string, payload?: unknown): Promise<CommandExecutionResult>;
423
- /** Public browser Document API facade (read-only-guarded, async-capable), or `null` when unavailable. */
424
- doc: Record<string, any> | null;
441
+ /**
442
+ * The host's browser Document API facade (read-only-guarded, async-capable),
443
+ * or `null` when unavailable.
444
+ *
445
+ * Partial for the same reason {@link SuperDocEditorLike.doc} is: this is the
446
+ * host's own object handed straight through, and a duck-typed host is only
447
+ * required to carry the operations it implements. Typing it as the complete
448
+ * facade would promise operations a custom adapter or stub never defines.
449
+ *
450
+ * Prefer {@link CustomCommandContext.execute}, `executeAsync`, and
451
+ * `insertText` where they cover the work: those route through the controller
452
+ * and fail closed with a reason or a receipt when an operation is missing.
453
+ * Reach for `doc` when you need an operation the controller does not route,
454
+ * and guard the call.
455
+ */
456
+ doc: PartialBrowserDocumentApi | null;
425
457
  /** Read-only selection snapshot at invocation time. */
426
458
  selection: SelectionSlice;
427
459
  /** Current document mode. */
@@ -1228,14 +1260,23 @@ export interface SearchHandle extends SnapshotSubscribable<SearchSlice> {
1228
1260
  export interface SuperDocEditorLike {
1229
1261
  /** Runtime evidence of the bundled v2 editor. */
1230
1262
  editorVersion?: number;
1231
- /** Public, read-only-guarded browser Document API facade (async-capable in browser). */
1232
- doc?: Record<string, any> | null;
1263
+ /**
1264
+ * Public, read-only-guarded browser Document API facade (async-capable in
1265
+ * browser). Partial by design: this is what a host supplies, and a stub or
1266
+ * custom adapter carries only the operations it implements.
1267
+ *
1268
+ * `CustomCommandContext.doc` is the same partial type, because the controller
1269
+ * passes this object straight through and can promise no more than the host
1270
+ * does. {@link BrowserDocumentApi}, the complete facade, is the type of
1271
+ * `activeEditor.doc` on a real `Editor`.
1272
+ */
1273
+ doc?: PartialBrowserDocumentApi | null;
1233
1274
  /** Stable reason the Document API is unavailable. */
1234
1275
  documentApiUnavailableReason?: string | null;
1235
1276
  /** Editor-scoped event subscription. */
1236
- on?(event: string, handler: (...args: any[]) => void): unknown;
1277
+ on?(event: string, handler: (...args: unknown[]) => void): unknown;
1237
1278
  /** Editor-scoped event unsubscription. */
1238
- off?(event: string, handler: (...args: any[]) => void): unknown;
1279
+ off?(event: string, handler: (...args: unknown[]) => void): unknown;
1239
1280
  /** Export the active editor's document. */
1240
1281
  exportDocx?(...args: unknown[]): Promise<unknown>;
1241
1282
  /** Save the active editor's document. */
@@ -1251,10 +1292,19 @@ export interface SuperDocEditorLike {
1251
1292
  export interface SuperDocLike {
1252
1293
  /** The routed active editor, when one is mounted. */
1253
1294
  activeEditor?: SuperDocEditorLike | null;
1295
+ /**
1296
+ * The host-owned UI controller. A real `SuperDoc` instance always exposes
1297
+ * one and owns its lifecycle; bare structural stubs may not, which is why
1298
+ * this is optional. Consumers should read it rather than build their own.
1299
+ *
1300
+ * Borrowed, not owned: the host tears this down, so the type omits
1301
+ * `destroy()` and a reader cannot call it.
1302
+ */
1303
+ ui?: BorrowedSuperDocUI;
1254
1304
  /** Lifecycle event subscription. */
1255
- on?(event: string, handler: (...args: any[]) => void): unknown;
1305
+ on?(event: string, handler: (...args: unknown[]) => void): unknown;
1256
1306
  /** Lifecycle event unsubscription. */
1257
- off?(event: string, handler: (...args: any[]) => void): unknown;
1307
+ off?(event: string, handler: (...args: unknown[]) => void): unknown;
1258
1308
  /** Set the document mode across the instance. */
1259
1309
  setDocumentMode?(mode: string): unknown;
1260
1310
  /** Export the active document. */
@@ -1351,6 +1401,25 @@ export interface SuperDocUI {
1351
1401
  readonly formatPainter: FormatPainterHandle;
1352
1402
  /** Create a disposable subscription scope. */
1353
1403
  createScope(): SuperDocUIScope;
1354
- /** Tear down all subscriptions and detach from the host. */
1404
+ /**
1405
+ * Tear down all subscriptions and detach from the host.
1406
+ *
1407
+ * Only the owner calls this. A controller obtained from `createSuperDocUI()`
1408
+ * is owned by its caller. The one at `superdoc.ui` is owned by the instance
1409
+ * and is typed {@link BorrowedSuperDocUI}, which does not carry this method.
1410
+ */
1355
1411
  destroy(): void;
1356
1412
  }
1413
+ /**
1414
+ * The controller as a *consumer* sees it: everything except `destroy()`.
1415
+ *
1416
+ * This is what `superdoc.ui` and the React hooks return. The instance owns that
1417
+ * controller and tears it down in `superdoc.destroy()`, so a consumer calling
1418
+ * `destroy()` would freeze command state for the built-in toolbar and every
1419
+ * other reader of the same instance. Omitting the method makes that a compile
1420
+ * error rather than a documented convention nobody reads.
1421
+ *
1422
+ * Derived from {@link SuperDocUI} rather than declared separately so the two
1423
+ * cannot drift: every handle added there appears here automatically.
1424
+ */
1425
+ export type BorrowedSuperDocUI = Omit<SuperDocUI, 'destroy'>;
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * SuperDoc public facade: `superdoc/ui/react` entry.
3
3
  *
4
- * v2-native React bindings for the `createSuperDocUI` controller: the
5
- * provider, the lifecycle bind hook, the generic slice hook, and the domain
6
- * hooks.
4
+ * v2-native React bindings for the SuperDoc-owned UI controller
5
+ * (`superdoc.ui`): the provider, the bind hook, the generic slice hook, and
6
+ * the domain hooks. This layer consumes the controller; SuperDoc creates and
7
+ * destroys it.
7
8
  *
8
9
  * v2 NOTE: this is NOT the v1 re-export. It routes through the local,
9
10
  * self-contained v2 React layer under `./ui/react.ts`, which is built on the
@@ -1,5 +1,7 @@
1
1
  // Generated by scripts/ensure-types.cjs. Do not edit by hand.
2
2
  import type { ActiveParagraphStyle as __Cjs_ActiveParagraphStyle } from './ui.js' with { "resolution-mode": "import" };
3
+ import type { BorrowedSuperDocUI as __Cjs_BorrowedSuperDocUI } from './ui.js' with { "resolution-mode": "import" };
4
+ import type { BrowserDocumentApi as __Cjs_BrowserDocumentApi } from './ui.js' with { "resolution-mode": "import" };
3
5
  import type { CommandExecutionResult as __Cjs_CommandExecutionResult } from './ui.js' with { "resolution-mode": "import" };
4
6
  import type { CommandHandle as __Cjs_CommandHandle } from './ui.js' with { "resolution-mode": "import" };
5
7
  import type { CommandsHandle as __Cjs_CommandsHandle } from './ui.js' with { "resolution-mode": "import" };
@@ -22,6 +24,7 @@ import type { CustomCommandHandle as __Cjs_CustomCommandHandle } from './ui.js'
22
24
  import type { CustomCommandHandleState as __Cjs_CustomCommandHandleState } from './ui.js' with { "resolution-mode": "import" };
23
25
  import type { CustomCommandRegistration as __Cjs_CustomCommandRegistration } from './ui.js' with { "resolution-mode": "import" };
24
26
  import type { CustomCommandRegistrationResult as __Cjs_CustomCommandRegistrationResult } from './ui.js' with { "resolution-mode": "import" };
27
+ import type { DocumentApi as __Cjs_DocumentApi } from './ui.js' with { "resolution-mode": "import" };
25
28
  import type { DocumentHandle as __Cjs_DocumentHandle } from './ui.js' with { "resolution-mode": "import" };
26
29
  import type { DocumentSlice as __Cjs_DocumentSlice } from './ui.js' with { "resolution-mode": "import" };
27
30
  import type { EntityAddress as __Cjs_EntityAddress } from './ui.js' with { "resolution-mode": "import" };
@@ -31,6 +34,7 @@ import type { FontsHandle as __Cjs_FontsHandle } from './ui.js' with { "resoluti
31
34
  import type { FontSizeOption as __Cjs_FontSizeOption } from './ui.js' with { "resolution-mode": "import" };
32
35
  import type { FontsSlice as __Cjs_FontsSlice } from './ui.js' with { "resolution-mode": "import" };
33
36
  import type { MetadataHandle as __Cjs_MetadataHandle } from './ui.js' with { "resolution-mode": "import" };
37
+ import type { PartialBrowserDocumentApi as __Cjs_PartialBrowserDocumentApi } from './ui.js' with { "resolution-mode": "import" };
34
38
  import type { Receipt as __Cjs_Receipt } from './ui.js' with { "resolution-mode": "import" };
35
39
  import type { ScrollIntoViewInput as __Cjs_ScrollIntoViewInput } from './ui.js' with { "resolution-mode": "import" };
36
40
  import type { ScrollIntoViewOutput as __Cjs_ScrollIntoViewOutput } from './ui.js' with { "resolution-mode": "import" };
@@ -90,6 +94,8 @@ import type { WorkflowScrollResult as __Cjs_WorkflowScrollResult } from './ui.js
90
94
  import type { ZoomHandle as __Cjs_ZoomHandle } from './ui.js' with { "resolution-mode": "import" };
91
95
  import type { ZoomSlice as __Cjs_ZoomSlice } from './ui.js' with { "resolution-mode": "import" };
92
96
  export type { __Cjs_ActiveParagraphStyle as ActiveParagraphStyle };
97
+ export type { __Cjs_BorrowedSuperDocUI as BorrowedSuperDocUI };
98
+ export type { __Cjs_BrowserDocumentApi as BrowserDocumentApi };
93
99
  export declare const BUILT_IN_COMMAND_IDS: typeof import('./ui.js', { with: { "resolution-mode": "import" } }).BUILT_IN_COMMAND_IDS;
94
100
  export type { __Cjs_CommandExecutionResult as CommandExecutionResult };
95
101
  export type { __Cjs_CommandHandle as CommandHandle };
@@ -114,6 +120,7 @@ export type { __Cjs_CustomCommandHandle as CustomCommandHandle };
114
120
  export type { __Cjs_CustomCommandHandleState as CustomCommandHandleState };
115
121
  export type { __Cjs_CustomCommandRegistration as CustomCommandRegistration };
116
122
  export type { __Cjs_CustomCommandRegistrationResult as CustomCommandRegistrationResult };
123
+ export type { __Cjs_DocumentApi as DocumentApi };
117
124
  export type { __Cjs_DocumentHandle as DocumentHandle };
118
125
  export type { __Cjs_DocumentSlice as DocumentSlice };
119
126
  export type { __Cjs_EntityAddress as EntityAddress };
@@ -123,6 +130,7 @@ export type { __Cjs_FontsHandle as FontsHandle };
123
130
  export type { __Cjs_FontSizeOption as FontSizeOption };
124
131
  export type { __Cjs_FontsSlice as FontsSlice };
125
132
  export type { __Cjs_MetadataHandle as MetadataHandle };
133
+ export type { __Cjs_PartialBrowserDocumentApi as PartialBrowserDocumentApi };
126
134
  export type { __Cjs_Receipt as Receipt };
127
135
  export type { __Cjs_ScrollIntoViewInput as ScrollIntoViewInput };
128
136
  export type { __Cjs_ScrollIntoViewOutput as ScrollIntoViewOutput };
@@ -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, SuperDocUIOptions, SuperDocUIState, SuperDocUIScope, SuperDocLike, SuperDocEditorLike, CommandHandle, CommandState, CommandExecutionResult, WorkflowReceipt, WorkflowActionResult, WorkflowScrollResult, SelectionRestoreResult, SuperDocUIReason, CommandsHandle, ContextMenuItem, CustomCommandHandle, CustomCommandHandleState, CustomCommandRegistration, CustomCommandRegistrationResult, MetadataHandle, SelectionHandle, ToolbarHandle, CommentsHandle, TrackChangesHandle, ContentControlsHandle, ContentControlFocusResult, FontsHandle, ZoomHandle, DocumentHandle, ViewportHandle, StylesHandle, ActiveParagraphStyle, SliceStatus, SelectionSlice, SelectionCapture, CommentAnchorCapture, ToolbarSnapshotSlice, CommentsSlice, TrackChangesSlice, ContentControlsSlice, FontsSlice, ZoomSlice, DocumentSlice, StylesSlice, 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, Receipt, SelectionInfo, SelectionTarget, SelectionPoint, TextTarget, TextAddress, ScrollIntoViewInput, ScrollIntoViewOutput, EntityAddress, CommentsListResult, TrackChangesListResult, ContentControlsListResult, ContentControlInfo, } 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, CommandsHandle, ContextMenuItem, CustomCommandHandle, CustomCommandHandleState, CustomCommandRegistration, CustomCommandRegistrationResult, MetadataHandle, SelectionHandle, ToolbarHandle, CommentsHandle, TrackChangesHandle, ContentControlsHandle, ContentControlFocusResult, FontsHandle, ZoomHandle, DocumentHandle, ViewportHandle, StylesHandle, ActiveParagraphStyle, SliceStatus, SelectionSlice, SelectionCapture, CommentAnchorCapture, ToolbarSnapshotSlice, CommentsSlice, TrackChangesSlice, ContentControlsSlice, FontsSlice, ZoomSlice, DocumentSlice, StylesSlice, 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, } from './ui/types.js';