Skip to content

Documents ​

A diagram is a title, a direction, and three lists: nodes, groups and edges. The schemas and types are on @adecore/diagram/protocol.

json
{
    "version": 1,
    "rev": 0,
    "meta": { "title": "Release", "direction": "right" },
    "nodes": [
        { "id": "build", "label": "Build", "sub": "bun run build" },
        { "id": "approved", "label": "Approved?", "shape": "diamond", "tone": "orange" }
    ],
    "groups": [{ "id": "ci", "label": "CI", "wraps": ["build"] }],
    "edges": [{ "from": "build", "to": "approved", "label": "green" }]
}

DiagramDocumentSchema is that object, with version at DIAGRAM_VERSION (1) and a rev the app raises on every save. DiagramContentSchema is the same without version and rev. EMPTY_DIAGRAM has an empty title, runs right and has empty lists; copy it before you change it.

PartFields
Metatitle, and direction: right or down.
Nodeid, label; optional sub (a second, smaller line), shape, tone, and pos: [x, y] on a node a person dragged.
Groupid, label, wraps (a list of node ids); optional tone.
Edgefrom and to (node ids); optional label, style (solid, dashed or dotted) and tone.

A tone is a palette name of @adecore/drawing. Absent, a node is rect in ink, and a group and an edge are muted and solid. Nodes come in file order, and that order is also the starting order inside a layer of the layout.

tsx
import { toSvg } from '@adecore/diagram';
import { DIAGRAM_SHAPES, type DiagramContent } from '@adecore/diagram/protocol';
import { THEME_PALETTE, THEME_PAPER } from '../shared/canvas-theme.ts';

const STYLES = ['solid', 'dashed', 'dotted', 'solid'] as const;

const SHAPES: DiagramContent = {
    meta: { title: 'Shapes and edge styles', direction: 'right' },
    nodes: DIAGRAM_SHAPES.map((shape) => ({ id: shape, label: shape, shape, tone: 'blue' })),
    groups: [],
    edges: STYLES.map((style, index) => ({ from: DIAGRAM_SHAPES[index]!, to: DIAGRAM_SHAPES[index + 1]!, label: style, style }))
};

export default function DiagramShapesDemo() {
    const svg = toSvg(SHAPES, { palette: THEME_PALETTE, paper: THEME_PAPER });

    return <div className="w-full [&_svg]:h-auto [&_svg]:w-full" dangerouslySetInnerHTML={{ __html: svg }} />;
}

DIAGRAM_SHAPES lists the five shapes in the order above.

Checking a diagram ​

The schema checks shapes, not references. Run diagramProblemIn after every parse:

ts
import { diagramProblemIn, migrateDiagram } from '@adecore/diagram/protocol';

const diagram = migrateDiagram(JSON.parse(file));
const problem = diagram && diagramProblemIn(diagram);
// 'The edge from "build" to "deploy" names "deploy", which is not a node'

migrateDiagram returns the parsed document or null. diagramProblemIn returns the first rule the content breaks, as a sentence that names the id, or null. An agent that wrote the file can repair it from that sentence. The rules, in the order it checks them:

  • At most 100 nodes and 120 edges (DIAGRAM_LIMITS). Edges that skip many layers make a layout slow, so the limit lives here rather than in the schema.
  • Node ids are unique. Groups share that namespace, so a group id is neither a node id nor another group's.
  • A group wraps nodes only, never another group, and a node is in at most one group.
  • Both ends of every edge are nodes.

Cycles, edges from a node to itself, several edges between the same two nodes and empty groups are all allowed. An edge has no id; its index in edges tells two parallel edges apart.

Schemas ​

SchemaType
DiagramShapeSchemaDiagramShape
DiagramDirectionSchemaDiagramDirection
DiagramEdgeStyleSchemaDiagramEdgeStyle
DiagramNodeSchemaDiagramNode
DiagramGroupSchemaDiagramGroup
DiagramEdgeSchemaDiagramEdge
DiagramMetaSchemaDiagramMeta
DiagramContentSchemaDiagramContent
DiagramDocumentSchemaDiagramDocument

Parsing drops keys the schemas do not know and leaves optional fields out. DiagramEdgeStyleSchema is the stroke style schema of the drawing package.

Licenses and third-party notices are listed in each package.