Skip to content

Reference

Graphs and flow

Flowcharts, trees and networks that lay themselves out, with edges that trace on and carry pulses.

import { ... } from 'cseen/flow';

Boxes and arrows that place themselves.

function diagram(o?: DiagramOpts): Diagram
ParameterType
o?DiagramOpts

Returns Diagram

Options: DiagramOpts

Example

import { Scene } from 'cseen';
import { diagram } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [360, 200] });
const d = s.add(diagram({ direction: 'right' }));
d.node('a', 'source', { shape: 'round' });
d.node('b', 'build');
d.node('c', 'deploy', { role: 'accent' });
d.edge('a', 'b');
d.edge('b', 'c');
Run it in the playground →

A flowchart from a list of steps. Each step goes to the next one unless it says where else, and a decision lists its branches.

function flowchart(steps: FlowStep[], o?: DiagramOpts): Diagram
ParameterType
stepsFlowStep[]
o?DiagramOpts

Returns Diagram

Options: DiagramOpts

Example

import { Scene } from 'cseen';
import { flowchart } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [360, 300] });
s.add(flowchart([
{ label: 'start', kind: 'start' },
{ label: 'logged in?', kind: 'decision', to: [['home', 'yes'], ['login', 'no']] },
{ label: 'login', to: ['home'] },
{ label: 'home', kind: 'end' },
]));
Run it in the playground →

A sequence diagram: who talks to whom, in order. See Sequence.

function sequence(spec: SequenceSpec, o?: SequenceOpts): Sequence
ParameterType
specSequenceSpec
o?SequenceOpts

Returns Sequence

Options: SequenceOpts

Example

import { Scene } from 'cseen';
import { sequence } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [320, 220] });
s.add(sequence({
participants: ['client', 'server'],
messages: [{ from: 'client', to: 'server', label: 'hello' }, { note: 'checks the token', over: 'server' }, { from: 'server', to: 'client', label: 'ok', reply: true }],
}));
Run it in the playground →

A tree from nested data: a label and its children. Parents sit centred over their children.

function treeDiagram(data: TreeData, o?: DiagramOpts): Diagram
ParameterType
dataTreeData
o?DiagramOpts

Returns Diagram

Options: DiagramOpts

Example

import { Scene } from 'cseen';
import { treeDiagram } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [360, 240] });
s.add(treeDiagram({ label: 'app', children: [{ label: 'ui', children: [{ label: 'forms' }, { label: 'tables' }] }, { label: 'api' }] }));
Run it in the playground →

Boxes and arrows that place themselves. Add nodes and edges, and the diagram lays them out: layered for flows, tree for hierarchies, force for networks. It lies on the page (x right, z up), so use view: 'front'. Everything is a node of the scene: link a diagram to a device with at, send a pulse along an edge with rail, trace edges on with draw.

new Diagram(o?: DiagramOpts): Diagram

Options: DiagramOpts

Example

import { Scene } from 'cseen';
import { Diagram } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [360, 260] });
const d = s.add(new Diagram());
d.node('in', 'request', { shape: 'round' });
d.node('ok', 'valid?', { shape: 'diamond', role: 'accent' });
d.node('go', 'handle');
d.node('no', 'reject');
d.edge('in', 'ok');
d.edge('ok', 'go', { label: 'yes' });
d.edge('ok', 'no', { label: 'no' });
Run it in the playground →

Extends Group.

MemberDescription
o: DiagramOpts
nodes: Map<string, DiagramNode>the nodes by id
edges: DiagramEdge[]the edges in the order they were added
node(id: string, label: string, o?: NodeSpec): DiagramNodeadds a node and places everything again. Returns the node so you can animate it.
edge(from: string, to: string, o?: EdgeSpec): DiagramEdgeadds an edge from one node to another and places everything again. Returns the edge so you can animate it.
at(id: string, side?: 'center' | 'top' | 'bottom' | 'left' | 'right'): (): V3a point on a node that follows it: the center (default), or the middle of a side. Use it as the end of a link.
route(from: string, to: string): Point[]the route of the first edge between two nodes, as points in the scene, for a pulse to ride
extent(): [number, number]the size of the diagram on the page, width and height in world units
batch<T>(build: (d: this): T): TRuns build, which adds nodes and edges, and places everything once at the end instead of after every call. Use it when you add many things, since a force layout of a few dozen nodes takes noticeable time on each placing.
collect(out: Prim[]): voidappends what this node draws right now to out, in world coordinates. Draws nothing when fully transparent.

A line between two nodes, routed by the layout. Animate draw from 0 to 1 to trace it on. If you move a node by hand (pos), the edge is routed again between the nodes where they are now, and goes back to the layout’s route when both nodes are back where the layout put them.

new DiagramEdge(from: string, to: string, o: EdgeSpec & { role: string; }): DiagramEdge

Extends Group.

