Skip to content
D
Documentation

Layout — interfaces i–l

reference
11 min readUpdated

Interfaces I–L

Import these from @grafloria/engine.

Interfaces

ILayoutAlgorithm

ts
interface ILayoutAlgorithm

Members

  • getName(): string — Get the name of the layout algorithm
  • getType(): 'grid' | 'force-directed' | 'hierarchical' | 'hybrid' — Get the type of the layout algorithm
  • calculatePlacement(options: PlacementOptions): PlacementResult — Calculate position for a single new node

This is called when a node is added to the diagram. The algorithm should return a position that:

  • Doesn't overlap with existing nodes
  • Follows the layout strategy
  • Fits within the viewport (or is close to existing content)
  • reLayout(diagram: DiagramModel, config?: LayoutConfiguration): Map<string, Point> — Re-layout all nodes in the diagram

This is called when the user explicitly requests a re-layout (e.g., clicks "Re-Arrange" button). The algorithm should calculate new positions for ALL nodes.

  • configure(config: LayoutConfiguration): void — Configure the layout algorithm
  • getConfiguration(): LayoutConfiguration — Get current configuration
  • canApply(diagram: DiagramModel): { valid: boolean; reason?: string } — Validate if this algorithm can be applied to the given diagram

For example:

  • Hierarchical layout requires a DAG (no cycles)
  • Force-directed works better with connected nodes
  • onActivate?(): void — Called when the algorithm is activated Use this to initialize any state or caches
  • onDeactivate?(): void — Called when the algorithm is deactivated Use this to clean up state or caches

IncrementalLayoutOptions

Options for incremental layout

ts
interface IncrementalLayoutOptions

Properties

NameTypeDefaultDescription
strategy?IncrementalLayoutStrategy'pin-existing'Strategy to use for incremental layout
newNodeIds?string[]Nodes that are new (to be laid out) If not provided, nodes without valid positions are considered new
anchorNodeIds?string[]Anchor nodes that should never move (in addition to strategy constraints) These have highest priority
maxShift?numberMaximum distance a non-anchor node can move (pixels) Only applies to 'minimal-shift' strategy
proximityRadius?number200Radius around new nodes where existing nodes can be adjusted (pixels) Only applies to 'proximity-aware' strategy
allowMinorAdjustments?booleanfalseWhether to allow slight adjustments to improve layout quality
customConstraints?LayoutConstraintsCustom constraints to apply in addition to incremental constraints

IncrementalLayoutResult

Result of incremental layout operation

ts
interface IncrementalLayoutResult

Properties

NameTypeDefaultDescription
movedNodeIdsstring[]IDs of nodes that were moved during layout
pinnedNodeIdsstring[]IDs of nodes that were pinned/fixed
newlyLaidOutNodeIdsstring[]IDs of nodes that were newly laid out
maxMovementnumberMaximum distance any node moved (pixels)
avgMovementnumberAverage distance nodes moved (pixels)
strategyIncrementalLayoutStrategyStrategy that was used
autoConstraintCountnumberNumber of constraints that were auto-generated

LabelBox

The box an edge label needs. Layout's job is to reserve it; not to place it.

ts
interface LabelBox

Properties

NameTypeDefaultDescription
idstringThe label this box belongs to.
linkIdstringThe link the label rides on.
textstring
widthnumber
heightnumber

LabelClearanceResult

ts
interface LabelClearanceResult

Properties

NameTypeDefaultDescription
overlapsnumberLabel boxes that land on top of a node.
judgednumberLabelled links that could be judged.
scorenumber100 = no label box collides with any node.
collidingLinksstring[]Which links' labels collided, for the report.

LayeringEstimate

Longest-path layering estimate for a DAG — the two numbers that predict which hierarchical engine will choke (measured, not guessed; see the perf spec):

• dagre's pathology is DEPTH: a 2,000-rank chain never returns, while a 2,000-node, ~1,000-wide tree takes ~700ms. • our layered (Sugiyama) engine's pathology is WIDTH: crossing minimisation over a ~1,000-node rank runs for tens of seconds, while a 45-wide, 90-deep mesh takes ~480ms and a width-1, 2,000-deep chain ~130ms.

O(n + m) via Kahn's algorithm. Only meaningful when the graph is acyclic; nodes left unranked by a cycle default to rank 0.

ts
interface LayeringEstimate

Properties

NameTypeDefaultDescription
depthnumberNumber of layers a longest-path layering would produce.
maxWidthnumberNode count of the widest layer.

LayoutAdapter

Interface that all layout adapters must implement

ts
interface LayoutAdapter

Properties

NameTypeDefaultDescription
namestringName of the layout adapter (e.g., 'dagre', 'elk')

