# Interfaces A–T

Import these from `@grafloria/renderer`.

## Interfaces

### `AnchorContext`

```ts
interface AnchorContext
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `end` | `LinkEnd` |  | The end being anchored. |
| `other` | `LinkEnd` |  | The OTHER end's node — direction-aware anchors (perimeter) need it. |
| `link` | `LinkModel` |  | The link, for reading style/metadata. |
| `defaultPoint` | `ExtPoint` |  | The point the DEFAULT (port-based) pipeline would have produced. An anchor that only wants to nudge the default does not have to recompute it. |
| `args` | `Record<string, unknown>` |  | Free-form args from `link.metadata.sourceAnchorArgs` / `targetAnchorArgs`. |

### `AnchorResult`

```ts
interface AnchorResult
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `point` | `ExtPoint` |  |  |
| `side?` | `ExtSide` |  | The side the link should LEAVE from. Routers use it to pick the exit stub. |

### `AnimationCapability`

Contribute named animations. Wraps CustomAnimationRegistry.

```ts
interface AnimationCapability
```

**Members**

- `register(definition: CustomAnimationDefinition): Disposer`
- `has(name: string): boolean`
- `list(): CustomAnimationDefinition[]`

### `CanvasTool`

A canvas tool. `hitTest` is the claim: return true on pointerdown and this
tool OWNS the whole gesture (move/up/cancel) — no other tool, and none of the
built-in ladder, will see it.

```ts
interface CanvasTool
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `ToolId` |  |  |
| `priority?` | `number` |  | Higher wins when several tools claim the same gesture. Built-in-replacing tools should use a priority > 0; the built-in ladder is effectively 0. |

**Members**

- `hitTest(event: ToolPointerEvent, hit: ToolHitContext): boolean` — Claim this gesture?
- `onPointerDown?(event: ToolPointerEvent, hit: ToolHitContext): void`
- `onPointerMove?(event: ToolPointerEvent, hit: ToolHitContext): void`
- `onPointerUp?(event: ToolPointerEvent, hit: ToolHitContext): void`
- `onCancel?(): void`
- `dispose?(): void` — Called when the tool is unregistered while active.

### `ConnectionCandidate`

Everything a validator needs to judge a proposed connection.

```ts
interface ConnectionCandidate
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `sourceNode` | `NodeModel` |  |  |
| `sourcePort` | `PortModel \| null` |  |  |
| `targetNode` | `NodeModel` |  |  |
| `targetPort` | `PortModel \| null` |  |  |
| `link?` | `LinkModel` |  | Present when RECONNECTING an existing link rather than drawing a new one. |

### `ConnectionPointContext`

```ts
interface ConnectionPointContext
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `link` | `LinkModel` |  |  |
| `source` | `LinkEnd` |  |  |
| `target` | `LinkEnd` |  |  |
| `defaults` | `ConnectionPointResult` |  | What the default port-based pipeline would have produced for both ends. |

**Members**

- `boundaryPoint(node: NodeModel, rect: ExtRect, side: ExtSide, cross: number): ExtPoint` — The shape registry's boundary solver, handed in so a strategy can attach to
a node's REAL silhouette (a diamond's slanted face, a custom path shape)
without importing the shape registry itself.
- `nearestVisiblePort(node: NodeModel, side: ExtSide, near: ExtPoint): ExtPoint | null` — The nearest VISIBLE port on a side, or null. Strategies use it to honour the
rule that visible ports win over free-floating attachment.
- `nearestPort(node: NodeModel, side: ExtSide, near: ExtPoint): ExtPoint | null` — The nearest port on a side REGARDLESS of visibility, or null. The
'port-facing' default uses it: a node's ports are its connection anatomy
whether or not the glyphs are currently drawn, so attachment must not
change when visibility does (an endpoint that jumps when you hover a node
is worse than either behaviour it jumps between).

### `ConnectionPointResult`

```ts
interface ConnectionPointResult
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `start` | `ExtPoint` |  |  |
| `end` | `ExtPoint` |  |  |
| `sourceDirection?` | `ExtSide` |  |  |
| `targetDirection?` | `ExtSide` |  |  |

### `ConnectionValidity`

```ts
interface ConnectionValidity
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `valid` | `boolean` |  |  |
| `reason?` | `string` |  | The first veto's reason, when it gave one. |

### `ConnectorContext`

```ts
interface ConnectorContext
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `points` | `ExtPoint[]` |  | The routed polyline in world coordinates. Never empty; never length 1. |
| `link?` | `LinkModel` |  | The link being drawn. Optional because a few internal call sites (the connection PREVIEW, which has no LinkModel yet) also build paths. |
| `style?` | `Partial<LinkStyle>` |  |  |
| `cornerRadius` | `number` |  | The corner radius the renderer resolved for this link. |

