# Interfaces

Import these from `@grafloria/renderer`.

## Interfaces

### `Bounds`

```ts
interface Bounds
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `minX` | `number` |  |  |
| `minY` | `number` |  |  |
| `maxX` | `number` |  |  |
| `maxY` | `number` |  |  |

### `CanvasFrameStats`

Per-frame numbers the dirty-redraw path actually produces.

```ts
interface CanvasFrameStats
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `painted` | `number` |  | Elements drawn this frame. |
| `culled` | `number` |  | Elements skipped because they fell outside every dirty rect. |
| `dirtyRects` | `number` |  | Dirty rects this frame; 0 means a full repaint. |
| `fullRepaint` | `boolean` |  | True when the whole canvas was repainted. |
| `changedEntities` | `number` |  | Entities whose VNode changed. |

### `CanvasLike`

A canvas element, structurally — so tests can hand in a fake.

```ts
interface CanvasLike
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `width` | `number` |  |  |
| `height` | `number` |  |  |
| `style?` | `{ width?: string; height?: string; [key: string]: unknown }` |  |  |

**Members**

- `getContext(id: '2d', options?: unknown): Canvas2DLike | null`
- `toDataURL?(type?: string, quality?: number): string`

### `CanvasPick`

What was under the cursor.

```ts
interface CanvasPick
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `kind` | `HitRecord['kind']` |  |  |
| `id` | `string` |  |  |
| `vnode` | `VNode` |  |  |

### `CanvasRefusedEvent`

```ts
interface CanvasRefusedEvent
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `hazards` | `readonly CanvasHazard[]` |  |  |
| `explanation` | `string` |  |  |

### `CanvasRendererOptions`

```ts
interface CanvasRendererOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `canvas?` | `CanvasLike \| null` |  | The visible canvas. Required to paint; omit only for pure measurement. |
| `hitCanvas?` | `CanvasLike \| null` |  | The offscreen picking canvas. Created from `canvas`'s document when absent. Pass `null` (with `enableHitDetection: false`) to run without one. |
| `devicePixelRatio?` | `number` |  | Default: `globalThis.devicePixelRatio ?? 1`. Overridable for tests. |
| `theme?` | `Theme` |  |  |
| `producerConfig?` | `SVGRendererConfig` |  | Config for the VNode producer. Defaults match the SVG backend exactly. |
| `producer?` | `SVGRenderer` |  | Reuse an existing VNode producer — this is how a live diagram switches backends without rebuilding its scene (render-backend.ts). |
| `enableHitDetection?` | `boolean` |  | Enable the colour-keyed hit canvas. Default true. |
| `hitCanvasScale?` | `number` |  | Sub-sampling factor for the hit canvas. 1 = pixel-exact picking (default). 0.5 halves its memory at the cost of ~1px of picking slop. |
| `enableDirtyRegions?` | `boolean` |  | Enable dirty-rectangle partial redraw. Default true. |
| `styleHost?` | `Element \| null` |  | Element whose computed `--grafloria-*` custom properties override the theme — normally the canvas's host. This is what lets a host theme canvas mode with the same CSS variables it uses for SVG mode. |

### `CanvasSafety`

```ts
interface CanvasSafety
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `safe` | `boolean` |  | True when nothing would be lost by drawing this diagram on a canvas. |
| `hazards` | `CanvasHazard[]` |  | Everything that would be lost. Empty iff `safe`. |

### `CanvasSafetyInput`

```ts
interface CanvasSafetyInput
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `a11yActive` | `boolean` |  |  |
| `focusInside` | `boolean` |  |  |
| `hasForeignObject` | `boolean` |  |  |

### `ComputedStyle`

Everything the painter needs to know to draw one element.

