# Functions

Import these from `@grafloria/renderer`.

## Functions

### `analyseTopology`

```ts
function analyseTopology(diagram: DiagramLike): Topology
```

### `boundsOfPoints`

The world bounds of a routed link — its polyline, grown a little.

```ts
function boundsOfPoints(
  points: { x: number; y: number }[],
  pad = 8
): Rectangle | null
```

### `buildAdjacency`

```ts
function buildAdjacency(diagram: DiagramLike): Adjacency
```

### `buildOutline`

```ts
function buildOutline(diagram: DiagramLike): DiagramOutline
```

### `childrenByParent`

Group/parent containment: parentId → child nodes.

```ts
function childrenByParent(diagram: DiagramLike): Map<string, NodeModel[]>
```

### `degreeOf`

Incoming / outgoing degree of a node. Self-loops count on both sides.

```ts
function degreeOf(
  nodeId: string,
  diagram: DiagramLike
): { incoming: number; outgoing: number }
```

### `diagramAccessibleName`

The canvas's own accessible name: "Diagram, 12 nodes, 14 edges". Read when focus first enters the canvas, so the user knows the size of what
they have landed in before they start walking it.

```ts
function diagramAccessibleName(diagram: DiagramLike, title?: string): string
```

### `diagramOf`

Resolve the diagram off an engine, tolerating a bare DiagramModel.

```ts
function diagramOf(engine: DiagramEngine | DiagramLike | undefined): DiagramLike | undefined
```

### `diagramRoleDescription`

The `aria-roledescription` for the whole canvas.

```ts
function diagramRoleDescription(diagramType?: string): string
```

### `edgeAccessibleName`

An edge's ACCESSIBLE NAME.

"Edge from Start to Is order valid?, labelled yes, selected"

```ts
function edgeAccessibleName(link: LinkModel, diagram: DiagramLike): string
```

### `edgeRoleDescription`

The `aria-roledescription` for an edge. Respects the link's own semantics.

```ts
function edgeRoleDescription(link: LinkModel): string
```

### `ensureMotionPreferenceStyles`

Inject the motion-preference stylesheet once per document.

Idempotent and SSR-safe: no document → no-op, and a second call finds the
existing element by id and returns it.

```ts
function ensureMotionPreferenceStyles(doc?: Document): HTMLStyleElement | undefined
```

### `findComponents`

Connected components, treating edges as undirected.

```ts
function findComponents(diagram: DiagramLike, adjacency: Adjacency): string[][]
```

### `findCycles`

Every cycle reachable in the directed graph, found by DFS with a colour mark. Reported once each, normalised to start at its smallest node id so the same
cycle is never announced twice under two rotations.

```ts
function findCycles(diagram: DiagramLike, adjacency: Adjacency): string[][]
```

### `humaniseType`

Humanise an unknown type: `my_customNode` → "My custom node".

```ts
function humaniseType(type: string | undefined): string
```

### `incidentEdges`

The edges incident on a node, ordered for keyboard traversal: outgoing first
(the direction a reader follows a flow), then incoming, each in the reading
order of the node at the far end — so pressing the same key twice always
walks the same way.

```ts
function incidentEdges(
  nodeId: string,
  diagram: DiagramLike,
  adjacency?: Adjacency
): Incidence[]
```

### `linkLabelText`

A link's own label text, if it carries one.

```ts
function linkLabelText(link: LinkModel): string | undefined
```

### `nameOf`

Debug/summary helper: name a node id.

```ts
function nameOf(id: string, diagram: DiagramLike): string
```

### `nodeAccessibleName`

A node's ACCESSIBLE NAME — what the screen reader reads on focus.

"Decision, Is order valid?, 1 incoming, 2 outgoing, selected"

The degree counts are the position context an AT user cannot get any other
way: sighted users see the edges converging on a shape; a screen-reader user
is told.

```ts
function nodeAccessibleName(node: NodeModel, diagram?: DiagramLike): string
```

### `nodeName`

A node's human NAME: its label, else its type + a short id. Single source of truth — the renderer's `aria-label`, the keyboard
controller's announcements, and the outline text-mirror all call THIS, so a
node can never be called two different things by two different surfaces.

```ts
function nodeName(node: NodeModel): string
```

### `nodeRoleDescription`

The `aria-roledescription` for a node — its SHAPE, in human words.

```ts
function nodeRoleDescription(node: NodeModel): string
```

### `outlineNodeLabel`

"Decision, Is order valid?, node 3 of 12, 1 incoming, 2 outgoing, in a loop"

```ts
function outlineNodeLabel(node: OutlineNode): string
```

### `outlineSignature`

A cheap signature of everything the outline DEPENDS on: ids, names, states,
containment and endpoints. Geometry is deliberately NOT in it — dragging a
node changes the picture but not the topology, so it must not rebuild the
mirror.

This is what makes the "no thrash" guarantee real rather than aspirational:
the view rebuilds only when this string changes, so a quiet frame — and a
pure-movement frame — does ZERO outline work.

```ts
function outlineSignature(diagram: DiagramLike): string
```

### `positionContext`

Reading-order position context: "node 3 of 12, 2 incoming, 1 outgoing".

```ts
function positionContext(nodeId: string, diagram: DiagramLike): string
```

### `readingOrder`

Reading order: the order a sighted user's eye takes. Focus order matches it.

```ts
function readingOrder(nodes: NodeModel[]): NodeModel[]
```

### `removeMotionPreferenceStyles`

Remove the injected stylesheet (teardown / tests).

```ts
function removeMotionPreferenceStyles(doc?: Document): void
```

### `rootNodes`

Nodes with no parent — the roots of the containment tree.

```ts
function rootNodes(diagram: DiagramLike): NodeModel[]
```

### `sourceNodeIdOf`

```ts
function sourceNodeIdOf(link: LinkModel, diagram: DiagramLike): string
```

### `summarise`

The NATURAL-LANGUAGE SUMMARY. What a colleague would say if you asked them
"what does this diagram show?" over the phone.

"Flowchart with 8 nodes and 9 edges. It starts at Receive order. It ends at
 Ship order or Reject order. It contains 1 loop: Review → Amend → Review.
 1 node is disconnected: Legacy step."

```ts
function summarise(
  outline: Omit<DiagramOutline, 'summary' | 'signature'>,
  diagram: DiagramLike
): string
```

### `targetNodeIdOf`

```ts
function targetNodeIdOf(link: LinkModel, diagram: DiagramLike): string
```
