> ## Documentation Index
> Fetch the complete documentation index at: https://superdoc-caio-pizzol-docs-ai-core-preset.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Methods

Methods are functions you call on the SuperDoc instance to perform actions.

## Document operations

### `export`

Export the document with various options.

<ParamField path="options" type="Object">
  Export configuration

  <Expandable title="properties" defaultOpen>
    <ParamField path="exportType" type="string[]" default="['docx']">
      Export formats
    </ParamField>

    <ParamField path="isFinalDoc" type="boolean" default="false">
      Replace fields with values
    </ParamField>

    <ParamField path="commentsType" type="string" default="'external'">
      Comment handling: 'external', 'clean', or custom
    </ParamField>

    <ParamField path="exportedName" type="string" default="'document'">
      Base filename
    </ParamField>

    <ParamField path="triggerDownload" type="boolean" default="true">
      Automatically trigger a browser file download. Set to `false` to get a `Blob` back without downloading.
    </ParamField>

    <ParamField path="fieldsHighlightColor" type="string" default="'#FFFF00'">
      Field highlight color
    </ParamField>
  </Expandable>
</ParamField>

**Returns:** `Promise<Blob>` - Document blob

<CodeGroup>
  ```javascript Usage theme={null}
  const blob = await superdoc.export({
    isFinalDoc: true,
    commentsType: 'clean',
  });
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: async ({ superdoc }) => {
      const blob = await superdoc.export({
        isFinalDoc: true,
        commentsType: 'clean',
      });
    },
  });
  ```
</CodeGroup>

### `save`

Save document if in collaboration mode.

**Returns:** `Promise<void>`

<CodeGroup>
  ```javascript Usage theme={null}
  await superdoc.save();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: async ({ superdoc }) => {
      await superdoc.save();
    },
  });
  ```
</CodeGroup>

### `getHTML`

Get HTML content of all editors.

<ParamField path="options" type="Object">
  HTML options

  <Expandable title="properties">
    <ParamField path="unflattenLists" type="boolean" default="false">
      Preserve nested list structure
    </ParamField>
  </Expandable>
</ParamField>

**Returns:** `string[]` - Array of HTML strings, one per editor

<CodeGroup>
  ```javascript Usage theme={null}
  const htmlArray = superdoc.getHTML();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const htmlArray = superdoc.getHTML();
      console.log(htmlArray);
    },
  });
  ```
</CodeGroup>

## Collaboration methods

### `upgradeToCollaboration`

Promote a local SuperDoc instance into collaboration without creating a new instance.

<Warning>
  This is a promotion flow, not a passive join flow. SuperDoc seeds the target
  room with the current local document state, comments, and lock state.
</Warning>

<ParamField path="options" type="Object" required>
  Upgrade configuration

  <Expandable title="properties" defaultOpen>
    <ParamField path="ydoc" type="Y.Doc" required>
      The Yjs document for the target room
    </ParamField>

    <ParamField path="provider" type="Object" required>
      The collaboration provider connected to the same room as `ydoc`
    </ParamField>
  </Expandable>
</ParamField>

**Returns:** `Promise<void>`

**Requirements:**

* The SuperDoc instance must already be ready
* The instance must not already be collaborative
* The current instance must contain a single DOCX document
* You must provide a matching `{ ydoc, provider }` pair

<Note>
  SuperDoc waits for provider sync internally. You do not need to wait for the
  provider's `sync` event before calling this method.
</Note>

<CodeGroup>
  ```javascript Usage theme={null}
  await superdoc.upgradeToCollaboration({ ydoc, provider });
  ```

  ```javascript Full Example theme={null}
  import * as Y from 'yjs';
  import { WebsocketProvider } from 'y-websocket';
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: file,
    user: {
      name: 'John Smith',
      email: 'john@example.com',
    },
  });

  superdoc.on('ready', async () => {
    const ydoc = new Y.Doc();
    const provider = new WebsocketProvider('wss://collab.example.com', 'document-123', ydoc);

    await superdoc.upgradeToCollaboration({ ydoc, provider });
  });
  ```
</CodeGroup>

See [Upgrade to Collaboration](/editor/collaboration/upgrade-to-collaboration) for the full workflow guide.

## Mode control

### `setDocumentMode`

Change the document mode.

