Functions
Import these from @grafloria/renderer.
Functions
analyseTopology
tsfunction analyseTopology(diagram: DiagramLike): Topology
boundsOfPoints
The world bounds of a routed link — its polyline, grown a little.
tsfunction boundsOfPoints(
points: { x: number; y: number }[],
pad = 8
): Rectangle | null
buildAdjacency
tsfunction buildAdjacency(diagram: DiagramLike): Adjacency
buildOutline
tsfunction buildOutline(diagram: DiagramLike): DiagramOutline
childrenByParent
Group/parent containment: parentId → child nodes.
tsfunction childrenByParent(diagram: DiagramLike): Map<string, NodeModel[]>
degreeOf
Incoming / outgoing degree of a node. Self-loops count on both sides.
tsfunction 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.
tsfunction diagramAccessibleName(diagram: DiagramLike, title?: string): string
diagramOf
Resolve the diagram off an engine, tolerating a bare DiagramModel.
tsfunction diagramOf(engine: DiagramEngine | DiagramLike | undefined): DiagramLike | undefined
diagramRoleDescription
The aria-roledescription for the whole canvas.
tsfunction diagramRoleDescription(diagramType?: string): string
edgeAccessibleName
An edge's ACCESSIBLE NAME.
"Edge from Start to Is order valid?, labelled yes, selected"
tsfunction edgeAccessibleName(link: LinkModel, diagram: DiagramLike): string
edgeRoleDescription
The aria-roledescription for an edge. Respects the link's own semantics.
tsfunction 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.
tsfunction ensureMotionPreferenceStyles(doc?: Document): HTMLStyleElement | undefined
findComponents
Connected components, treating edges as undirected.
tsfunction 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.
tsfunction findCycles(diagram: DiagramLike, adjacency: Adjacency): string[][]
humaniseType
Humanise an unknown type: my_customNode → "My custom node".
tsfunction 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.
tsfunction incidentEdges(
nodeId: string,
diagram: DiagramLike,
adjacency?: Adjacency
): Incidence[]
linkLabelText
A link's own label text, if it carries one.
tsfunction linkLabelText(link: LinkModel): string | undefined
nameOf
Debug/summary helper: name a node id.
tsfunction 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.
tsfunction 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.
tsfunction nodeName(node: NodeModel): string
nodeRoleDescription
The aria-roledescription for a node — its SHAPE, in human words.
tsfunction nodeRoleDescription(node: NodeModel): string
outlineNodeLabel
"Decision, Is order valid?, node 3 of 12, 1 incoming, 2 outgoing, in a loop"
tsfunction 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.
tsfunction outlineSignature(diagram: DiagramLike): string
positionContext
Reading-order position context: "node 3 of 12, 2 incoming, 1 outgoing".
tsfunction positionContext(nodeId: string, diagram: DiagramLike): string
readingOrder
Reading order: the order a sighted user's eye takes. Focus order matches it.
tsfunction readingOrder(nodes: NodeModel[]): NodeModel[]
removeMotionPreferenceStyles
Remove the injected stylesheet (teardown / tests).
tsfunction removeMotionPreferenceStyles(doc?: Document): void
rootNodes
Nodes with no parent — the roots of the containment tree.
tsfunction rootNodes(diagram: DiagramLike): NodeModel[]
sourceNodeIdOf
tsfunction 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."
tsfunction summarise(
outline: Omit<DiagramOutline, 'summary' | 'signature'>,
diagram: DiagramLike
): string
targetNodeIdOf
tsfunction targetNodeIdOf(link: LinkModel, diagram: DiagramLike): string
Was this page helpful?