```ts
interface ComputedStyle
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `fill?` | `string` |  |  |
| `stroke?` | `string` |  |  |
| `strokeWidth` | `number` |  |  |
| `strokeDasharray?` | `number[]` |  |  |
| `opacity` | `number` |  | Element opacity, already multiplied down the group chain. |
| `fillOpacity?` | `number` |  |  |
| `strokeOpacity?` | `number` |  |  |
| `fontFamily` | `string` |  |  |
| `fontSize` | `number` |  |  |
| `fontWeight` | `string` |  |  |
| `fontStyle` | `string` |  |  |
| `textAnchor` | `'start' \| 'middle' \| 'end'` |  |  |
| `dominantBaseline` | `string` |  |  |
| `visible` | `boolean` |  | `display: none` / `visibility: hidden` → not painted at all. |
| `filter?` | `string` |  | CSS filter string (e.g. `blur(4px)`), passed through when supported. |
| `clipPathId?` | `string` |  | `clip-path: url(#id)` → the referenced clip id. |

### `DirtyDiff`

```ts
interface DirtyDiff
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `rects` | `Bounds[] \| null` |  | World rects to repaint, or `null` for "repaint everything" (first frame, camera move, theme swap, or too much changed to be worth clipping). |
| `changed` | `string[]` |  | Entities whose VNode object is new this frame. |
| `removed` | `string[]` |  | Entities that disappeared. |

### `EntityScope`

The entity a subtree belongs to.

```ts
interface EntityScope
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `kind` | `HitKind` |  |  |
| `id` | `string` |  |  |
| `key` | `string` |  | The VNode key — `node-n1`, and therefore the dirty tracker's entity key. |

### `EntitySnapshot`

The bounds of one top-level entity, and the VNode that produced them.

```ts
interface EntitySnapshot
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `vnode` | `VNode` |  |  |
| `bounds` | `Bounds \| null` |  |  |

### `HitRecord`

One pickable region, in WORLD coordinates.

Produced by the paint pass, consumed by both picking strategies (the colour-
keyed hit canvas and the geometric fallback). `zIndex` is paint order, so the
last-painted region under the cursor is the topmost one — which is the same
rule `DiagramModel.getNodeAtPosition` applies when it iterates nodes in
reverse.

```ts
interface HitRecord
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `kind` | `HitKind` |  |  |
| `id` | `string` |  | Entity id (node id / link id / port id). |
| `cmds` | `PathCmd[]` |  | World-space geometry — the exact path that was drawn. |
| `filled` | `boolean` |  | True when the region is the filled interior; false when it is the stroke. |
| `tolerance` | `number` |  | Pick tolerance for stroke regions (world units, half-width). |
| `zIndex` | `number` |  | Paint order. |
| `vnode` | `VNode` |  | The VNode that produced the region (the `IRenderer.hitTest` return value). |
| `colorKey` | `string` |  | Colour key for the offscreen picking canvas (`#rrggbb`). |
| `bounds` | `Bounds \| null` |  |  |

### `Matrix`

A 2D affine transform, in the order a canvas `setTransform(a,b,c,d,e,f)` takes.

```ts
interface Matrix
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `a` | `number` |  |  |
| `b` | `number` |  |  |
| `c` | `number` |  |  |
| `d` | `number` |  |  |
| `e` | `number` |  |  |
| `f` | `number` |  |  |

### `PaintOptions`

```ts
interface PaintOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `worldToDevice` | `Matrix` |  | World → device matrix (viewBox + zoom + devicePixelRatio, composed). |
| `dirtyWorld?` | `Bounds[]` |  | Only repaint elements intersecting these WORLD rects. Omit for a full repaint. The caller is responsible for having clipped/cleared them. |
| `pickingPass?` | `boolean` |  | Paint the colour-key silhouettes instead of the real styles (hit canvas). |
| `measureOnly?` | `boolean` |  | Compute bounds and hit regions, draw nothing. Used to measure a changed entity's extent before deciding what to repaint. |
| `allocateColorKey?` | `(stableId: string) => string` |  | Colour-key allocator, keyed by a STABLE per-element id. |

### `PaintResult`

```ts
interface PaintResult
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `hitRecords` | `HitRecord[]` |  | Every pickable region produced this frame, in paint order. |
| `colorKeyIndex` | `Map<string, HitRecord>` |  | colour key → record, for the offscreen picking canvas. |
| `unpaintableNodes` | `VNode[]` |  | Elements the canvas cannot draw (foreignObject) — the host may overlay them. |
| `bounds` | `Bounds \| null` |  | World bounds of everything painted. |
| `entityBounds` | `Map<string, Bounds \| null>` |  | Per-entity world bounds (`node-n1` → its extent), for the dirty tracker. |
| `paintedCount` | `number` |  | Elements actually painted (after dirty-rect culling). |
| `culledCount` | `number` |  | Elements skipped because they fell outside the dirty region. |

### `RenderBackendOptions`

```ts
interface RenderBackendOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `mode?` | `BackendMode` |  | Initial backend. Default 'svg' — the historical behaviour. |
| `theme?` | `Theme` |  |  |
| `producerConfig?` | `SVGRendererConfig` |  | Config for the shared VNode producer. |
| `devicePixelRatio?` | `number` |  |  |
| `enableHitDetection?` | `boolean` |  |  |
| `enableDirtyRegions?` | `boolean` |  |  |
| `guardCanvas?` | `boolean` |  | REFUSE a switch to canvas that would take something away. |
| `onCanvasRefused?` | `(event: CanvasRefusedEvent) => void` |  | Told when the backend refuses a canvas switch, and what it would have cost. |

### `StyleResolverOptions`

```ts
interface StyleResolverOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `theme` | `Theme` |  |  |
| `varOverrides?` | `Record<string, string>` |  | CSS custom-property overrides — normally read off the diagram's host element with {@link readCssVarOverrides}, so a host that redefines `--grafloria-*` in its own stylesheet gets the same paint on canvas as it does on SVG. |

### `SubPath`

One flattened sub-path: a polyline, plus whether it was explicitly closed.

```ts
interface SubPath
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `points` | `Point[]` |  |  |
| `closed` | `boolean` |  |  |

### `TextLine`

One drawn line of text, already positioned in the element's local space.

```ts
interface TextLine
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `text` | `string` |  |  |
| `x` | `number` |  |  |
| `y` | `number` |  |  |