<ParamField path="mode" type="string" required>
  New document mode

  <Expandable title="Available modes">
    * `'viewing'` - Read-only
    * `'suggesting'` - Track changes
    * `'editing'` - Normal editing
  </Expandable>
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setDocumentMode('suggesting');
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setDocumentMode('suggesting');
    },
  });
  ```
</CodeGroup>

### `lockSuperdoc`

Lock or unlock the document.

<ParamField path="isLocked" type="boolean" required>
  Lock state
</ParamField>

<ParamField path="lockedBy" type="User">
  User who locked the document
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.lockSuperdoc(true, currentUser);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.lockSuperdoc(true, {
        name: 'Jane Smith',
        email: 'jane@example.com',
      });
    },
  });
  ```
</CodeGroup>

### `setHighContrastMode`

Enable/disable high contrast mode.

<ParamField path="enabled" type="boolean" required>
  High contrast state
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setHighContrastMode(true);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setHighContrastMode(true);
    },
  });
  ```
</CodeGroup>

## UI methods

### `setActiveEditor`

Set which editor is currently active. Useful when working with multiple documents.

<ParamField path="editor" type="Editor" required>
  Editor instance to set as active
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setActiveEditor(editor);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  /** @type {Array<import('superdoc').Editor>} */
  const createdEditors = [];

  const superdoc = new SuperDoc({
    selector: '#editor',
    documents: [doc1, doc2],
    onEditorCreate: ({ editor }) => {
      // Each per-document editor reaches `onEditorCreate` in `documents` order.
      createdEditors.push(editor);

      // Switch to the second editor as soon as it exists.
      if (createdEditors.length === 2) {
        queueMicrotask(() => {
          superdoc.setActiveEditor(editor);
        });
      }
    },
  });
  ```
</CodeGroup>

### `setDisableContextMenu`

Toggle the custom context menu at runtime.

<ParamField path="disabled" type="boolean" default="true">
  Whether to disable the context menu
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setDisableContextMenu(true);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setDisableContextMenu(true);
    },
  });
  ```
</CodeGroup>

### `openSurface`

Open a `dialog` or `floating` surface above the document.

**Returns:** `SurfaceHandle`

<ParamField path="request" type="Object" required>
  Surface request. Set `mode` to `'dialog'` or `'floating'`, then provide content via `render` (framework-agnostic) or `component` (Vue). See [Surfaces](/editor/superdoc/surfaces) for the full request shape.
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  const handle = superdoc.openSurface({
    mode: 'floating',
    title: 'Find',
    floating: { placement: 'top-right', width: 360 },
    render: ({ container }) => {
      container.innerHTML = '<input placeholder="Find..." style="width:100%" />';
    },
  });
  ```

  ```javascript Full Example theme={null}
  const handle = superdoc.openSurface({
    mode: 'dialog',
    title: 'Confirm action',
    render: ({ container, close }) => {
      container.innerHTML = '<button type="button">Close</button>';
      container.querySelector('button')?.addEventListener('click', () => close('manual-close'));
    },
  });

  const outcome = await handle.result;
  console.log(outcome.status);
  ```
</CodeGroup>

See [Surfaces](/editor/superdoc/surfaces) for the full request shape, Vue/React examples, and resolver-based usage.

### `closeSurface`

Close a specific surface by id, or the topmost active surface when no id is provided. When both a dialog and a floating surface are open, the dialog closes first.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.closeSurface();
  ```

  ```javascript Full Example theme={null}
  const handle = superdoc.openSurface({
    mode: 'floating',
    title: 'Find',
    render: ({ container }) => {
      container.innerHTML = '<input placeholder="Find..." style="width:100%" />';
    },
  });

  superdoc.closeSurface(handle.id);
  ```
</CodeGroup>

See [Surfaces](/editor/superdoc/surfaces) for lifecycle behavior and close ordering.

### `setTrackedChangesPreferences`

Override how tracked changes are rendered in the layout engine.

<ParamField path="preferences" type="Object">
  <Expandable title="properties" defaultOpen>
    <ParamField path="mode" type="string">
      Rendering mode: `'review'`, `'original'`, `'final'`, or `'off'`
    </ParamField>

    <ParamField path="enabled" type="boolean">
      Whether tracked change metadata is included
    </ParamField>
  </Expandable>
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setTrackedChangesPreferences({ mode: 'final' });
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setTrackedChangesPreferences({ mode: 'final' });
    },
  });
  ```
</CodeGroup>

### `toggleRuler`

