# DiagramInstance

Import it from `@grafloria/renderer`.

```ts
interface DiagramInstance
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `viewport` | `ViewportController` |  |  |
| `interaction` | `InteractionController` |  |  |
| `animations` | `AnimationService` |  | The renderer's animation service. Host policy lives here: global enable/speed, reduced-motion overrides, and the battery-saver auto-toggle (`updateConfig({ respectBatteryStatus: false })` to opt out — on by default, and on a low unplugged battery it disables edge animations). |
| `registry` | `DiagramRegistry` |  | THIS diagram's contribution registry — shapes, named styles, link/label templates, markers, anchors, connection points, connectors, animations. |
| `container` | `HTMLElement` |  | Escape hatches for hosts and tests. |
| `scheduler` | `RenderScheduler` |  |  |
| `patcher` | `VNodePatcher` |  |  |

**Members**

- `setNodes(nodes: NodeInput[]): void`
- `setEdges(edges: EdgeInput[]): void`
- `setGroups(groups: Array<GroupSpec | GroupModel>): void` — Reconcile the zones (groups) — add, restyle, remove. Removing a zone keeps its boxes.
- `getModel(): DiagramModel`
- `getEngine(): DiagramEngine`
- `getCommentStore(): CommentStore | null` — The comment store, when `comments` was enabled; `null` otherwise.
- `on<K extends DiagramEventName>(event: K, handler: DiagramEventHandler<K>): Unsubscribe`
- `off<K extends DiagramEventName>(event: K, handler: DiagramEventHandler<K>): void`
- `setTheme(theme: Theme): void` — Theme swap (re-injects this instance's CSS variable block only).
- `setColorMode(mode: ColorMode, themes?: ThemeSet): void` — Follow the OS colour scheme (`'system'`), or pin light/dark.

`'system'` also honours `prefers-contrast: more` and forced-colors by
upgrading to the high-contrast theme — an accessibility preference outranks
an aesthetic one.
- `getColorMode(): ColorMode | undefined`
- `setTokenBridge(bridge: TokenBridge | null | undefined): void` — Re-point Grafloria's CSS variables at the host design system's tokens.
- `setHighlightConnected(value: boolean | HighlightConnectedOptions): void` — Turn the selected nodes' line highlight on (`true`, or options) or off
(`false`) — see `CreateDiagramOptions.highlightConnected`. Repaints.
- `setHighlighterConfig(value: boolean | Partial<HighlighterConfig>): void` — Turn the outline layer on (`true`, or an object of kinds) or off (`false`) —
see `CreateDiagramOptions.highlighterConfig`. Repaints.
- `getHighlightConnected(): boolean | HighlightConnectedOptions` — The current `highlightConnected` setting (`false` when off).
- `export(format?: ExportFormat, options?: ExportOptions): Promise<string>` — Export the CURRENT view. `'svg'` returns SVG source; `'png' | 'jpeg' |
'webp' | 'pdf'` return a `data:` URL.

Pass `{ embedModel: true }` (PNG and SVG) and the diagram model rides inside
the artifact — the exported file re-opens as an editable diagram.

THE ASYNC ONE, and the only one. If a custom node's `renderCustomNode` returned a
promise — "I draw later: a rAF, a fetch, a framework's render, a web font" — this
waits for it before reading the host, bounded by
{@link ExportOptions.customNodeTimeout}. The synchronous entry points below cannot,
and say so in their `warnings`. Read the fidelity report through
{@link ExportOptions.onWarnings}, which fires on every format.
- `exportSvgString(options?: ExportOptions): SvgExportResult` — Synchronous, DOM-free, deterministic. Carries `warnings`.

Synchronous means a widget whose painter is still running is captured as it stands
and REPORTED, not waited for — `await export('svg')` is the entry point that waits.
- `exportPdf(options?: ExportOptions): PdfExportResult` — A real vector PDF: paths stay paths, text stays selectable text.
- `getQualityState(): { tier: LODLevel; governor?: GovernorState }` — The LOD tier actually rendered, and the adaptive governor's last verdict.
- `fitView(padding?: number): void` — Frame all content.
- `render(): void` — Queue a repaint (coalesced into one frame).
- `renderNow(): void` — Repaint synchronously — use when you must measure right after a change.
- `batchUpdate(mutate: (model: DiagramModel) => void): void` — Apply many mutations as ONE frame.

```ts
diagram.batchUpdate((model) => {
  for (const n of model.getNodes()) n.setPosition(n.position.x + 10, n.position.y);
});
```

Two distinct things are coalesced, and they are coalesced in two different
places, which is worth being precise about:

- **Events.** `DiagramModel.beginBatch()` QUEUES its change events instead
    of firing them, so a thousand `setPosition()` calls do not walk a
    thousand listener chains on their way to the same rAF.
  - **Frames.** `RenderScheduler` folds every `schedule()` in a tick into one
    rAF callback, so the thousand mutations produce exactly one `render()`
    and one `reconcile()` — one patch, not a thousand.

Nesting is depth-counted (it bottoms out in `DiagramEntity`), so a batch
inside a batch is still one frame. `mutate` throwing does not strand the
model in batch mode.

It never paints synchronously — that is the point. If you need the DOM to be
correct before you measure it, follow with `renderNow()`.
- `exportText(options?: ExportTextOptions): string` — Mermaid-compatible text export (with the lossless sidecar by default) —
feed the result back to `loadText` for a full round-trip.
- `loadText(text: string, options?: ImportTextOptions): ImportTextResult` — Parse Mermaid-compatible text (sidecar-aware) and reconcile it INTO the
live diagram through the same spec reconciler `setNodes`/`setEdges` use —
listeners, plugins, and the renderer all stay attached.
- `dispose(): void`
- `getDraggingNodeIds(): string[]` — The nodes currently being dragged (past the movement
threshold). Custom node components receive this as the `dragging` prop.
- `beginLabelEdit( target: { type: 'node' | 'link-label'; nodeId?: string; linkId?: string; labelIndex?: number }, opts?: { seed?: string } ): boolean` — visio-depth — open the in-place label editor programmatically: a node's
label (`{ type: 'node', nodeId }`) or a link label
(`{ type: 'link-label', linkId, labelIndex }`). The seam a host's
context-menu Rename / F2 binding uses; the same editor + undoable commit
that double-click opens. `seed` replaces the text the editor opens with
(type-to-replace). Returns false when the target is missing, not editable,
or the instance is readonly.