### `DiagramApi`

```ts
interface DiagramApi
```

**Members**

- `getNodes(): NodeModel[]`
- `getEdges(): LinkModel[]`
- `getSelectedNodes(): NodeModel[]`
- `getSelectedEdges(): LinkModel[]`
- `getViewport(): Rectangle`
- `getZoom(): number`
- `getSnapshot(): DiagramSnapshot` — One consistent snapshot — never a torn read across two getters.
- `subscribe<T>(selector: Selector<T>, listener: (value: T) => void): Disposer` — Observe a projection of the state. The listener fires only when the
SELECTED value changes, not on every internal event.
- `fitView(padding?: number): void` — Frame all content.
- `zoomTo(zoom: number): void` — Set absolute zoom, about the viewport centre.
- `zoomIn(step?: number): void`
- `zoomOut(step?: number): void`
- `centerOn(point: FlowPoint): void` — Pan so `point` sits at the centre of the viewport.
- `screenToFlow(point: FlowPoint): FlowPoint` — Screen (client) coordinates → world/flow coordinates.
- `flowToScreen(point: FlowPoint): FlowPoint` — World/flow coordinates → screen (client) coordinates.
- `getIntersectingNodes(rect: Rectangle, options?: GetIntersectingOptions): NodeModel[]` — Every node overlapping `rect` (world coords). The marquee/drop-target primitive.
- `getNodeAt(point: FlowPoint): NodeModel | null` — The topmost node under a world point, or null.
- `execute(command: unknown): Promise<void>` — Run an engine command through the undo/redo stack. Async — see the impl.
- `undo(): Promise<void>`
- `redo(): Promise<void>`
- `dispose(): void`

### `DiagramSnapshot`

The reactive snapshot a host binds to.

```ts
interface DiagramSnapshot
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `nodes` | `NodeModel[]` |  |  |
| `edges` | `LinkModel[]` |  |  |
| `selectedNodes` | `NodeModel[]` |  |  |
| `selectedEdges` | `LinkModel[]` |  |  |
| `viewport` | `Rectangle` |  |  |
| `zoom` | `number` |  |  |

### `Disposable`

Something that can be torn down.

```ts
interface Disposable
```

**Members**

- `dispose(): void`

### `Extension`

An extension. `activate` receives ONLY the capabilities its manifest declared.

```ts
const starPlugin: Extension<'shapes'> = {
  manifest: {
    id: 'acme.stars',
    version: '1.2.0',
    engines: { grafloria: '^1.0.0' },
    capabilities: ['shapes'],
  },
  activate({ capabilities }) {
    // `capabilities.routers` does not exist here — not typed, not present.
    capabilities.shapes.registerPath('star', starPath);
  },
};
host.register(starPlugin);
```

```ts
interface Extension<C extends CapabilityName = CapabilityName>
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `manifest` | `ExtensionManifest<C>` |  |  |

**Members**

- `activate(context: ExtensionContext<C>): void | Disposer | Promise<void | Disposer>` — Set up. Anything you register is tracked and undone on dispose; you may also
return a disposer (or push onto `context.onDispose`) for your own resources.
- `deactivate?(): void` — Optional explicit teardown, run before the tracked disposers.

### `ExtensionCapabilities`

The full capability set. An extension's `activate()` receives a PARTIAL of
this — exactly the keys its manifest declared.

```ts
interface ExtensionCapabilities
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `shapes` | `ShapeCapability` |  |  |
| `links` | `LinkCapability` |  |  |
| `routers` | `RouterCapability` |  |  |
| `templates` | `TemplateCapability` |  |  |
| `animations` | `AnimationCapability` |  |  |
| `tools` | `ToolCapability` |  |  |
| `panels` | `PanelCapability` |  |  |

### `ExtensionContext`

What an extension is given at activation, beyond its capabilities: a scoped
logger, its own resolved manifest, and a disposal bag.

```ts
interface ExtensionContext<C extends CapabilityName = CapabilityName>
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `capabilities` | `Pick<ExtensionCapabilities, C>` |  | Only the capabilities the manifest declared. |
| `id` | `string` |  | The extension's own id. |

**Members**

- `onDispose(disposer: Disposer): void` — Anything pushed here is disposed with the extension. Use it for your own
timers/listeners; registry registrations are tracked automatically.