Toggle ruler visibility.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.toggleRuler();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.toggleRuler();
    },
  });
  ```
</CodeGroup>

<ParamField path="togglePagination" type="string" deprecated>
  <Warning>**Removed in v1.0**: Pagination is now handled by the layout engine. Use `viewOptions.layout` in [configuration](/editor/superdoc/configuration) instead.</Warning>
</ParamField>

### `getZoom`

Get the current zoom level as a percentage.

**Returns:** `number` - Current zoom level (e.g., `100`, `150`, `200`). Defaults to `100`.

<CodeGroup>
  ```javascript Usage theme={null}
  const zoom = superdoc.getZoom();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const zoom = superdoc.getZoom();
      console.log(`Current zoom: ${zoom}%`);
    },
  });
  ```
</CodeGroup>

### `setZoom`

Set an explicit zoom level and switch zoom mode to `manual`. Use `setZoomMode('fit-width')` to turn automatic fitting back on.

<ParamField path="percent" type="number" required>
  Zoom level as a percentage (e.g., `100`, `150`, `200`). Must be a positive finite number.
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setZoom(150);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setZoom(150);

      superdoc.on('zoomChange', ({ zoom, mode }) => {
        console.log(`Zoom changed to ${zoom}% (${mode})`);
      });
    },
  });
  ```
</CodeGroup>

### `setZoomMode`

Switch between manual zoom and automatic fit-width zoom. `'fit-width'` keeps DOCX and PDF documents fitted to the available container width, using the bounds from [`zoom.fitWidth`](/editor/superdoc/configuration#param-zoom). Calling `setZoom()` switches back to `'manual'`.

<ParamField path="mode" type="'manual' | 'fit-width'" required>
  The zoom mode to switch to.
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.setZoomMode('fit-width');
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.setZoomMode('fit-width');

      superdoc.on('zoomChange', ({ zoom, mode }) => {
        console.log(`Zoom: ${zoom}% (${mode})`);
      });
    },
  });
  ```
</CodeGroup>

### `getZoomState`

Get the current zoom mode, value, latest fit calculation, and effective fit bounds.

**Returns:** `SuperDocZoomState` - `{ mode, value, fitZoom, min, max }`. `fitZoom` is `null` before the first viewport measurement.

<CodeGroup>
  ```javascript Usage theme={null}
  const { mode, value, fitZoom } = superdoc.getZoomState();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const state = superdoc.getZoomState();
      console.log(`Mode: ${state.mode}, value: ${state.value}%`);
    },
  });
  ```
</CodeGroup>

### `getViewportMetrics`

Get the latest fit-width measurements. Use this when you need custom zoom behavior instead of `zoom.mode: 'fit-width'`.

**Returns:** `SuperDocViewportMetrics | null` - `{ availableWidth, documentWidth, fitZoom }`, or `null` until the first measurement (editors still mounting).

<CodeGroup>
  ```javascript Usage theme={null}
  const metrics = superdoc.getViewportMetrics();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const metrics = superdoc.getViewportMetrics();
      if (metrics) {
        superdoc.setZoom(Math.min(100, metrics.fitZoom));
      }
    },
  });
  ```
</CodeGroup>

### `focus`

Focus the active editor or first available.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.focus();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.focus();
    },
  });
  ```
</CodeGroup>

## Search methods

### `search`

Search for text or regex in active editor.

<ParamField path="query" type="string | RegExp" required>
  Search query
</ParamField>

**Returns:** `Array<SearchResult>` - Search matches

<CodeGroup>
  ```javascript Usage theme={null}
  const results = superdoc.search('contract');
  const regexResults = superdoc.search(/section \d+/gi);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const results = superdoc.search('contract');
      if (results) {
        console.log(`Found ${results.length} matches`);
      }

      const regexResults = superdoc.search(/section \d+/gi);
    },
  });
  ```
</CodeGroup>

### `goToSearchResult`

Navigate to a search result.

<ParamField path="match" type="SearchResult" required>
  Search result to navigate to
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.goToSearchResult(results[0]);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const results = superdoc.search('contract');
      if (results && results.length) {
        superdoc.goToSearchResult(results[0]);
      }
    },
  });
  ```
</CodeGroup>

## Comments methods

<Note>
  **`addCommentsList` and `removeCommentsList` mount the built-in comments sidebar.** For custom React UI, render your own panel from `useSuperDocComments` instead: see [Custom UI › Comments](/editor/custom-ui/comments). The methods below stay supported for apps using the built-in sidebar.
</Note>

### `addCommentsList`

Add a comments list to the specified element.

<ParamField path="element" type="HTMLElement" required>
  Container element for the comments list
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  const sidebar = document.getElementById('comments-sidebar');
  if (sidebar) superdoc.addCommentsList(sidebar);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      const sidebar = document.getElementById('comments-sidebar');
      if (sidebar) superdoc.addCommentsList(sidebar);
    },
  });
  ```
</CodeGroup>

### `removeCommentsList`

