import type { GraphIR } from "./graph-ir.js"; /** * Layout-position export — node coordinates a custom painter consumes (the * rackattack pattern: an engine lays out, the painter draws). The engine is used * for LAYOUT ONLY; any rendering it can do is discarded. See issue #497 / epic * #492, and #509 for the size-aware redesign. * * The engine takes an **engine-neutral {@link LayoutInput}** — sized nodes plus * edges — not a DOT string, so the painter's real node sizes drive spacing * (without sizes a layout engine packs for tiny default boxes and big cards * collide). Two engines implement it: * * - {@link DagreLayout} (default) — pure JS, size-aware, **no native dependency**. * - {@link GraphvizLayout} — opt-in; shells `dot`. Honours `groups` as clusters. * * Coordinate convention (both engines): **y grows up, origin bottom-left**, as * `dot -Tjson` reports. A painter flips y to read top-to-bottom. */ /** A laid-out position in the engine's coordinate space (y-up). */ export interface Point { x: number; y: number; } /** Node positions plus the overall canvas size a painter needs. Centres are * y-up (origin bottom-left). `w`/`h` echo the footprint the engine laid out * with, so a painter can route edges to card borders rather than centres. */ export interface Layout { /** Canvas width in the engine's coordinate space. */ width: number; /** Canvas height in the engine's coordinate space. */ height: number; /** Each node's centre position (+ footprint), ordered by id for determinism. */ nodes: Array<{ id: string; w?: number; h?: number; } & Point>; } /** A node's painted footprint, in layout units (≈ px / points). */ export interface NodeSize { w: number; h: number; } /** Engine-neutral layout input: sized nodes + edges (+ optional groups). */ export interface LayoutInput { nodes: Array<{ id: string; } & NodeSize>; edges: Array<{ from: string; to: string; }>; /** Group name → member ids, for cluster-aware engines (graphviz subgraphs). */ groups?: Record; } /** Turns sized nodes + edges into node positions. The painter consumes the * result; it never asks the engine to paint. */ export interface LayoutEngine { readonly name: string; layout(input: LayoutInput): Promise; } /** Graphviz's default node box, in layout units — the fallback for a node the * painter didn't measure, so a size-less call still lays out as it always did. */ export declare const DEFAULT_NODE_SIZE: NodeSize; /** Build engine input from an IR and a painter-measured size map (id → {w,h}). * Nodes absent from the map fall back to {@link DEFAULT_NODE_SIZE}. Pure. */ export declare function toLayoutInput(ir: GraphIR, sizes?: Record): LayoutInput; /** * Layout via dagre — pure JS, size-aware, no native dependency. The default. * Fed nodes/edges in id order so the result is deterministic. dagre's space is * y-down; we flip to y-up so the {@link Layout} contract matches Graphviz. */ export declare class DagreLayout implements LayoutEngine { readonly name = "dagre"; layout(input: LayoutInput): Promise; } /** Layout via `dot -Tjson`. Opt-in; requires Graphviz (`brew install graphviz`). * Lays out with real node sizes (`fixedsize`) and honours `groups` as clusters. */ export declare class GraphvizLayout implements LayoutEngine { readonly name = "graphviz"; layout(input: LayoutInput): Promise; } /** Resolve a layout engine by name. Defaults to dagre (no native dependency). */ export declare function getLayoutEngine(name?: string): LayoutEngine; /** Parse `dot -Tjson` output into a {@link Layout}. Pure; exported for testing. */ export declare function parseDotJson(json: string): Layout; //# sourceMappingURL=graph-layout.d.ts.map