Native TypeScript graph layout algorithms built directly on
@statelyai/graph.
This is not a new graph interchange format. Public APIs consume Graph and
return VisualGraph; positions remain node fields and routes remain
GraphEdge.points.
The native layered implementation covers the complete 152-option elkjs 0.11.1 layered inventory with one simplified typed name per ELK option. Flat and compound graphs, cross-hierarchy edges, ports, labels, self-loops, wrapping, four directions, constraints, and replaceable phases are differential-tested against elkjs. Partial, incremental, and route-only layout remain explicit unimplemented capabilities.
pnpm add @statelyai/layout @statelyai/graphimport { createGraph } from "@statelyai/graph";
import { getLayeredLayout, getLayout } from "@statelyai/layout";
const graph = createGraph({
nodes: [{ id: "a" }, { id: "b" }],
edges: [{ id: "ab", sourceId: "a", targetId: "b" }],
});
const visualGraph = getLayeredLayout(graph, { direction: "right" });
const result = await getLayout({
graph,
algorithm: "layered",
options: { direction: "right" },
});
result.graph;
result.patches;
result.diagnostics;
result.metrics;Legacy consumers can migrate through an isolated compatibility entry point:
import ELK from "@statelyai/layout/elkjs";
const elk = new ELK();
const legacyResult = await elk.layout(elkJsonGraph);The adapter accepts ELK JSON and option aliases, translates to
@statelyai/graph, runs native algorithms, and translates the result back.
Native algorithms never consume ELK JSON directly.
Advanced layered settings use shorter names such as
layering.strategy, spacing.edgeNode, and nodePlacement.strategy.
toElkLayeredOptions and fromElkLayeredOptionId provide the exact one-to-one
mapping when migration tooling needs ELK IDs. elkLayeredOptionDefinitions
exposes the complete mapping, value type, and valid graph-element targets;
elkLayeredEnumValues exposes every accepted enum value.
The browser lab contains the same 45 categorized examples as ELK Live, sourced
from the canonical eclipse/elk-models catalog. Each is pre-laid out with the
elkjs oracle after zero-sized nodes and ports receive consistent visual bounds.
The canonical ELKT source remains unchanged; elkjs is never bundled into the
browser.
The workbench places a CodeMirror JSON5 editor beside a coordinate-faithful SVG viewer in keyboard-accessible shadcn resizable panels. Selecting an example loads its complete XGraph into the editor; pasted or edited XGraph redraws automatically. Existing visual geometry is preserved; topology-only graphs run through native layered layout. Invalid input is marked inline while the last valid preview remains visible. Pan, zoom, selection details, and optional overlays expose exact node coordinates, edge-label rectangles, route points, routing modes, and node-relative ports.
pnpm demo:generate
pnpm demoThe demo opens at https://layout.localhost through Portless.
pnpm demo:sync refreshes the pinned ELK Live catalog and its converted ELK
JSON inputs. Normal generation and browser use remain offline.
The embed target defaults to http://localhost:3000. Override it with
?editor=http://localhost:4864 when the Viz editor runs elsewhere.
Layered phases are replaceable independently:
breakCyclesassignLayersminimizeCrossingsplaceNodesrouteEdges
Strategies exchange typed artifacts keyed by graph entity IDs. They never convert the public graph into an ELK-shaped API.
const result = getLayeredLayout(graph, {
strategies: {
routeEdges(input, orientation, placement) {
return myRouter(input, orientation, placement);
},
},
});See API reference, Architecture, Roadmap, and Upstream and provenance. Parity tracks API coverage separately from native algorithm fidelity.
pnpm install
pnpm verify
pnpm bench
pnpm demo
pnpm changeset
pnpm releasepnpm verify checks Oxfmt, Oxlint, source and repository TypeScript projects,
generated layered-option and demo-corpus freshness, tests,
declarations/runtime builds, the demo bundle, and the packed package surface.
Add a release note with pnpm changeset. When it reaches main, the release
workflow opens or updates a version pull request. Merging that pull request
publishes the package to npm and creates the GitHub release and tag.
Before the first automated release, publish the initial 0.0.0 package and
configure npm Trusted Publishing for statelyai/layout using
.github/workflows/release.yml.