Remove the comments list.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.removeCommentsList();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.removeCommentsList();
    },
  });
  ```
</CodeGroup>

### `scrollToComment`

Scroll to a comment in the document and set it as active.

<ParamField path="commentId" type="string" required>
  The comment ID to scroll to
</ParamField>

<ParamField path="options" type="object">
  Scroll behavior options

  <Expandable>
    <ParamField path="behavior" type="ScrollBehavior" default="smooth">
      Scroll behavior: `"smooth"`, `"instant"`, or `"auto"`
    </ParamField>

    <ParamField path="block" type="ScrollLogicalPosition" default="start">
      Vertical alignment: `"start"`, `"center"`, `"end"`, or `"nearest"`
    </ParamField>
  </Expandable>
</ParamField>

**Returns:** `boolean`: `true` if the comment was found, `false` otherwise.

<CodeGroup>
  ```javascript Usage theme={null}
  // Get a comment ID from the document API
  const editor = superdoc.activeEditor;
  if (editor) {
    const { items } = editor.doc.comments.list();
    if (items.length > 0) superdoc.scrollToComment(items[0].id);
  }
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    modules: { comments: {} },
    onReady: ({ superdoc }) => {
      const editor = superdoc.activeEditor;
      if (!editor) return;
      const { items } = editor.doc.comments.list();
      if (items.length > 0) {
        superdoc.scrollToComment(items[0].id, {
          behavior: 'smooth',
          block: 'center',
        });
      }
    },
  });
  ```
</CodeGroup>

### `scrollToElement`

Scroll to any document element by its ID. Pass a paragraph `nodeId`, comment `entityId`, or tracked change `entityId`: the method figures out what kind of element it is and scrolls there.

<ParamField path="elementId" type="string" required>
  The element's stable ID. Get this from `query.match` results (`address.nodeId`), `comments.list` (`entityId`), or `trackChanges.list` (`entityId`).
</ParamField>

**Returns:** `Promise<boolean>`: `true` if the element was found and scrolled to, `false` otherwise. Never throws.

<CodeGroup>
  ```javascript Usage theme={null}
  // Get a paragraph's nodeId from the Document API
  const result = editor.doc.query.match({
    select: { type: 'text', pattern: 'Introduction', mode: 'contains' },
    require: 'first',
  });
  const first = result.items[0];
  if (first && first.address.kind === 'block') {
    await superdoc.scrollToElement(first.address.nodeId);
  }
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    modules: { comments: {} },
    onReady: async ({ superdoc }) => {
      const editor = superdoc.activeEditor;
      if (!editor) return;

      // Navigate to a paragraph (block addresses carry `nodeId`; narrow first)
      const match = editor.doc.query.match({
        select: { type: 'text', pattern: 'Summary', mode: 'contains' },
        require: 'first',
      });
      const first = match.items[0];
      if (first && first.address.kind === 'block') {
        await superdoc.scrollToElement(first.address.nodeId);
      }

      // Navigate to a comment
      const comments = editor.doc.comments.list();
      if (comments.items.length > 0) {
        await superdoc.scrollToElement(comments.items[0].id);
      }

      // Navigate to a tracked change
      const changes = editor.doc.trackChanges.list();
      if (changes.items.length > 0) {
        await superdoc.scrollToElement(changes.items[0].id);
      }
    },
  });
  ```
</CodeGroup>

<Info>
  For DOCX-imported documents, paragraph `nodeId` values come from the OOXML `paraId` attribute and are stable across sessions. See [cross-session block addressing](/document-api/common-workflows#cross-session-block-addressing) for the full pattern.
</Info>

## User management

### `addSharedUser`

Add a user to the shared users list.

<ParamField path="user" type="User" required>
  User to add

  <Expandable title="User properties">
    <ParamField path="name" type="string" required>
      Display name
    </ParamField>

    <ParamField path="email" type="string" required>
      Email address
    </ParamField>
  </Expandable>
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.addSharedUser({
    name: 'Jane Smith',
    email: 'jane@example.com',
  });
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.addSharedUser({
        name: 'Jane Smith',
        email: 'jane@example.com',
      });
    },
  });
  ```
</CodeGroup>

### `removeSharedUser`

Remove a user from shared users.

<ParamField path="email" type="string" required>
  Email of user to remove
</ParamField>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.removeSharedUser('jane@example.com');
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      superdoc.removeSharedUser('jane@example.com');
    },
  });
  ```
</CodeGroup>

## Lifecycle

### `destroy`

Completely destroy the SuperDoc instance.

<Warning>This is irreversible. Cleans up all resources, events, and DOM.</Warning>

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.destroy();
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
  });

  // Later, when you're done with the editor:
  superdoc.destroy();
  ```
