# Interfaces

Import these from `@grafloria/renderer`.

## Interfaces

### `Adjacency`

```ts
interface Adjacency
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `outgoing` | `Map<string, Incidence[]>` |  | nodeId → edges leaving it. |
| `incoming` | `Map<string, Incidence[]>` |  | nodeId → edges arriving at it. |

### `ContainmentResult`

```ts
interface ContainmentResult
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `action` | `ContainmentAction` |  |  |
| `dx` | `number` |  | World-space delta applied (or to be applied, when animating). |
| `dy` | `number` |  |  |
| `zoom?` | `number` |  | Zoom applied, when `action === 'zoom'`. |

### `DiagramLike`

The minimum of DiagramModel these pure functions need.

```ts
interface DiagramLike
```

**Members**

- `getNode(id: string): NodeModel | undefined`
- `getNodes(): NodeModel[]`
- `getLink(id: string): LinkModel | undefined`
- `getLinks(): LinkModel[]`
- `getNodeByPortId?(portId: string): NodeModel | undefined`
- `getGroups?(): unknown[]`

### `DiagramOutline`

```ts
interface DiagramOutline
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `summary` | `string` |  | Natural-language summary, read when focus enters the diagram. |
| `roots` | `OutlineNode[]` |  | The containment forest, in reading order. |
| `flat` | `OutlineNode[]` |  | Flat reading-order view — what the roving tabindex walks. |
| `entryPoints` | `string[]` |  |  |
| `terminals` | `string[]` |  |  |
| `isolated` | `string[]` |  |  |
| `cycles` | `string[][]` |  |  |
| `nodeCount` | `number` |  |  |
| `edgeCount` | `number` |  |  |
| `componentCount` | `number` |  |  |
| `edges` | `{ linkId: string; text: string }[]` |  | Every edge, as an AT-readable sentence (the edge list of the mirror). |
| `signature` | `string` |  | Cheap change key — see `outlineSignature`. |

### `FocusContainmentOptions`

```ts
interface FocusContainmentOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `padding?` | `number` |  | CSS-pixel margin kept between the focused element and the viewport edge. |
| `durationMs?` | `number` |  | Pan animation duration, ms. 0 (or reduced motion) → instant. |
| `reducedMotion?` | `() => boolean` |  | Override reduced-motion detection (tests). |
| `now?` | `() => number` |  | Injected clock/frame source (tests). |
| `requestFrame?` | `(cb: (t: number) => void) => number` |  |  |
| `cancelFrame?` | `(handle: number) => void` |  |  |

### `Incidence`

Graph TOPOLOGY — the structural facts an assistive-technology user cannot
see: which nodes start the flow, which end it, what cycles back, what is
unreachable.

This is the analysis engine behind two cards:
  - follow-edge keyboard traversal — walking the real graph, not
    the geometry;
  - the navigable outline + natural-language summary.

Pure, framework-free, model-in / facts-out. No DOM, no rendering.

.

```ts
interface Incidence
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `link` | `LinkModel` |  | The link. |
| `otherId` | `string` |  | The node at the OTHER end of it. |
| `direction` | `'outgoing' \| 'incoming'` |  | Are we the source (outgoing) or the target (incoming)? |

### `LiveRegionOptions`

```ts
interface LiveRegionOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `coalesceMs?` | `number` |  | Announcements arriving within this many ms of the previous one REPLACE it rather than following it. 0 disables coalescing (tests use this). |
| `now?` | `() => number` |  | Injected clock, so tests need no timers. |
| `schedule?` | `(fn: () => void, ms: number) => unknown` |  | Injected scheduler, so tests need no real setTimeout. |
| `cancel?` | `(handle: unknown) => void` |  |  |

### `OutlineEdgeRef`

The DIAGRAM OUTLINE — a screen-reader-navigable TEXT MIRROR of the graph.

This is the capability no competitor ships. Mermaid is read-only pictures;
React Flow / GoJS / JointJS give a screen reader, at best, a bag of labelled
shapes with no edges. None of them
give an AT user the *topology*: where a flow starts, what each node leads to,
what loops back, what is unreachable.

The outline is that topology, as a structured tree the AT virtual cursor can
browse with its normal list/tree keys — plus a natural-language summary read
on entry, so the user knows the shape of the thing before walking it.

Pure model → outline. Rendering it to DOM is `outline-view.ts`'s job; keeping
the two apart is what lets us unit-test the *content* with no DOM at all.

.

```ts
interface OutlineEdgeRef
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `linkId` | `string` |  |  |
| `targetId` | `string` |  |  |
| `targetName` | `string` |  |  |
| `label?` | `string` |  | The edge's own label ("yes" / "no" on a decision), if any. |
| `closesCycle` | `boolean` |  | True when this edge closes a cycle — the single most useful fact. |

### `OutlineNode`

```ts
interface OutlineNode
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `nodeId` | `string` |  |  |
| `name` | `string` |  |  |
| `roleDescription` | `string` |  | Human shape name — "Decision", "Process". |
| `incoming` | `number` |  |  |
| `outgoing` | `number` |  |  |
| `targets` | `OutlineEdgeRef[]` |  | Where this node leads. |
| `children` | `OutlineNode[]` |  | Nested nodes (group / parent containment). |
| `isEntryPoint` | `boolean` |  |  |
| `isTerminal` | `boolean` |  |  |
| `isIsolated` | `boolean` |  |  |
| `inCycle` | `boolean` |  | Participates in at least one cycle. |
| `index` | `number` |  | 1-based position in reading order, and the total — "node 3 of 12". |
| `total` | `number` |  |  |

### `OutlineViewOptions`

The outline's DOM MIRROR: a visually-hidden, semantically-structured tree the
AT virtual cursor browses with its ordinary list/tree keys.

Structure (all off-screen, never focusable by Tab — the canvas owns the tab
stop; this is virtual-cursor territory):

<div role="region" aria-label="Diagram outline">
    <p>{natural-language summary}</p>
    <ul role="tree">
      <li role="treeitem" aria-level=1 aria-label="Decision, Is order valid?, …">
        <ul role="group"> …children… </ul>
      </li>
    </ul>
    <ul role="list" aria-label="Edges"> … </ul>
  </div>

THRASH CONTROL — the non-negotiable. `update()` is safe to call on every
frame: it recomputes only the outline SIGNATURE (ids/names/states/endpoints,
never geometry) and returns immediately when it is unchanged. A quiet frame,
and a pure-drag frame, do ZERO DOM work. `getRebuildCount()` exists so a test
can PROVE it rather than trust it.

.

```ts
interface OutlineViewOptions
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `label?` | `string` |  | Accessible name of the outline region. |
| `diagramType?` | `string` |  | Diagram type, used in the roledescription ("Flowchart diagram"). |
| `includeEdgeList?` | `boolean` |  | Include the per-edge list. Default true. |

### `Topology`

```ts
interface Topology
```

**Properties**

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `adjacency` | `Adjacency` |  |  |
| `entryPoints` | `NodeModel[]` |  | Nodes with no incoming edges — where a reader should start. |
| `terminals` | `NodeModel[]` |  | Nodes with no outgoing edges — where flows terminate. |
| `isolated` | `NodeModel[]` |  | Nodes with neither incoming nor outgoing edges. |
| `cycles` | `string[][]` |  | Each cycle as the ordered node ids around it. |
| `components` | `string[][]` |  | Connected components (undirected), as node-id lists. |
| `ordered` | `NodeModel[]` |  | Nodes in reading order (top-to-bottom, then left-to-right). |