### `ExtensionContributions`

What a plugin says it adds. Discovery/UX only — not a security boundary.

```ts
interface ExtensionContributions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `shapes?` | `string[]` |  |  |
| `routers?` | `string[]` |  |  |
| `connectors?` | `string[]` |  |  |
| `anchors?` | `string[]` |  |  |
| `connectionPoints?` | `string[]` |  |  |
| `markers?` | `string[]` |  |  |
| `linkTemplates?` | `string[]` |  |  |
| `labelTemplates?` | `string[]` |  |  |
| `tools?` | `string[]` |  |  |
| `panels?` | `string[]` |  |  |
| `animations?` | `string[]` |  |  |
| `templates?` | `string[]` |  |  |

### `ExtensionHostOptions`

Also has every member of `HostBindings`, listed on its own entry.

```ts
interface ExtensionHostOptions extends HostBindings
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `apiVersion?` | `string` |  | Reject manifests whose `engines.grafloria` range excludes this. |

### `ExtensionManifest`

```ts
interface ExtensionManifest<C extends CapabilityName = CapabilityName>
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` |  | Reverse-DNS recommended: `acme.flowchart-shapes`. Must be unique per host. |
| `version` | `string` |  | The plugin's own semver. |
| `name?` | `string` |  | Human-facing. |
| `description?` | `string` |  |  |
| `engines?` | `{ grafloria?: string }` |  | The host API range this plugin supports, e.g. `{ grafloria: '^1.0.0' }`. Checked against `EXTENSION_API_VERSION` and REJECTED on mismatch. |
| `capabilities` | `readonly C[]` |  | The ENFORCED privilege grant. `activate()` receives exactly these and nothing else. |
| `contributes?` | `ExtensionContributions` |  | Declarative inventory, for discovery before load. |

### `ExtPoint`

```ts
interface ExtPoint
```

**Properties**

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

### `ExtRect`

A node's world-space box.

```ts
interface ExtRect
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `x` | `number` |  |  |
| `y` | `number` |  |  |
| `w` | `number` |  |  |
| `h` | `number` |  |  |

### `FlowPoint`

```ts
interface FlowPoint
```

**Properties**

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

### `GetIntersectingOptions`

```ts
interface GetIntersectingOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `fully?` | `boolean` |  | Require FULL containment rather than any overlap. This is the difference between a marquee that grabs everything it touches and one that only grabs what it encloses — both are legitimate, so it is the caller's call. |
| `visibleOnly?` | `boolean` |  | Ignore hidden nodes. Default true. |

### `HostBindings`

The host's own view of the world. Passed to the capability factories so they
can reach the real registries. NOT exposed to extensions.

```ts
interface HostBindings
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `engine` | `DiagramEngine` |  |  |
| `registry?` | `import('./diagram-registry').DiagramRegistry` |  | The registry every contribution is written into. Pass `diagram.registry` and this host's extensions contribute to THAT DIAGRAM ONLY. |
| `templateRegistry?` | `TemplateRegistry` |  | The engine's node-template registry. |
| `root?` | `HTMLElement` |  | The diagram root element — panels attach here. May be absent (headless). |
| `htmlLayer?` | `HTMLElement` |  | The camera-transformed HTML layer — world-space panels attach here. |
| `viewport?` | `import('../viewport/viewport-controller').ViewportController` |  | The camera, for counter-scaled panels. |
| `requestRender?` | `() => void` |  | Ask the host to repaint (a contributed shape/connector changes the picture). |

### `LinkCapability`

Contribute link visuals + the four link-pipeline stages.

```ts
interface LinkCapability
```

**Members**

- `registerTemplate(name: string, template: LinkTemplate): Disposer` — Whole-link VNode template (`link.style.template`).
- `registerLabelTemplate(name: string, template: LabelTemplate): Disposer` — Label VNode template (`label.template`).
- `registerMarker(name: string, definition: MarkerDefinition): Disposer` — Arrowhead / marker (`arrowHead.type`).
- `registerConnector(name: string, connector: ConnectorFn): Disposer` — Polyline → SVG path `d` (`link.connector`).
- `registerAnchor(name: string, anchor: AnchorFn): Disposer` — Per-end attachment point (`link.metadata.sourceAnchor` / `targetAnchor`).
- `registerConnectionPoint(name: string, strategy: ConnectionPointFn): Disposer` — Whole-link, two-ended attachment strategy (`link.metadata.connectionPoint`).
- `listConnectors(): string[]`
- `listAnchors(): string[]`
- `listConnectionPoints(): string[]`

### `LinkEnd`

One end of a link, as the strategies see it.

```ts
interface LinkEnd
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `node` | `NodeModel` |  |  |
| `port` | `PortModel \| null` |  | The assigned port, when the link has one. |
| `rect` | `ExtRect` |  | The node's world rect. |

