Classes
Import these from @grafloria/engine.
Classes
BaseLayoutAlgorithm
Base abstract class for layout algorithms
Provides common functionality that all layout algorithms can use. Extend this class when implementing a new layout algorithm.
tsabstract class BaseLayoutAlgorithm implements ILayoutAlgorithm
Methods
constructor(config?: LayoutConfiguration)abstract getName(): string— Get the name of the layout algorithmabstract getType(): 'grid' | 'force-directed' | 'hierarchical' | 'hybrid'— Get the type of the layout algorithmabstract 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)
abstract 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 algorithmgetConfiguration(): LayoutConfiguration— Get current configurationcanApply(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
CommunityLayoutAdapter
Community Detection Layout Adapter
Uses Louvain algorithm to detect communities and arranges them.
tsclass CommunityLayoutAdapter implements LayoutAdapter
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | 'community' | Name of the layout adapter (e.g., 'dagre', 'elk') |
Methods
async apply( nodes: NodeModel[], links: LinkModel[], options: Partial<CommunityLayoutOptions> = {} ): Promise<LayoutResult>— Apply community detection layoutasync applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: any, layoutOptions?: Partial<CommunityLayoutOptions> ): Promise<LayoutResult & { incremental: any }>— Apply incremental layoutvalidateOptions(options: Partial<CommunityLayoutOptions>): boolean— Validate options
CompoundLayoutService
tsclass CompoundLayoutService
Methods
constructor( private readonly diagram: DiagramModel, private readonly options: CompoundLayoutOptions = {} )async layout(): Promise<CompoundLayoutResult>— Run the compound layout over the whole diagram.
ConstraintManager
Helper class for managing and applying layout constraints
tsclass ConstraintManager
Methods
constructor(constraints?: LayoutConstraints)addConstraints(constraints: LayoutConstraints): void— Add constraints to the managergetConstraints(nodeId: string): NodeConstraint[]— Get all constraints for a specific nodehasConstraints(nodeId: string): boolean— Check if a node has any constraintsapplyConstraints( nodeId: string, proposedPosition: Position, conflictResolution: 'priority' | 'first' | 'last' = 'priority' ): Position— Apply constraints to a position, returning the constrained positionclear(): void— Clear all constraintsremoveConstraints(nodeId: string): void— Remove constraints for a specific nodegetConstrainedNodeCount(): number— Get total number of constrained nodesgetConstrainedNodeIds(): string[]— Get all constrained node IDs
DagreLayoutAdapter
Dagre Layout Adapter
Provides hierarchical layout using the Dagre library. Converts between Grafloria's node/link model and Dagre's graph structure.
tsclass DagreLayoutAdapter implements LayoutAdapter
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | 'dagre' | Name of the layout adapter (e.g., 'dagre', 'elk') |
Methods
async apply( nodes: NodeModel[], links: LinkModel[], options: Partial<DagreLayoutOptions> = {} ): Promise<LayoutResult>— Apply Dagre layout to nodes and linksvalidateOptions(options: Partial<DagreLayoutOptions>): boolean— Validate Dagre layout optionsasync applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: IncrementalLayoutOptions, layoutOptions?: Partial<DagreLayoutOptions> ): Promise<LayoutResult & { incremental: IncrementalLayoutResult }>— Apply incremental layout - layout new nodes while preserving existing positions
EdgeBundlingManager
Edge bundling computation utilities
tsclass EdgeBundlingManager
Methods
static computeBundling( edges: EdgeInfo[], nodePositions: Map<string, Point2D>, portPositions: Map<string, Point2D>, options: EdgeBundlingOptions ): EdgeBundlingResult(static) — Compute edge bundling for a set of edges
ELKLayoutAdapter
ELK Layout Adapter
Provides advanced layout algorithms using the Eclipse Layout Kernel. Supports multiple algorithms with extensive configuration options.
tsclass ELKLayoutAdapter implements LayoutAdapter
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | 'elk' | Name of the layout adapter (e.g., 'dagre', 'elk') |
Methods
async apply( nodes: NodeModel[], links: LinkModel[], options: Partial<ELKLayoutOptions> = {} ): Promise<LayoutResult>— Apply ELK layout to nodes and linksvalidateOptions(options: Partial<ELKLayoutOptions>): boolean— Validate ELK layout optionsasync applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: IncrementalLayoutOptions, layoutOptions?: Partial<ELKLayoutOptions> ): Promise<LayoutResult & { incremental: IncrementalLayoutResult }>— Apply incremental layout - layout new nodes while preserving existing positions
ForceLayoutAdapter
Force-Directed Layout Adapter
Implements Fruchterman-Reingold algorithm with Barnes-Hut optimization.
tsclass ForceLayoutAdapter implements SteppableLayoutAdapter
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | 'force' | Name of the layout adapter (e.g., 'dagre', 'elk') |
Methods
createRun( nodes: NodeModel[], links: LinkModel[], options: Partial<ForceLayoutOptions> = {} ): LayoutRun— The simulation, exposed one iteration at a time.
This is where the physics lives, and it is the ONLY place it lives: apply()
below is now just "drive this to convergence". Splitting the loop out (rather
than copying it into a worker-flavoured twin) is what keeps the off-thread
path honest — the worker and the main thread run the same arithmetic in the
same order, so they cannot drift.
Pure and synchronous: no clock, no DOM, and randomness only through the seeded generator. Those three abstinences are the whole reason a worker run and an inline run produce byte-identical coordinates.
snapshot() is meaningful after ANY number of steps, which is what makes a
cancelled force layout return the 200-iteration picture it already has
instead of throwing it away.
async apply( nodes: NodeModel[], links: LinkModel[], options: Partial<ForceLayoutOptions> = {} ): Promise<LayoutResult>— Apply force-directed layout (run the simulation to convergence).async applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: any, layoutOptions?: Partial<ForceLayoutOptions> ): Promise<LayoutResult & { incremental: any }>— Apply incremental layoutvalidateOptions(options: Partial<ForceLayoutOptions>): boolean— Validate options
IncrementalLayoutManager
Helper class for managing incremental layouts
tsclass IncrementalLayoutManager
Methods
static identifyNewNodes( nodes: NodeModel[], options: IncrementalLayoutOptions ): string[](static) — Identify new nodes that need to be laid outstatic identifyExistingNodes( nodes: NodeModel[], newNodeIds: string[] ): string[](static) — Identify existing nodes that should be constrainedstatic generateConstraints( nodes: NodeModel[], options: IncrementalLayoutOptions ): LayoutConstraints(static) — Generate constraints for incremental layout based on strategystatic calculateResult( nodes: NodeModel[], oldPositions: Map<string, { x: number; y: number }>, newNodeIds: string[], constraints: LayoutConstraints, strategy: IncrementalLayoutStrategy ): IncrementalLayoutResult(static) — Calculate movement statistics after incremental layout
LayoutHistory
Layout History Manager
Manages undo/redo stack for layout operations
tsclass LayoutHistory
Methods
constructor(options: LayoutHistoryOptions = {})pushSnapshot( nodes: NodeModel[], description?: string, algorithm?: string, options?: any ): LayoutSnapshot— Create and push a new snapshotundo(): LayoutSnapshot | undefined— Undo to previous snapshotredo(): LayoutSnapshot | undefined— Redo to next snapshotcanUndo(): boolean— Check if undo is possiblecanRedo(): boolean— Check if redo is possiblegetCurrentSnapshot(): LayoutSnapshot | undefined— Get current snapshotgetAllSnapshots(): LayoutSnapshot[]— Get all snapshotsgetSnapshotById(id: string): LayoutSnapshot | undefined— Get snapshot by IDrestoreSnapshot(id: string): LayoutSnapshot | undefined— Restore a specific snapshot by IDclear(): void— Clear all historysize(): number— Get history sizegetCurrentIndex(): number— Get current index in historystatic applySnapshot(snapshot: LayoutSnapshot, nodes: NodeModel[]): number(static) — Apply snapshot to nodesexportToJSON(): string— Export history to JSONimportFromJSON(json: string): boolean— Import history from JSONgetStatistics(): { totalSnapshots: number; currentIndex: number; canUndo: boolean; canRedo: boolean; oldestTimestamp: number; newestTimestamp: number; averageInterval: number; }— Get history statistics
LayoutHost
The caller-side host.
Pass a real Worker (or anything satisfying LayoutPort) to run off-thread;
pass nothing to run inline on the same thread. Identical behaviour, no protocol
drift, because BOTH paths speak through serveLayout.
tsclass LayoutHost
Methods
constructor(port?: LayoutPort, deps: ServeLayoutDeps = {})run( algorithm: string, graph: LayoutGraph, options: LayoutWireOptions = {}, runOptions: LayoutRunOptions = {} ): Promise<HostLayoutResult>
LayoutPresets
Predefined layout presets for common scenarios
tsclass LayoutPresets
Properties
| Name | Type | Default | Description |
|---|---|---|---|
HIERARCHICAL (static) | LayoutPresetCategory | Organizational/Hierarchical Layouts | |
FLOW (static) | LayoutPresetCategory | Process/Flow Layouts | |
NETWORK (static) | LayoutPresetCategory | Network/Graph Layouts | |
ARCHITECTURE (static) | LayoutPresetCategory | Architecture/System Layouts | |
INTERACTIVE (static) | LayoutPresetCategory | Interactive/Dashboard Layouts |
Methods
static getAllCategories(): LayoutPresetCategory[](static) — Get all preset categoriesstatic getAllPresets(): LayoutPreset[](static) — Get all presets across all categoriesstatic findPreset(id: string): LayoutPreset | undefined(static) — Find preset by IDstatic findPresetsByTag(tag: string): LayoutPreset[](static) — Find presets by tagstatic findPresetsByAdapter(adapter: 'dagre' | 'elk'): LayoutPreset[](static) — Find presets by adapter typestatic searchPresets(query: string): LayoutPreset[](static) — Search presets by name or description
LayoutQualityMetrics
Layout Quality Metrics Calculator
tsclass LayoutQualityMetrics
Methods
static assess( nodes: NodeModel[], links: LinkModel[], options: QualityAssessmentOptions = {} ): LayoutQualityResult(static) — Assess the quality of a layout
LayoutRegistry
The named-algorithm registry.
tsclass LayoutRegistry
Methods
register(engine: RegisteredLayout): () => voidget(name: string): RegisteredLayout | undefinedhas(name: string): booleannames(): string[]— Registered names, sorted — a stable list is part of being deterministic.adapters(): Record<string, LayoutAdapter>— Name → adapter, for every registered engine that exposes one.
This is what nested (compound) layout resolves a container's algorithm
against — so group.subgraphLayout = { algorithm: 'force' } works, and so
does an algorithm an extension registered, rather than only the hard-coded
dagre|elk pair.
LayoutService
Layout Service
Manages layout adapters and provides a unified API for applying layouts. Can be used as a singleton or instantiated per diagram.
tsclass LayoutService
Methods
constructor()registerAdapter(adapter: LayoutAdapter): void— Register a custom layout adaptergetAdapter(name: string): LayoutAdapter | undefined— Get a registered adapter by namegetAdapterNames(): string[]— Get all registered adapter namesasync applyLayout(diagram: DiagramModel, config: ApplyLayoutConfig): Promise<LayoutResult>— Apply layout to diagram
SpectralLayoutAdapter
Spectral Layout Adapter
Uses eigendecomposition of graph Laplacian for optimal layout.
tsclass SpectralLayoutAdapter implements LayoutAdapter
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | 'spectral' | Name of the layout adapter (e.g., 'dagre', 'elk') |
Methods
async apply( nodes: NodeModel[], links: LinkModel[], options: Partial<SpectralLayoutOptions> = {} ): Promise<LayoutResult>— Apply spectral layoutasync applyIncremental( nodes: NodeModel[], links: LinkModel[], incrementalOptions: any, layoutOptions?: Partial<SpectralLayoutOptions> ): Promise<LayoutResult & { incremental: any }>— Apply incremental layoutvalidateOptions(options: Partial<SpectralLayoutOptions>): boolean— Validate options
Was this page helpful?