import { AfterContentInit } from '@angular/core'; import { AfterViewInit } from '@angular/core'; import { ElementRef } from '@angular/core'; import { EventEmitter } from '@angular/core'; import * as i0 from '@angular/core'; import { Injector } from '@angular/core'; import { InputSignal } from '@angular/core'; import { OnDestroy } from '@angular/core'; import { OnInit } from '@angular/core'; import { Provider } from '@angular/core'; import { Signal } from '@angular/core'; import { Type } from '@angular/core'; import { WritableSignal } from '@angular/core'; /** * Type representing an absolute edge label position in pixels. * Positive values measure from the source, negative from the target. * * @example `'30px'` — 30px from source, `'-20px'` — 20px from target * * @public * @since 1.1.0 * @category Types/Model */ export declare type AbsoluteEdgeLabelPosition = `${number}px`; /** * Interface representing the current state of various user interactions in the diagram. * * This state is read-only and automatically managed by the library. It provides * information about active operations such as resizing, linking, dragging, and other * user interactions. Use this to observe the current state, not to modify it. * * @public * @since 0.8.0 * @category Internals */ export declare interface ActionState { /** * State related to node resizing action */ resize?: ResizeActionState; /** * State related to linking nodes */ linking?: LinkingActionState; /** * State related to copy-paste actions */ copyPaste?: CopyPasteActionState; /** * State related to highlighting groups */ highlightGroup?: HighlightGroupActionState; /** * State related to node rotation */ rotation?: RotationActionState; /** * State related to dragging elements */ dragging?: DraggingActionState; /** * State related to panning the viewport */ panning?: PanningActionState; /** * State related to selection gestures */ selection?: SelectionActionState; } /** * Event payload emitted when the action state changes. * * This event fires when an action like resizing, rotating, or linking * starts or ends, allowing subscribers to react to state changes. * * @internal */ declare interface ActionStateChangedEvent { /** The current action state */ actionState: Readonly; } /** * **Internal manager** for temporary state during ongoing user actions. * Tracks the state of interactive operations like resizing, linking, rotating, and dragging * until the action completes. * * @remarks * **For application code, use {@link NgDiagramService.actionState} signal instead.** * This class is exposed primarily for middleware development where you can access it * via `context.actionStateManager`. * * @example * ```typescript * const middleware: Middleware = { * name: 'resize-validator', * execute: (context, next, cancel) => { * const resizeState = context.actionStateManager.resize; * if (resizeState) { * console.log('Currently resizing node:', resizeState.nodeId); * } * next(); * } * }; * ``` * * @public * @since 0.8.0 * @category Internals */ export declare class ActionStateManager { private readonly eventManager; private state; constructor(eventManager: EventManager); /** * Gets the current action state (readonly). * * @returns The complete action state object */ getState(): Readonly; /** * Emits an 'actionStateChanged' event with the current state. * @internal */ private emitStateChanged; /** * Gets the current resize action state. * * @returns The resize state if a resize is in progress, undefined otherwise */ get resize(): ResizeActionState | undefined; /** * Sets the resize action state. * * @param value - The resize state to set, or undefined to clear */ set resize(value: ResizeActionState | undefined); /** * Gets the current linking action state. * * @returns The linking state if a link is being created, undefined otherwise */ get linking(): LinkingActionState | undefined; /** * Sets the linking action state. * * @param value - The linking state to set, or undefined to clear */ set linking(value: LinkingActionState | undefined); /** * Gets the current copy/paste action state. * * @returns The copy/paste state if a copy/paste operation is in progress, undefined otherwise */ get copyPaste(): CopyPasteActionState | undefined; /** * Sets the copy/paste action state. * * @param value - The copy/paste state to set, or undefined to clear */ set copyPaste(value: CopyPasteActionState | undefined); /** * Gets the current highlight group action state. * * @returns The highlight group state if a group is being highlighted, undefined otherwise */ get highlightGroup(): HighlightGroupActionState | undefined; /** * Sets the highlight group action state. * * @param value - The highlight group state to set, or undefined to clear */ set highlightGroup(value: HighlightGroupActionState | undefined); /** * Gets the current rotation action state. * * @returns The rotation state if a rotation is in progress, undefined otherwise */ get rotation(): RotationActionState | undefined; /** * Sets the rotation action state. * * @param value - The rotation state to set, or undefined to clear */ set rotation(value: RotationActionState | undefined); /** * Gets the current dragging action state. * * @returns The dragging state if nodes are being dragged, undefined otherwise */ get dragging(): DraggingActionState | undefined; /** * Sets the dragging action state. * * @param value - The dragging state to set, or undefined to clear */ set dragging(value: DraggingActionState | undefined); /** * Gets the current panning action state. * * @returns The panning state if viewport is being panned, undefined otherwise */ get panning(): PanningActionState | undefined; /** * Sets the panning action state. * * @param value - The panning state to set, or undefined to clear */ set panning(value: PanningActionState | undefined); /** * Clears the resize action state. */ clearResize(): void; /** * Clears the linking action state. */ clearLinking(): void; /** * Clears the copy/paste action state. */ clearCopyPaste(): void; /** * Clears the highlight group action state. */ clearHighlightGroup(): void; /** * Clears the rotation action state. */ clearRotation(): void; /** * Clears the dragging action state. */ clearDragging(): void; /** * Checks if a resize operation is currently in progress. */ isResizing(): boolean; /** * Checks if a linking operation is currently in progress. */ isLinking(): boolean; /** * Checks if a rotation operation is currently in progress. */ isRotating(): boolean; /** * Checks if a dragging operation is currently in progress. */ isDragging(): boolean; /** * Clears the panning action state. */ clearPanning(): void; /** * Checks if a panning operation is currently in progress. */ isPanning(): boolean; /** * Gets the current selection action state. * * @returns The selection state if set, undefined otherwise */ get selection(): SelectionActionState | undefined; /** * Sets the selection action state. * * @param value - The selection state to set, or undefined to clear */ set selection(value: SelectionActionState | undefined); /** * Clears the selection action state. */ clearSelection(): void; } declare interface AddEdgeLabelsBulkCommand { name: 'addEdgeLabelsBulk'; additions: Map; } declare interface AddEdgesCommand { name: 'addEdges'; edges: Edge[]; } declare interface AddNodesCommand { name: 'addNodes'; nodes: Node_2[]; } declare interface AddPortsBulkCommand { name: 'addPortsBulk'; additions: Map; } declare interface AddToGroupCommand { name: 'addToGroup'; groupId: Node_2['id']; nodeIds: Node_2['id'][]; } declare function angleBetweenPoints(from: Point, to: Point): number; /** * `AppMiddlewares` is a tuple type representing the default middleware chain used by ngDiagram. * * This type is used as the default for the `createMiddlewares` factory and as the base type for customizing * or extending the middleware chain in your application. * * @internal */ export declare type AppMiddlewares = typeof BUILTIN_MIDDLEWARES; /** * Configuration for the diagram background. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface BackgroundConfig { /** * Distance in pixels between consecutive dots in the background pattern. * @default 30 */ dotSpacing?: number; /** * The size of the smallest grid cell (minor grid spacing). * Supports rectangular grids by specifying different width and height values. * @default { width: 10, height: 10 } */ cellSize?: Size; /** * Specifies how often major grid lines occur, measured in counts of minor grid cells. * E.g., { x: 5, y: 5 } draws a major vertical line every 5 minor columns and * a major horizontal line every 5 minor rows. * @default { x: 5, y: 5 } */ majorLinesFrequency?: { x: number; y: number; }; } /** * @deprecated Use {@link NgDiagramBaseEdgeLabelComponent} instead. This alias will be removed in a future version. * * @public * @since 0.8.0 * @category Other */ export declare const BaseEdgeLabelComponent: typeof NgDiagramBaseEdgeLabelComponent; declare interface BaseInputEvent { name: InputEventName; id: string; timestamp: number; modifiers: InputModifiers; } /** * Base data interface for palette items. All palette item data should extend this interface and include at minimum a `label` property. * * @public * @since 0.8.0 * @category Types/Palette */ export declare interface BasePaletteItemData { /** * The display label for the palette item. */ label: string; } declare interface BasePointerInputEvent extends BaseInputEvent { target: Node_2 | Edge | undefined; targetType: 'node' | 'edge' | 'diagram'; /** * The last input point in the client coordinates. */ lastInputPoint: Point; } /** * Generic batch processor that collects operations (add, update, delete) within * the same JavaScript tick and flushes them together in a single microtask. * * Before flushing, two deduplication strategies are applied: * 1. **Intent cancellation**: matching add+delete pairs for the same item ID are * removed from both queues (e.g. type change destroys and recreates a port * with the same ID in the same tick). * 2. **Measurement filtering**: remaining adds with no matching delete are checked * via `getMeasuredIds`. If the item is already measured, the add is dropped * (e.g. virtualization re-mounts a component for a port that was never deleted * from the model). * * Remaining operations are flushed sequentially in order: adds → updates → deletes. * Each operation is awaited before the next begins, ensuring that later * operations read fresh state left by earlier ones. * * Callbacks are stored per-key, so different callers can safely use the same * BatchProcessor instance with different flush targets. * * @typeParam TAdd - Type of items being added (must have an `id` property) * @typeParam TUpdate - Type of update descriptors */ declare class BatchProcessor { private readonly getMeasuredIds?; private readonly pendingAdds; private readonly pendingUpdates; private readonly pendingDeletes; private flushScheduled; constructor(getMeasuredIds?: GetMeasuredIdsFn | undefined); processAdd(key: string, item: TAdd, onFlush: FlushCallback): void; processUpdate(key: string, update: TUpdate, onFlush: FlushCallback): void; processDelete(key: string, itemId: string, onFlush: FlushCallback): void; private scheduleFlush; /** * Flushes all pending operations. * First cancels matching add+delete intents for the same item ID, * then filters out redundant adds for items that are already measured, * then executes remaining operations sequentially: adds → updates → deletes. * Each callback is awaited before the next to prevent read-modify-write races. */ private flush; /** * Groups entries by callback reference and invokes each callback once * with all its keys collected into a single Map. */ private invokeCallbacks; /** * Cancels out items that appear in both pendingAdds and pendingDeletes for the same key. * This prevents scenarios where an add+delete (or delete+add) in the same tick * produces counter-intuitive results due to flush ordering. */ private cancelMatchingIntents; /** * Filters out adds for items that are already measured and have no matching delete. * This runs after cancelMatchingIntents, so any remaining add without a delete * is an "orphaned" add — typically from virtualization re-mounting a component * for an item that was never removed from the model. */ private filterAlreadyMeasuredAdds; private getOrCreate; private takeAll; } /** * Configuration for box selection behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface BoxSelectionConfig { /** * Whether to select nodes that are only partially within the selection box. * @default true */ partialInclusion?: boolean; /** * Whether to select nodes in real-time as the selection box is being drawn. * If false, nodes will only be selected when the box selection ends. * @default true */ realtime?: boolean; } export declare class BoxSelectionDirective implements OnInit, OnDestroy { private readonly inputEventsRouter; private readonly boxSelectionProvider; private readonly flowCoreProvider; private readonly elementRef; private startPoint; ngOnInit(): void; ngOnDestroy(): void; private onPointerDownCapture; onPointerDown(event: PointerInputEvent): void; onPointerUp: (event: PointerEvent) => void; private onMouseMove; private shouldHandle; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface BringToFrontCommand { name: 'bringToFront'; nodeIds?: string[]; edgeIds?: string[]; } /** * List of built-in edge routing names in registration order. * * @remarks * These routings are automatically registered when an EdgeRoutingManager is created: * - `orthogonal`: Routes edges with right-angle turns * - `bezier`: Routes edges with smooth Bezier curves * - `polyline`: Routes edges as straight line segments * * @category Types/Routing */ declare const BUILT_IN_EDGE_ROUTINGS: readonly ["orthogonal", "bezier", "polyline"]; declare const BUILTIN_MIDDLEWARES: [Middleware, Middleware<"z-index">, Middleware]; /** * Type representing built-in edge routing names * @internal */ declare type BuiltInEdgeRoutingName = (typeof BUILT_IN_EDGE_ROUTINGS)[number]; declare interface CenterOnNodeCommand { name: 'centerOnNode'; nodeOrId: string | Node_2; } declare interface CenterOnRectCommand { name: 'centerOnRect'; rect: Rect; } declare interface ClearModelCommand { name: 'clearModel'; } /** * Event payload emitted when clipboard content is pasted into the diagram. * * This event fires when nodes and edges are added via paste operations, * either through keyboard shortcuts or programmatic paste commands. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface ClipboardPastedEvent { /** Nodes that were pasted into the diagram */ nodes: Node_2[]; /** Edges that were pasted into the diagram */ edges: Edge[]; } /** * Type for system commands that can be emitted by InputEventHandler or user */ declare type Command = InitCommand | SelectCommand | SelectAllCommand | SelectEndCommand | DeselectCommand | DeselectAllCommand | MoveNodesByCommand | MoveNodesStartCommand | MoveNodesStopCommand | DeleteSelectionCommand | AddNodesCommand | UpdateNodeCommand | UpdateNodesCommand | PaletteDropNodeCommand | DeleteNodesCommand | AddEdgesCommand | UpdateEdgeCommand | UpdateEdgesCommand | DeleteEdgesCommand | CopyCommand | CutCommand | PasteCommand | MoveViewportCommand | MoveViewportByCommand | StartLinkingCommand | MoveTemporaryEdgeCommand | FinishLinkingCommand | StartLinkingFromPositionCommand | FinishLinkingToPositionCommand | ResizeNodeCommand | ResizeNodeStartCommand | ResizeNodeStopCommand | ZoomCommand | AddPortsBulkCommand | UpdatePortsBulkCommand | DeletePortsBulkCommand | BringToFrontCommand | SendToBackCommand | AddEdgeLabelsBulkCommand | UpdateEdgeLabelsBulkCommand | DeleteEdgeLabelsBulkCommand | RotateNodeToCommand | RotateNodeStartCommand | RotateNodeStopCommand | HighlightGroupCommand | HighlightGroupClearCommand | AddToGroupCommand | ClearModelCommand | RemoveFromGroupCommand | CenterOnNodeCommand | CenterOnRectCommand | ZoomToFitCommand; /** * Type for command by name */ declare type CommandByName = Extract; /** * Type for command callback function */ declare type CommandCallback = (command: CommandByName) => void; /** * Core implementation of CommandHandler interface * Handles command emission and registration of callbacks for system commands */ declare class CommandHandler implements CommandHandler_2 { private callbacks; readonly flowCore: FlowCore; constructor(flowCore: FlowCore); /** * Emit a system command to all registered callbacks for the command type * @param commandName Command name * @param rest Command props */ emit(commandName: K, ...props: IsEmpty> extends true ? [] | [WithoutName>] : [WithoutName>]): Promise; /** * Internal emit method that can bypass transaction checking * @param commandName Command name * @param bypassTransaction Whether to bypass transaction checking * @param rest Command props */ emitInternal(commandName: K, bypassTransaction: boolean, ...props: IsEmpty> extends true ? [] | [WithoutName>] : [WithoutName>]): Promise; /** * Register a callback for specific command types * @param commandName Type of command to listen for * @param callback Function to be called when command occurs * @returns Function to unregister the callback */ register(commandName: K, callback: CommandCallback): () => void; private getCommandCallbacks; } /** * Interface for interpreting and routing system commands * This is a core component that handles commands from InputEventHandler or user */ declare interface CommandHandler_2 { readonly flowCore: FlowCore; /** * Emit a system command * @param command Command to emit */ emit(commandName: K, ...props: IsEmpty> extends true ? [] | [WithoutName>] : [WithoutName>]): Promise; /** * Register a callback for specific command types * @param commandType Type of command to listen for * @param callback Function to be called when command occurs */ register(commandType: K, callback: CommandCallback): void; } /** * Type for command name */ declare type CommandName = Command['name']; /** * Merges user shortcuts with base shortcuts, user shortcuts override by actionName * * @param userShortcuts - User-provided shortcuts that will override matching base shortcuts * @param baseShortcuts - Base shortcuts to merge with. Optional parameter that defaults to built-in shortcuts * @returns Merged shortcut definitions * * @example * ```ts * // Merge with default built-in shortcuts * config = { * shortcuts: configureShortcuts([ * { * actionName: 'keyboardMoveSelectionUp', * bindings: [{ key: 'w' }], * }, * ]), * } satisfies NgDiagramConfig; * ``` * * @example * ```ts * // Merge with existing config shortcuts * const currentShortcuts = ngDiagramService.config().shortcuts; * const updatedShortcuts = configureShortcuts( * [ * { * actionName: 'paste', * bindings: [{ key: 'b', modifiers: { primary: true } }], * }, * ], * currentShortcuts * ); * ``` * * @public * @since 0.8.0 * @category Utilities */ export declare function configureShortcuts(userShortcuts: ShortcutDefinition[], baseShortcuts?: ShortcutDefinition[]): ShortcutDefinition[]; declare interface CopyCommand { name: 'copy'; } /** * State containing copied nodes and edges for paste operations. * * @public * @since 0.8.0 * @category Internals */ export declare interface CopyPasteActionState { /** Array of nodes that were copied. */ copiedNodes: Node_2[]; /** Array of edges that were copied. */ copiedEdges: Edge[]; } /** * Factory method to create a list of middlewares for ng-diagram. * Allows modifying the default middleware chain by removing, replacing, or adding new middlewares. * * @template TMiddlewares - The type of the resulting middleware chain * @param middlewares - Function that receives default middlewares and returns modified middleware chain * @returns The modified middleware chain * * Use with extreme caution - incorrectly modifying required middlewares can break the library * * @public * @since 0.8.0 * @category Utilities */ export declare function createMiddlewares(middlewares: (defaults: AppMiddlewares) => TMiddlewares): TMiddlewares; export declare class CursorPositionTrackerDirective { private readonly cursorPositionService; onMouseMove(event: MouseEvent): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface CutCommand { name: 'cut'; } export declare type DataObject = object; declare type DeepPartial = { [P in keyof T]?: T[P] extends (...args: unknown[]) => unknown ? T[P] : T[P] extends object ? DeepPartial : T[P]; }; declare const DEFAULT_GROUP_SIZE: { width: string; height: string; }; declare const DEFAULT_NODE_SIZE: { width: string; height: string; }; declare interface DeleteEdgeLabelsBulkCommand { name: 'deleteEdgeLabelsBulk'; deletions: Map; } declare interface DeleteEdgesCommand { name: 'deleteEdges'; ids: string[]; } declare interface DeleteNodesCommand { name: 'deleteNodes'; ids: string[]; } declare interface DeletePortsBulkCommand { name: 'deletePortsBulk'; deletions: Map; } declare interface DeleteSelectionCommand { name: 'deleteSelection'; } declare interface DeselectAllCommand { name: 'deselectAll'; } declare interface DeselectCommand { name: 'deselect'; nodeIds?: string[]; edgeIds?: string[]; } /** * Map of all available diagram events and their payload types * * @public * @since 0.8.0 * @category Types/Events */ export declare interface DiagramEventMap { /** * Event emitted when the diagram initialization is complete. * * This event fires after all nodes and edges including their internal parts * (ports, labels) have been measured and positioned. */ diagramInit: DiagramInitEvent; /** * Event emitted when selected nodes are moved within the diagram. * * This event fires when the user moves nodes manually by dragging or * programmatically using the diagram node service. */ selectionMoved: SelectionMovedEvent; /** * Event emitted when the selection state changes in the diagram. * * This event fires when the user selects or deselects nodes and edges through * clicking or programmatically using the diagram selection service. */ selectionChanged: SelectionChangedEvent; /** * Event emitted when selected elements are deleted from the diagram. * * This event fires when the user deletes nodes and edges using the delete key, * or programmatically through the diagram service. */ selectionRemoved: SelectionRemovedEvent; /** * Event emitted when nodes are grouped or ungrouped. * * This event fires when the user moves nodes in or out of a group node, * changing their group membership status. */ groupMembershipChanged: GroupMembershipChangedEvent; /** * Event emitted when a node is rotated in the diagram. * * This event fires when the user rotates a node manually using the rotation handle * or programmatically using the diagram node service. */ selectionRotated: SelectionRotatedEvent; /** * Event emitted when the viewport changes through panning or zooming. * * This event fires during pan and zoom operations, including mouse wheel zoom, * and programmatic viewport changes. */ viewportChanged: ViewportChangedEvent; /** * Event emitted when a user manually draws an edge between two nodes. * * This event only fires for user-initiated edge creation through the UI, * but not for programmatically added edges. * * @deprecated Use `edgeDrawEnded` instead, which fires for both successful and cancelled draws. */ edgeDrawn: EdgeDrawnEvent; /** * Event emitted when an edge draw gesture ends, regardless of outcome. * * Fires on every linking completion — both successful and cancelled. * For successful draws, includes the created edge and target. * For cancelled draws, includes the cancellation reason. * * @since 1.2.0 */ edgeDrawEnded: EdgeDrawEndedEvent; /** * Event emitted when clipboard content is pasted into the diagram. * * This event fires when nodes and edges are added via paste operations, * either through keyboard shortcuts or programmatic paste commands. */ clipboardPasted: ClipboardPastedEvent; /** * Event emitted when a node or group size changes. * * This event fires when a node is resized manually by dragging resize handles * or programmatically using resize methods. */ nodeResized: NodeResizedEvent; /** * Event emitted when a palette item is dropped onto the diagram. * * This event fires when users drag items from the palette and drop them * onto the canvas to create new nodes. */ paletteItemDropped: PaletteItemDroppedEvent; /** * Event emitted when a node resize operation begins. * * This event fires once when the user starts resizing a node by dragging * a resize handle. */ nodeResizeStarted: NodeResizeStartedEvent; /** * Event emitted when a node resize operation ends. * * This event fires when the user releases the pointer after resizing a node. * The node will have its final size when this event is received. */ nodeResizeEnded: NodeResizeEndedEvent; /** * Event emitted when a node rotation operation begins. * * This event fires once when the user starts rotating a node by dragging * the rotation handle. */ nodeRotateStarted: NodeRotateStartedEvent; /** * Event emitted when a node rotation operation ends. * * This event fires when the user releases the pointer after rotating a node. * The node will have its final angle when this event is received. */ nodeRotateEnded: NodeRotateEndedEvent; /** * Event emitted when a selection gesture is complete. * * This event fires on pointerup after a selection operation completes - * whether from clicking a node/edge, box selection, or select-all. */ selectionGestureEnded: SelectionGestureEndedEvent; /** * Event emitted when a node drag operation begins. * * This event fires once when the drag threshold is crossed, signaling the * start of a drag operation. */ nodeDragStarted: NodeDragStartedEvent; /** * Event emitted when a node drag operation ends. * * This event fires when the user releases the pointer after dragging nodes. * Nodes will have their final positions when this event is received. */ nodeDragEnded: NodeDragEndedEvent; } /** * Event payload emitted when the diagram initialization is complete. * * This event fires after all nodes and edges including their internal parts * (ports, labels) have been measured and positioned. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface DiagramInitEvent { /** All nodes present in the diagram after initialization */ nodes: Node_2[]; /** All edges present in the diagram after initialization */ edges: Edge[]; /** Current viewport configuration including position and scale */ viewport: Viewport; } export declare class DiagramSelectionDirective extends ObjectSelectionDirective { targetType: BasePointerInputEvent['targetType']; readonly targetData: InputSignal | Node_2 | undefined>; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * State tracking a drag operation in progress. * * @public * @since 0.8.0 * @category Internals */ export declare interface DraggingActionState { /** IDs of all nodes participating in the drag (selected + children, filtered by draggable). */ nodeIds: string[]; /** Input modifiers (e.g., Ctrl, Shift) active during the drag. */ modifiers: InputModifiers; /** * Accumulated deltas per node that haven't yet resulted in a snap movement. * Key is node ID, value is the accumulated delta that hasn't been applied due to snapping. */ accumulatedDeltas: Map; /** * Whether the pointer has moved beyond the move threshold, indicating an actual drag. * `false` when the drag state is first created (on pointer down), `true` once movement exceeds the threshold. */ movementStarted: boolean; } /** * Interface representing an edge (connection) between nodes in the flow diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare interface Edge { /** * The unique identifier for the edge. */ id: string; /** * The source node of the edge. If empty string it will use sourcePosition. */ source: string; /** * The target node of the edge. If empty string it will use targetPosition. */ target: string; /** * The data associated with the edge. */ data: T; /** * The points of the edge defining the path. */ points?: Point[]; /** * Whether the edge is selected */ selected?: boolean; /** * The type of the edge declared in edgeTemplateMap. */ type?: string; /** * The port of the source node. */ sourcePort?: string; /** * The port of the target node. */ targetPort?: string; /** * The id of the source arrowhead of the edge. */ sourceArrowhead?: string; /** * The id of the target arrowhead of the edge. */ targetArrowhead?: string; /** * The routing of the edge. */ routing?: EdgeRoutingName; /** * The routing mode of the edge. * 'auto' (default): Points are computed automatically based on routing algorithm * 'manual': Points are provided by the user and routing algorithm is used to render the path */ routingMode?: RoutingMode; /** * The position of the edge start. */ sourcePosition?: Point; /** * The position of the edge end. */ targetPosition?: Point; /** * Whether the edge is temporary. */ temporary?: boolean; /** * The z-order of the edge. When set, overrides the default edge z-index * (which is derived from connected nodes). When a connected node is selected, * the node's elevation is added so the edge stays visible above elevated nodes. * * Set by `bringToFront` / `sendToBack` commands, or manually. * @see {@link computedZIndex} for the final rendered z-index. */ zOrder?: number; /** * @readonly * @remarks ComputedZIndex is computed by the system and should not be set manually. * The final z-index applied to the DOM element for rendering order. * Without `zOrder`: derived from `max(source, target)` connected node z-indices. * With `zOrder`: uses the explicit value plus connected node elevation. */ readonly computedZIndex?: number; /** * @readonly * @remarks MeasuredLabels are computed by the system and should not be set manually. * The labels of the edge with computed position and size. */ readonly measuredLabels?: EdgeLabel[]; } /** * Reason an edge draw gesture was cancelled. * * - `noTarget` — the user released on empty space (no target node/port snapped) * - `invalidConnection` — `validateConnection()` returned false * - `invalidTarget` — the target node doesn't exist or the target port has wrong type * * @public * @since 1.2.0 * @category Types/Events */ export declare type EdgeDrawCancelReason = 'noTarget' | 'invalidConnection' | 'invalidTarget'; /** * Event payload emitted when an edge draw gesture ends, regardless of outcome. * * Fires on every linking completion — both successful and cancelled. * For successful completions, `edge`, `target`, and `targetPort` are populated. * For cancellations, `reason` indicates why the gesture was cancelled. * * @public * @since 1.2.0 * @category Types/Events */ export declare interface EdgeDrawEndedEvent { /** The source node from which the edge was drawn */ source: Node_2; /** Source port identifier if connected to a specific port */ sourcePort?: string; /** The position where the pointer was released */ dropPosition: Point; /** Whether the edge was successfully created */ success: boolean; /** The created edge (only present on success) */ edge?: Edge; /** The target node (only present on success) */ target?: Node_2; /** Target port identifier (only present on success) */ targetPort?: string; /** The reason the draw was cancelled (only present on cancel) */ reason?: EdgeDrawCancelReason; } /** * Event payload emitted when a user manually draws an edge between two nodes. * * This event only fires for user-initiated edge creation through the UI, * but not for programmatically added edges. * * @deprecated Use {@link EdgeDrawEndedEvent} instead, which fires for both successful and cancelled draws. * @public * @since 0.8.0 * @category Types/Events */ export declare interface EdgeDrawnEvent { /** The newly created edge object */ edge: Edge; /** The source node from which the edge originates */ source: Node_2; /** The target node to which the edge connects */ target: Node_2; /** Source port identifier if connected to a specific port */ sourcePort?: string; /** Target port identifier if connected to a specific port */ targetPort?: string; } /** * Interface representing a label of an edge. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface EdgeLabel { /** * The id of the label. */ id: string; /** * The position of the label on the edge. * * - **Relative** (`number`, 0-1): 0 is the source, 1 is the target, 0.5 is the midpoint. * - **Absolute** (`'Npx'`): pixel distance from source (positive) or target (negative). * * @example * ```ts * positionOnEdge: 0.5 // midpoint (relative) * positionOnEdge: '30px' // 30px from source (absolute) * positionOnEdge: '-20px' // 20px from target (absolute) * ``` */ positionOnEdge: EdgeLabelPosition; /** * The position of the label on flow. */ position?: Point; /** * The size of the label. */ size?: Size; } /** * Type representing edge label position — either relative (0-1) or absolute (`'Npx'`). * * - **Relative** (`number`, 0-1): percentage along the path. Clamped to [0, 1]. * - **Absolute** (`string`, `'Npx'`): pixel distance from source (positive) or target (negative). Clamped to path length. * * @public * @since 1.1.0 * @category Types/Model */ export declare type EdgeLabelPosition = number | AbsoluteEdgeLabelPosition; /** * Interface for routing implementations * * @public * @since 0.8.0 * @category Types/Routing */ export declare interface EdgeRouting { /** * Name identifier for the routing. */ name: string; /** * Computes the points for the edge path. * This is the core routing logic that determines * how an edge is drawn between source and target. * * @param context - The routing context containing source/target info and layout state. * @param [config] - Optional configuration parameters for routing behavior. * @returns An array of points representing the routed edge path. */ computePoints(context: EdgeRoutingContext, config?: EdgeRoutingConfig): Point[]; /** * Generates an SVG path string from points. * Converts the routed points into a valid `d` attribute * for an `` SVG element. * * @param points - The points defining the edge path. * @param [config] - Optional configuration parameters for path generation. * @returns An SVG path string. */ computeSvgPath(points: Point[], config?: EdgeRoutingConfig): string; /** * Gets a point on the path at a given percentage (0-1). * Useful for positioning labels, decorations, or interaction handles. * * @param points - The points defining the path. * @param percentage - Position along the path (0 = start, 1 = end). * @returns The point at the given percentage along the path. */ computePointOnPath?(points: Point[], percentage: number): Point; /** * Gets a point on the path at a given pixel distance from the start. * Negative values measure from the end of the path. * * @param points - The points defining the path. * @param distancePx - Distance in pixels (positive = from start, negative = from end). * @returns The point at the given distance along the path. */ computePointAtDistance?(points: Point[], distancePx: number): Point; } /** * Configuration for edge routing behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface EdgeRoutingConfig { /** * The default edge routing algorithm to use for edges. * Can be one of the built-in routing names or a custom string for user-defined routing. * @see EdgeRoutingName * @default 'orthogonal' */ defaultRouting: EdgeRoutingName; /** configuration options for bezier routing */ bezier?: { /** bezier control point offset * @default 100 */ bezierControlOffset?: number; }; /** configuration options for orthogonal routing */ orthogonal?: { /** first/last segment length * @default 20 */ firstLastSegmentLength?: number; /** maximum corner radius * @default 15 */ maxCornerRadius?: number; }; /** * Allow custom edge routing configurations. */ [edgeRoutingName: string]: Record | EdgeRoutingName | undefined; } /** * Context object containing all information needed for routing computation * * @public * @since 0.8.0 * @category Types/Routing */ export declare interface EdgeRoutingContext { /** * Source port location */ sourcePoint: PortLocation; /** * Target port location */ targetPoint: PortLocation; /** * The edge being routed */ edge: Edge; /** * Source node */ sourceNode?: Node_2; /** * Target node */ targetNode?: Node_2; /** * Source port (if edge is connected to a specific port) */ sourcePort?: Port; /** * Target port (if edge is connected to a specific port) */ targetPort?: Port; } /** * **Internal manager** for registration, selection, and execution of edge routing implementations. * * @remarks * **For application code, use {@link NgDiagramService} routing methods instead.** * This class is exposed primarily for middleware development where you can access it * via `context.edgeRoutingManager`. * * The manager comes pre-populated with built-in routings (`orthogonal`, `bezier`, `polyline`). * You can register custom routings at runtime. * * @example * ```typescript * const middleware: Middleware = { * name: 'routing-optimizer', * execute: (context, next) => { * const routingManager = context.edgeRoutingManager; * const defaultRouting = routingManager.getDefaultRouting(); * console.log('Using routing:', defaultRouting); * next(); * } * }; * ``` * * @public * @since 0.8.0 * @category Internals */ export declare class EdgeRoutingManager { private routings; private defaultRouting; private getRoutingConfig; /** * Creates a new EdgeRoutingManager and registers built-in routings. * * @param defaultEdgeRouting - The routing to use when none is specified (defaults to `'orthogonal'`) * @param getRoutingConfiguration - Function returning the current routing configuration * * @internal */ constructor(defaultEdgeRouting: EdgeRoutingName, getRoutingConfiguration: () => EdgeRoutingConfig); /** * Registers (or replaces) a routing implementation. * * @param routing - The routing instance to register. Its name must be non-empty. */ registerRouting(routing: EdgeRouting): void; /** * Unregisters a routing by name. * * @param name - The routing name to remove */ unregisterRouting(name: EdgeRoutingName): void; /** * Gets a routing implementation by name. * * @param name - The routing name to look up * @returns The routing implementation or `undefined` if not registered */ getRouting(name: EdgeRoutingName): EdgeRouting | undefined; /** * Gets all registered routing names. * * @returns An array of registered routing names (built-in and custom) */ getRegisteredRoutings(): EdgeRoutingName[]; /** * Checks whether a routing is registered. * * @param name - The routing name to check * @returns `true` if registered; otherwise `false` */ hasRouting(name: EdgeRoutingName): boolean; /** * Computes the routed points for an edge using the specified routing algorithm. * * @param routingName - The routing to use. If omitted or undefined, the default routing is used. * @param context - The routing context containing source/target nodes, ports, edge data, etc. * @returns The computed polyline as an array of points * * @example * ```typescript * const points = routingManager.computePoints('orthogonal', { * sourceNode: node1, * targetNode: node2, * sourcePosition: { x: 100, y: 50 }, * targetPosition: { x: 300, y: 200 }, * edge: edge * }); * ``` */ computePoints(routingName: EdgeRoutingName | undefined, context: EdgeRoutingContext): Point[]; /** * Computes an SVG path string for the given points using the specified routing. * * @param routingName - The routing to use. If omitted or undefined, the default routing is used. * @param points - The points to convert into an SVG path string * @returns An SVG path string suitable for the `d` attribute of an SVG `` element * * @example * ```typescript * const points = [{ x: 0, y: 0 }, { x: 100, y: 100 }, { x: 200, y: 100 }]; * const path = routingManager.computePath('polyline', points); * // Returns: "M 0 0 L 100 100 L 200 100" * ``` */ computePath(routingName: EdgeRoutingName | undefined, points: Point[]): string; /** * Computes a point along the path at a given percentage. * * @remarks * If the selected routing implements `computePointOnPath`, it will be used. * Otherwise, falls back to linear interpolation between the first and last points. * * @param routingName - The routing to use. If omitted or undefined, the default routing is used. * @param points - The path points * @param percentage - Position along the path in range [0, 1] where 0 = start, 1 = end * @returns The interpolated point on the path * * @example * ```typescript * const points = [{ x: 0, y: 0 }, { x: 100, y: 100 }]; * const midpoint = routingManager.computePointOnPath('polyline', points, 0.5); * // Returns: { x: 50, y: 50 } * const quarterPoint = routingManager.computePointOnPath('polyline', points, 0.25); * // Returns: { x: 25, y: 25 } * ``` */ computePointOnPath(routingName: EdgeRoutingName | undefined, points: Point[], percentage: number): Point; /** * Computes a point along the path at a given pixel distance from the start. * * @remarks * If the selected routing implements `computePointAtDistance`, it will be used. * Otherwise, falls back to segment-based distance traversal along the points array. * Negative values measure from the end of the path. * * @param routingName - The routing to use. If omitted, the default routing is used. * @param points - The path points * @param distancePx - Distance in pixels (positive = from start, negative = from end) * @returns The point on the path at the given distance */ computePointAtDistance(routingName: EdgeRoutingName | undefined, points: Point[], distancePx: number): Point; /** * Sets the default routing to use for all edges when no specific routing is specified. * * @param name - The routing name to set as default */ setDefaultRouting(name: EdgeRoutingName): void; /** * Gets the current default routing name. * * @returns The name of the current default routing */ getDefaultRouting(): EdgeRoutingName; } /** * Type representing edge routing name - can be built-in or custom * * **Allowed values:** `'orthogonal' | 'bezier' | 'polyline'` * * @public * @since 0.8.0 * @category Types/Routing */ export declare type EdgeRoutingName = LooseAutocomplete; export declare class EdgeSelectionDirective extends ObjectSelectionDirective { targetType: BasePointerInputEvent['targetType']; readonly targetData: InputSignal | Node_2 | undefined>; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Interface representing environment information * * @public * @since 0.8.0 * @category Internals */ export declare interface EnvironmentInfo { /** User Operating system name */ os: LooseAutocomplete<'MacOS' | 'Windows' | 'Linux' | 'iOS' | 'Android' | 'Unknown'> | null; /** User Browser name (when applicable) */ browser: LooseAutocomplete<'Chrome' | 'Firefox' | 'Safari' | 'Edge' | 'Opera' | 'IE' | 'Other'> | null; /** Platform identity for high-level adapter routing */ runtime: LooseAutocomplete<'web' | 'node' | 'other'> | null; /** Current timestamp in ms */ now: () => number; /** Generates a unique ID */ generateId: () => string; } declare abstract class EventHandler { protected readonly flow: FlowCore; constructor(flow: FlowCore); abstract handle(event: TEvent): void | Promise; } /** * Type for event listeners */ declare type EventListener_2 = (event: T) => void; /** * Manages event subscriptions and emissions for the diagram */ declare class EventManager { private listeners; private enabled; private deferredEmits; /** * Subscribe to an event * @param event The event name * @param callback The callback to invoke when the event is emitted * @returns A function to unsubscribe */ on(event: K, callback: EventListener_2): UnsubscribeFn; /** * Subscribe to an event that will only fire once * @param event The event name * @param callback The callback to invoke when the event is emitted * @returns A function to unsubscribe */ once(event: K, callback: EventListener_2): UnsubscribeFn; /** * Emit an event * @param event The event name * @param payload The event payload */ emit(event: K, payload: InternalDiagramEventMap[K]): void; /** * Queue an event to be emitted later * @param event The event name * @param payload The event payload */ deferredEmit(event: K, payload: InternalDiagramEventMap[K]): void; /** * Remove all listeners for an event, or a specific listener * @param event The event name * @param callback Optional specific callback to remove */ off(event: K, callback?: EventListener_2): void; /** * Remove all event listeners */ offAll(): void; /** * Enable or disable event emissions * @param enabled Whether events should be emitted */ setEnabled(enabled: boolean): void; /** * Check if event emissions are enabled */ isEnabled(): boolean; /** * Check if there are any listeners for an event * @param event The event name * @returns True if there are listeners */ hasListeners(event: keyof InternalDiagramEventMap): boolean; /** * Flush all deferred emits */ flushDeferredEmits(): void; /** * Clear all deferred emits without executing them */ clearDeferredEmits(): void; private removeListener; } declare interface FinishLinkingCommand { name: 'finishLinking'; position?: Point; } declare interface FinishLinkingToPositionCommand { name: 'finishLinkingToPosition'; position: Point; } /** * The main configuration interface for the flow system. * * This type defines all available configuration options for the diagram engine. * * For most use cases, you should use {@link NgDiagramConfig}, which allows you to override only the properties you need. * * @public * @since 0.8.0 * @category Types/Configuration */ export declare interface FlowConfig { /** * Computes a unique ID for a node. * @returns The node's unique ID. */ computeNodeId: () => string; /** * Computes a unique ID for an edge. * @returns The edge's unique ID. */ computeEdgeId: () => string; /** * Configuration for node resizing. */ resize: ResizeConfig; /** * Configuration for linking (edge creation). */ linking: LinkingConfig; /** * Configuration for node grouping. */ grouping: GroupingConfig; /** * Configuration for zooming. */ zoom: ZoomConfig; /** * Configuration for edge routing. */ edgeRouting: EdgeRoutingConfig; /** * Configuration for background behavior. */ background: BackgroundConfig; /** * Configuration for node rotation behavior. */ nodeRotation: NodeRotationConfig; /** * Configuration for snapping behavior. */ snapping: SnappingConfig; /** * Configuration for selection moving behavior. */ selectionMoving: SelectionMovingConfig; /** * Configuration for z-index layering behavior. */ zIndex: ZIndexConfig; /** * Configuration for box selection behavior. */ boxSelection: BoxSelectionConfig; /** * Configuration for viewport virtualization. * Improves performance for large diagrams by only rendering visible elements. */ virtualization: VirtualizationConfig; /** * Configuration for keyboard shortcuts. */ shortcuts: ShortcutDefinition[]; /** * Enables or disables debug mode for the diagram. * When enabled, additional console logs are printed. * @default false */ debugMode: boolean; /** * @since 0.9.0 * * Hides the ngDiagram watermark when set to true. * @default undefined */ hideWatermark?: boolean; /** * @since 1.2.0 * * Sets the preferred position for the ngDiagram watermark. * If the chosen position collides with a registered panel (e.g., minimap), * the watermark shifts to the nearest available corner. * @default 'bottom-right' */ watermarkPosition?: NgDiagramPanelPosition; /** * @since 0.9.0 * * Enables or disables panning on the diagram. * When set to false, user is not able to move the viewport by panning. * @default true */ viewportPanningEnabled: boolean; /** * @since 1.0.0 * * Enables or disables node dragging on the diagram. * When set to false, users cannot move nodes via mouse dragging or keyboard arrow keys. * @default true */ nodeDraggingEnabled: boolean; } declare class FlowCore { readonly renderer: Renderer; readonly inputEventsRouter: InputEventsRouter; readonly environment: EnvironmentInfo; private _model; private _config; readonly initUpdater: InitUpdater; readonly internalUpdater: InternalUpdater; private readonly updateSemaphore; readonly commandHandler: CommandHandler; readonly middlewareManager: MiddlewareManager; readonly spatialHash: SpatialHash; readonly modelLookup: ModelLookup; readonly transactionManager: TransactionManager; readonly portBatchProcessor: PortBatchProcessor; readonly labelBatchProcessor: LabelBatchProcessor; readonly actionStateManager: ActionStateManager; readonly edgeRoutingManager: EdgeRoutingManager; readonly eventManager: EventManager; readonly shortcutManager: ShortcutManager; readonly measurementTracker: MeasurementTracker; private readonly directRenderStrategy; private readonly virtualizedRenderStrategy; readonly getFlowOffset: () => Point; readonly getViewportSize: () => { width: number; height: number; }; constructor(modelAdapter: ModelAdapter, renderer: Renderer, inputEventsRouter: InputEventsRouter, environment: EnvironmentInfo, middlewares?: MiddlewareChain, getFlowOffset?: () => Point, getViewportSize?: () => { width: number; height: number; }, config?: DeepPartial); destroy(): void; private init; /** * Sets initial viewport size from element dimensions. * * This must be called BEFORE renderStrategy.init() for two reasons: * 1. The viewport size is needed for features like zoomToFit on init * 2. At this point, no onChange callbacks are registered yet, so updateMetadata won't trigger events * * Without this, the ResizeObserver might not fire on reinitialization, * leaving viewport.width/height as undefined. */ private initializeViewportSize; /** * Gets the current model that flow core is using */ get model(): ModelAdapter; /** * Gets the current environment information */ getEnvironment(): EnvironmentInfo; get config(): FlowConfig; updateConfig(updatedConfig: DeepPartial): void; /** * Registers a new middleware in the chain * @param middleware Middleware to register * @returns Function to unregister the middleware */ registerMiddleware(middleware: Middleware): () => void; /** * Unregister a middleware from the chain * @param name Name of the middleware to unregister */ unregisterMiddleware(name: string): void; /** * Gets the current state of the flow */ getState(): FlowState; /** * Gets the active render strategy based on virtualization config. * When virtualization is enabled, uses VirtualizedRenderStrategy. * When disabled, uses DirectRenderStrategy. */ get renderStrategy(): RenderStrategy; /** * Sets the current state of the flow * @param state State to set */ setState(state: FlowState): void; /** * Executes a function within a transaction context. * All state updates within the callback are batched and applied atomically. * * @example * // Simple transaction * await flowCore.transaction(async (tx) => { * await tx.emit('addNode', { node }); * await tx.emit('selectNode', { nodeId: node.id }); * }); * * // Named transaction * await flowCore.transaction('batchUpdate', async (tx) => { * await tx.emit('updateNodes', { nodes }); * if (error) { * tx.rollback(); // Discard all changes * } * }); * * // With savepoints * await flowCore.transaction(async (tx) => { * await tx.emit('step1', {}); * tx.savepoint('afterStep1'); * * await tx.emit('step2', {}); * if (step2Failed) { * tx.rollbackTo('afterStep1'); * } * }); * * // Wait for measurements to complete before continuing * await flowCore.transaction(async (tx) => { * await tx.emit('addNodes', { nodes: [newNode] }); * }, { waitForMeasurements: true }); * // Now safe to call zoomToFit() - node dimensions are measured * await viewportService.zoomToFit(); */ transaction(callback: TransactionCallback): Promise; transaction(callback: TransactionCallback, options: TransactionOptions): Promise; transaction(name: LooseAutocomplete, callback: TransactionCallback): Promise; transaction(name: LooseAutocomplete, callback: TransactionCallback, options: TransactionOptions): Promise; /** * Applies an update to the flow state * @param stateUpdate Partial state to apply * @param modelActionTypes Action type(s) that triggered this update. Can be a single type or an array of types (from transactions). */ applyUpdate(stateUpdate: FlowStateUpdate, modelActionTypes: LooseAutocomplete | ModelActionTypes): Promise; /** * Fast-path for viewport-only updates (panning/zooming). * Bypasses middleware chain and only updates viewport metadata. * Use this for high-frequency viewport changes where middleware processing is unnecessary. */ applyViewportOnlyUpdate(viewportUpdate: Partial): void; /** * Converts a client position to a flow position * @param clientPosition Client position * @returns { x: number, y: number } Flow position */ clientToFlowPosition(clientPosition: Point): Point; /** * Converts a flow position to a client position * @param flowPosition Flow position * @returns { x: number, y: number } Client position */ flowToClientPosition(flowPosition: Point): Point; /** * Converts a client position to a position relative to the flow viewport * @param clientPosition Client position * @returns position on the flow viewport */ clientToFlowViewportPosition(clientPosition: Point): Point; /** * Gets a node by id * @param nodeId Node id * @returns Node */ getNodeById(nodeId: string): Node_2 | null; /** * Gets an edge by id * @param edgeId Edge id * @returns Edge */ getEdgeById(edgeId: string): Edge | null; /** * Gets all nodes in a range from a point * @param point Point to check from * @param range Range to check in * @returns Array of nodes in range */ getNodesInRange(point: Point, range: number): Node_2[]; /** * Gets the nearest node in a range from a point * @param point Point to check from * @param range Range to check in * @returns Nearest node in range or null */ getNearestNodeInRange(point: Point, range: number): Node_2 | null; /** * Gets the nearest port in a range from a point * @param point Point to check from * @param range Range to check in * @returns Nearest port in range or null */ getNearestPortInRange(point: Point, range: number): Port | null; /** * Gets all edges connected to a node * @param nodeId Node id * @returns Array of edges where the node is either source or target */ getConnectedEdges(nodeId: string): Edge[]; /** * Gets all nodes connected to a node via edges * @param nodeId Node id * @returns Array of nodes connected to the given node */ getConnectedNodes(nodeId: string): Node_2[]; /** * Gets the source and target nodes of an edge * @param edgeId Edge id * @returns Object containing source and target nodes, or null if edge doesn't exist */ getNodeEnds(edgeId: string): { source: Node_2; target: Node_2; } | null; /** * Gets all children nodes for a given group node id * @param groupId group node id * @returns Array of child nodes */ getChildren(groupId: string): Node_2[]; /** * Gets all nested children (descendants) of a group node * @param groupId Group node id * @returns Array of all descendant nodes (children, grandchildren, etc.) */ getChildrenNested(groupId: string): Node_2[]; /** * Checks if a node is a nested child (descendant) of a group node * @param nodeId Node id * @param groupId Group node id * @returns True if the node is part of the group's nested subgraph */ isNestedChild(nodeId: string, groupId: string): boolean; /** * Gets the full chain of parent group Nodes for a given nodeId. * @param nodeId Node id * @returns Array of parent group Node objects, from closest parent to farthest ancestor */ getParentHierarchy(nodeId: string): GroupNode[]; /** * Detects collision with other nodes by finding all nodes whose rectangles intersect * with the specified node's bounding rectangle. * * @param nodeId - The ID of the node to check for collisions * @returns An array of Nodes that overlap with the specified node */ getOverlappingNodes(nodeId: string): Node_2[]; /** * Detects collision with other nodes by finding all nodes whose rectangles intersect * with the specified node's bounding rectangle. * * @param node - The node to check for collisions * @returns An array of Nodes that overlap with the specified node */ getOverlappingNodes(node: Node_2): Node_2[]; /** * Checks if a node is currently rendered (visible in viewport). * In direct mode, always returns true. In virtualized mode, checks if the node * is in the current set of visible nodes. * * @param nodeId Node id to check * @returns True if the node is currently rendered */ isNodeCurrentlyRendered(nodeId: string): boolean; /** * Returns the current zoom scale */ getScale(): number; /** * Returns the current viewport */ getViewport(): Viewport; get updater(): Updater; /** * Returns true if the diagram has completed its initialization phase. */ get isInitialized(): boolean; /** * Returns true if virtualization is enabled. */ get isVirtualizationActive(): boolean; setDebugMode(debugMode: boolean): void; } declare class FlowCoreProviderService { private readonly renderer; private readonly inputEventsRouter; private readonly environment; private flowCore; private _isInitialized; readonly isInitialized: Signal; init(model: ModelAdapter, middlewares: MiddlewareChain, getFlowOffset: () => Point, getViewportSize: () => { width: number; height: number; }, config?: DeepPartial): void; destroy(): void; provide(): FlowCore; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * The complete state of the flow diagram. * Represents the current state of all nodes, edges, and metadata. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface FlowState { /** All nodes currently in the diagram */ nodes: Node_2[]; /** All edges currently in the diagram */ edges: Edge[]; /** Diagram metadata (selection, viewport, etc.) */ metadata: Metadata; } /** * Describes a set of changes to apply to the diagram state. * Middlewares can modify state by passing a FlowStateUpdate to the `next()` function. * * @example * ```typescript * const middleware: Middleware = { * name: 'auto-arranger', * execute: (context, next) => { * // Apply state changes * next({ * nodesToUpdate: [ * { id: 'node1', position: { x: 100, y: 200 } }, * { id: 'node2', position: { x: 300, y: 200 } } * ], * metadataUpdate: { * viewport: { x: 0, y: 0, zoom: 1 } * } * }); * } * }; * ``` * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface FlowStateUpdate { /** Nodes to add to the diagram */ nodesToAdd?: Node_2[]; /** Partial node updates (only changed properties need to be specified) */ nodesToUpdate?: (Partial & { id: Node_2['id']; })[]; /** IDs of nodes to remove from the diagram */ nodesToRemove?: string[]; /** Edges to add to the diagram */ edgesToAdd?: Edge[]; /** Partial edge updates (only changed properties need to be specified) */ edgesToUpdate?: (Partial & { id: Edge['id']; })[]; /** IDs of edges to remove from the diagram */ edgesToRemove?: string[]; /** Partial metadata update (viewport, selection, etc.) */ metadataUpdate?: Partial; /** * IDs of nodes currently rendered in the viewport. * - `undefined` means all nodes are rendered (DirectRenderStrategy / no virtualization) * - `string[]` means only those specific IDs are rendered (VirtualizedRenderStrategy) * Used by 'init' action to track which nodes need measurement. * @internal */ renderedNodeIds?: string[]; /** * IDs of edges currently rendered in the viewport. * - `undefined` means all edges are rendered (DirectRenderStrategy / no virtualization) * - `string[]` means only those specific IDs are rendered (VirtualizedRenderStrategy) * Used by 'init' action to track which edges need measurement. * @internal */ renderedEdgeIds?: string[]; } declare type FlushCallback = (all: Map) => void | Promise; /** * Returns the set of item IDs that are already measured for a given key. * Used at flush time to filter out redundant adds (e.g. virtualization re-mounts * a component for an item that was never deleted from the model). */ declare type GetMeasuredIdsFn = (key: string) => Set; /** * Configuration for node grouping behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface GroupingConfig { /** * Determines if a node can be grouped into a group node. * @param node The node to group. * @param group The group node. * @returns True if the node can be grouped, false otherwise. * @default () => true */ canGroup: (node: Node_2, group: Node_2) => boolean; } /** * Event payload emitted when nodes are grouped or ungrouped. * * This event fires when the user moves nodes in or out of a group node, * changing their group membership status. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface GroupMembershipChangedEvent { /** Nodes added to groups, organized by target group */ grouped: { nodes: Node_2[]; targetGroup: GroupNode; }[]; /** Nodes removed from groups */ ungrouped: Node_2[]; } /** * Interface representing a group node in the diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare interface GroupNode extends SimpleNode { /** * Flag indicating the node is a group */ isGroup: true; /** * Whether the group is highlighted. For example, when a node is being dragged over it. */ highlighted: boolean; } /** * Data structure for group node palette items. Extends {@link SimpleNodeData} with the {@link GroupNode#isGroup} property to identify it as a group. * * @public * @since 0.8.0 * @category Types/Palette */ export declare type GroupNodeData = SimpleNodeData & Pick; declare type HandlePosition = Extract; /** * State tracking which group is currently highlighted. * * @public * @since 0.8.0 * @category Internals */ export declare interface HighlightGroupActionState { /** ID of the highlighted group, or null if no group is highlighted. */ highlightedGroupId: string | null; } declare interface HighlightGroupClearCommand { name: 'highlightGroupClear'; } declare interface HighlightGroupCommand { name: 'highlightGroup'; groupId: Node_2['id']; nodes: Node_2[]; } declare namespace i1 { export { NgDiagramServicesAvailabilityCheckerDirective } } declare namespace i10 { export { PaletteDropDirective } } declare namespace i11 { export { DiagramSelectionDirective, EdgeSelectionDirective, NodeSelectionDirective } } declare namespace i1_2 { export { ZIndexDirective } } declare namespace i1_3 { export { DEFAULT_NODE_SIZE, DEFAULT_GROUP_SIZE, NodeSizeDirective } } declare namespace i1_4 { export { LinkingInputDirective } } declare namespace i2 { export { BoxSelectionDirective } } declare namespace i2_2 { export { NodePositionDirective } } declare namespace i3 { export { MobileBoxSelectionDirective } } declare namespace i4 { export { CursorPositionTrackerDirective } } declare namespace i4_2 { export { PointerMoveSelectionDirective } } declare namespace i5 { export { ZoomingWheelDirective } } declare namespace i6 { export { PanningDirective } } declare namespace i7 { export { MobilePanningDirective } } declare namespace i8 { export { MobileZoomingDirective } } declare namespace i9 { export { KeyboardInputsDirective } } declare interface InitCommand { name: 'init'; /** IDs of nodes currently rendered (for virtualization) */ renderedNodeIds?: string[]; /** IDs of edges currently rendered (for virtualization) */ renderedEdgeIds?: string[]; } /** * Creates a model adapter with initial nodes, edges, and metadata. * * This helper sets up a model instance ready for use in ng-diagram. * It must be run in an Angular injection context unless the `injector` option is provided manually. * * ⚠️ This is only for creating the initial model. Any changes to the model or * access to current data should be done via {@link NgDiagramModelService}. * * @example * ```typescript * // Create an empty model * model = initializeModel(); * * // Create a model with initial data * model = initializeModel({ * nodes: [{ id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } }], * edges: [], * }); * * // With an explicit injector (outside injection context) * model = initializeModel({ nodes: [...], edges: [...] }, this.injector); * * // Safe to use inside reactive contexts (computed, effect, linkedSignal) * model = computed(() => initializeModel(this.myModel(), this.injector)); * ``` * * ## Version History * * | Version | Changes | * |---------|---------| * | v0.8.0 | Introduced | * | v1.2.0 | Can now be safely used inside reactive contexts (`computed`, `effect`, `linkedSignal`) | * * @param model Initial model data (nodes, edges, metadata). * @param injector Optional Angular `Injector` if not running inside an injection context. * * @public * @since 0.8.0 * @category Utilities */ export declare function initializeModel(model?: Partial, injector?: Injector): ModelAdapter; /** * Initializes an existing model adapter for use in ng-diagram. * * Prepares all nodes and edges in the adapter so they are ready for * rendering by ng-diagram. Use this when providing a custom * {@link ModelAdapter} implementation. * * @example * ```typescript * // Basic usage with a custom adapter * model = initializeModelAdapter(new NgRxModelAdapter(this.store)); * * // With initial model data to seed the adapter * model = initializeModelAdapter(new NgRxModelAdapter(this.store), { * nodes: [{ id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } }], * edges: [], * }); * * // With an explicit injector (outside injection context) * model = initializeModelAdapter(new NgRxModelAdapter(this.store), undefined, this.injector); * ``` * * @param adapter An existing ModelAdapter to initialize. * @param model Optional initial model data to seed the adapter with. * @param injector Optional Angular `Injector` if not running inside an injection context. * * @public * @since 1.1.0 * @category Utilities */ export declare function initializeModelAdapter(adapter: ModelAdapter, model?: Partial, injector?: Injector): ModelAdapter; /** * InitUpdater batches all initialization data and applies it in a single state update. * * Strategy: * 1. Wait for entity creation to stabilize (addPort, addEdgeLabel) using StabilityDetectors * 2. Immediately collect measurements (applyNodeSize, applyPortChanges, applyEdgeLabelChanges) * 3. Finish when: entities stabilized AND all rendered entities have measurements * 4. Apply everything in one setState * 5. Queue late arrivals to prevent data loss during finish transition * 6. Safety timeout: If measurements don't arrive within MEASUREMENT_TIMEOUT, force finish * * Note: With virtualization, only rendered nodes/edges are tracked for initialization. * Non-rendered elements will be initialized when they become visible. */ declare class InitUpdater implements Updater { private flowCore; /** Flag indicating whether initialization has completed */ isInitialized: boolean; /** Flag indicating whether entity additions (ports/labels) have stabilized */ private entitiesStabilized; /** Detects when port additions have stabilized */ private portStabilityDetector; /** Detects when label additions have stabilized */ private labelStabilityDetector; /** Collects all initialization data and applies it to diagram state */ private initState; /** Queues updates that arrive during finish to prevent data loss */ private lateArrivalQueue; /** Callback to execute when initialization completes */ private onCompleteCallback?; /** Safety timeout to prevent indefinite waiting for measurements */ private measurementTimeout; /** * Creates a new InitUpdater. * * @param flowCore - The FlowCore instance to update */ constructor(flowCore: FlowCore); /** * Starts the initialization process. * Collects pre-existing measurements and waits for entity additions to stabilize. * * @param nodes - Rendered nodes to track for initialization * @param edges - Rendered edges to track for initialization * @param onComplete - Optional callback to execute after initialization completes */ start(nodes: Node_2[], edges: Edge[], onComplete?: () => void | Promise): void; /** * Records a node size measurement. * Queues the update if finishing is in progress, otherwise records and attempts to finish. * * @param nodeId - The node ID * @param size - The measured size */ applyNodeSize(nodeId: string, size: NonNullable): void; applyNodeSizes(updates: { id: string; size: NonNullable; }[]): void; /** * Adds a new port created during initialization. * Queues if finishing, otherwise adds to init state and notifies stability detector. * * @param nodeId - The node ID the port belongs to * @param port - The port to add */ addPort(nodeId: string, port: Port): void; /** * Applies port changes (size, position, side, type, etc.). * During initialization, only size/position measurements are tracked for init completion. * Non-geometric changes (side, type) are ignored since ports are being created with initial values. * * @param nodeId - The node ID the ports belong to * @param portUpdates - Array of port updates */ applyPortChanges(nodeId: string, portUpdates: PortUpdate[]): void; /** * Adds a new edge label created during initialization. * Queues if finishing, otherwise adds to init state and notifies stability detector. * * @param edgeId - The edge ID the label belongs to * @param label - The label to add */ addEdgeLabel(edgeId: string, label: EdgeLabel): void; /** * Deletes an edge label. During initialization, queues for replay after init completes. */ deleteEdgeLabel(edgeId: string, labelId: string): void; /** * Applies edge label changes (size, positionOnEdge, etc.). * During initialization, only size measurements are tracked for init completion. * Non-size changes (positionOnEdge) are ignored since labels are being created with initial values. * * @param edgeId - The edge ID the labels belong to * @param labelUpdates - Array of label updates */ applyEdgeLabelChanges(edgeId: string, labelUpdates: LabelUpdate[]): void; /** * Attempts to finish initialization if conditions are met. * Conditions: not already finishing, not initialized, entities stabilized, all rendered entities measured. */ private tryFinish; /** * Completes initialization by applying all collected data. * Marks as finishing, applies state, executes callback, marks as initialized, processes late arrivals. */ private finish; /** * Forces initialization to finish even if conditions aren't fully met. * Used as a fallback when entity stabilization fails. */ private forceFinish; /** * Starts a safety timeout to prevent indefinite waiting for measurements. * If measurements don't arrive within MEASUREMENT_TIMEOUT, initialization is forced to complete. * This handles cases where entities may not be measurable (e.g., display: none). */ private startMeasurementTimeout; /** * Clears the measurement timeout if it's active. */ private clearMeasurementTimeout; } declare type InputEventName = 'copy' | 'cut' | 'paste' | 'select' | 'selectAll' | 'deleteSelection' | 'panning' | 'keyboardPanning' | 'wheelPanning' | 'pointerMoveSelection' | 'keyboardMoveSelection' | 'resize' | 'zoom' | 'linking' | 'rotate' | 'paletteDrop' | 'boxSelection' | 'undo' | 'redo'; declare abstract class InputEventsRouter { private handlers; emit(event: TEvent): void | Promise; register(eventName: K, handler: EventHandler): void; registerDefaultCallbacks(flow: FlowCore): void; hasHandler(eventName: InputEventName): boolean; } /** * Interface representing keyboard and modifier keys state during an input event. * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare interface InputModifiers { /** * Ctrl key (Windows/Linux) OR Cmd key (Mac) */ primary: boolean; /** * Alt key */ secondary: boolean; /** * Shift key */ shift: boolean; /** * Windows key OR Cmd key */ meta: boolean; } /** * Internal event map that extends the public DiagramEventMap with internal-only events. * These events are used internally by the library but are not part of the public API. * * @internal */ declare interface InternalDiagramEventMap extends DiagramEventMap { /** * Event emitted when the action state changes. * * This event fires when an action like resizing, rotating, or linking * starts or ends, allowing subscribers to react to state changes. * * @internal - For internal use only. Use the `actionState` signal on NgDiagramService instead. */ actionStateChanged: ActionStateChangedEvent; } declare class InternalUpdater implements Updater { private readonly flowCore; private readonly onPortAddsFlush; private readonly onPortUpdatesFlush; private readonly onPortDeletesFlush; private readonly onLabelAddsFlush; private readonly onLabelUpdatesFlush; private readonly onLabelDeletesFlush; constructor(flowCore: FlowCore); /** * @internal */ applyNodeSize(nodeId: string, size: NonNullable): void; /** * @internal */ applyNodeSizes(updates: { id: string; size: NonNullable; }[]): void; /** * @internal */ addPort(nodeId: string, port: Port): void; /** * @internal */ deletePort(nodeId: string, portId: string): void; /** * @internal * Filters out updates where no property actually differs from current state. */ applyPortChanges(nodeId: string, portUpdates: PortUpdate[]): void; /** * @internal */ addEdgeLabel(edgeId: string, label: EdgeLabel): void; /** * @internal */ deleteEdgeLabel(edgeId: string, labelId: string): void; /** * @internal * Filters out updates where no property actually differs from current state. */ applyEdgeLabelChanges(edgeId: string, labelUpdates: LabelUpdate[]): void; /** * Filters out port updates where none of the changed properties actually differ from current state. * Uses exact equality for all comparisons (size, position, side, type). */ private filterUnchangedPortUpdates; /** * Filters out label updates where none of the changed properties actually differ from current state. * Uses exact equality for all comparisons (size, positionOnEdge). */ private filterUnchangedLabelUpdates; } /** * Options for selective invalidation of diagram element measurements. * When provided to `invalidateMeasurements()`, only the specified elements * are re-measured. When omitted, all elements are re-measured. * * @public * @since 1.2.3 */ export declare interface InvalidateMeasurementsOptions { /** * Nodes to re-measure. Invalidating a node also re-measures all its ports. */ nodes?: { nodeId: string; }[]; /** * Edges whose labels should be re-measured. */ edges?: { edgeId: string; }[]; } /** * Type for command without name */ declare type IsEmpty = keyof WithoutName extends never ? true : false; /** * Keyboard action names that can be triggered by keyboard events * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type KeyboardActionName = KeyboardMoveSelectionAction | KeyboardPanAction | KeyboardZoomAction | Extract; export declare class KeyboardInputsDirective { private readonly flowCoreProvider; private readonly inputEventsRouter; private readonly keyboardActions; private readonly elementRef; onPointerDown(): void; onKeyDown(event: KeyboardEvent): void; private isInputFieldFocused; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Keyboard movement actions that map to directional events * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type KeyboardMoveSelectionAction = 'keyboardMoveSelectionUp' | 'keyboardMoveSelectionDown' | 'keyboardMoveSelectionLeft' | 'keyboardMoveSelectionRight'; /** * Keyboard panning actions that map to directional events * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type KeyboardPanAction = 'keyboardPanUp' | 'keyboardPanDown' | 'keyboardPanLeft' | 'keyboardPanRight'; /** * Defines a keyboard shortcut binding with a key * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare interface KeyboardShortcutBinding { /** * Key value (e.g., 'c', 'Delete', 'ArrowUp') * * @see https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values - Complete list of valid key values */ key: string; /** Required modifier keys (all are optional - omitted means no modifiers required) */ modifiers?: Partial; } /** * Keyboard shortcut definition with key-based bindings * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare interface KeyboardShortcutDefinition { /** Action name for keyboard events */ actionName: KeyboardActionName; /** Key-based bindings (at least one must have a key) */ bindings: (KeyboardShortcutBinding | ModifierOnlyShortcutBinding)[]; } /** * Keyboard zooming actions * * @public * @since 1.1.0 * @category Types/Configuration/Shortcuts */ export declare type KeyboardZoomAction = 'keyboardZoomIn' | 'keyboardZoomOut'; declare class LabelBatchProcessor extends BatchProcessor { constructor(getEdgeById: (edgeId: string) => Edge | null | undefined); } declare interface LabelUpdate { labelId: string; labelChanges: Partial; } declare type LinePosition = Extract; /** * State tracking an edge creation operation in progress. * * @public * @since 0.8.0 * @category Internals */ export declare interface LinkingActionState { /** ID of the node where the edge starts. */ sourceNodeId: string; /** ID of the port where the edge starts. */ sourcePortId: string; /** Temporary edge displayed while creating the connection. */ temporaryEdge: Edge | null; /** Position where the pointer was released. */ dropPosition?: Point; /** Reason the linking gesture was cancelled (set by finishLinking on failure paths). */ cancelReason?: EdgeDrawCancelReason; } /** * Configuration for linking (edge creation) behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface LinkingConfig { /** * The maximum distance (in pixels) at temporary edge will snap to target port. * @default 10 */ portSnapDistance: number; /** * Validates whether a connection between two nodes and ports is allowed. * @param source The source node. * @param sourcePort The source port. * @param target The target node. * @param targetPort The target port. * @returns True if the connection is valid, false otherwise. * @default () => true */ validateConnection: (source: Node_2 | null, sourcePort: Port | null, target: Node_2 | null, targetPort: Port | null) => boolean; /** * Allows customization of the temporary edge object shown while the user is dragging to create a new edge. * Receives the default temporary edge (with source/target node/port IDs and positions) * and should return a fully-formed Edge object for rendering the temporary edge. * @param defaultTemporaryEdgeData The default temporary edge data (may be incomplete). * @returns The Edge object to use for the temporary edge. * @default (edge) => Edge */ temporaryEdgeDataBuilder: (defaultTemporaryEdgeData: Edge) => Edge; /** * Allows customization of the final edge object when the user completes edge creation. * Receives the default finalized edge (with source/target node/port IDs) * and should return a fully-formed Edge object to be added to the flow. * @param defaultFinalEdgeData The default finalized edge data (may be incomplete). * @returns The Edge object to use for the finalized edge. * @default (edge) => Edge */ finalEdgeDataBuilder: (defaultFinalEdgeData: Edge) => Edge; /** * Enable edge panning when the routed edge is near the edge of the viewport. * * @default true */ edgePanningEnabled: boolean; /** * Multiplier for edge panning speed while routing edge is near the edge of the viewport. * * @default 10 */ edgePanningForce: number; /** * The threshold in pixels for edge panning to start. * If the mouse pointer is within this distance from the edge of the viewport, panning will be triggered. * * @default 30 */ edgePanningThreshold: number; /** * Whether to select a node when the user presses a port to start linking. * When true (default), pressing a port also triggers node selection events. * When false, port press only initiates the linking gesture without selecting the node. * * @default true * @since 1.2.0 */ selectNodeOnPortPress: boolean; } export declare class LinkingInputDirective implements OnDestroy { private readonly linkingEventService; private readonly flowCoreProviderService; private readonly touchEventsStateService; private target; private edgePanningInterval; portId: InputSignal; ngOnDestroy(): void; setTargetNode(node: Node_2): void; onPointerDown($event: PointerInputEvent): void; onPointerMove: ($event: PointerInputEvent) => void; onPointerUp: ($event: PointerInputEvent) => void; private shouldHandle; private cleanup; private startEdgePanning; private stopEdgePanning; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Middleware used for logging NgDiagram internal events and state changes. * * @internal * @category Types/Middleware */ export declare const loggerMiddleware: Middleware; /** * @ignore */ declare type LooseAutocomplete = T | (string & {}); /** * Tracks pending measurements and notifies when all measurements are complete. * * This class coordinates asynchronous DOM measurements (node sizes, port positions, labels, etc.) * with transaction completion using a two-phase observation model. * * ## Timing Model * * ### Phase 1: Discovery Window * After `registerParticipants()` is called, a discovery window opens. The tracker waits * to see if any measurement activity occurs for the registered participant entities. * * - If a **measurement signal** arrives (via `signalMeasurement()`): transitions to Phase 2. * - If a **ResizeObserver early signal** arrives (via `signalObserverActivity()`): * if remaining time is below `OBSERVER_ACTIVITY_MIN_REMAINING`, the timer resets * to full `discoveryWindowMs`, giving the double-RAF pipeline time to deliver. * - If the timer expires with no activity: resolves — nothing to measure. * * ### Phase 2: Debounce * Once the first measurement arrives, subsequent measurements reset a debounce timer. * When no measurements arrive for `debounceMs`, measurements are considered settled. * * @example * ```typescript * tracker.requestTracking({ discoveryWindowMs: 50, debounceMs: 50 }); * tracker.registerParticipants(['node:abc', 'edge:xyz']); // starts discovery window * * // ResizeObserver fired for a participant — extend if running low * tracker.signalObserverActivity('node:abc'); * * // Measurement arrived — transition to debounce * tracker.signalMeasurement('node:abc'); * * await tracker.waitForMeasurements(); * ``` * * @internal */ declare class MeasurementTracker { private phase; private participantIds; private pendingConfig; private discoveryWindow; private debounce; private settlementPromise; private settlementResolve; /** * Stages tracking configuration for the next middleware-driven registration pass. * Called before `applyUpdate()` when `waitForMeasurements` is requested. */ requestTracking(config?: MeasurementTrackingConfig): void; /** * Returns true if tracking has been requested via `requestTracking()`. * Used by the measurement-tracking middleware to decide first-pass vs subsequent-pass mode. */ isTrackingRequested(): boolean; /** * Registers entities that participated in the transaction. * Consumes the pending config from `requestTracking()`. * * If entityIds is empty (full no-op), just clears the pending config. * Otherwise, adds IDs to `participantIds` and starts the discovery window. * * @param entityIds - Prefixed entity IDs (e.g. 'node:abc', 'edge:xyz') */ registerParticipants(entityIds: string[]): void; /** * Signals that a ResizeObserver fired for a participant entity before batch processing. * This is an early indicator that measurements are in the pipeline (the double-RAF * processing hasn't delivered them yet). * * In both phases, if the remaining time is below `OBSERVER_ACTIVITY_MIN_REMAINING`, * the active timer resets to its full duration. */ signalObserverActivity(entityId: string): void; /** * Signals that an actual measurement arrived for a participant entity * (e.g., `measuredPorts`, `size`, `position`, `measuredLabels` changed via `setState`). * * - During discovery window: transitions to debounce phase. * - During debounce phase: resets the debounce timer. */ signalMeasurement(entityId: string): void; /** * Returns a promise that resolves when all currently pending measurements are complete. * If there are no pending measurements, resolves immediately. */ waitForMeasurements(): Promise; hasPendingMeasurements(): boolean; private activeTimer; private remainingTime; private startTimer; private clearTimer; private resolve; } declare interface MeasurementTrackingConfig { discoveryWindowMs?: number; debounceMs?: number; } /** * Interface representing the metadata of the diagram. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface Metadata { /** * Viewport of the diagram */ viewport: Viewport; /** * Custom user data associated with the diagram */ data?: T; } /** * Middleware interface for intercepting and modifying diagram state changes. * * Middlewares form a chain where each can: * - Inspect the current state and action type * - Modify the state by passing updates to `next()` * - Block operations by calling `cancel()` * - Perform side effects (logging, validation, etc.) * * @template TName - The middleware name type (string literal for type safety) * * @example * ```typescript * // Read-only middleware that blocks modifications * const readOnlyMiddleware: Middleware<'read-only'> = { * name: 'read-only', * execute: (context, next, cancel) => { * const blockedActions = ['addNodes', 'deleteNodes', 'updateNode']; * if (context.modelActionTypes.some((action) => blockedActions.includes(action))) { * console.warn('Action blocked in read-only mode'); * cancel(); * return; * } * next(); * } * }; * * // Auto-snap middleware that modifies positions * const snapMiddleware: Middleware<'auto-snap'> = { * name: 'auto-snap', * execute: (context, next) => { * const gridSize = 20; * const nodesToSnap = context.helpers.getAffectedNodeIds(['position']); * * const updates = nodesToSnap.map(id => { * const node = context.nodesMap.get(id)!; * return { * id, * position: { * x: Math.round(node.position.x / gridSize) * gridSize, * y: Math.round(node.position.y / gridSize) * gridSize * } * }; * }); * * next({ nodesToUpdate: updates }); * } * }; * * // Register middleware * ngDiagramService.registerMiddleware(snapMiddleware); * ``` * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface Middleware { /** Unique identifier for the middleware */ name: TName; /** * The middleware execution function. * * @param context - Complete context including state, helpers, and configuration * @param next - Call this to continue to the next middleware (optionally with state updates) * @param cancel - Call this to abort the entire operation */ execute: (context: MiddlewareContext, next: (stateUpdate?: FlowStateUpdate) => Promise, cancel: () => void) => Promise | void; } /** * An array of middlewares that will be executed in sequence. * * @public * @since 0.8.0 * @category Types/Middleware */ export declare type MiddlewareChain = Middleware[]; /** * The context object passed to middleware execute functions. * Provides access to the current state, helper functions, and configuration. * * @example * ```typescript * const middleware: Middleware = { * name: 'validation', * execute: (context, next, cancel) => { * // Check if any nodes were added * if (context.helpers.anyNodesAdded()) { * console.log('Nodes added:', context.state.nodes); * } * * // Access configuration * console.log('Cell size:', context.config.background.cellSize); * * // Check what actions triggered this (supports transactions with multiple actions) * if (context.modelActionTypes.includes('addNodes')) { * // Validate new nodes * const isValid = validateNodes(context.state.nodes); * if (!isValid) { * cancel(); // Block the operation * return; * } * } * * next(); // Continue to next middleware * } * }; * ``` * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface MiddlewareContext { /** The state before any modifications (before the initial action and before any middleware modifications) */ initialState: FlowState; /** The current state (includes the initial modification and all changes from previous middlewares) */ state: FlowState; /** * Map for quick node lookup by ID. * Contains the current state after previous middleware processing. * Use this to access nodes by ID instead of iterating through `state.nodes`. */ nodesMap: Map; /** * Map for quick edge lookup by ID. * Contains the current state after previous middleware processing. * Use this to access edges by ID instead of iterating through `state.edges`. */ edgesMap: Map; /** * The initial nodes map before any modifications (before the initial action and before any middleware modifications). * Use this to compare state before and after all modifications. * Common usage: Access removed node instances that no longer exist in `nodesMap`. */ initialNodesMap: Map; /** * The initial edges map before any modifications (before the initial action and before any middleware modifications). * Use this to compare state before and after all modifications. * Common usage: Access removed edge instances that no longer exist in `edgesMap`. */ initialEdgesMap: Map; /** * Map from node ID to connected edge IDs (edges where node is source or target) * before any modifications (before the initial action and before any middleware modifications). * Use this to find edges connected to specific nodes without scanning all edges. * @since 1.2.3 */ initialConnectedEdgesMap: Map; /** * The action that triggered the middleware execution. * @deprecated Use `modelActionTypes` instead, which supports multiple actions from transactions. * For single actions, this returns the first (and only) action type. */ modelActionType: ModelActionType; /** * All action types that triggered the middleware execution. * For transactions, this contains the transaction name followed by all action types * from commands executed within the transaction. * For single commands outside transactions, this is a single-element array. * * @example * ```typescript * // For a transaction named 'batchUpdate' with addNodes and moveViewport commands: * // modelActionTypes = ['batchUpdate', 'addNodes', 'moveViewport'] * * // For a single command outside a transaction: * // modelActionTypes = ['addNodes'] * ``` * * @since 0.9.0 */ modelActionTypes: ModelActionTypes; /** Helper functions to check what changed (tracks all cumulative changes from the initial action and all previous middlewares) */ helpers: MiddlewareHelpers; /** All state updates from previous middlewares in the chain */ history: MiddlewareHistoryUpdate[]; /** Manager for action states (resizing, linking, etc.) */ actionStateManager: ActionStateManager; /** Manager for edge routing algorithms */ edgeRoutingManager: EdgeRoutingManager; /** * The initial state update that triggered the middleware chain. * Middlewares can add their own updates to the state, so this may not contain all modifications * that will be applied. Use `helpers` to get actual knowledge about all changes. */ initialUpdate: FlowStateUpdate; /** The current diagram configuration */ config: FlowConfig; /** Environment information (browser, rendering engine, etc.) */ environment: EnvironmentInfo; } /** * Helper functions for checking what changed during middleware execution. * These helpers track all cumulative changes from the initial state update and all previous middlewares. * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface MiddlewareHelpers { /** * Checks if a specific node has been modified. * @param id - The node ID to check * @returns true if the node was modified (any property changed) by the initial state update or any previous middleware */ checkIfNodeChanged: (id: string) => boolean; /** * Checks if a specific edge has been modified. * @param id - The edge ID to check * @returns true if the edge was modified (any property changed) by the initial state update or any previous middleware */ checkIfEdgeChanged: (id: string) => boolean; /** * Checks if a specific node was added. * @param id - The node ID to check * @returns true if the node was added by the initial state update or any previous middleware */ checkIfNodeAdded: (id: string) => boolean; /** * Checks if a specific node was removed. * @param id - The node ID to check * @returns true if the node was removed by the initial state update or any previous middleware */ checkIfNodeRemoved: (id: string) => boolean; /** * Checks if a specific edge was added. * @param id - The edge ID to check * @returns true if the edge was added by the initial state update or any previous middleware */ checkIfEdgeAdded: (id: string) => boolean; /** * Checks if a specific edge was removed. * @param id - The edge ID to check * @returns true if the edge was removed by the initial state update or any previous middleware */ checkIfEdgeRemoved: (id: string) => boolean; /** * Checks if any node has one or more of the specified properties changed. * @param props - Array of property names to check (e.g., ['position', 'size']) * @returns true if any node has any of these properties modified by the initial state update or any previous middleware */ checkIfAnyNodePropsChanged: (props: string[]) => boolean; /** * Checks if any edge has one or more of the specified properties changed. * @param props - Array of property names to check (e.g., ['sourcePosition', 'targetPosition']) * @returns true if any edge has any of these properties modified by the initial state update or any previous middleware */ checkIfAnyEdgePropsChanged: (props: string[]) => boolean; /** * Checks if any nodes were added. * @returns true if at least one node was added by the initial state update or any previous middleware */ anyNodesAdded: () => boolean; /** * Checks if any edges were added. * @returns true if at least one edge was added by the initial state update or any previous middleware */ anyEdgesAdded: () => boolean; /** * Checks if any nodes were removed. * @returns true if at least one node was removed by the initial state update or any previous middleware */ anyNodesRemoved: () => boolean; /** * Checks if any edges were removed. * @returns true if at least one edge was removed by the initial state update or any previous middleware */ anyEdgesRemoved: () => boolean; /** * Gets all node IDs that have one or more of the specified properties changed. * @param props - Array of property names to check (e.g., ['position', 'size']) * @returns Array of node IDs that have any of these properties modified by the initial state update or any previous middleware */ getAffectedNodeIds: (props: string[]) => string[]; /** * Gets all edge IDs that have one or more of the specified properties changed. * @param props - Array of property names to check (e.g., ['sourcePosition', 'targetPosition']) * @returns Array of edge IDs that have any of these properties modified by the initial state update or any previous middleware */ getAffectedEdgeIds: (props: string[]) => string[]; /** * Gets all node IDs that have any property changed, regardless of which property. * @since 1.2.2 * @returns Array of node IDs that were modified by the initial state update or any previous middleware */ getChangedNodeIds: () => string[]; /** * Gets all edge IDs that have any property changed, regardless of which property. * @since 1.2.2 * @returns Array of edge IDs that were modified by the initial state update or any previous middleware */ getChangedEdgeIds: () => string[]; /** * Gets all nodes that were added. * @returns Array of node instances that were added by the initial state update or any previous middleware */ getAddedNodes: () => Node_2[]; /** * Gets all edges that were added. * @returns Array of edge instances that were added by the initial state update or any previous middleware */ getAddedEdges: () => Edge[]; /** * Gets all nodes that were removed. * Uses `initialNodesMap` to access the removed instances. * @returns Array of node instances that were removed by the initial state update or any previous middleware */ getRemovedNodes: () => Node_2[]; /** * Gets all edges that were removed. * Uses `initialEdgesMap` to access the removed instances. * @returns Array of edge instances that were removed by the initial state update or any previous middleware */ getRemovedEdges: () => Edge[]; } /** * Records a state update made by a specific middleware. * Used to track the history of state transformations through the middleware chain. * * @example * ```typescript * const middleware: Middleware = { * name: 'audit-logger', * execute: (context, next) => { * // Check what previous middlewares did * context.history.forEach(update => { * console.log(`${update.name} modified:`, update.stateUpdate); * }); * next(); * } * }; * ``` * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface MiddlewareHistoryUpdate { /** The name of the middleware that made the update */ name: string; /** The state update that was applied */ stateUpdate: FlowStateUpdate; } declare class MiddlewareManager { private middlewareChain; private eventEmitterMiddleware; private measurementTrackingMiddleware; readonly flowCore: FlowCore; constructor(flowCore: FlowCore, middlewares?: MiddlewareChain); isRegistered(name: string): boolean; /** * Registers a new middleware in the chain * @param middleware Middleware to register * @returns Function to unregister the middleware */ register>(middleware: T): () => void; /** * Unregister a middleware from the chain * @param name Name of the middleware to unregister */ unregister(name: string): void; /** * Executes all registered middlewares in sequence * @param initialState Initial state to be transformed * @param stateUpdate State update to be applied * @param modelActionTypes Model action types which trigger the middleware (array for transactions, single-element for direct calls) * @returns State after all middlewares have been applied */ execute(initialState: FlowState, stateUpdate: FlowStateUpdate, modelActionTypes: ModelActionTypes): Promise; } /** * Bounding box and transform for a node in minimap coordinate space. * * @public * @since 1.0.0 * @category Types/Minimap */ declare interface MinimapBounds { id: string; x: number; y: number; width: number; height: number; angle: number; transform: string; } /** * Pre-computed node data for minimap rendering. * Contains transformed bounds, original node reference, styling, and optional custom template. */ declare interface MinimapNodeData { bounds: MinimapBounds; diagramNode: Node_2; nodeStyle: MinimapNodeStyle; template: Type | null; } /** * Available shapes for minimap node rendering. * * @public * @since 1.0.0 * @category Types/Minimap */ export declare type MinimapNodeShape = 'rect' | 'circle' | 'ellipse'; /** * Style properties that can be applied to minimap nodes. * All properties are optional - unset properties use CSS defaults. * * @public * @since 1.0.0 * @category Types/Minimap */ export declare interface MinimapNodeStyle { /** Shape of the node in the minimap. Defaults to 'rect'. */ shape?: MinimapNodeShape; /** Fill color for the node */ fill?: string; /** Stroke color for the node */ stroke?: string; /** Stroke width in pixels */ strokeWidth?: number; /** Opacity from 0 to 1 */ opacity?: number; /** CSS class to apply to the node */ cssClass?: string; } /** * Function signature for the nodeStyle callback. * Return style properties to override defaults, or null/undefined to use defaults. * * @public * @since 1.0.0 * @category Types/Minimap * * @example * ```typescript * const nodeStyle: MinimapNodeStyleFn = (node) => ({ * fill: node.type === 'database' ? '#4CAF50' : '#9E9E9E', * opacity: node.selected ? 1 : 0.6, * }); * ``` */ export declare type MinimapNodeStyleFn = (node: Node_2) => MinimapNodeStyle | null | undefined; /** * Represents the calculated transform data for minimap rendering. */ declare interface MinimapTransform { scale: number; offsetX: number; offsetY: number; } /** * Represents the viewport rectangle in minimap space. */ declare interface MinimapViewportRect { x: number; y: number; width: number; height: number; } export declare class MobileBoxSelectionDirective { private readonly inputEventsRouter; private readonly boxSelectionProvider; private readonly flowCoreProvider; private readonly touchEventsStateService; private touchStartPoint; private isBoxSelectionActive; private longPressTimer; private readonly LONG_PRESS_DELAY; private readonly MOVE_THRESHOLD; onTouchStart(event: TouchEvent): void; onTouchMove(event: TouchEvent): void; onTouchEnd(event: TouchEvent): void; private cancelBoxSelection; private clearLongPressTimer; private isSingleTouch; private shouldCancelDuringLongPress; private emitBoxSelectionEvent; private updateBoundingBox; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } export declare class MobilePanningDirective { private readonly inputEventsRouter; private readonly diagramService; private readonly touchEventsStateService; private isPanning; /** * Stores the last touch point during a panning gesture. * Used to emit the last input point on touch end. */ private lastTouch; onTouchStart(event: TouchEvent): void; onTouchMove(event: TouchEvent): void; onTouchEnd(event: TouchEvent): void; private getMidpoint; private shouldHandle; private isTwoFingerTouch; private shouldContinuePanning; private emitPanningEvent; private preventDefaultAndStop; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } export declare class MobileZoomingDirective { private readonly elementRef; private readonly flowCoreProvider; private readonly inputEventsRouterService; private readonly touchEventsStateService; private touchCache; /** * Stores the last distance between two touch points during a pinch gesture. * Used to calculate the zoom factor smoothly on each move event. */ private lastDistance?; /** * Stores the initial distance between two touch points at the start of a pinch gesture. * Used to determine if the gesture should be recognized as a zoom (pinch) based on a threshold. */ private initialDistance?; /** * Flag indicating if zooming gesture is currently active. * Once set to true, it remains true until all fingers are lifted. */ private isZoomingActive; /** * Minimal change in distance (in pixels) between two touch points required to trigger zoom. * Prevents accidental zooming on small finger movements. */ private readonly ZOOM_TRIGGER_DELTA; onTouchStart(event: TouchEvent): void; onTouchEnd(event: TouchEvent): void; onTouchMove(event: TouchEvent): void; private removeTouchFromCache; private computeDistance; private updateTouchInCache; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Interface representing the entire model of the flow diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare interface Model { /** * Array of nodes in the diagram */ nodes: Node_2[]; /** * Array of edges connecting the nodes */ edges: Edge[]; /** * Metadata associated with the diagram */ metadata: Partial; } /** * Individual model action type that can trigger middleware execution. * These represent all possible operations that modify the diagram state. * * @example * ```typescript * const blockedActions: ModelActionType[] = ['addNodes', 'deleteNodes', 'updateNode']; * ``` * * @public * @since 0.8.0 * @category Types/Middleware */ export declare type ModelActionType = 'init' | 'changeSelection' | 'moveNodesBy' | 'deleteSelection' | 'addNodes' | 'updateNode' | 'updateNodes' | 'deleteNodes' | 'clearModel' | 'paletteDropNode' | 'addEdges' | 'updateEdge' | 'deleteEdges' | 'deleteElements' | 'addEdgeLabelsBulk' | 'updateEdgeLabelsBulk' | 'deleteEdgeLabelsBulk' | 'addPortsBulk' | 'updatePortsBulk' | 'deletePortsBulk' | 'paste' | 'moveViewport' | 'resizeNode' | 'resizeNodeStart' | 'resizeNodeStop' | 'startLinking' | 'moveTemporaryEdge' | 'finishLinking' | 'zoom' | 'changeZOrder' | 'rotateNodeTo' | 'rotateNodeStart' | 'rotateNodeStop' | 'highlightGroup' | 'highlightGroupClear' | 'moveNodes' | 'moveNodesStart' | 'moveNodesStop' | 'selectEnd'; /** * Array of model action types, used to track all actions in a transaction or a single action. * Supports both known action types with autocomplete and custom string action types. * * @example * ```typescript * const middleware: Middleware = { * name: 'logger', * execute: (context, next) => { * console.log('Action types:', context.modelActionTypes.join(', ')); * next(); * } * }; * ``` * * @public * @since 0.9.0 * @category Types/Middleware */ export declare type ModelActionTypes = LooseAutocomplete[]; /** * Interface for model adapters that handle the data management of a flow diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare interface ModelAdapter { /** * Destroy the model adapter and clean up resources * This should be called when the model is no longer needed to prevent memory leaks */ destroy(): void; /** * Get all nodes in the model */ getNodes(): Node_2[]; /** * Get all edges in the model */ getEdges(): Edge[]; /** * Update nodes in the model * @param nodes Array of nodes to set * @param nodesFn Function that takes current nodes and returns new nodes */ updateNodes(nodes: Node_2[]): void; updateNodes(nodesFn: (nodes: Node_2[]) => Node_2[]): void; /** * Update edges in the model * @param edges Array of edges to set * @param edgesFn Function that takes current edges and returns new edges */ updateEdges(edges: Edge[]): void; updateEdges(edgesFn: (edges: Edge[]) => Edge[]): void; /** * Get metadata associated with the model */ getMetadata(): Metadata; /** * Set metadata for the model * @param metadata Metadata to set * @param metadataFn Function that takes current metadata and returns new metadata */ updateMetadata(metadata: Metadata): void; updateMetadata(metadataFn: (metadata: Metadata) => Metadata): void; /** * Register a callback to be called when the model changes * @param callback Function to be called on changes */ onChange(callback: ({ nodes, edges, metadata }: ModelChanges) => void): void; /** * Unregister a callback from being called when the model changes * @param callback Function to unregister from changes */ unregisterOnChange(callback: ({ nodes, edges, metadata }: ModelChanges) => void): void; /** * Undo the last change */ undo(): void; /** * Redo the last undone change */ redo(): void; /** * Convert the model to a JSON string */ toJSON(): string; } /** * Interface representing a snapshot of the diagram model state. * * This read-only interface is provided by the library when the model changes. * It contains the complete current state of nodes, edges, and metadata. * Typically received in `onChange` callbacks to observe model updates. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface ModelChanges { /** Current array of all nodes in the diagram. */ nodes: Node_2[]; /** Current array of all edges in the diagram. */ edges: Edge[]; /** Current metadata associated with the diagram. */ metadata: Metadata; } declare class ModelLookup { private readonly flowCore; private _nodesMap; private _edgesMap; private _directChildrenMap; private _descendantsCache; private _connectedEdgesMap; constructor(flowCore: FlowCore); /** * Desynchronizes the model lookup */ desynchronize(): void; /** * Gets the nodes map if it is not synchronized synchronize it * @returns Nodes map */ get nodesMap(): Map; /** * Gets the edges map if it is not synchronized synchronize it * @returns Edges map */ get edgesMap(): Map>; /** * Gets the direct children map if it is not synchronized synchronize it * @returns Direct children map */ get directChildrenMap(): Map; /** * Gets the connected edges map if it is not synchronized synchronize it * @returns Connected edges map */ get connectedEdgesMap(): Map; /** * Gets the descendants cache if it is not synchronized synchronize it * @returns Descendants cache */ private get descendantsCache(); /** * Builds a map of group nodes to their children * @param nodes Nodes array * @returns Map where key is group id and value is array of child ids */ private buildDirectChildrenMap; /** * Builds a map of nodes to their connected edges * @param edges Edges array * @returns Map where key is node id and value is array of connected edge ids */ private buildConnectedEdgesMap; /** * Gets a node by id * @param nodeId Node id * @returns Node */ getNodeById(nodeId: string): Node_2 | null; /** * Gets an edge by id * @param edgeId Edge id * @returns Edge */ getEdgeById(edgeId: string): Edge | null; /** * Gets all edges connected to a node * @param nodeId Node id * @returns Array of edges where the node is either source or target */ getConnectedEdges(nodeId: string): Edge[]; /** * Gets all nodes connected to a node via edges * @param nodeId Node id * @returns Array of nodes connected to the given node */ getConnectedNodes(nodeId: string): Node_2[]; /** * Gets the source and target nodes of an edge * @param edgeId Edge id * @returns Object containing source and target nodes, or null if edge doesn't exist */ getNodeEnds(edgeId: string): { source: Node_2; target: Node_2; } | null; /** * Gets all children ids for a given group node id * @param groupId group node id * @returns Array of child node ids */ private getChildrenIds; /** * Gets all children nodes for a given group node id * @param groupId group node id * @returns Array of child nodes */ getChildren(groupId: string): Node_2[]; /** * Gets all descendant IDs for a given group node id (with caching) * @param groupId group node id * @returns Array of all descendant node ids (children, grandchildren, etc.) */ getAllDescendantIds(groupId: string): Node_2['id'][]; /** * Recursively computes all descendants for a given group node id * @param groupId group node id * @returns Array of all descendant node ids */ private computeAllDescendants; /** * Gets all descendant nodes for a given group node id * @param groupId group node id * @returns Array of all descendant nodes (children, grandchildren, etc.) */ getAllDescendants(groupId: string): Node_2[]; /** * Checks if a node has children * @param nodeId Node id * @returns True if the node has children */ hasChildren(nodeId: string): boolean; /** * Checks if a node has any descendants (children, grandchildren, etc.) * @param nodeId Node id * @returns True if the node has any descendants */ hasDescendants(nodeId: string): boolean; /** * Gets the children map (read-only access) * @returns Children map */ getChildrenMap(): ReadonlyMap; /** * Gets all selected nodes * @returns Array of directly selected nodes */ getSelectedNodes(): Node_2[]; /** * Gets the children of a node * @param nodeId Node id * @param directOnly Whether to get only direct children * @returns Array of children nodes */ getNodeChildren(nodeId: string, { directOnly }?: { directOnly?: boolean; }): Node_2[]; /** * Gets the children ids of a node * @param nodeId Node id * @param directOnly Whether to get only direct children * @returns Array of children node ids */ getNodeChildrenIds(nodeId: string, { directOnly }?: { directOnly?: boolean; }): Node_2['id'][]; /** * Gets all selected nodes with their children * @returns Array of selected nodes with their children */ getSelectedNodesWithChildren({ directOnly }?: { directOnly?: boolean; }): Node_2[]; /** * Gets all selected edges * @returns Array of selected edges */ getSelectedEdges(): Edge[]; /** * Checks if a node is descendant of a group node * @param nodeId Node id * @param groupId Group node id * @returns True if the node is descendant of the group node */ isNodeDescendantOfGroup(nodeId: string, groupId: string): boolean; /** * Check for potential circular dependency between a node and a group * @param nodeId Node id * @param groupId Group node id * @returns True if the group is a descendant of the node or the node is the group */ wouldCreateCircularDependency(nodeId: string, groupId: string): boolean; /** * Gets the full chain of parent group Nodes for a given nodeId. * @param nodeId Node id * @returns Array of parent group Node objects, from closest parent to farthest ancestor */ getParentChain(nodeId: string): GroupNode[]; } /** * Defines a modifier-only shortcut binding (for pointer events) * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare interface ModifierOnlyShortcutBinding { /** * Key must not be present for modifier-only bindings */ key?: never; /** Required modifier keys - at least one modifier is typically required */ modifiers: Partial; } declare interface MoveNodesByCommand { name: 'moveNodesBy'; nodes: Node_2[]; delta: Point; } declare interface MoveNodesStartCommand { name: 'moveNodesStart'; } declare interface MoveNodesStopCommand { name: 'moveNodesStop'; } declare interface MoveTemporaryEdgeCommand { name: 'moveTemporaryEdge'; position: Point; } declare interface MoveViewportByCommand { name: 'moveViewportBy'; x: number; y: number; } declare interface MoveViewportCommand { name: 'moveViewport'; x: number; y: number; } /** * The `NgDiagramBackgroundComponent` is responsible for rendering the background of the diagram. * * ## Example usage * ```html * * * * * * * * * * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramBackgroundComponent implements AfterContentInit { private readonly custom; /** * The type of background pattern to display. * @default 'dots' */ type: InputSignal<"grid" | "dots">; protected hasContent: boolean; /** @internal */ protected isDottedBackground: Signal; /** @internal */ ngAfterContentInit(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Base edge component that handles edge rendering. * It can be extended or used directly to render edges in the diagram. * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramBaseEdgeComponent { private readonly flowCoreProvider; private readonly markerRegistry; /** * Whether to use inline markers (Safari fallback). * Safari doesn't support context-stroke, so we render markers inline per edge. */ readonly useInlineMarkers: boolean; /** * Edge data model */ edge: InputSignal>; /** * Edge routing mode */ routing: InputSignal; /** * Stroke color of the edge. Edge model data has precedence over this property. */ stroke: InputSignal; /** * ID of a source element in the SVG document. Edge model data has precedence over this property. */ sourceArrowhead: InputSignal; /** * ID of a target element in the SVG document. Edge model data has precedence over this property. */ targetArrowhead: InputSignal; /** * Stroke opacity of the edge */ strokeOpacity: InputSignal; /** * Stroke width of the edge */ strokeWidth: InputSignal; /** * Stroke dash array of the edge (e.g., '5 5' for dashed line, '10 5 2 5' for dash-dot pattern). */ strokeDasharray: InputSignal; readonly points: Signal; readonly path: Signal; readonly sourceMarkerId: Signal; readonly targetMarkerId: Signal; readonly markerStart: Signal; readonly markerEnd: Signal; readonly selected: Signal; readonly temporary: Signal; readonly labels: Signal; readonly class: Signal; private prevRouting; private prevRoutingMode; private prevPoints; constructor(); private syncEdgePropertiesToModel; private checkRoutingChanges; private checkRoutingModeChanges; private checkPointsChanges; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramBaseEdgeLabelComponent` is responsible for displaying a label at a specific position along an edge. * * ## Example usage * ```html * * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramBaseEdgeLabelComponent implements OnInit, OnDestroy { private readonly flowCoreProvider; private readonly hostElement; private readonly edgeComponent; private readonly batchResizeObserver; /** * The unique identifier for the edge label. */ id: InputSignal; /** * The relative position of the label along the edge (from 0 to 1). */ positionOnEdge: InputSignal; readonly edgeData: Signal>; readonly points: Signal; readonly edgeId: Signal; private ownerInternalId; readonly position: Signal; readonly isVisible: Signal; private lastPositionOnEdge; get transform(): string; constructor(); /** @internal */ ngOnInit(): void; /** @internal */ ngOnDestroy(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramBaseNodeTemplateComponent` provides a base template for custom nodes with default node styling and features. * * This component wraps custom node content while providing the default node's visual appearance, selection states, * resize and rotate adornments, and default ports. Use this as a convenient way to create custom nodes that * maintain the default node's look and feel while adding custom content. * * @example * ```html * * *
{{ node().data.title }}
*
{{ node().data.description }}
*
* ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramBaseNodeTemplateComponent implements NgDiagramNodeTemplate { private readonly diagramService; node: InputSignal; isSelected: Signal; classes: Signal; enablePortHover: Signal; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Base service class providing access to the FlowCore instance. * * @internal */ declare abstract class NgDiagramBaseService { protected readonly flowCoreProvider: FlowCoreProviderService; protected get flowCore(): FlowCore; } /** * The `NgDiagramClipboardService` provides clipboard operations for diagram. * * ## Example usage * ```typescript * private clipboardService = inject(NgDiagramClipboardService); * * // Copy selected elements * this.clipboardService.copy(); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramClipboardService extends NgDiagramBaseService { /** * Copies the current selection to the clipboard. */ copy(): void; /** * Cuts the current selection to the clipboard. */ cut(): void; /** * Pastes the clipboard content at the specified position. * @param position The position where to paste the content. */ paste(position: Point): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Main diagram component for rendering flow diagrams with nodes and edges. * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramComponent implements OnInit, OnDestroy { private readonly elementRef; private readonly flowCoreProvider; private readonly renderer; private readonly flowResizeBatchProcessor; private readonly flowOffsetService; private readonly templateProviderService; private initializedModel; private resizeObserver; /** * Global configuration options for the diagram. */ config: InputSignal | undefined>; /** * The model to use in the diagram. */ model: InputSignal; /** * Optional — the initial middlewares to use. * When provided, the middleware list can be modified to add new items, * replace existing ones, or override the defaults. * * ⚠️ Use with caution — incorrectly implemented custom middlewares * can degrade performance or completely break the data flow. */ middlewares: InputSignal; /** * The node template map to use for the diagram. */ nodeTemplateMap: InputSignal; /** * The edge template map to use for the diagram. * Optional - if not provided, default edge rendering will be used. */ edgeTemplateMap: InputSignal; readonly nodes: WritableSignal; readonly edges: WritableSignal[]>; readonly viewport: WritableSignal; /** Whether panning is enabled in the diagram. */ readonly viewportPannable: WritableSignal; /** * Event emitted when the diagram initialization is complete. * * This event fires after all nodes and edges including their internal parts * (ports, labels) have been measured and positioned. */ diagramInit: EventEmitter; /** * Event emitted when a user manually draws an edge between two nodes. * * This event only fires for user-initiated edge creation through the UI, * but not for programmatically added edges. * * @deprecated Use `edgeDrawEnded` instead, which fires for both successful and cancelled draws. */ edgeDrawn: EventEmitter; /** * Event emitted when an edge draw gesture ends, regardless of outcome. * * Fires on every linking completion — both successful and cancelled. * For successful draws, includes the created edge and target. * For cancelled draws, includes the cancellation reason. */ edgeDrawEnded: EventEmitter; /** * Event emitted when selected nodes are moved within the diagram. * * This event fires when the user moves nodes manually by dragging or * programmatically using the `NgDiagramNodeService.moveNodesBy()` method. */ selectionMoved: EventEmitter; /** * Event emitted when the selection state changes in the diagram. * * This event fires when the user selects or deselects nodes and edges through * clicking or programmatically using the `NgDiagramSelectionService`. */ selectionChanged: EventEmitter; /** * Event emitted when a selection gesture is complete. * * This event fires on pointerup after a selection operation completes — * whether from clicking a node/edge, box selection, or select-all. */ selectionGestureEnded: EventEmitter; /** * Event emitted when selected elements are deleted from the diagram. * * This event fires when the user deletes nodes and edges using the delete key, * or programmatically through the diagram service. */ selectionRemoved: EventEmitter; /** * Event emitted when nodes are grouped or ungrouped. * * This event fires when the user moves nodes in or out of a group node, * changing their group membership status. */ groupMembershipChanged: EventEmitter; /** * Event emitted when a node is rotated in the diagram. * * This event fires when the user rotates a node manually using the rotation handle * or programmatically using the `NgDiagramNodeService` rotation methods. */ selectionRotated: EventEmitter; /** * Event emitted when a node rotation operation begins. * * This event fires once when the user starts rotating a node by dragging * the rotation handle. */ nodeRotateStarted: EventEmitter; /** * Event emitted when a node rotation operation ends. * * This event fires when the user releases the pointer after rotating a node. * The node will have its final angle when this event is received. */ nodeRotateEnded: EventEmitter; /** * Event emitted when the viewport changes through panning or zooming. * * This event fires during pan and zoom operations, including mouse wheel zoom, * and programmatic viewport changes. */ viewportChanged: EventEmitter; /** * Event emitted when clipboard content is pasted into the diagram. * * This event fires when nodes and edges are added via paste operations, * either through keyboard shortcuts or programmatic paste commands. */ clipboardPasted: EventEmitter; /** * Event emitted when a node or group size changes. * * This event fires when a node is resized manually by dragging resize handles * or programmatically using resize methods. */ nodeResized: EventEmitter; /** * Event emitted when a node resize operation begins. * * This event fires once when the user starts resizing a node by dragging * a resize handle. */ nodeResizeStarted: EventEmitter; /** * Event emitted when a node resize operation ends. * * This event fires when the user releases the pointer after resizing a node. * The node will have its final size when this event is received. */ nodeResizeEnded: EventEmitter; /** * Event emitted when a palette item is dropped onto the diagram. * * This event fires when users drag items from the palette and drop them * onto the canvas to create new nodes. */ paletteItemDropped: EventEmitter; /** * Event emitted when a node drag operation begins. * * This event fires once when the drag threshold is crossed, signaling the * start of a drag operation. */ nodeDragStarted: EventEmitter; /** * Event emitted when a node drag operation ends. * * This event fires when the user releases the pointer after dragging nodes. * Nodes will have their final positions when this event is received. */ nodeDragEnded: EventEmitter; constructor(); /** @ignore */ ngOnInit(): void; /** @ignore */ ngOnDestroy(): void; /** * Retrieves the custom Angular component template for rendering a specific node type. * * This method performs a lookup in the node template map to find a custom component * for the given node type. If no custom template is registered, it returns null, * which will cause the diagram to fall back to the default node template. * * @param nodeType - The type identifier of the node to get a template for. * * @returns The Angular component class registered for the node type, or * null if no custom template is registered for this type * * @example * Basic usage in template: * ```typescript * // In your component * const nodeTemplates = new Map([ * ['database', DatabaseNodeComponent], * ['api', ApiNodeComponent] * ]); * * // The method will return DatabaseNodeComponent for database nodes * const dbTemplate = this.getNodeTemplate('database'); // Returns DatabaseNodeComponent * ``` * @see {@link nodeTemplateMap} - The input property where templates are registered * @see {@link NgDiagramNodeTemplateMap} - Type definition for the template map * * @throws This method does not throw exceptions - it handles all edge cases gracefully */ getNodeTemplate(nodeType: Node_2['type']): Type>> | Type> | null; getEdgeTemplate(edgeType: Edge['type']): Type> | null; trackNode: (_index: number, node: Node_2) => any; trackEdge: (_index: number, edge: Edge) => any; isGroup(node: Node_2): node is GroupNode; castToGroupNode(node: Node_2): GroupNode; getBoundingClientRect(): DOMRect; private getViewportSize; private setupViewportSizeTracking; private cleanupViewportSizeTracking; private updateViewportSize; private setupEventBridge; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The recommended configuration type for ng-diagram. * * This type allows you to provide only the configuration options you want to override. * All properties are optional and correspond to those in {@link FlowConfig}. * * @see {@link FlowConfig} – for the full list of available configuration options * @see {@link NgDiagramComponent} * @see {@link NgDiagramService} * * @example * ```ts * // define configuration in a component * const config: NgDiagramConfig = { * zoom: { max: 3 }, * edgeRouting: { defaultRouting: 'orthogonal' }, * }; * ``` * @example * ```html * * * ``` * * @public * @since 0.8.0 * @category Types/Configuration */ export declare type NgDiagramConfig = DeepPartial; /** * `NgDiagramEdgeTemplate` is an interface for custom edge components in ng-diagram. * It describes the required input signal for edge data and properties. * * This interface is used when creating custom edge components to ensure they receive the correct edge input. * * ## Example usage * ```typescript * @Component({...}) * export class MyCustomEdgeComponent implements NgDiagramEdgeTemplate { * edge!: InputSignal>; * } * ``` * * @public * @since 0.8.0 * @template Data - The type of data associated with the edge * @category Types/Templates */ export declare interface NgDiagramEdgeTemplate { /** Input signal containing the edge data and properties. */ edge: InputSignal>; } /** * `NgDiagramEdgeTemplateMap` is a map that associates edge type names with their corresponding Angular component classes. * * ## Example usage * ```typescript * // Define a map of edge types to their components * const edgeTemplateMap = new NgDiagramEdgeTemplateMap([['someEdge', SomeEdgeComponent]]); * ``` * * ```html * * * ``` * * @public * @since 0.8.0 * @category Types/Templates */ export declare class NgDiagramEdgeTemplateMap extends Map>> { } /** * The `NgDiagramGroupHighlightedDirective` conditionally applies a highlight class to a group node in the diagram when it is highlighted. * * ## Example usage * ```html *
* *
* ``` * * When the group's {@link GroupNode#highlighted} property is `true`, the `ng-diagram-group-highlight` CSS class is applied. * * @public * @since 0.8.0 * @category Directives */ export declare class NgDiagramGroupHighlightedDirective { /** * The group node instance to monitor for highlight state. */ node: InputSignal>; protected readonly highlighted: Signal; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Interface for custom group node components. * * @public * @since 0.8.0 * @template Data - The type of data associated with the group node * @category Types/Templates */ export declare interface NgDiagramGroupNodeTemplate extends NgDiagramNodeTemplate> { } /** * The `NgDiagramGroupsService` provides methods for managing node groups in the diagram. * * ## Example usage * ```typescript * private groupsService = inject(NgDiagramGroupsService); * * // Add nodes to a group * this.groupsService.addToGroup('groupId', ['nodeId1', 'nodeId2']); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramGroupsService extends NgDiagramBaseService { /** * Adds nodes to a group. * @param groupId The ID of the group to add nodes to. * @param nodeIds Array of node IDs to add to the group. */ addToGroup(groupId: string, nodeIds: string[]): void; /** * Highlights a group. * @param groupId The ID of the group to highlight. * @param nodes The nodes to highlight as part of the group. */ highlightGroup(groupId: string, nodes: Node_2[]): void; /** * Clears all group highlights. */ highlightGroupClear(): void; /** * Removes nodes from a group. * @param groupId The ID of the group to remove nodes from. * @param nodeIds Array of node IDs to remove from the group. */ removeFromGroup(groupId: string, nodeIds: string[]): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Component for defining SVG markers with cross-browser SVG2 support. * * This component enables the use of SVG2 properties like `context-stroke` and `context-fill` * in marker definitions across all browsers. These properties allow markers to automatically * inherit the stroke/fill color from the referencing edge, enabling dynamic color changes * on hover, selection, and other states. * * Safari does not natively support `context-stroke`/`context-fill`, so this component * registers the marker element for automatic inline rendering with `currentColor` fallback. * * @example * ```html * * * * * * * * * * ``` * * @public * @since 0.9.0 * @category Components */ export declare class NgDiagramMarkerComponent implements AfterViewInit { private readonly elementRef; private readonly markerRegistry; private readonly destroyRef; private markerId; ngAfterViewInit(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Collection of mathematical utility functions for diagram calculations. * * @internal */ export declare const NgDiagramMath: { angleBetweenPoints: typeof angleBetweenPoints; angleToSide: (angleDegrees: number, inverse?: boolean) => PortSide; clamp: ({ min, value, max }: { min: number; value: number; max: number; }) => number; distanceBetweenPoints: (a: Point, b: Point) => number; normalizeAngle: (angle: number) => number; snapAngle: typeof snapAngle; snapNumber: (value: number, step: number) => number; snapPoint: (point: Point, step: Size) => { x: number; y: number; }; calculateEdgePanningForce: (containerBox: Rect, clientPosition: Point, detectionThreshold: number, forceMultiplier: number) => Point | null; }; /** * A minimap component that displays a bird's-eye view of the diagram. * * Shows all nodes as small rectangles and a viewport rectangle indicating * the currently visible area. The minimap updates reactively when the * diagram viewport changes (pan/zoom) or when nodes are added/removed/updated. * * The minimap also supports navigation: click and drag on the minimap to pan * the diagram viewport to different areas. * * @public * @since 1.0.0 * @category Components */ export declare class NgDiagramMinimapComponent implements AfterViewInit { private readonly VIEWPORT_STROKE_WIDTH_CSS_VAR; private readonly renderer; private readonly flowCoreProvider; private readonly interactionTracker; private readonly elementRef; private readonly directStrategy; private readonly virtualizedStrategy; /** Cached stroke padding to avoid layout thrashing from repeated getComputedStyle calls. */ private strokePadding; /** Position of the minimap panel within the diagram container. */ position: InputSignal; /** Width of the minimap in pixels. */ width: InputSignal; /** Height of the minimap in pixels. */ height: InputSignal; /** Whether to show zoom controls in the minimap footer. */ showZoomControls: InputSignal; /** * Optional callback function to customize node styling. * Return style properties to override defaults, or null/undefined to use CSS defaults. * * @example * ```typescript * nodeStyle = (node: Node) => ({ * fill: node.type === 'database' ? '#4CAF50' : '#9E9E9E', * opacity: node.selected ? 1 : 0.6, * }); * ``` */ nodeStyle: InputSignal; /** * Optional template map for complete control over node rendering per node type. * Components registered in the map should render SVG elements. * * @example * ```typescript * const minimapTemplateMap = new NgDiagramMinimapNodeTemplateMap([ * ['database', DatabaseMinimapNodeComponent], * ['api', ApiMinimapNodeComponent], * ]); * * // Usage: * * ``` */ minimapNodeTemplateMap: InputSignal; /** * When enabled, minimap node positions are frozen during drag, resize, and * rotation operations — updated only when the operation ends. * * The viewport indicator rectangle always updates in real-time. * * @default false * @since 1.2.0 */ deferNodeUpdates: InputSignal; /** @ignore */ ngAfterViewInit(): void; isDiagramInitialized: WritableSignal; viewport: WritableSignal; hasValidViewport: Signal; viewportRect: Signal; /** * @internal * Active minimap strategy based on virtualization mode. * Delegates mode-specific logic (node rendering, bounds) to the strategy. * * Note: isVirtualizationActive is a plain getter (not a signal). * This works because switching virtualization mode requires model recreation, * which triggers a full diagram re-init cycle (isInitialized: true → false → true). */ private strategy; /** * @internal * Main transform for minimap - updates when viewport or diagram bounds change. * Used for SVG group transform and viewport rect calculation. */ protected transform: Signal; /** * @internal * SVG transform attribute for the nodes group. * Converts diagram coordinates to minimap coordinates. */ protected nodesGroupTransform: Signal; private isDeferringUpdates; private cachedMinimapNodes; private cachedDiagramBounds; /** * @internal * Pre-computed minimap node data in DIAGRAM coordinates (not minimap coordinates). * The SVG group transform handles the coordinate conversion, so nodes only recalculate * when diagram content changes, NOT during pan/zoom. * * When deferNodeUpdates is enabled, returns frozen data during interactions. * Angular's conditional signal tracking ensures renderer.nodes() is not subscribed * while deferring, avoiding per-frame recomputation entirely. */ protected minimapNodes: Signal; /** * @internal * Whether the diagram bounds outline should be shown on the minimap. * Diagram bounds are shown in virtualized mode to indicate the full diagram extent. */ protected showDiagramBounds: Signal; protected diagramBounds: Signal; private viewportBoundsInDiagramSpace; private combinedBounds; /** * Reads viewport stroke width from CSS to use as internal padding. * This prevents the viewport rectangle stroke from being clipped at minimap edges. */ private getStrokePaddingFromCss; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Directive that enables drag navigation on the minimap. * Users can drag on the minimap to move the diagram viewport. * * Supports both mouse and touch input. * Uses pointer capture for reliable touch tracking on mobile devices. * * @public * @since 1.0.0 * @category Directives */ export declare class NgDiagramMinimapNavigationDirective implements OnDestroy { private readonly viewportService; private readonly flowCoreProvider; transform: InputSignal; viewport: InputSignal; private dragState; ngOnDestroy(): void; onPointerDown(event: PointerEvent): void; private onPointerMove; private onPointerUp; private capturePointer; private releasePointer; private attachDocumentListeners; private removeDocumentListeners; private setPanningState; private calculateClientDelta; private calculateViewportDelta; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Interface for custom minimap node components. * Components implementing this interface can be registered in NgDiagramMinimapNodeTemplateMap * to customize how specific node types are rendered in the minimap. * * Custom templates are rendered inside a foreignObject that handles positioning and sizing, * so the component only needs to render content that fills its container. * * @public * @since 1.0.0 * @category Types/Minimap * * @example * ```typescript * @Component({ * selector: 'my-minimap-node', * standalone: true, * template: ` *
* {{ node().type }} *
* `, * styles: [`.minimap-icon { width: 100%; height: 100%; }`] * }) * export class MyMinimapNodeComponent implements NgDiagramMinimapNodeTemplate { * node = input.required(); * nodeStyle = input(); // Required by interface, can be ignored if not needed * } * ``` */ export declare interface NgDiagramMinimapNodeTemplate { /** Input signal containing the original Node object for accessing node data, type, etc. */ node: InputSignal; /** Input signal for style overrides computed by nodeStyle callback. Can be ignored if not needed. */ nodeStyle: InputSignal; } /** * Map that associates node type names with their corresponding minimap Angular component classes. * Used by ng-diagram-minimap to determine which custom component to render based on node type. * * @public * @since 1.0.0 * @category Types/Minimap * * @example * ```typescript * const minimapTemplateMap = new NgDiagramMinimapNodeTemplateMap([ * ['database', DatabaseMinimapNodeComponent], * ['api', ApiMinimapNodeComponent], * ]); * * // Usage in template: * * ``` */ export declare class NgDiagramMinimapNodeTemplateMap extends Map> { } /** * The `NgDiagramModelService` provides methods for accessing and manipulating the diagram's model. * * ## Example usage * ```typescript * private modelService = inject(NgDiagramModelService); * * // Add nodes * this.modelService.addNodes([node1, node2]); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramModelService extends NgDiagramBaseService implements OnDestroy { private readonly diagramService; private _nodes; private _edges; private _metadata; /** * Readonly signal of current nodes in the diagram. */ readonly nodes: Signal; /** * Readonly signal of current edges in the diagram. */ readonly edges: Signal[]>; /** * Readonly signal of current diagram metadata. */ readonly metadata: Signal>; constructor(); /** * Unregisters the model listener to support custom model adapters * that may outlive this service (e.g., singleton or shared adapters). * @internal */ ngOnDestroy(): void; /** * Returns the current model that NgDiagram instance is using. * Returns null if flowCore is not initialized. */ getModel(): ModelAdapter; /** * Serializes the current model to a JSON string. * @returns The model as a JSON string. */ toJSON(): string; /** * Adds new edges to the diagram. * @param edges Array of edges to add. */ addEdges(edges: Edge[]): void; /** * Adds new nodes to the diagram. * @param nodes Array of nodes to add. */ addNodes(nodes: Node_2[]): void; /** * Gets an edge by id. * @typeParam T - The type of the edge's `data` property. Defaults to `DataObject`. * @param edgeId Edge id. * @returns Edge or null if not found. */ getEdgeById(edgeId: string): Edge | null; /** * Gets the nearest node in a range from a point. * @typeParam T - The type of the node's `data` property. Defaults to `DataObject`. * @param point Point to check from. * @param range Range to check in. * @returns Nearest node in range or null. */ getNearestNodeInRange(point: Point, range: number): Node_2 | null; /** * Gets the nearest port in a range from a point. * @param point Point to check from. * @param range Range to check in. * @returns Nearest port in range or null. */ getNearestPortInRange(point: Point, range: number): Port | null; /** * Gets a node by id. * @typeParam T - The type of the node's `data` property. Defaults to `DataObject`. * @param nodeId Node id. * @returns Node or null if not found. */ getNodeById(nodeId: string): Node_2 | null; /** * Gets all nodes in a range from a point. * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param point Point to check from. * @param range Range to check in. * @returns Array of nodes in range. */ getNodesInRange(point: Point, range: number): Node_2[]; /** * Gets all edges connected to a node * @typeParam T - The type of the edges' `data` property. Defaults to `DataObject`. * @param nodeId Node id * @returns Array of edges where the node is either source or target */ getConnectedEdges(nodeId: string): Edge[]; /** * Gets all nodes connected to a node via edges * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param nodeId Node id * @returns Array of nodes connected to the given node */ getConnectedNodes(nodeId: string): Node_2[]; /** * Gets the source and target nodes of an edge * @typeParam S - The type of the source node's `data` property. Defaults to `DataObject`. * @typeParam T - The type of the target node's `data` property. Defaults to `DataObject`. * @param edgeId Edge id * @returns Object containing source and target nodes, or null if edge doesn't exist */ getNodeEnds(edgeId: string): { source: Node_2; target: Node_2; } | null; /** * Gets all children nodes for a given group node id * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param groupId group node id * @returns Array of child nodes */ getChildren(groupId: string): Node_2[]; /** * Gets all nested children (descendants) of a group node * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param groupId Group node id * @returns Array of all descendant nodes (children, grandchildren, etc.) */ getChildrenNested(groupId: string): Node_2[]; /** * Checks if a node is a nested child (descendant) of a group node * @param nodeId Node id * @param groupId Group node id * @returns True if the node is part of the group's nested subgraph */ isNestedChild(nodeId: string, groupId: string): boolean; /** * Gets the full chain of parent group Nodes for a given nodeId. * @typeParam T - The type of the group nodes' `data` property. Defaults to `DataObject`. * @param nodeId Node id * @returns Array of parent group Node objects, from closest parent to farthest ancestor */ getParentHierarchy(nodeId: string): GroupNode[]; /** * Detects collision with other nodes by finding all nodes whose rectangles intersect * with the specified node's bounding rectangle. * * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param nodeId - The ID of the node to check for collisions * @returns An array of Nodes that overlap with the specified node */ getOverlappingNodes(nodeId: string): Node_2[]; /** * @since 0.9.0 * * Detects collision with other nodes by finding all nodes whose rectangles intersect * with the specified node's bounding rectangle. * * @typeParam T - The type of the nodes' `data` property. Defaults to `DataObject`. * @param node - The node to check for collisions * @returns An array of Nodes that overlap with the specified node */ getOverlappingNodes(node: Node_2): Node_2[]; /** * @since 0.9.0 * * Computes the axis-aligned bounding rectangle that contains all specified nodes and edges. * @param nodes Array of nodes * @param edges Array of edges * @returns Bounding rectangle containing all nodes and edges */ computePartsBounds(nodes: Node_2[], edges: Edge[]): Rect; /** * Updates the properties of an edge. * @param edgeId Edge id. * @param edge New edge properties. */ updateEdge(edgeId: string, edge: Partial): void; /** * Updates the data of an edge. * @typeParam T - The type of the edge's `data` property. Defaults to `DataObject`. * @param edgeId Edge id. * @param data New data to set for the edge. */ updateEdgeData(edgeId: string, data: T): void; /** * Updates the properties of a node. * @param nodeId Node id. * @param node New node properties. */ updateNode(nodeId: string, node: Partial): void; /** * Updates the data of a node. * @typeParam T - The type of the node's `data` property. Defaults to `DataObject`. * @param nodeId Node id. * @param data New data to set for the node. */ updateNodeData(nodeId: string, data: T): void; /** * Updates multiple nodes at once. * @param nodes Array of node updates (must include id and any properties to update). */ updateNodes(nodes: (Pick & Partial)[]): void; /** * Updates multiple edges at once. * @param edges Array of edge updates (must include id and any properties to update). */ updateEdges(edges: (Pick & Partial)[]): void; /** * Deletes edges by their IDs. * @param ids Array of edge IDs to delete. */ deleteEdges(ids: string[]): void; /** * Deletes nodes by their IDs. * @param ids Array of node IDs to delete. */ deleteNodes(ids: string[]): void; private modelListener; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } declare class NgDiagramNodeComponent { private readonly portsService; private readonly flowCore; node: InputSignal; readonly rotate: Signal; readonly id: Signal; readonly size: Signal; constructor(); private syncPorts; private setupPortSyncEffect; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramNodeResizeAdornmentComponent` displays resize handles and lines around a selected, resizable node. * * ## Example usage * ```html * * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramNodeResizeAdornmentComponent extends NodeContextGuardBase { private readonly diagramService; /** * Whether the node is resizable. * * @default undefined */ defaultResizable: InputSignal; readonly nodeData: Signal; readonly dataResizable: Signal; readonly isResizable: Signal; readonly showAdornment: Signal; readonly linePositions: LinePosition[]; readonly handlePositions: HandlePosition[]; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramNodeRotateAdornmentComponent` displays a rotation handle for a selected, rotatable node. * * ## Example usage * ```html * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramNodeRotateAdornmentComponent extends NodeContextGuardBase { private readonly diagramService; /** * Whether the node is rotatable. * * @default undefined */ defaultRotatable: InputSignal; readonly dataRotatable: Signal; readonly isRotating: WritableSignal; readonly nodeData: Signal; readonly isRotatable: Signal; readonly eventTarget: Signal< { type: "rotate-handle"; element: Node_2 | undefined; }>; readonly showAdornment: Signal; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramNodeSelectedDirective` conditionally applies a selected class to a node in the diagram when it is selected. * * ## Example usage * ```html *
* *
* ``` * * When the node's {@link SimpleNode#selected} property is `true`, the `ng-diagram-node-selected` CSS class is applied. * * @public * @since 0.8.0 * @category Directives */ export declare class NgDiagramNodeSelectedDirective { /** * The node instance to monitor for selection state. */ node: InputSignal; protected readonly selected: Signal; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * The `NgDiagramNodeService` provides methods for manipulating nodes in the diagram. * * ## Example usage * ```typescript * private nodeService = inject(NgDiagramNodeService); * * // Move nodes by a delta * this.nodeService.moveNodesBy([node1, node2], { x: 10, y: 20 }); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramNodeService extends NgDiagramBaseService { /** * Moves nodes by the specified amounts. * @param nodes Array of nodes to move. * @param delta The amount to move the nodes by. */ moveNodesBy(nodes: Node_2[], delta: Point): void; /** * Resizes a node to the specified dimensions. * `Node.autoSize` must be set to false to resize a node. * @param id The ID of the node to resize. * @param size The new size of the node. * @param position Optional new position of the node. * @param disableAutoSize Optional flag to disable auto-sizing. */ resizeNode(id: string, size: Size, position?: Point, disableAutoSize?: boolean): void; /** * Rotates a node to the specified angle. * @param nodeId The ID of the node to rotate. * @param angle The rotation angle in degrees. */ rotateNodeTo(nodeId: string, angle: number): void; /** * Brings the specified nodes and edges to the front (highest z-index). * @param nodeIds Array of node IDs to bring to front. * @param edgeIds Array of edge IDs to bring to front. */ bringToFront(nodeIds?: string[], edgeIds?: string[]): void; /** * Sends the specified nodes and edges to the back (lowest z-index). * @param nodeIds Array of node IDs to send to back. * @param edgeIds Array of edge IDs to send to back. */ sendToBack(nodeIds?: string[], edgeIds?: string[]): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * Interface for custom node components. * * @public * @since 0.8.0 * @template Data - The type of data associated with the node * @template NodeType - The type of node (SimpleNode or GroupNode) * @category Types/Templates */ export declare interface NgDiagramNodeTemplate = SimpleNode> { /** Input signal containing the node data and properties. */ node: InputSignal; } /** * Map that associates node type names with their corresponding Angular component classes. * Used by ng-diagram to determine which custom node component to render based on node type. * * @public * @since 0.8.0 * @category Types/Templates */ export declare class NgDiagramNodeTemplateMap extends Map> | Type>> { } /** * The {@link NgDiagramPaletteItem} represents the data structure for items that can be shown in the diagram palette * and dragged onto the canvas to create nodes or groups. * It supports both simple nodes and group nodes, allowing you to specify * properties such as type, data, size, rotation, and grouping. * * Example usage: * ```typescript * const paletteItem: NgDiagramPaletteItem = { * type: 'customNode', * data: { label: 'My Node' }, * resizable: true, * rotatable: false, * }; * ``` * * @public * @since 0.8.0 * @category Types/Palette */ export declare type NgDiagramPaletteItem = SimpleNodeData | GroupNodeData; /** * The `NgDiagramPaletteItemComponent` represents a single item in the diagram palette. * * ## Example usage * ```html * * * * * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramPaletteItemComponent { private paletteService; private paletteItemPreviewComponent; /** * The palette item data to be rendered and managed. */ item: InputSignal; /** @internal */ onDragStart(event: DragEvent): void; /** @internal */ onMouseDown(): void; /** @internal */ onTouchStart(event: TouchEvent): void; /** * Clones the preview element and appends it to document.body so that setDragImage * is immune to ancestor overflow:hidden clipping. The clone is removed on the next frame. */ private setDragPreviewImage; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramPaletteItemPreviewComponent` is responsible for rendering a live preview of a palette item * when it is being dragged or hovered in the palette. * * ## Example usage * ```html * * * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramPaletteItemPreviewComponent { private paletteService; private environment; private browser; readonly id: string; readonly preview: Signal | undefined>; protected readonly scale: Signal; protected readonly isSafari: boolean; protected readonly isChrome: boolean; protected readonly isVisible: Signal; get scaleTransform(): string; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * Position for diagram overlay panels (minimap, watermark, etc.). * * @public * @since 1.0.0 * @category Types */ export declare type NgDiagramPanelPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; /** * The `NgDiagramPortComponent` represents a single port on a node within the diagram. * * ## Example usage * ```html * * ``` * * @public * @since 0.8.0 * @category Components */ export declare class NgDiagramPortComponent extends NodeContextGuardBase implements OnInit, OnDestroy, AfterContentInit { private readonly hostElement; private readonly flowCoreProvider; private readonly batchResizeObserver; private readonly linkingInputDirective; protected readonly isInitialized: WritableSignal; protected readonly lastSide: WritableSignal; protected readonly lastType: WritableSignal<"source" | "target" | "both" | undefined>; private lastOriginPoint; private ownerInternalId; protected readonly nodeData: Signal; /** * The unique identifier for the port. */ id: InputSignal; /** * The type of the port (e.g., source, target, both). */ type: InputSignal<"source" | "target" | "both">; /** * The side of the node where the port is rendered (e.g., top, right, bottom, left). */ side: InputSignal; /** * The origin point for the port (e.g., topLeft, center, bottomRight). * This value determines the transform origin of the port for precise positioning. * By default, it is set to 'center'. */ originPoint: InputSignal; get portClass(): string; constructor(); /** @internal */ ngOnInit(): void; /** @internal */ ngOnDestroy(): void; private readonly custom; protected hasContent: boolean; /** @internal */ ngAfterContentInit(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } /** * The `NgDiagramSelectionService` provides methods for managing the selection state of nodes and edges in the diagram. * * ## Example usage * ```typescript * private selectionService = inject(NgDiagramSelectionService); * * // Select nodes and edges * this.selectionService.select(['nodeId1'], ['edgeId1']); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramSelectionService extends NgDiagramBaseService { private readonly modelService; /** * Returns a computed signal for the current selection of nodes and edges. */ selection: Signal< { nodes: Node_2[]; edges: Edge[]; }>; /** * Selects nodes and edges by their IDs. * @param nodeIds Array of node IDs to select. * @param edgeIds Array of edge IDs to select. */ select(nodeIds?: string[], edgeIds?: string[]): void; /** * Deselects nodes and edges by their IDs. * @param nodeIds Array of node IDs to deselect. * @param edgeIds Array of edge IDs to deselect. */ deselect(nodeIds?: string[], edgeIds?: string[]): void; /** * Deselects all currently selected nodes and edges. */ deselectAll(): void; /** * Deletes the current selection of nodes and edges. */ deleteSelection(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } /** * The `NgDiagramService` provides advanced access to the diagram's core API, * including configuration, layout, event management, routing, transactions, and more. * * ## Example usage * ```typescript * private ngDiagramService = inject(NgDiagramService); * * // Check if diagram is initialized (reactive signal) * effect(() => { * if (this.ngDiagramService.isInitialized()) { * console.log('Diagram ready!'); * } * }); * * // Access reactive config * const isDebugMode = this.ngDiagramService.config().debugMode; * * // Update configuration * this.ngDiagramService.updateConfig({ debugMode: true }); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramService extends NgDiagramBaseService { private readonly manualLinkingService; private readonly batchResizeObserver; private readonly renderer; /** * Returns whether the diagram is fully initialized and all elements are measured. * This signal is set to `true` when the `diagramInit` event fires. */ isInitialized: Signal; private config$; /** * Reactive signal that tracks the current configuration (readonly). * To update the configuration, use {@link updateConfig}. */ readonly config: Signal>>; private actionState$; /** * Reactive signal that tracks the current action state (readonly). * This signal is managed internally by the diagram and updates automatically * when actions like resizing, rotating, or linking start/end. * * @readonly - This property cannot be modified directly. */ readonly actionState: Signal>; constructor(); /** * Updates the current configuration. * @param config Partial configuration object containing properties to update. * @example * // Enable debug mode * this.ngDiagramService.updateConfig({ debugMode: true }); */ updateConfig(config: Partial): void; /** * Gets the current environment information. * @returns The environment info object. */ getEnvironment(): EnvironmentInfo; /** * Registers a new middleware in the chain. * @param middleware Middleware to register. * @returns Function to unregister the middleware. */ registerMiddleware(middleware: Middleware): () => void; /** * Unregister a middleware from the chain. * @param name Name of the middleware to unregister. */ unregisterMiddleware(name: string): void; /** * Registers a custom routing implementation. * @param routing Routing implementation to register. * @example * const customRouting: Routing = { * name: 'custom', * computePoints: (source, target) => [...], * computeSvgPath: (points) => '...' * }; * ngDiagramService.registerRouting(customRouting); */ registerRouting(routing: EdgeRouting): void; /** * Unregisters a routing implementation. * @param name Name of the routing to unregister. */ unregisterRouting(name: string): void; /** * Gets all registered routing names. * @returns Array of registered routing names. */ getRegisteredRoutings(): string[]; /** * Sets the default routing to use when not specified on edges. * @param name Name of the routing to set as default. */ setDefaultRouting(name: string): void; /** * Gets the current default routing name. * @returns Name of the default routing. */ getDefaultRouting(): string; /** * Call this method to start linking from your custom logic. * @param node The node from which the linking starts. * @param portId The port ID from which the linking starts. Creates a floating edge when undefined. */ startLinking(node: Node_2, portId?: string): void; /** * Add an event listener for a diagram event. * @param event The event name. * @param callback The callback to invoke when the event is emitted. * @returns A function to unsubscribe. * @example * const unsubscribe = ngDiagramService.addEventListener('selectionChanged', (event) => { * console.log('Selection changed', event.selectedNodes); * }); */ addEventListener(event: K, callback: EventListener_2): UnsubscribeFn; /** * Add an event listener that will only fire once. * @param event The event name. * @param callback The callback to invoke when the event is emitted. * @returns A function to unsubscribe. * @example * ngDiagramService.addEventListenerOnce('diagramInit', (event) => { * console.log('Diagram initialized', event); * }); */ addEventListenerOnce(event: K, callback: EventListener_2): UnsubscribeFn; /** * Remove an event listener. * @param event The event name. * @param callback Optional specific callback to remove. * @example * // Remove all listeners for an event * ngDiagramService.removeEventListener('selectionChanged'); * * // Remove a specific listener * ngDiagramService.removeEventListener('selectionChanged', myCallback); */ removeEventListener(event: K, callback?: EventListener_2): void; /** * Remove all event listeners. * @example * ngDiagramService.removeAllEventListeners(); */ removeAllEventListeners(): void; /** * Enable or disable event emissions. * @param enabled Whether events should be emitted. * @example * // Disable all events * ngDiagramService.setEventsEnabled(false); * * // Re-enable events * ngDiagramService.setEventsEnabled(true); */ setEventsEnabled(enabled: boolean): void; /** * Check if event emissions are enabled. * @returns True if events are enabled. */ areEventsEnabled(): boolean; /** * Check if there are any listeners for an event. * @param event The event name. * @returns True if there are listeners. * @example * if (ngDiagramService.hasEventListeners('selectionChanged')) { * // There are listeners for selection changes * } */ hasEventListeners(event: keyof DiagramEventMap): boolean; /** * @since 0.9.0 * * Executes an async function within a transaction context. * All state updates within the callback are batched and applied atomically. * * @param callback The async function to execute within the transaction. * @returns A promise that resolves with the transaction result. * * @example * // Async transaction with data fetching * await this.ngDiagramService.transaction(async () => { * const nodes = await fetchNodesFromServer(); * this.ngDiagramModelService.addNodes(node); * }); */ transaction(callback: () => Promise): Promise; /** * @since 0.9.0 * * Executes an async function within a transaction context with options. * All state updates within the callback are batched and applied atomically. * * @param callback The async function to execute within the transaction. * @param options Transaction options. * @returns A promise that resolves with the transaction result. * * @example * // Async transaction that waits for measurements * await this.ngDiagramService.transaction(async () => { * const nodes = await fetchNodesFromServer(); * this.ngDiagramModelService.addNodes(nodes); * }, { waitForMeasurements: true }); */ transaction(callback: () => Promise, options: TransactionOptions): Promise; /** * Executes a function within a transaction context. * All state updates within the callback are batched and applied atomically. * * @param callback The function to execute within the transaction. * * @example * this.ngDiagramService.transaction(() => { * this.ngDiagramModelService.addNodes([node1, node2]); * this.ngDiagramModelService.addEdges([edge1]); * }); */ transaction(callback: () => void): void; /** * @since 0.9.0 * * Executes a function within a transaction context with options. * All state updates within the callback are batched and applied atomically. * * @param callback The function to execute within the transaction. * @param options Transaction options. * @returns A promise that resolves with the transaction result. * * @example * // Transaction that waits for measurements to complete * await this.ngDiagramService.transaction(() => { * this.ngDiagramModelService.addNodes([node1, node2]); * }, { waitForMeasurements: true }); */ transaction(callback: () => void, options: TransactionOptions): Promise; /** * Forces re-measurement of diagram elements via ResizeObserver. * * When called with no arguments, all nodes, ports, and edge labels are re-measured. * When called with specific options, only the targeted elements are re-measured. * Invalidating a node also re-measures all its ports. * * @param options Optional. Specifies which elements to re-measure. * * @example * // Re-measure the entire diagram * ngDiagramService.invalidateMeasurements(); * * // Re-measure specific nodes (including their ports) * ngDiagramService.invalidateMeasurements({ * nodes: [{ nodeId: 'node-1' }], * }); * * // Re-measure all labels on specific edges * ngDiagramService.invalidateMeasurements({ * edges: [{ edgeId: 'edge-1' }], * }); * * @since 1.2.3 */ invalidateMeasurements(options?: InvalidateMeasurementsOptions): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } export declare class NgDiagramServicesAvailabilityCheckerDirective { private readonly service; constructor(); static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * The `NgDiagramViewportService` provides methods and signals for interacting with the diagram viewport. * * ## Example usage * ```typescript * private viewportService = inject(NgDiagramViewportService); * * // Move viewport to (100, 200) * this.viewportService.moveViewport(100, 200); * * // Zoom in by a factor of 1.2 * this.viewportService.zoom(1.2); * ``` * * @public * @since 0.8.0 * @category Services */ export declare class NgDiagramViewportService extends NgDiagramBaseService { private readonly renderer; /** * Returns a computed signal for the viewport that safely handles uninitialized state. */ viewport: Signal; /** * Returns a computed signal for the scale that safely handles uninitialized state. */ scale: Signal; /** * Returns the minimum zoom scale from the diagram configuration. */ get minZoom(): number; /** * Returns the maximum zoom scale from the diagram configuration. */ get maxZoom(): number; /** * Returns true if the current zoom level is below the maximum and can be increased. */ canZoomIn: Signal; /** * Returns true if the current zoom level is above the minimum and can be decreased. */ canZoomOut: Signal; /** * Converts a client position to a flow position. * @param clientPosition Client position to convert. * @returns Flow position. */ clientToFlowPosition(clientPosition: Point): Point; /** * Converts a client position to a position relative to the flow viewport. * @param clientPosition Client position. * @returns Position on the flow viewport. */ clientToFlowViewportPosition(clientPosition: Point): Point; /** * Converts a flow position to a client position. * @param flowPosition Flow position to convert. * @returns Client position. */ flowToClientPosition(flowPosition: Point): Point; /** * Moves the viewport to the specified coordinates. * @param x The x-coordinate to move the viewport to. * @param y The y-coordinate to move the viewport to. */ moveViewport(x: number, y: number): void; /** * Moves the viewport by the specified amounts. * @param dx The amount to move the viewport in the x-direction. * @param dy The amount to move the viewport in the y-direction. */ moveViewportBy(dx: number, dy: number): void; /** * Sets the viewport to an absolute position and scale. * * @example * ```typescript * // Reset to origin at 50% zoom * this.viewportService.setViewport(0, 0, 0.5); * ``` * * @param x The absolute x-coordinate for the viewport. * @param y The absolute y-coordinate for the viewport. * @param scale The absolute zoom scale (clamped to configured min/max). * * @since 1.2.0 */ setViewport(x: number, y: number, scale: number): void; /** * Zooms the viewport by the specified factor. * @param factor The factor to zoom by (e.g., 1.1 for 10% zoom in, 0.9 for 10% zoom out). * @param center The center point to zoom towards. */ zoom(factor: number, center?: Point | undefined): void; /** * Automatically adjusts the viewport to fit all diagram content (or a specified subset) within the visible area. * * @remarks * When calling `zoomToFit()` immediately after adding or modifying nodes/edges, their dimensions may not be measured yet. * Use the `waitForMeasurements` transaction option to ensure accurate results: * ```typescript * await this.ngDiagramService.transaction(() => { * this.modelService.addNodes([newNode]); * }, { waitForMeasurements: true }); * this.viewportService.zoomToFit(); // Now includes new node dimensions * ``` * * @param options Optional configuration object * @param options.nodeIds Array of node IDs to fit. If not provided, all nodes are included. * @param options.edgeIds Array of edge IDs to fit. If not provided, all edges are included. * @param options.padding Padding around the content (default: 50). Supports CSS-like syntax: * - Single number: uniform padding on all sides * - [top/bottom, left/right]: vertical and horizontal padding * - [top, left/right, bottom]: top, horizontal, bottom padding * - [top, right, bottom, left]: individual padding for each side * * @example * ```typescript * // Fit all nodes and edges with default padding * this.viewportService.zoomToFit(); * * // Fit with custom uniform padding * this.viewportService.zoomToFit({ padding: 100 }); * * // Fit with different padding on each side [top, right, bottom, left] * this.viewportService.zoomToFit({ padding: [50, 100, 50, 100] }); * * // Fit only specific nodes * this.viewportService.zoomToFit({ nodeIds: ['node1', 'node2'] }); * * // Custom zoomToFit with anchor positioning using setViewport * // anchor: (0,0) = top-left, (0.5,0.5) = center, (1,1) = bottom-right * const anchor = { x: 0.5, y: 0.5 }; * const { width, height } = this.modelService.metadata().viewport; * const bounds = this.modelService.computePartsBounds(nodes, edges); * const scale = Math.min(width / bounds.width, height / bounds.height); * const x = width * anchor.x - (bounds.x + bounds.width * anchor.x) * scale; * const y = height * anchor.y - (bounds.y + bounds.height * anchor.y) * scale; * this.viewportService.setViewport(x, y, scale); * ``` */ zoomToFit(options?: { nodeIds?: string[]; edgeIds?: string[]; padding?: number | [number, number] | [number, number, number] | [number, number, number, number]; }): void; /** * Centers the Node within the current viewport bounds. * * @remarks * When calling `centerOnNode()` immediately after adding or modifying a node, its dimensions may not be measured yet. * Use the `waitForMeasurements` transaction option to ensure accurate centering: * ```typescript * await this.ngDiagramService.transaction(() => { * this.modelService.addNodes([newNode]); * }, { waitForMeasurements: true }); * this.viewportService.centerOnNode(newNode.id); // Now centers correctly * ``` * * @param nodeOrId The ID of the node or the node object to center on. */ centerOnNode(nodeOrId: string | Node_2): void; /** * Centers the rectangle within the current viewport bounds. * @param rect The rectangle to center on. */ centerOnRect(rect: Rect): void; } /** * Interface representing all possible node types in the diagram * * @public * @since 0.8.0 * @category Types/Model */ declare type Node_2 = SimpleNode | GroupNode; export { Node_2 as Node } /** * Base class that provides node component context guarding functionality. * Components can extend this class to prevent rendering when they're outside the node component context. */ declare abstract class NodeContextGuardBase { protected nodeComponent: NgDiagramNodeComponent | null; /** * Computed signal that indicates whether the component is rendered within the node component context. * Returns true when the node component is available. */ protected readonly isRenderedOnCanvas: Signal; } /** * Event payload emitted when a node drag operation ends. * * This event fires when the user releases the pointer after dragging nodes. * Nodes will have their final positions when this event is received. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeDragEndedEvent { /** Nodes that were dragged, with their final positions */ nodes: Node_2[]; } /** * Event payload emitted when a node drag operation begins. * * This event fires once when the drag threshold is crossed, signaling the * start of a drag operation. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeDragStartedEvent { /** Nodes being dragged */ nodes: Node_2[]; } export declare class NodePositionDirective { node: InputSignal; position: Signal; get transform(): string; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Event payload emitted when a node or group size changes. * * This event fires when a node is resized manually by dragging resize handles * or programmatically using resize methods. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface NodeResizedEvent { /** Node that was resized with its updated size */ node: Node_2; /** Previous size of the node before the change */ previousSize: Size; } /** * Event payload emitted when a node resize operation ends. * * This event fires when the user releases the pointer after resizing a node. * The node will have its final size when this event is received. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeResizeEndedEvent { /** The node that was resized, with its final size */ node: Node_2; } /** * Event payload emitted when a node resize operation begins. * * This event fires once when the user starts resizing a node by dragging * a resize handle. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeResizeStartedEvent { /** The node being resized */ node: Node_2; } /** * Event payload emitted when a node rotation operation ends. * * This event fires when the user releases the pointer after rotating a node. * The node will have its final angle when this event is received. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeRotateEndedEvent { /** The node that was rotated, with its final angle */ node: Node_2; } /** * Event payload emitted when a node rotation operation begins. * * This event fires once when the user starts rotating a node by dragging * the rotation handle. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface NodeRotateStartedEvent { /** The node being rotated */ node: Node_2; } /** * Configuration for node rotation behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface NodeRotationConfig { /** * Determines if rotation snapping should be enabled for a node. * @param node The node to check for rotation snapping. * @returns True if rotation should snap, false otherwise. * @default () => false */ shouldSnapForNode: (node: Node_2) => boolean; /** * Computes the snap angle for a node's rotation. * @param node The node to compute the snap angle for. * @returns The angle in degrees to snap to, or null if default snapping should be used. * @default () => null */ computeSnapAngleForNode: (node: Node_2) => number | null; /** * The default snap angle in degrees. Used if computeSnapAngleForNode returns null. * @default 30 */ defaultSnapAngle: number; /** * The default rotatable state for nodes. * @default true */ defaultRotatable: boolean; } export declare class NodeSelectionDirective extends ObjectSelectionDirective { targetType: BasePointerInputEvent['targetType']; readonly targetData: InputSignal | Node_2 | undefined>; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Directive that manages node sizing behavior in the diagram. * * Handles two sizing modes: * 1. **Auto-size mode** (default): Node size adapts to content with configurable defaults * 2. **Explicit size mode**: Node has fixed dimensions * * Size configuration priority: * 1. Explicit size from node data (when autoSize=false) * 2. Built-in defaults for default node types (no type specified) * 3. User's CSS (for custom node types) * @internal */ export declare class NodeSizeDirective implements OnDestroy, OnInit { private readonly hostElement; private readonly renderer; private readonly batchResizeObserver; private readonly flowCoreProvider; node: InputSignal; size: Signal; autoSize: Signal; id: Signal; sizeState: Signal< { size: Size | undefined; autoSize: boolean; }>; constructor(); ngOnInit(): void; ngOnDestroy(): void; /** * Main entry point for setting node size. * Determines whether to apply explicit sizing or auto-sizing based on provided dimensions. * * @param width - Explicit width in pixels * @param height - Explicit height in pixels */ private setSize; /** * Applies explicit dimensions to the node. * Also sets minimum size constraints based on configuration or defaults. * * @param width - Explicit width in pixels * @param height - Explicit height in pixels * @param node - The node to size */ private applyExplicitSize; /** * Applies auto-sizing to the node based on built-in defaults. * For custom nodes, resets inline styles to let CSS take control. * * @param node - The node to size */ private applyAutoSize; /** * Applies sizing for default group nodes. * Default groups get both explicit dimensions and minimum constraints to ensure * their bounds are visually apparent even when empty. * * @param size - The size to apply */ private applyDefaultGroupSize; /** * Applies sizing for default nodes. * Default nodes use flexible sizing with minimum constraints, * allowing content to expand beyond the minimum if needed. * * @param size - The minimum size to apply */ private applyDefaultNodeSize; /** * Resets explicit width/height styles to allow content-based sizing. * Used for custom node types without configuration. */ private resetExplicitSizes; /** * Connects the resize observer to track node size changes. * This allows the diagram to update port positions and other * size-dependent features when nodes resize. */ private connectResizeObserver; private disconnectResizeObserver; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Normalized keyboard input for shortcut matching * Contains the key and already-normalized modifiers */ declare interface NormalizedKeyboardInput { key?: string; modifiers: InputModifiers; } declare abstract class ObjectSelectionDirective implements OnDestroy { private readonly inputEventsRouter; private readonly flowCoreProvider; targetData: InputSignal | Node_2 | undefined>; abstract targetType: BasePointerInputEvent['targetType']; ngOnDestroy(): void; onPointerDown(event: PointerInputEvent): void; onPointerUp: (event: PointerEvent) => void; private shouldHandle; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * The origin point options for port placement. * @category Types/Model */ export declare type OriginPoint = 'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' | 'center' | 'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight'; export declare class PaletteDropDirective implements OnInit, OnDestroy { private readonly inputEventsRouterService; private readonly paletteService; private readonly el; private touchMoveListener; private touchEndListener; ngOnInit(): void; ngOnDestroy(): void; onDrop(event: DragEvent): void; onDragOver(event: DragEvent): void; private onGlobalTouchMove; private onGlobalTouchEnd; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface PaletteDropNodeCommand { name: 'paletteDropNode'; node: Node_2; } /** * Event payload emitted when a palette item is dropped onto the diagram. * * This event fires when users drag items from the palette and drop them * onto the canvas to create new nodes. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface PaletteItemDroppedEvent { /** The node that was created from the dropped palette item */ node: Node_2; /** The position where the item was dropped */ dropPosition: Point; } /** * State tracking a panning operation in progress. * * @public * @since 1.1.2 * @category Internals */ export declare interface PanningActionState { /** Whether panning is currently active. */ active: boolean; } export declare class PanningDirective implements OnDestroy { private readonly inputEventsRouter; private readonly elementRef; private readonly diagramService; private readonly flowCoreProvider; ngOnDestroy(): void; onPointerDown(event: PointerInputEvent): void; onPointerUp: (event: PointerEvent) => void; onWheel(event: WheelInputEvent): void; private onMouseMove; private finishPanning; private shouldHandle; private shouldHandleWheel; private toggleGrabbingCursor; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface PasteCommand { name: 'paste'; position?: Point; } /** * Interface representing a point in the flow diagram * * @public * @since 0.8.0 * @category Types/Geometry */ export declare interface Point { /** * X coordinate of the point */ x: number; /** * Y coordinate of the point */ y: number; } /** * Defines custom event types used throughout the ngDiagram library for handling user input. * * The main type, `PointerInputEvent`, extends the native `PointerEvent` with additional flags * that indicate whether specific diagram interactions (such as selection, zooming, linking, rotation) * have already been handled. These flags are used by input event directives and handlers * to coordinate and prevent duplicate processing of the same pointer event. * * This type is used as the event parameter in input event handlers and services * across the public API and internal logic. * * Example usage: * ```ts * onPointerDown(event: PointerInputEvent) { * if (!event.linkingHandled) { * // handle linking logic * event.linkingHandled = true; * } * } * ``` */ declare interface PointerInputEvent extends PointerEvent { moveSelectionHandled?: boolean; zoomingHandled?: boolean; linkingHandled?: boolean; rotateHandled?: boolean; selectHandled?: boolean; boxSelectionHandled?: boolean; } declare class PointerMoveSelectionDirective implements OnDestroy { private readonly inputEventsRouter; private readonly diagramComponent; private readonly flowCoreProvider; private readonly touchEventsStateService; targetData: InputSignal; private edgePanningInterval; private cachedDiagramRect; ngOnDestroy(): void; onPointerDown(event: PointerInputEvent): void; onPointerUp: (event: PointerEvent) => void; private onPointerMove; private finishDragging; private shouldHandle; private startEdgePanning; private stopEdgePanning; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Pointer-only action names that can only be triggered by pointer events with modifiers * (e.g., Shift+Click, Ctrl+Click) * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type PointerOnlyActionName = 'multiSelection' | 'boxSelection'; /** * Pointer-only shortcut definition with modifier-only bindings * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare interface PointerOnlyShortcutDefinition { /** Action name for pointer events */ actionName: PointerOnlyActionName; /** Modifier-only bindings (keys are not allowed) */ bindings: ModifierOnlyShortcutBinding[]; } /** * Interface representing a port in the node. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface Port { /** * The unique identifier for the port. */ id: string; /** * The position of the port in the node. */ position?: Point; /** * The size of the port. */ size?: Size; /** * The type of the port. */ type: 'source' | 'target' | 'both'; /** * The id of the node that the port belongs to. */ nodeId: string; /** * The side of the node that the port is on. */ side: PortSide; } declare class PortBatchProcessor extends BatchProcessor { constructor(getNodeById: (nodeId: string) => Node_2 | null | undefined); } /** * Interface representing the location of a port on a node * * @public * @since 0.8.0 * @category Types/Model */ export declare type PortLocation = { side: PortSide; } & Point; /** * Interface representing a port side on a node in the diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare type PortSide = 'top' | 'right' | 'bottom' | 'left'; declare interface PortUpdate { portId: string; portChanges: Partial; } /** * Provides all the services required for ng-diagram to function. * * @returns Array of providers for all ng-diagram services * * @example * ```typescript * @Component({ * imports: [NgDiagramComponent], * providers: [provideNgDiagram()], * template: `` * }) * export class Diagram { * model = initializeModel({ * nodes: [ * { * id: '1', * position: { x: 0, y: 0 }, * data: { label: 'Node 1' } * } * ] * }); * } * ``` * * @public * @since 0.8.0 * @category Utilities */ export declare function provideNgDiagram(): Provider[]; /** * Interface representing a rect in the flow diagram * * @public * @since 0.8.0 * @category Types/Geometry */ export declare interface Rect { /** * X coordinate of the rect's top-left corner */ x: number; /** * Y coordinate of the rect's top-left corner */ y: number; /** * Width dimension */ width: number; /** * Height dimension */ height: number; } declare interface RectWithId extends Rect { id: string; } declare interface RemoveFromGroupCommand { name: 'removeFromGroup'; groupId: GroupNode['id']; nodeIds: Node_2['id'][]; } /** * Interface for the Renderer that handles drawing the flow diagram */ declare interface Renderer { /** * Draws the current state of the flow diagram * @param nodes List of nodes to render * @param edges List of edges to render * @param viewport Viewport to render */ draw(nodes: Node_2[], edges: Edge[], viewport: Viewport): void; } declare interface RenderStrategy { /** * Initializes the strategy. Sets up model change handlers and starts the init process. */ init(): void; process(nodes: Node_2[], edges: Edge[], viewport: Viewport | undefined): RenderStrategyResult; /** * Checks if a node is currently rendered (visible in viewport). * In direct mode, always returns true. In virtualized mode, checks the cached visible nodes. */ isNodeRendered(nodeId: string): boolean; } declare interface RenderStrategyResult { nodes: Node_2[]; edges: Edge[]; nodeIds: Set; edgeIds: Set; } /** * State tracking a node resize operation in progress. * * @public * @since 0.8.0 * @category Internals */ export declare interface ResizeActionState { /** Initial width of the node before resize. */ startWidth: number; /** Initial height of the node before resize. */ startHeight: number; /** Initial X coordinate in screen space where the resize started. */ startX: number; /** Initial Y coordinate in screen space where the resize started. */ startY: number; /** Initial X position of the node in diagram space. */ startNodePositionX: number; /** Initial Y position of the node in diagram space. */ startNodePositionY: number; /** Reference to the node being resized. */ resizingNode: Node_2; } /** * Configuration for node resizing behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface ResizeConfig { /** * Returns the minimum allowed size for a node. * @param node The node to compute the minimum size for. * @default () => ({ width: 20, height: 20 }) */ getMinNodeSize: (node: Node_2) => Size; /** * Allows resizing a group node smaller than its children bounds. * When set to false, a group node cannot be resized smaller than the bounding box of its children. * By default a group can be resized below children size. * @default true */ allowResizeBelowChildrenBounds: boolean; /** * The default resizable state for nodes. * @default true */ defaultResizable: boolean; } declare type ResizeDirection = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left' | 'right' | 'top' | 'bottom'; declare interface ResizeNodeCommand { name: 'resizeNode'; id: string; size: Required['size']; position?: Node_2['position']; disableAutoSize?: boolean; } declare interface ResizeNodeStartCommand { name: 'resizeNodeStart'; } declare interface ResizeNodeStopCommand { name: 'resizeNodeStop'; } declare interface RotateNodeStartCommand { name: 'rotateNodeStart'; } declare interface RotateNodeStopCommand { name: 'rotateNodeStop'; } declare interface RotateNodeToCommand { name: 'rotateNodeTo'; nodeId: string; angle: number; } /** * State tracking a node rotation operation in progress. * * @public * @since 0.8.0 * @category Internals */ export declare interface RotationActionState { /** Angle in degrees at the start of the rotation operation. */ startAngle: number; /** Initial angle of the node before rotation. */ initialNodeAngle: number; /** ID of the node being rotated. */ nodeId: string; } /** * Type representing edge routing mode * * @public * @since 0.8.0 * @category Types/Routing */ export declare type RoutingMode = 'manual' | 'auto'; declare interface SelectAllCommand { name: 'selectAll'; } declare interface SelectCommand { name: 'select'; nodeIds?: string[]; edgeIds?: string[]; multiSelection?: boolean; } declare interface SelectEndCommand { name: 'selectEnd'; } /** * State tracking whether a selection gesture has changed the selection. * * Set by selection commands when they apply changes, cleared when * the `selectionGestureEnded` event is emitted on `selectEnd`. * * @public * @since 1.1.2 * @category Internals */ export declare interface SelectionActionState { /** Whether selection has changed since the gesture started. */ selectionChanged: boolean; } /** * Event payload emitted when the selection state changes in the diagram. * * This event fires when the user selects or deselects nodes and edges through clicking * or programmatically using the {@link NgDiagramSelectionService}. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface SelectionChangedEvent { /** Currently selected nodes */ selectedNodes: Node_2[]; /** Currently selected edges */ selectedEdges: Edge[]; /** Previously selected nodes before the change */ previousNodes: Node_2[]; /** Previously selected edges before the change */ previousEdges: Edge[]; } /** * Event payload emitted when a selection gesture is complete. * * This event fires on pointerup after a selection operation completes — * whether from clicking a node/edge, box selection, or select-all. * * @public * @since 1.1.0 * @category Types/Events */ export declare interface SelectionGestureEndedEvent { /** Currently selected nodes after the selection gesture */ nodes: Node_2[]; /** Currently selected edges after the selection gesture */ edges: Edge[]; } /** * Event payload emitted when selected nodes are moved within the diagram. * * This event fires when the user moves nodes manually by dragging or programmatically * using the {@link NgDiagramNodeService.moveNodesBy} method. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface SelectionMovedEvent { /** Nodes that were moved with their updated positions */ nodes: Node_2[]; } /** * Configuration for selection moving behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface SelectionMovingConfig { /** * Enable edge panning when the moved node is near the edge of the viewport. * * @default true */ edgePanningEnabled: boolean; /** * Multiplier for edge panning speed while dragging nodes near the edge of the viewport. * * @default 10 */ edgePanningForce: number; /** * The threshold in pixels for edge panning to start. * If the mouse pointer is within this distance from the edge of the viewport, panning will be triggered. * * @default 30 */ edgePanningThreshold: number; } /** * Event payload emitted when selected elements are deleted from the diagram. * * This event fires when the user deletes nodes and edges using the delete key, * or programmatically through the diagram service. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface SelectionRemovedEvent { /** Nodes that were deleted from the diagram */ deletedNodes: Node_2[]; /** Edges that were deleted from the diagram */ deletedEdges: Edge[]; } /** * Event payload emitted when a node is rotated in the diagram. * * This event fires when the user rotates a node manually using the rotation handle * or programmatically using the {@link NgDiagramNodeService} rotation methods. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface SelectionRotatedEvent { /** The node that was rotated */ node: Node_2; /** The new angle of the node in degrees */ angle: number; /** The previous angle of the node in degrees */ previousAngle: number; } declare interface SendToBackCommand { name: 'sendToBack'; nodeIds?: string[]; edgeIds?: string[]; } /** * All valid action names for shortcuts * * Includes: * - Keyboard actions (e.g., 'keyboardMoveSelectionUp', 'copy', 'selectAll') * - Pointer-only actions (e.g., 'multiSelection', 'boxSelection') * - Wheel-only actions (e.g. 'zoom') * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type ShortcutActionName = KeyboardActionName | PointerOnlyActionName | WheelOnlyActionName; /** * Shortcut definition for registering keyboard and pointer shortcuts * * This is a discriminated union that enforces: * - Pointer-only actions (multiSelection, boxSelection) can only have modifier-only bindings * - Wheel-only actions (zoom) can only have modifier-only bindings * - Keyboard actions must have at least one key-based binding * * @public * @since 0.8.0 * @category Types/Configuration/Shortcuts */ export declare type ShortcutDefinition = KeyboardShortcutDefinition | PointerOnlyShortcutDefinition | WheelOnlyShortcutDefinition; /** * Manages keyboard shortcuts and input event matching * * Supports two types of shortcuts: * 1. Key-based shortcuts: Require a specific key with optional modifiers (e.g., Ctrl+C for copy) * 2. Modifier-only shortcuts: Require only modifier keys without a specific key (e.g., Alt for box-selection) * * @example * // Key-based shortcut * { * actionName: 'copy', * bindings: [{ key: 'c', modifiers: { primary: true } }] * } * * @example * // Modifier-only shortcut (useful for modal interactions like box-selection) * { * actionName: 'boxSelection', * bindings: [{ modifiers: { secondary: true } }] // Triggered when Alt is pressed * } */ declare class ShortcutManager { private readonly flowCore; constructor(flowCore: FlowCore); /** * Find all matching shortcuts for normalized keyboard input * * Each shortcut must have a binding that matches the input * * @param input - Normalized keyboard input (key + already-normalized modifiers) * @returns Array of matching shortcut definitions (empty if no matches) */ match(input: NormalizedKeyboardInput): ShortcutDefinition[]; /** * Check if the current modifiers match any binding for a specific action * * Useful for checking modifier-only shortcuts (like box-selection triggered by pointer events) * * @param actionName - The action name to check * @param modifiers - The current modifier state * @returns true if any binding for this action matches the modifiers * * @example * // Check if current modifiers match box selection shortcut * if (shortcutManager.matchesAction('boxSelection', { modifiers: event.modifiers })) { * // Start box selection * } */ matchesAction(actionName: LooseAutocomplete, input: NormalizedKeyboardInput): boolean; /** * Check if a normalized keyboard input matches a shortcut binding * * Compares: * - Key values (if specified in binding) - case-insensitive for single letters * - Modifier states * * Matching rules: * - If binding has a key: input must have the same key (case-insensitive for letters) * - If binding has no key (modifier-only): input must also have no key * (modifier-only shortcuts are for pointer events, not keyboard events) * * @param input - Normalized keyboard input * @param binding - Shortcut binding to match against * @returns true if the input matches the binding */ private matchBinding; /** * Check if modifiers match a binding's modifier requirements * * Ensures exact modifier matching: * - All modifiers specified in binding must match the input * - All modifiers NOT specified in binding must be false in the input * - Exception: meta modifier is ignored when checking if not explicitly specified in binding, * because on macOS, meta and primary both map to the Command key * * @param modifiers - Current modifier state * @param binding - Shortcut binding to match against * @returns true if modifiers match the binding's requirements exactly */ private matchModifiers; /** * Check if two keys match, using case-insensitive comparison for single letters * * This ensures shortcuts work regardless of CapsLock state. * Special keys like "Delete", "ArrowUp", etc. are compared as-is. * * @param inputKey - The key from the keyboard input * @param bindingKey - The key defined in the shortcut binding * @returns true if the keys match */ private keysMatch; } /** * Interface representing the most basic node in the diagram * * @public * @since 0.8.0 * @category Types/Model */ export declare interface SimpleNode { /** * The unique identifier for the node. */ id: string; /** * The position of the node in the diagram. */ position: Point; /** * The data associated with the node. */ data: T; /** * The type of the node declared in nodeTemplateMap. */ type?: string; /** * Whether the node is selected. */ selected?: boolean; /** * The size of the node. */ size?: Size; /** * Whether the size of the node is automatically resized based on the content. */ autoSize?: boolean; /** * The z-order of the node. Controls relative ordering among nodes on the same hierarchy level. * With proper values, it can also influence ordering across different hierarchy levels, * since each nesting level adds +1 to the computed z-index per child. * - Root nodes: used directly as the base z-index (negative values allowed). * - Grouped nodes: acts as a minimum floor — cannot go below the parent's z-index. * * Set by `bringToFront` / `sendToBack` commands, or manually. * @see {@link computedZIndex} for the final rendered z-index. */ zOrder?: number; /** * @readonly * @remarks ComputedZIndex is computed by the system and should not be set manually. * The final z-index applied to the DOM element for rendering order. * Computed from `zOrder`, group hierarchy, and selection elevation. * Children are always above their parent group. */ readonly computedZIndex?: number; /** * @readonly * @remarks MeasuredPorts are computed by the system and should not be set manually. * The ports of the node with computed position and size. */ readonly measuredPorts?: Port[]; /** * Whether the node is resizable. */ resizable?: boolean; /** * Whether the node is rotatable. */ rotatable?: boolean; /** * Whether the node is draggable. */ draggable?: boolean; /** * The angle of the node from 0 to 360. */ angle?: number; /** * The id of the parent node. */ groupId?: Node_2['id']; /** * @readonly * @remarks MeasuredBounds are computed by the system and should not be set manually. * Bounding box that encompasses the node including its ports, accounting for rotation. */ measuredBounds?: Rect; } /** * Data structure for node palette items. Contains the essential properties needed to create a fully configured node from the palette. * * @public * @since 0.8.0 * @category Types/Palette */ export declare type SimpleNodeData = Pick, 'type' | 'data' | 'resizable' | 'rotatable' | 'size' | 'angle' | 'autoSize' | 'zOrder'>; /** * Interface representing size in the flow diagram * * @public * @since 0.8.0 * @category Types/Geometry */ export declare interface Size { /** * Width dimension */ width: number; /** * Height dimension */ height: number; } /** * Applies snapping and step logic to a rotation angle. * @param angle The raw angle after initial transformation (can be positive or negative, in degrees) * @param step The snapping step (e.g., 5 for 5-degree increments) * @returns The snapped angle (in degrees) */ declare function snapAngle(angle: number, step: number): number; /** * Configuration for node dragging behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface SnappingConfig { /** * Determines if a node should snap to grid while dragging. * @param node The node being dragged. * @returns True if the node should snap to grid, false otherwise. * @default () => false */ shouldSnapDragForNode: (node: Node_2) => boolean; /** * Determines if a node should snap to grid while resizing. * @param node The node being resized. * @returns True if the node should snap to grid, false otherwise. * @default () => false */ shouldSnapResizeForNode: (node: Node_2) => boolean; /** * Computes the snap size for a node while dragging. If null is returned, a default snap size will be used. * If computeSnapForNodeDrag is used, it takes precedence over defaultDragSnap. * @param node The node to compute the snap size for dragging. * @returns The snap size for the node while dragging, or null. * @default () => null */ computeSnapForNodeDrag: (node: Node_2) => Size | null; /** * Computes the snap size for a node while resizing. If null is returned, a default snap size will be used. * @param node The node to compute the snap size for resizing. * @returns The snap size for the node while resizing, or null. * @default () => null */ computeSnapForNodeSize: (node: Node_2) => Size | null; /** * The default snap size for node dragging. * If computeSnapForNodeDrag is used, it takes precedence over this value. * @default { width: 10, height: 10 } */ defaultDragSnap: Size; /** * The default snap size for node resizing. * @default { width: 10, height: 10 } */ defaultResizeSnap: Size; } declare class SpatialHash { private readonly cellSize; private readonly grid; private readonly idToCells; private readonly idToRect; process(nodes: Node_2[]): void; query(range: Rect): RectWithId[]; queryIds(range: Rect): string[]; private _query; private nodeToRect; private addToCell; private removeFromCell; private updateInCell; private addToGrid; private updateInGrid; private removeFromGrid; private getCellsRange; private getCells; } declare interface StartLinkingCommand { name: 'startLinking'; source: string; sourcePort?: string; } declare interface StartLinkingFromPositionCommand { name: 'startLinkingFromPosition'; position: Point; } declare class Transaction { private readonly name; private readonly parent; private readonly flowCore; private queue; private savepoints; private _isAborted; private children; private _context; constructor(name: LooseAutocomplete, parent: Transaction | null, flowCore: TFlowCore); /** * Get the transaction context, creating it lazily if needed */ get context(): TransactionContext; /** * Check if the transaction has been completely aborted */ isAborted(): boolean; /** * Completely abort the transaction, making it unusable. * This also aborts all child transactions. */ abort(): void; /** * Create a savepoint that can be rolled back to later */ addSavepoint(name: string): void; /** * Rollback to a savepoint or to the beginning of the transaction. * Unlike abort(), this keeps the transaction active. * @param savepointName - If provided, rollback to this savepoint. If not provided, rollback to the beginning. */ rollback(savepointName?: string): void; /** * Commit the transaction by merging changes to parent or applying them */ commit(): void; /** * Check if the transaction can be committed (not aborted and has changes) */ canCommit(): boolean; /** * Ensure the transaction is not aborted, throwing an error if it is */ private ensureNotAborted; hasChanges(): boolean; getQueue(): readonly { update: FlowStateUpdate; actionTypes: ModelActionTypes; }[]; queueUpdate(update: FlowStateUpdate, actionTypes: ModelActionTypes): void; getState(): TransactionState; mergeToParent(): void; getMergedUpdates(): { mergedUpdate: FlowStateUpdate; commandsCount: number; actionTypes: ModelActionTypes; }; } declare type TransactionCallback = (context: TransactionContext) => void | Promise; declare interface TransactionContext { /** * Emits a command in the core system. * @param name - The name of the command to emit. * @returns A promise that resolves when the command is emitted. */ emit: CommandHandler_2['emit']; /** * Discards all changes in the current transaction */ abort(): void; /** * Saves a point in the transaction. * @param name - The name of the savepoint. */ savepoint(name: string): void; /** * Rolls back the transaction to a previously created savepoint * or to the beginning of the transaction if no savepoint is provided. * @param savepoint - The name of the savepoint to rollback to. */ rollbackTo(savepoint?: string): void; /** * Starts a new nested transaction. * @param name - The name of the transaction. * @param callback - The callback to execute in the transaction. * @returns A promise that resolves when the transaction is complete. */ transaction(name: LooseAutocomplete, callback: TransactionCallback): Promise; /** * Checks if the transaction has changes. * @returns True if the transaction has changes, false otherwise. */ hasChanges(): boolean; /** * Checks if the transaction is dirty. * @returns True if the transaction is dirty, false otherwise. */ isDirty(): boolean; /** * Gets the queued updates in the transaction. * @returns Readonly array of queued updates. */ getQueuedUpdates(): readonly { update: FlowStateUpdate; actionTypes: ModelActionTypes; }[]; } declare class TransactionManager { private readonly flowCore; private transactionStack; private pendingOptions; constructor(flowCore: TFlowCore); transaction(callback: TransactionCallback): Promise; transaction(callback: TransactionCallback, options: TransactionOptions): Promise; transaction(name: LooseAutocomplete, callback: TransactionCallback): Promise; transaction(name: LooseAutocomplete, callback: TransactionCallback, options: TransactionOptions): Promise; /** * Gets the options for the current root transaction. * Returns null if no transaction is active or no options were provided. */ getCurrentOptions(): TransactionOptions | null; queueUpdate(update: FlowStateUpdate, actionTypes: ModelActionTypes): void; isActive(): boolean; getTransactionName(): LooseAutocomplete | null; getCurrentTransaction(): Transaction | null; private parseArgs; } /** * Options for configuring transaction behavior. * * @public * @since 0.9.0 * @category Types/Middleware */ export declare interface TransactionOptions { /** * When true, the transaction promise will not resolve until all measurements * (node sizes, port positions, etc.) triggered by the transaction are complete. * * This is useful when you need to perform operations that depend on measured values, * such as `zoomToFit()` after adding nodes or edges. * * @default false * * @example * ```typescript * // Without waitForMeasurements - zoomToFit might not include new nodes * await diagramService.transaction(() => { * modelService.addNodes([newNode]); * }); * viewportService.zoomToFit(); // May not account for new node dimensions * * // With waitForMeasurements - zoomToFit will include new nodes * await diagramService.transaction(() => { * modelService.addNodes([newNode]); * }, { waitForMeasurements: true }); * viewportService.zoomToFit(); // Correctly includes new node dimensions * ``` */ waitForMeasurements?: boolean; } /** * Result of a transaction execution. * * @public * @since 0.8.0 * @category Types/Middleware */ export declare interface TransactionResult { /** * Results of the transaction as a state update */ results: FlowStateUpdate; /** * Number of commands emitted during the transaction */ commandsCount: number; /** * All action types that were executed within the transaction. * @since 0.9.0 */ actionTypes: ModelActionTypes; } declare interface TransactionState { name: LooseAutocomplete; queue: { update: FlowStateUpdate; actionTypes: ModelActionTypes; }[]; savepoints: Map; isAborted: boolean; parent: Transaction | null; } /** * Type for event unsubscribe function */ declare type UnsubscribeFn = () => void; declare interface UpdateEdgeCommand { name: 'updateEdge'; id: string; edgeChanges: Partial; } declare interface UpdateEdgeLabelsBulkCommand { name: 'updateEdgeLabelsBulk'; updates: Map; }[]>; } declare interface UpdateEdgesCommand { name: 'updateEdges'; edges: (Pick & Partial)[]; } declare interface UpdateNodeCommand { name: 'updateNode'; id: string; nodeChanges: Partial; } declare interface UpdateNodesCommand { name: 'updateNodes'; nodes: (Pick & Partial)[]; } declare interface UpdatePortsBulkCommand { name: 'updatePortsBulk'; updates: Map; }[]>; } declare interface Updater { /** * Apply a single node size change */ applyNodeSize(nodeId: string, size: NonNullable): void; /** * Apply node size changes in a single batch */ applyNodeSizes(updates: { id: string; size: NonNullable; }[]): void; /** * Add a port to a node */ addPort(nodeId: string, port: Port): void; /** * Apply port changes (size, position, side, type, etc.) */ applyPortChanges(nodeId: string, portUpdates: PortUpdate[]): void; /** * Add an edge label */ addEdgeLabel(edgeId: string, label: EdgeLabel): void; /** * Apply edge label changes (size, positionOnEdge, etc.) */ applyEdgeLabelChanges(edgeId: string, labelUpdates: LabelUpdate[]): void; /** * Delete an edge label */ deleteEdgeLabel(edgeId: string, labelId: string): void; } /** * Interface representing the viewport of the diagram. * * @public * @since 0.8.0 * @category Types/Model */ export declare interface Viewport { /** X coordinate of the viewport center */ x: number; /** Y coordinate of the viewport center */ y: number; /** Scale factor of the viewport */ scale: number; /** Width of the viewport */ width?: number; /** Height of the viewport */ height?: number; } /** * Event payload emitted when the viewport changes through panning or zooming. * * This event fires during pan and zoom operations, including mouse wheel zoom, * and programmatic viewport changes. * * @public * @since 0.8.0 * @category Types/Events */ export declare interface ViewportChangedEvent { /** Current viewport state after the change */ viewport: Viewport; /** Previous viewport state before the change */ previousViewport: Viewport; } export declare class ViewportDirective { viewport: InputSignal; get transform(): string; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } /** * Configuration for viewport virtualization behavior. * When enabled, only nodes and edges visible in the viewport (plus padding) are rendered, * significantly improving performance for large diagrams. * * @public * @since 1.0.0 * @category Types/Configuration/Features */ export declare interface VirtualizationConfig { /** * Whether viewport virtualization is enabled. * When disabled, all nodes/edges are rendered regardless of viewport. * @default false */ enabled: boolean; /** * Padding multiplier relative to viewport size. * The actual padding is calculated as: max(viewportWidth, viewportHeight) * padding * For example, 0.5 means 50% of the viewport size as padding in each direction. * @default 0.5 */ padding: number; /** * Delay in milliseconds after panning stops before re-rendering visible nodes. * @default 100 */ idleDelay?: number; } /** * Defines custom event type used throughout the ngDiagram library for handling user input. * * The main type, `WheelInputEvent`, extends the native `WheelEvent` with additional flag * that indicate zooming diagram interaction have already been handled. * These flag is used by input event directives and handlers * to coordinate and prevent duplicate processing of the same pointer event. * * This type is used as the event parameter in input event handlers and services * across the public API and internal logic. * * Example usage: * ```ts * onWheel(event: WheelInputEvent) { * if (!event.zoomingHandled) { * // handle zooming logic * event.zoomingHandled = true; * } * } * ``` */ declare interface WheelInputEvent extends WheelEvent { zoomingHandled?: boolean; } /** * Wheel-only action names that can only be triggered by wheel events with modifiers * (e.g., Shift+Wheel, Ctrl+Wheel) * * @public * @since 1.1.0 * @category Types/Configuration/Shortcuts */ export declare type WheelOnlyActionName = 'zoom'; /** * Wheel-only shortcut definition with modifier-only bindings * * @public * @since 1.1.0 * @category Types/Configuration/Shortcuts */ export declare interface WheelOnlyShortcutDefinition { /** Action name for wheel events */ actionName: WheelOnlyActionName; /** Modifier-only bindings (keys are not allowed) */ bindings: ModifierOnlyShortcutBinding[]; } /** * Type for command without name */ declare type WithoutName = Omit; /** * Configuration for z-index layering behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface ZIndexConfig { /** * Whether z-index middleware is enabled. * @default true */ enabled: boolean; /** * The z-index value added to selected elements' computed z-index. * Applied cumulatively — a selected child inside a selected parent * receives this value twice (once from the parent's elevation, once from its own). * @default 10000 */ selectedZIndex: number; /** * The z-index value for temporary edge. * @default 2147483647 */ temporaryEdgeZIndex: number; /** * Whether edges should appear above their connected nodes. * @default false */ edgesAboveConnectedNodes: boolean; /** * Whether selected elements should be elevated by adding `selectedZIndex` to their computed z-index. * @default true */ elevateOnSelection: boolean; } export declare class ZIndexDirective { data: InputSignal | Node_2>; zIndex: Signal; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface ZoomCommand { name: 'zoom'; x: number; y: number; scale: number; } /** * Configuration for zooming behavior. * * @public * @since 0.8.0 * @category Types/Configuration/Features */ export declare interface ZoomConfig { /** * The minimum allowed zoom level. * @default 0.01 */ min: number; /** * The maximum allowed zoom level. * @default 10.0 */ max: number; /** * The zoom step increment. * @default 0.03 */ step: number; /** * Configuration for zoom-to-fit operations. */ zoomToFit: ZoomToFitConfig; } export declare class ZoomingWheelDirective { private readonly flowCoreProvider; private readonly inputEventsRouterService; onWheel(event: WheelInputEvent): void; private shouldHandle; /** * A pinch gesture on trackpads is typically represented * as a wheel event with ctrlKey=true and a small deltaY compared to regular scrolls. */ private isPinchGesture; private getZoomFactor; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵdir: i0.ɵɵDirectiveDeclaration; } declare interface ZoomToFitCommand { name: 'zoomToFit'; nodeIds?: string[]; edgeIds?: string[]; padding?: number | [number, number] | [number, number, number] | [number, number, number, number]; } /** * Configuration for zoom-to-fit behavior. * * @category Types/Configuration/Features */ declare interface ZoomToFitConfig { /** * The default padding (in pixels) to use for zoom-to-fit operations. * Supports CSS-like padding syntax: * - Single number: applies to all sides * - [v, h]: vertical, horizontal * - [t, h, b]: top, horizontal, bottom * - [t, r, b, l]: top, right, bottom, left * Can be overridden per command invocation. * @default 50 */ padding: number | [number, number] | [number, number, number] | [number, number, number, number]; /** * Whether to automatically zoom to fit all content when the diagram is initialized. * @default false */ onInit: boolean; } export { }