### `NodeComponent`

```ts
interface NodeComponent<D = Record<string, unknown>>
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `NodeRenderFn<D>` |  |  |
| `onUpdate?` | `(props: NodeComponentProps<D>, element: HTMLElement) => void` |  | Called on every prop change AFTER the first render. Optional fast path. |
| `onDestroy?` | `(element: HTMLElement) => void` |  | Unmount your framework's subtree here. |
| `autoSize?` | `boolean` |  | Measure the rendered element and write the size back into the model, so layout + routing see the node's REAL extent. Default false — a node whose size is authored should not be silently overridden by its content. |
| `sizeThreshold?` | `number` |  | Ignore measurement deltas smaller than this (px). Default 1. |

### `NodeComponentProps`

The typed props a node component receives. Recomputed on every update.

```ts
interface NodeComponentProps<D = Record<string, unknown>>
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` |  |  |
| `data` | `D` |  | The node's own data bag (`node.data` / metadata). |
| `selected` | `boolean` |  |  |
| `dragging` | `boolean` |  |  |
| `hovered` | `boolean` |  |  |
| `zoom` | `number` |  | Current camera zoom — for LOD rendering ("hide the detail below 0.5"). |
| `width` | `number` |  |  |
| `height` | `number` |  |  |
| `ports` | `ReadonlyArray<{ id: string; side: string; type: string }>` |  | The node's ports, so a component can position its own handles. |
| `node` | `NodeModel` |  | Escape hatch: the live model. Prefer the fields above. |

### `PanelCapability`

Contribute on-canvas UI. This is the ONLY capability that hands back
a DOM element, and it is scoped to the diagram's own layers — an extension
cannot reach the rest of the page through it.

```ts
interface PanelCapability
```

**Members**

- `createPanel(options?: PortalOptions): Portal` — A floating panel pinned to the viewport (does not pan/zoom).
- `createViewportPanel(options?: { x?: number; y?: number; className?: string; style?: string }): ViewportPortal` — Content that lives IN the diagram (pans/zooms with the canvas).
- `createCounterScaledPanel(options?: { x?: number; y?: number; className?: string; style?: string }): ViewportPortal` — World-space, but held at a constant on-screen size.

### `Portal`

```ts
interface Portal
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `element` | `HTMLElement` |  | The element you render into. Already in the DOM. |

**Members**

- `update(options?: PortalOptions): void` — Re-pin (after changing placement/offset).
- `dispose(): void`

### `PortalOptions`

```ts
interface PortalOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `placement?` | `PortalPlacement` |  | Where to pin it. Default `'top-left'`. |
| `offset?` | `number` |  | Offset from the placement corner, in CSS px. Default 12. |
| `className?` | `string` |  | Extra class names on the portal element. |
| `style?` | `string` |  | Inline style appended after the placement rules (so it wins). |
| `zIndex?` | `number` |  | Stacking order within the screen layer. |

### `RegisteredExtension`

```ts
interface RegisteredExtension
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `manifest` | `ExtensionManifest` |  |  |
| `active` | `boolean` |  |  |
| `registrationCount` | `number` |  | Registrations this extension currently holds. |

### `RouterCapability`

Contribute routing algorithms. Wraps `RoutingEngine.registerRouter`.

```ts
interface RouterCapability
```

**Members**

- `register(name: string, router: IRouter): Disposer`
- `list(): string[]`
- `has(name: string): boolean`

### `ShapeCapability`

Contribute node geometry. Wraps the (already unified) shape registry.

```ts
interface ShapeCapability
```

**Members**

- `register(type: string, definition: Omit<ShapeDefinition, 'type'> & { type?: string }): Disposer` — Register a full shape definition.
- `registerPath(type: string, geometry: PathGeometry, options?: PathShapeOptions): Disposer` — Register a shape from an SVG path (boundary + port anchors auto-derived).
- `has(type: string): boolean`
- `list(): string[]`

### `TemplateCapability`

Contribute reusable node templates. Wraps the engine's TemplateRegistry.

```ts
interface TemplateCapability
```

**Members**

- `register(template: NodeTemplate): Disposer`
- `list(): NodeTemplate[]`
- `has(id: string): boolean`