Members

  • apply( nodes: NodeModel[], links: LinkModel[], options?: Partial<LayoutOptions> ): Promise<LayoutResult> — Apply layout to nodes and links
  • applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: IncrementalLayoutOptions, layoutOptions?: Partial<LayoutOptions> ): Promise<LayoutResult & { incremental: IncrementalLayoutResult }> — Apply incremental layout - layout new nodes while preserving existing positions
  • validateOptions(options: Partial<LayoutOptions>): boolean — Validate that options are valid for this adapter

LayoutCandidate

ts
interface LayoutCandidate

Properties

NameTypeDefaultDescription
namestringRegistered layout name to run.
optionsUnifiedLayoutOptionsOptions to run it with.
idstringA stable id for this candidate — name + tuning. Ties break on this.
portAwarebooleanIs this engine able to honour port sides?

LayoutConfiguration

Configuration for layout algorithms

ts
interface LayoutConfiguration

Properties

NameTypeDefaultDescription
type?LayoutAlgorithmTypeAlgorithm type (optional when passed to reLayout, as it uses current algorithm)
options?GridLayoutOptions | ForceDirectedOptions | HierarchicalOptions | HybridOptionsAlgorithm-specific options
animate?booleanWhether to animate layout changes
animationDuration?numberAnimation duration in ms
viewport?RectangleViewport for viewport-aware layout
margins?numberMargins around content
direction?'TB' | 'BT' | 'LR' | 'RL'Shorthand for hierarchical direction

LayoutConstraints

Collection of layout constraints to apply

ts
interface LayoutConstraints

Properties

NameTypeDefaultDescription
constraintsNodeConstraint[]Array of node constraints
conflictResolution?'priority' | 'first' | 'last'Strategy for handling conflicting constraints - 'priority': Use constraint priority to resolve conflicts - 'first': First constraint wins - 'last': Last constraint wins

LayoutErrorMessage

ts
interface LayoutErrorMessage

Properties

NameTypeDefaultDescription
seqnumber
kind'error'
messagestring

LayoutGraph

A whole graph, structured-clone-safe: no functions, no class instances.

ts
interface LayoutGraph

Properties

NameTypeDefaultDescription
nodesLayoutGraphNode[]
linksLayoutGraphLink[]

A link, as it crosses the boundary.

ts
interface LayoutGraphLink

Properties

NameTypeDefaultDescription
idstring
sourceNodeId?string
targetNodeId?string
sourcePortId?string
targetPortId?string

LayoutGraphNode

A node, as it crosses the boundary: geometry + topology only.

ts
interface LayoutGraphNode

Properties

NameTypeDefaultDescription
idstring
typestring
position{ x: number; y: number }
size{ width: number; height: number }
parentId?stringContainer membership — the nested-layout card needs it; harmless otherwise.
positionMode?'absolute' | 'relative' | 'layout'How position relates to the parent. Absent on pre-v3 payloads, which meant summation — i.e. 'relative'; the consumer below applies exactly that default.
ports?LayoutGraphPort[]

LayoutGraphPort

A port, as it crosses the boundary. Ids are preserved — see above.

ts
interface LayoutGraphPort

Properties

NameTypeDefaultDescription
idstring
type'input' | 'output' | 'bi'
side?'left' | 'right' | 'top' | 'bottom'
index?numberOrder within a side — carried so multi-port sides revive in the same order.
position?{ x: number; y: number }

LayoutHistoryOptions

Options for layout history management

ts
interface LayoutHistoryOptions

Properties

NameTypeDefaultDescription
maxHistorySize?numberMaximum number of history entries to keep
autoSnapshot?booleanWhether to automatically create snapshots
minSnapshotInterval?numberMinimum time between auto-snapshots (ms)

LayoutPort

The message-port surface the host needs — a real Worker satisfies it.

ts
interface LayoutPort

Properties

NameTypeDefaultDescription
onmessage((ev: { data: LayoutResponse }) => void) | null

Members

  • postMessage(msg: LayoutRequest): void

LayoutPreset

Layout preset configuration

ts
interface LayoutPreset

Properties

NameTypeDefaultDescription
idstringUnique identifier for the preset
namestringHuman-readable name
descriptionstringDescription of when to use this preset
adapter'dagre' | 'elk'Which adapter to use
optionsPartial<DagreLayoutOptions> | Partial<ELKLayoutOptions>Layout options for the adapter
constraints?LayoutConstraintsOptional pre-configured constraints
incrementalOptions?Partial<IncrementalLayoutOptions>Optional incremental layout settings
tags?string[]Tags for categorization

LayoutPresetCategory

Category of layout presets

ts
interface LayoutPresetCategory

Properties

