d3-dag
Version:
Layout algorithms for visualizing directed acylic graphs.
200 lines (199 loc) • 7.05 kB
TypeScript
import type { Operator, Rankdir } from "./layout";
/** @internal */
interface IdDagreNode extends DagreNode {
id: string;
}
type DagreOperator = Operator<IdDagreNode, undefined>;
export type { Rankdir } from "./layout";
/** quality preset for layout speed/quality trade-off */
export type DagreQuality = "fast" | "medium" | "slow";
/** layering algorithm for rank assignment */
export type DagreRanker = "network-simplex" | "longest-path" | "topological";
/** layout algorithm */
export type DagreAlgorithm = "sugiyama" | "zherebko" | "grid";
/** graph configuration set via {@link DagreGraph.setGraph} */
export interface DagreGraphConfig {
/** layout direction (default: `"TB"`) */
rankdir?: Rankdir;
/** within-layer gap (default: `50`) */
nodesep?: number;
/** between-layer gap (default: `50`) */
ranksep?: number;
/** quality preset (default: `"medium"`) */
quality?: DagreQuality;
/** layering algorithm (default: `undefined`, uses preset default) */
ranker?: DagreRanker;
/** layout algorithm (default: `"sugiyama"`); `quality`/`ranker` only apply to sugiyama */
algorithm?: DagreAlgorithm;
/** total layout width (set by {@link dagre.layout}) */
width?: number;
/** total layout height (set by {@link dagre.layout}) */
height?: number;
}
/** node label with position (x, y set by {@link dagre.layout}) */
export interface DagreNode {
/** center x coordinate */
x: number;
/** center y coordinate */
y: number;
/** node width */
width: number;
/** node height */
height: number;
}
/** a control point with x and y coordinates */
export interface DagrePoint {
/** x coordinate */
x: number;
/** y coordinate */
y: number;
}
/** edge label with control points (set by {@link dagre.layout}) */
export interface DagreEdge {
/** control points (matches dagre's `{x, y}` format) */
points: DagrePoint[];
}
/** edge descriptor returned by {@link DagreGraph.edges} */
export interface DagreEdgeDescriptor {
/** source node id */
v: string;
/** target node id */
w: string;
}
/**
* dagre-compatible mutable graph backed by d3-dag
*
* Accessed as `dagre.graphlib.Graph`. Use with {@link dagre.layout}.
*
* @example
*
* ```ts
* import { dagre } from "d3-dag";
*
* const grf = new dagre.graphlib.Graph();
* grf.setGraph({});
* grf.setDefaultEdgeLabel(() => ({}));
* grf.setNode("a", { width: 40, height: 40 });
* grf.setNode("b", { width: 40, height: 40 });
* grf.setEdge("a", "b");
* dagre.layout(grf);
* const pos = grf.node("a"); // { x, y, width, height }
* ```
*/
export declare class DagreGraph {
#private;
/** set graph configuration */
setGraph(config?: DagreGraphConfig): this;
/** get graph configuration (includes width/height after layout) */
graph(): Required<DagreGraphConfig>;
/** set default node label factory, used when {@link setNode} is called without a label */
setDefaultNodeLabel(fn: () => {
readonly width?: number;
readonly height?: number;
}): this;
/** set default edge label factory (accepted for compatibility, not used) */
setDefaultEdgeLabel(_fn: () => Record<string, unknown>): this;
/** add or update a node */
setNode(id: string, label?: {
readonly width?: number;
readonly height?: number;
}): this;
/** add or update multiple nodes */
setNodes(ids: string[], label?: {
readonly width?: number;
readonly height?: number;
}): this;
/** add an edge (label is accepted for dagre compatibility but not used) */
setEdge(v: string, w: string, _label?: Record<string, unknown>): this;
/** check if a node exists */
hasNode(id: string): boolean;
/** check if an edge exists */
hasEdge(v: string, w: string): boolean;
/** remove a node and all its edges */
removeNode(id: string): this;
/** remove an edge */
removeEdge(v: string, w: string): this;
/** get node label (includes x, y after layout) */
node(id: string): DagreNode;
/** get edge label (includes points after layout) */
edge(v: string, w: string): DagreEdge;
/** get all node ids */
nodes(): string[];
/** get all edges as `{ v, w }` descriptors */
edges(): DagreEdgeDescriptor[];
/** number of nodes */
nodeCount(): number;
/** number of edges */
edgeCount(): number;
/** get predecessor node ids */
predecessors(id: string): string[];
/** get successor node ids */
successors(id: string): string[];
/** get all neighbor node ids (predecessors and successors, deduplicated) */
neighbors(id: string): string[];
/** get incoming edge descriptors, optionally filtered to edges from `w` */
inEdges(v: string, w?: string): DagreEdgeDescriptor[];
/** get outgoing edge descriptors, optionally filtered to edges to `w` */
outEdges(v: string, w?: string): DagreEdgeDescriptor[];
/** get all edge descriptors incident to `v`, optionally filtered to edges with `w` */
nodeEdges(v: string, w?: string): DagreEdgeDescriptor[];
/** get source node ids (no parents) */
sources(): string[];
/** get sink node ids (no children) */
sinks(): string[];
/** always true — dagre graphs are directed */
isDirected(): true;
/** always false — compound graphs are not supported */
isCompound(): false;
/** true if the graph has multiple edges between the same pair of nodes */
isMultigraph(): boolean;
/** add edges between consecutive pairs of nodes */
setPath(nodes: string[]): this;
/** create a new graph containing only nodes that pass the filter */
filterNodes(fn: (id: string) => boolean): DagreGraph;
/**
* run layout — called by {@link dagre.layout}
*
* @internal
*/
static layout(grf: DagreGraph, operator?: DagreOperator): void;
}
/**
* dagre-compatible namespace backed by d3-dag
*
* Drop-in replacement for `dagre` using d3-dag's layout algorithms.
* Optionally pass a custom {@link sugiyama} or {@link zherebko} operator
* to `layout` for fine-tuned algorithm selection.
*
* @example
*
* ```ts
* import { dagre } from "d3-dag";
*
* const grf = new dagre.graphlib.Graph();
* grf.setGraph({});
* grf.setDefaultEdgeLabel(() => ({}));
* grf.setNode("a", { width: 40, height: 40 });
* grf.setNode("b", { width: 40, height: 40 });
* grf.setEdge("a", "b");
* dagre.layout(grf);
* const { x, y } = grf.node("a");
* ```
*/
export declare const dagre: {
/** graph constructors */
readonly graphlib: {
/** dagre-compatible graph class */
readonly Graph: typeof DagreGraph;
};
/**
* run layout on a graph, mutating it in-place
*
* Sets `x`/`y` on node labels, `points` on edge labels, and
* `width`/`height` on the graph config.
*
* @param grf - the graph to lay out
* @param operator - optional {@link Operator}; graph config is applied on top
*/
readonly layout: typeof DagreGraph.layout;
};