MemberDescription
from: stringthe id of the node it leaves
to: stringthe id of the node it enters
route: P2[]the route on the page, from one node to the other, as [x, z] points. Set by the layout.
labelAt?: ((route: P2[], w: number, h: number) => P2) | undefinedwhere the label sits for a route, as the centre [x, z]. The layouts leave it unset; a sequence diagram sets it.
laid: P2[]the layout’s own route, and the node positions [xa, za, xb, zb] it was made for and the ones last routed for
laidAt: number[]
seenAt: number[]
sync: () => voidbrings the route up to date with the nodes; set by the diagram that owns the edge
setRoute(r: P2[]): voidcalled by the diagram after every layout
rail(): Point[]the route as points in the scene, for a pulse to ride: pulse(edge.rail()). The points read the route when they are used, so the rail follows the edge if its nodes move; if the route then has a different number of corners, the points are spread along it by length.
collect(out: Prim[]): voidappends what this node draws right now to out, in world coordinates. Draws nothing when fully transparent.

One box of a diagram: a shape and the words in it. It sits where the layout put it. Animate opacity, fill, or move it with pos, scale and rot as with any node.

new DiagramNode(label: string, o: NodeSpec & { role: string; min?: [number, number]; }): DiagramNode

Extends Group.

MemberDescription
label: stringthe text of the node
shape: Shapethe look of the node
box: [number, number]the width and height of the node in world units
collect(out: Prim[]): voidappends what this node draws right now to out, in world coordinates. Draws nothing when fully transparent.

Participants as boxes along the top, each with a dashed lifeline below it, and messages as arrows between the lifelines in the order they happen, time flowing down. The spacing is worked out from the labels, so none of them overlap. Every part is a scene node: trace a message on with draw, fade a participant with opacity, ride a message with a pulse.

new Sequence(spec: SequenceSpec, o?: SequenceOpts): Sequence

Options: SequenceOpts

Example

import { Scene } from 'cseen';
import { sequence } from 'cseen/flow';
const s = new Scene({ view: 'front', size: [360, 260] });
const q = s.add(sequence({
participants: ['browser', 'api', 'db'],
messages: [
{ from: 'browser', to: 'api', label: 'GET /user' },
{ from: 'api', to: 'db', label: 'select' },
{ from: 'db', to: 'api', label: 'row', reply: true },
{ from: 'api', to: 'api', label: 'render' },
{ from: 'api', to: 'browser', label: '200', reply: true },
],
}));
Run it in the playground →

Extends Group.

MemberDescription
nodes: Map<string, DiagramNode>the participant boxes by id
lifelines: Map<string, DiagramEdge>the dashed line under each participant, by id
messages: DiagramEdge[]the arrows in the order they happen, from the top down
notes: DiagramNode[]the note boxes in the order they appear

Options of diagram.

Extends NodeOpts.

OptionTypeDefaultDescription
layout?'layered' | 'tree' | 'force'layered (default) for flows with direction, tree for hierarchies, force for networks
direction?'right' | 'down'the way things flow: down (default) or right
gap?[number, number]space between boxes along the flow and across it, in world units. Default [0.9, 0.5].
edges?'elbow' | 'straight'elbow routes edges with right angles, straight draws lines. Elbows by default, straight lines for force.
role?stringcolour role of everything that does not set its own
seed?numberstarts the force layout from a different arrangement

Options of Diagram.edge.

OptionTypeDefaultDescription
label?stringa word on the line, such as yes
role?stringcolour role (ink, faint, accent, s1 to s8) or a role you define in CSS
arrow?false | 'start' | 'end' | 'both'where to put arrowheads. end by default, false for a plain line.
dash?stringan SVG dash pattern such as '4 4'
flow?number | booleandashes travel along the edge, true or cycles per second

One step of a flowchart.

OptionTypeDefaultDescription
id?stringa name other steps use to point here. Defaults to the label.
labelstringwhat the step says
kind?'start' | 'end' | 'step' | 'decision'start and end are rounded, step is a box (default), decision is a diamond
to?(string | [string, string])[]where it goes next: ids, or [id, word] to put a word on the arrow. Default: the next step in the list, nothing after an end.

Options of Diagram.node.

OptionTypeDefaultDescription
shape?Shapebox (default), round (start and end of a flow), diamond (a decision) or circle (a point in a network)
role?stringcolour role (ink, faint, accent, s1 to s8) or a role you define in CSS
fill?numberhow strongly the role colour fills the shape, 0 to 1. Animatable.

One message of a sequence diagram: an arrow from one participant to another.

OptionTypeDefaultDescription
fromstringthe id of the participant it leaves
tostringthe id of the participant it reaches. The same as from draws a loop back to itself.
label?stringa few words on the arrow
reply?booleana reply is drawn dashed, as the answer to an earlier call
role?stringcolour role of this arrow

A note on a sequence diagram, in the list of messages where it happens.

OptionTypeDefaultDescription
notestringwhat the note says; \n breaks a line
overstring | [string, string]the participant it sits on, or two, to stretch across them

Options of sequence.

Extends NodeOpts.

OptionTypeDefaultDescription
role?stringcolour role of everything that does not set its own

What a sequence diagram shows.

OptionTypeDefaultDescription
participants(string | { id: string; label?: string; })[]the columns from left to right: an id, or { id, label } when the box should say something else
messages(SequenceMessage | SequenceNote)[]the messages in time order, from the top down, with notes among them

The look of a node.

type Shape = 'box' | 'round' | 'diamond' | 'circle'

The shape of a tree: a label and the branches below it.

OptionTypeDefaultDescription
id?stringa name for the node, if you want to point at it later with at. Defaults to a generated one.
labelstringthe text of the node
children?TreeData[]the branches below it