</CodeGroup>

## Event methods

### `on`

Subscribe to an event.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.on('ready', ({ superdoc }) => {
    console.log('SuperDoc ready');
  });
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
  });

  superdoc.on('ready', ({ superdoc }) => {
    console.log('SuperDoc ready');
  });
  ```
</CodeGroup>

### `once`

Subscribe to an event once.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.once('ready', () => {
    // Only called once
  });
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
  });

  superdoc.once('ready', () => {
    console.log('SuperDoc ready (one-time)');
  });
  ```
</CodeGroup>

### `off`

Unsubscribe from an event.

<CodeGroup>
  ```javascript Usage theme={null}
  superdoc.off('ready', handler);
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
  });

  /** @param {import('superdoc').SuperDocReadyPayload} payload */
  const handler = ({ superdoc }) => {
    console.log('SuperDoc ready');
  };

  superdoc.on('ready', handler);

  // Later, unsubscribe:
  superdoc.off('ready', handler);
  ```
</CodeGroup>

## Schema introspection

### `getSchemaIntrospection`

Returns a JSON schema summary with all nodes, marks, and their attributes. Useful for AI agents that need schema context.

```javascript theme={null}
import { getSchemaIntrospection } from 'superdoc';

const schema = await getSchemaIntrospection({ mode: 'docx' });
// Returns: { version, nodes: [...], marks: [...] }
```

<ParamField path="options" type="Object">
  <Expandable title="properties">
    <ParamField path="editor" type="Editor">
      Existing Editor instance to introspect. If provided, uses this instead of creating a temporary editor.
    </ParamField>

    <ParamField path="extensions" type="Array">
      Custom extensions to use when building the schema.
    </ParamField>

    <ParamField path="mode" type="string" default="'docx'">
      Editor mode: `'docx'`, `'html'`, or `'text'`
    </ParamField>
  </Expandable>
</ParamField>

## TypeScript types

SuperDoc exports TypeScript interfaces for all node and mark types:

```typescript theme={null}
import type { NodeName, NodeAttrs, ParagraphAttrs } from 'superdoc/types';

// NodeName shows all 39 node types in autocomplete
type Test = NodeAttrs<'paragraph'>; // Resolves to ParagraphAttrs
```

Available types: `NodeName`, `NodeAttrs<N>`, `MarkName`, `MarkAttrs<M>`, and specific interfaces like `ParagraphAttrs`, `TableAttrs`, `ImageAttrs`, etc.

## Properties

### `activeEditor`

Currently active editor instance. Returns `null` before the `ready` event.

<CodeGroup>
  ```javascript Usage theme={null}
  if (superdoc.activeEditor) {
    superdoc.activeEditor.commands.toggleBold();
  }
  ```

  ```javascript Full Example theme={null}
  import { SuperDoc } from 'superdoc';
  import 'superdoc/style.css';

  const superdoc = new SuperDoc({
    selector: '#editor',
    document: yourFile,
    onReady: ({ superdoc }) => {
      if (superdoc.activeEditor) {
        superdoc.activeEditor.commands.toggleBold();
      }
    },
  });
  ```
</CodeGroup>

<Warning>Always check for `null` before accessing.</Warning>

<Note>
  **For new code, prefer the typed surfaces.** `superdoc.activeEditor.commands.X()` is the chain-command path; it stays supported for backwards compatibility but isn't the recommended starting point. Use [`editor.doc.*`](/document-api/overview) for document mutations (insert, replace, format, comments, tracked changes) and [`ui.commands.*`](/editor/custom-ui/toolbar-and-commands) for React UI dispatch (typed, memoized per command).
</Note>

| Property          | Type                   | Description                         |
| ----------------- | ---------------------- | ----------------------------------- |
| `superdocId`      | `string`               | Unique identifier for this instance |
| `version`         | `string`               | SuperDoc version number             |
| `activeEditor`    | `Editor \| null`       | Currently active editor             |
| `element`         | `HTMLElement \| null`  | Container DOM element               |
| `state`           | `{ documents, users }` | Current state snapshot              |
| `isLocked`        | `boolean`              | Whether the document is locked      |
| `lockedBy`        | `User \| null`         | User who locked the document        |
| `isCollaborative` | `boolean`              | Whether collaboration is enabled    |
| `user`            | `User`                 | Current user information            |
| `users`           | `User[]`               | All users with document access      |
| `toolbar`         | `Toolbar \| null`      | Toolbar instance if configured      |