NameTypeDefaultDescription
namestringCategory name
descriptionstringCategory description
presetsLayoutPreset[]Presets in this category

LayoutProgress

ts
interface LayoutProgress

Properties

NameTypeDefaultDescription
progressnumber0..1.
phasestring
iterationnumber
totalIterationsnumber

LayoutProgressMessage

ts
interface LayoutProgressMessage

Properties

NameTypeDefaultDescription
seqnumber
kind'progress'
progressnumber0..1. Monotonic.
phasestring
iterationnumber
totalIterationsnumber

LayoutQualityResult

Overall layout quality assessment

ts
interface LayoutQualityResult

Properties

NameTypeDefaultDescription
overallScorenumberOverall quality score (0-100)
grade'A' | 'B' | 'C' | 'D' | 'F'Quality grade (A, B, C, D, F)
metrics{ edgeCrossings: QualityMetric; nodeOverlap: QualityMetric; edgeLength: QualityMetric; nodeDistribution: QualityMetric; symmetry: QualityMetric; aspectRatio: QualityMetric; }Individual metrics
topSuggestionsstring[]Top suggestions for improvement
timestampnumberTimestamp of assessment

LayoutRequestCancel

ts
interface LayoutRequestCancel

Properties

NameTypeDefaultDescription
seqnumber
kind'cancel'
targetnumberThe seq of the run to cancel.

LayoutRequestRun

ts
interface LayoutRequestRun

Properties

NameTypeDefaultDescription
seqnumber
kind'run'
algorithmstring
graphLayoutGraph
optionsLayoutWireOptions
timeBudgetMs?numberStop and return the best-so-far once this many ms have elapsed.
sliceMs?numberHow long to compute before surrendering the thread so cancel can land.
stopAfterIteration?numberStop after exactly N iterations — a DETERMINISTIC pre-emption.

LayoutResult

Result of applying a layout algorithm

ts
interface LayoutResult

Properties

NameTypeDefaultDescription
nodePositionsMap<string, { x: number; y: number }>Map of node IDs to their new positions
bounds{ x: number; y: number; width: number; height: number; }Bounding box of the laid-out graph
metadata?{ algorithm: string; executionTime: number; [key: string]: any; }Additional metadata about the layout execution
quality?LayoutQualityResultQuality assessment of the layout (if calculateQuality was true)
portAware?PortAwareLayoutResultPort-aware layout result (if portAware was enabled)
subgraph?SubgraphLayoutResultSubgraph layout result (if subgraph was enabled)
edgeBundling?EdgeBundlingResultEdge bundling result (if edgeBundling was enabled)
routing?LayoutRoutingHintsThe port positions and edge routes the layout engine computed. Present when the engine produces them (ELK does); previously computed and discarded.

LayoutResultMessage

ts
interface LayoutResultMessage

Properties

NameTypeDefaultDescription
seqnumber
kind'result'
algorithmstring
positionsArray<[string, { x: number; y: number }]>
bounds{ x: number; y: number; width: number; height: number }
partialbooleanTrue when the run stopped early — the answer is the best-so-far, not the end.
reason?LayoutStopReason
iterationnumber
totalIterationsnumber
metadata?LayoutResult['metadata']Everything else the adapter reported, carried verbatim.
quality?LayoutResult['quality']
portAware?LayoutResult['portAware']
subgraph?LayoutResult['subgraph']
edgeBundling?LayoutResult['edgeBundling']

LayoutRng

A seeded, deterministic source of randomness.

ts
interface LayoutRng

Properties

NameTypeDefaultDescription
seednumberThe seed this generator was created with (so a result can report it).

Members

  • next(): number — Uniform in [0, 1).
  • between(min: number, max: number): number — Uniform in [min, max).

LayoutRoutingHints

What the layout engine worked out about EDGES and PORTS, which until now was computed and then thrown in the bin.

ELK does genuine port-aware layered layout with orthogonal edge routing. The old adapter read back child.x / child.y and NOTHING else — every port position and every edge section ELK produced was discarded. These are those results.

They are HINTS, deliberately. Layout's job is to place nodes so a good route EXISTS and to say where it thinks that route runs — not to draw it.

ts
interface LayoutRoutingHints

Properties

NameTypeDefaultDescription
portPositionsMap<string, { x: number; y: number; side: PortSide }>Absolute position of each declared port, as the layout engine placed it.
edgeRoutesMap<string, { start: Point; end: Point; bends: Point[] }>The route the layout engine found for each link: endpoints + bend points.
labelSpaceMap<string, { width: number; height: number }>The box reserved for each labelled link (keyed by link id).
orthogonalbooleanWhether the engine routed orthogonally.

Was this page helpful?

Layout — interfaces i–l — Grafloria