Skip to content

API reference

Documented API v0.21.0
Exact package bun add @domudev/graphraum@0.21.0
Release notes Open reference Immutable contract Browse source
import {
Graphraum,
defineVisuals,
graphraumTheme,
type GraphraumData,
type GraphraumDataPatch,
type GraphraumDiagnostics,
type GraphraumLayoutPositions,
type GraphraumNodeUpdate,
type GraphraumOptions,
} from "@domudev/graphraum";
new Graphraum(container: HTMLElement, options?: GraphraumOptions)

The container must have a non-zero width and height. graphraum appends one canvas, observes container resizing, creates the selected camera, and renders on demand.

interface GraphraumOptions {
mode?: "2d" | "3d"; // default: "2d"
antialias?: boolean; // default: false
maxPixelRatio?: number; // default: 2
maxVisibleEdges?: number; // default: 100_000
maxVisibleNodes?: number; // default: 100_000
viewportCulling?: boolean; // default: true
viewportOverscan?: number; // default: 16 world units
theme?: Partial<GraphraumTheme>;
visuals?: GraphraumVisualMapper<NodeAttributes, EdgeAttributes>;
}

Invalid node and edge budgets, overscan values, positions, and node sizes fail at the boundary with an actionable error.

interface GraphraumData<NodeAttributes = undefined, EdgeAttributes = undefined> {
nodes: readonly GraphraumNode<NodeAttributes>[];
edges: readonly GraphraumEdge<EdgeAttributes>[];
}
interface GraphraumDataPatch<NodeAttributes = undefined, EdgeAttributes = undefined> {
addedNodes?: readonly GraphraumNode<NodeAttributes>[];
addedEdges?: readonly GraphraumEdge<EdgeAttributes>[];
removedNodeIds?: readonly string[];
removedEdgeIds?: readonly string[];
}
interface GraphraumNode {
id: string;
position: { x: number; y: number; z?: number };
color?: string | number;
shape?: GraphraumNodeShape;
size?: number; // shorthand; width/height default to size (then 4)
width?: number;
height?: number;
strokeWidth?: number; // world units; 0 by default (no stroke)
strokeColor?: string | number; // defaults to theme.nodeStroke when strokeWidth > 0
}
type GraphraumNodeShape =
| "circle"
| "square"
| "diamond"
| "hexagon"
| "triangle"
| "pill"
| "rounded";
interface GraphraumEdge {
id: string;
source: string;
target: string;
color?: string | number;
width?: number;
opacity?: number;
style?: "solid" | "dashed" | "dotted";
marker?: "none" | "triangle";
markerSize?: number;
markerEnd?: "target" | "source" | "both";
path?: "straight" | "quadratic" | "cubic";
controlPoints?: readonly { x: number; y: number; z?: number }[];
}

Node and edge IDs must be unique, every edge endpoint must exist, coordinates must be finite, and node size, width, and height must be positive when present. strokeWidth must be finite and non-negative. An unknown shape fails with the node ID in the error. Edge width and markerSize must be positive, and opacity must be between 0 and 1. Positions and sizes use world units.

Supply generic attribute types and defineVisuals() to compile domain data into node color, shape, size (or independent width/height), stroke, edge color, width, opacity, style, markers, and path, and immutable presentation metadata. See Node & edge presentation for the complete contract.

interface GraphraumEdgeVisual {
color?: string | number;
width?: number;
opacity?: number;
style?: "solid" | "dashed" | "dotted";
marker?: "none" | "triangle";
markerSize?: number;
markerEnd?: "target" | "source" | "both";
path?: "straight" | "quadratic" | "cubic";
controlPoints?: readonly { x: number; y: number; z?: number }[];
}

defineVisuals() maps typed edge attributes to this contract; direct edge fields use the same shape without a mapper. style selects a dash pattern, marker draws a triangle at markerEnd (target by default), and markerSize scales the triangle relative to width. path selects a polyline sampling of a straight, quadratic, or cubic curve; omit controlPoints for auto handles, or supply 1 (quadratic) / 2 (cubic) world-space points. Overview LOD collapses curves to a single straight segment. Endpoints always come from the source and target node positions. See Node & edge presentation for the full contract.

setData(data)

Validates and replaces the complete topology, rebuilds canonical buffers, fits the camera, materializes the viewport, and schedules a render.

applyDataPatch(patch)

Merges streamed additions and removals without fitting the camera. Additions within the preallocated capacity update existing GPU buffers; capacity growth falls back to one controlled rebuild.

updateNodes(updates)

Changes position, size, shape, or color for existing nodes and updates only the affected instance data and incident edge endpoints. Use setData when topology changes.

applyLayout(layout)

Applies a transferable XYZ position batch for existing nodes. Call it repeatedly as a worker produces progressive positions.

setSelection(nodeIds)

Applies the selected-node theme color without mutating source graph data. Missing and off-screen IDs are safe.

getNodePresentation(id)

Returns the compiled title, subtitle, properties, and action descriptors for a node, or null.

getEdgePresentation(id)

Returns the compiled presentation for an edge, or null.

render()

Schedules one render on the next animation frame. Repeated calls in the same frame are coalesced.

const updates: readonly GraphraumNodeUpdate[] = [
{ id: "person:ada", position: { x: 20, y: 12 } },
{ id: "place:london", color: "#73c7a5", shape: "square", size: 6 },
];
graph.updateNodes(updates);

GraphraumLayoutPositions keeps a layout worker separate from the renderer. positions contains an XYZ triplet for each ID in nodeIds; its buffer can be transferred from a worker.

const layout: GraphraumLayoutPositions = {
nodeIds: ["person:ada", "place:london"],
positions: new Float32Array([20, 12, 0, -20, 8, 0]),
};
graph.applyLayout(layout);

The package exports computeForcePositions() for a static layout, computeClusteredForcePositions() for data-defined coarse communities, and createForceSimulation() for incremental or worker-driven layouts. All accept ForceSettings; omitted settings use DEFAULT_FORCE_SETTINGS.

import { createForceSimulation, DEFAULT_FORCE_SETTINGS } from "@domudev/graphraum";
const simulation = createForceSimulation({
dimensions: 3,
edges: new Uint32Array([0, 1, 1, 2]),
nodeCount: 3,
settings: { ...DEFAULT_FORCE_SETTINGS, damping: 0.75, repulsion: 800 },
});
simulation.step(0.35);

The simulation recalculates and recenters its centroid after every step, so a live renderer can keep orbit controls focused without refitting the camera. In 2D every Z coordinate remains zero.

Use bindGraphology() when Graphology owns the mutable graph. The adapter renders the current graph immediately, maps node visual attributes (x, y, z, color, shape, and size), preserves all attributes for defineVisuals(), and subscribes to later mutations.

import Graph from "graphology";
import { Graphraum, bindGraphology } from "@domudev/graphraum";
type NodeAttributes = {
kind: "person" | "place";
x?: number;
y?: number;
};
type EdgeAttributes = Record<string, never>;
const source = new Graph<NodeAttributes, EdgeAttributes>();
source.addNode("person:ada", { kind: "person" });
source.addNode("place:london", { kind: "place", x: 20, y: 12 });
source.addEdgeWithKey("born-in", "person:ada", "place:london");
const container = document.querySelector<HTMLElement>("#graph");
if (!container) throw new Error("Missing #graph container");
const graph = new Graphraum<NodeAttributes, EdgeAttributes>(container);
const unbind = bindGraphology(graph, source);
source.mergeNodeAttributes("person:ada", { x: -20, y: 12 });
// Stop Graphology mutations from reaching this renderer.
unbind();
graph.destroy();

Missing coordinates default to zero so layout does not block the first render. Mutations are coalesced into one snapshot replacement per microtask, which reruns defineVisuals() for changed domain attributes. The source graph and renderer remain application-owned; unbind() only removes the adapter’s listeners.

pick(clientX, clientY)

Returns the nearest node ID or null. Uses the spatial grid in 2D and instance raycasting in 3D.

setMode(mode)

Switches between orthographic 2D and perspective 3D, replaces controls, and fits the current graph.

getMode()

Returns the active “2d” or “3d” mode.

fitView()

Fits the active camera to the complete graph bounds and rematerializes the viewport.

resize()

Synchronizes the renderer and active camera immediately. A ResizeObserver already calls this for normal container changes.

destroy()

Disconnects observation and controls, cancels pending rendering, disposes GPU resources, and removes the canvas.

graphraumTheme is immutable. Constructor overrides are copied per renderer, so one graph cannot change another graph’s defaults.

const graph = new Graphraum(container, {
theme: { ...graphraumTheme, edgeWidth: 2, selectedNode: "#73c7a5" },
});

edgeWidth and edgeOpacity are the fallback width and opacity for edges that supply no visual and no direct width or opacity field. nodeStroke is the fallback stroke color for a node that sets strokeWidth but no strokeColor. See Visual language for the canonical palette and application-owned semantic colors.

const diagnostics: GraphraumDiagnostics = graph.getDiagnostics();
interface GraphraumDiagnostics {
aggregatedNodeClusters: number;
cpuFrameMilliseconds: number;
gpuFrameMilliseconds: number | null;
gpuDrawCalls: number;
gpuGeometries: number;
gpuTextures: number;
lodLevel: "density" | "detail" | "overview";
pickingStrategy: "raycaster-3d" | "spatial-grid-2d";
totalEdges: number;
totalNodes: number;
visibleEdgeCandidates: number;
visibleEdgeMarkers: number;
visibleEdgeSegments: number;
visibleEdges: number;
visibleNodes: number;
visibleNodeCandidates: number;
}

Diagnostics describe the final rendered frame. GPU frame time is null when WebGL timer queries are unavailable. Node candidates and aggregate clusters expose density LOD decisions; total and visible counts expose the effective node and edge reductions without asking applications to re-derive them. visibleEdgeSegments counts rendered edge lines and visibleEdges is an alias for it; visibleEdgeMarkers counts rendered direction triangles, which the overview LOD tier drops first.