UNPKG

d3-graph-controller

Version:

A TypeScript library for visualizing and simulating directed, interactive graphs.

735 lines (734 loc) 22.1 kB
import { Selection } from "d3-selection"; import { ZoomBehavior } from "d3-zoom"; import { D3DragEvent, DragBehavior } from "d3-drag"; import { Simulation, SimulationLinkDatum, SimulationNodeDatum } from "d3-force"; //#region src/model/shared.d.ts /** * Label configuration. */ interface Label { /** * The color of the label. * Can be any valid CSS expression. */ readonly color: string; /** * The font size of the label. * Can be any valid CSS expression. */ readonly fontSize: string; /** * The text of the label. */ readonly text: string; } //#endregion //#region src/model/node.d.ts /** * Node representing a datum of a graph. */ interface GraphNode<T extends NodeTypeToken = NodeTypeToken> extends SimulationNodeDatum { /** * The type of the node. */ readonly type: T; /** * The ID of the node. */ readonly id: string; /** * The color of the node. * Can be any valid CSS expression. */ readonly color: string; /** * The label of the node. * Using false will disable the node's label. */ readonly label: false | Label; /** * The focus state of a node. * Warning: Used for internal logic. Should not be set manually! */ isFocused: boolean; /** * The x-coordinate of a node. */ x?: number | undefined; /** * The y-coordinate of a node. */ y?: number | undefined; /** * The fixed x-coordinate of a node. * If set, the node will not be simulated. */ fx?: number | undefined; /** * The fixed y-coordinate of a node. * If set, the node will not be simulated. */ fy?: number | undefined; /** * Timestamp of the node's last interaction. * Warning: Used for internal logic. Should not be set manually! */ lastInteractionTimestamp?: number | undefined; } /** * Define a node with type inference. * @param data - The data of the node. */ declare function defineNode<T extends NodeTypeToken = NodeTypeToken, Node extends GraphNode<T> = GraphNode<T>>(data: Node): Node; /** * Define a node with type inference and some default values. * @param data - The data of the node. */ declare function defineNodeWithDefaults<T extends NodeTypeToken = NodeTypeToken>(data: Partial<GraphNode<T>> & Pick<GraphNode, "id" | "type">): GraphNode<T>; //#endregion //#region src/model/link.d.ts /** * Link defining an edge from one node to another. */ interface GraphLink<T extends NodeTypeToken = NodeTypeToken, SourceNode extends GraphNode<T> = GraphNode<T>, TargetNode extends GraphNode<T> = SourceNode> extends SimulationLinkDatum<SourceNode | TargetNode> { /** * The source node of the link. */ readonly source: SourceNode; /** * The target node of the link */ readonly target: TargetNode; /** * The color of the link. * Can be any valid CSS expression. */ readonly color: string; /** * The label of the node. * Using false will disable the node's label. */ readonly label: false | Label; } /** * Define a link with type inference. * @param data - The data of the link. */ declare function defineLink<T extends NodeTypeToken = NodeTypeToken, SourceNode extends GraphNode<T> = GraphNode<T>, TargetNode extends GraphNode<T> = SourceNode, Link extends GraphLink<T, SourceNode, TargetNode> = GraphLink<T, SourceNode, TargetNode>>(data: Link): Link; //#endregion //#region src/model/graph.d.ts /** * Type token for nodes. */ type NodeTypeToken = string; /** * Graph containing nodes and links. */ interface Graph<T extends NodeTypeToken = NodeTypeToken, Node extends GraphNode<T> = GraphNode<T>, Link extends GraphLink<T, Node> = GraphLink<T, Node>> { /** * The nodes of the graph. */ readonly nodes: Node[]; /** * The links of the graph. */ readonly links: Link[]; } /** * Define a graph with type inference. * @param data - The nodes and links of the graph. If either are omitted, they default to an empty array. */ declare function defineGraph<T extends NodeTypeToken = NodeTypeToken, Node extends GraphNode<T> = GraphNode<T>, Link extends GraphLink<T, Node> = GraphLink<T, Node>>({ nodes, links }: Partial<Graph<T, Node, Link>>): Graph<T, Node, Link>; //#endregion //#region src/config/alpha.d.ts /** * Alpha values when label display changes. */ interface LabelAlphas { /** * Alpha value when labels are turned off. */ readonly hide: number; /** * Alpha value when labels are turned on. */ readonly show: number; } /** * Context of a resize. */ interface ResizeContext { /** * The old height. */ readonly oldHeight: number; /** * The old width. */ readonly oldWidth: number; /** * The new height. */ readonly newHeight: number; /** * The new width. */ readonly newWidth: number; } /** * Alpha value configuration for controlling simulation activity. */ interface AlphaConfig<T extends NodeTypeToken, Node extends GraphNode<T>> { /** * Target alpha values for dragging. */ readonly drag: { /** * Target alpha when a drag starts. * Should be larger than 0. */ readonly start: number; /** * Target alpha when a drag stops. * Should generally be 0. */ readonly end: number; }; /** * Alpha values for filter changes. */ readonly filter: { /** * Alpha value when the link filter changes. */ readonly link: number; /** * Alpha value when the node type filter changes. */ readonly type: number; /** * Alpha values when the inclusion of unlinked nodes changes. */ readonly unlinked: { /** * Alpha value when unlinked nodes are included. */ readonly include: number; /** * Alpha value when unlinked nodes are excluded. */ readonly exclude: number; }; }; /** * Alpha values when node focus changes. */ readonly focus: { /** * Alpha value when a node is focused. * @param node - The focused node. * @returns The alpha value. */ readonly acquire: (node: Node) => number; /** * Alpha value when a node is unfocused. * @param node - The unfocused node. * @returns The alpha value. */ readonly release: (node: Node) => number; }; /** * Alpha value when the graph is initialized. */ readonly initialize: number; /** * Alpha values when label display changes. */ readonly labels: { /** * Alpha values when link label display changes. */ readonly links: LabelAlphas; /** * Alpha values when node label display changes. */ readonly nodes: LabelAlphas; }; /** * Alpha values when the graph is resized. */ readonly resize: number | ((context: ResizeContext) => number); } /** * Create the default alpha configuration. */ declare function createDefaultAlphaConfig<T extends NodeTypeToken, Node extends GraphNode<T>>(): AlphaConfig<T, Node>; //#endregion //#region src/config/callbacks.d.ts /** * Callback configuration. */ interface Callbacks<T extends NodeTypeToken, Node extends GraphNode<T>> { /** * Callback when a node is double-clicked or double-tapped. * @param node - The node. */ readonly nodeClicked?: (node: Node) => void; } //#endregion //#region src/config/filter.d.ts /** * Link filter. * Receives a link and returns whether the link should be included or not. */ type LinkFilter<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = (link: Link) => boolean; //#endregion //#region src/config/initial.d.ts /** * Initial settings of a controller. */ interface InitialGraphSettings<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> { /** * Whether nodes without incoming or outgoing links will be shown or not. */ readonly includeUnlinked: boolean; /** * Link filter that decides whether links should be included or not. */ readonly linkFilter: LinkFilter<T, Node, Link>; /** * Node types that should be included. * If undefined, all node types will be included. */ readonly nodeTypeFilter?: T[] | undefined; /** * Whether link labels are shown or not. */ readonly showLinkLabels: boolean; /** * Whether node labels are shown or not. */ readonly showNodeLabels: boolean; } /** * Create default initial settings. */ declare function createDefaultInitialGraphSettings<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>>(): InitialGraphSettings<T, Node, Link>; //#endregion //#region src/config/marker.d.ts /** * Marker configuration. */ interface MarkerConfig { /** * Size of the marker's box. */ readonly size: number; /** * Get padding of the marker for calculating link paths. * @param node - The node the marker is pointing at. * @param config - The current config. * @returns The padding of the marker. */ readonly padding: <T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>>(node: Node, config: GraphConfig<T, Node, Link>) => number; /** * The ref of the marker. */ readonly ref: [number, number]; /** * The path of the marker. */ readonly path: [number, number][]; /** * The ViewBox of the marker. */ readonly viewBox: string; } /** * Collection of built-in markers. */ declare const Markers: { /** * Create an arrow marker configuration. * @param size - The size of the arrow */ Arrow: (size: number) => MarkerConfig; }; //#endregion //#region src/lib/types.d.ts type Canvas = Selection<SVGGElement, undefined, null, undefined>; type Drag<T extends NodeTypeToken, Node extends GraphNode<T>> = DragBehavior<SVGGElement, Node, Node>; type NodeDragEvent<T extends NodeTypeToken, Node extends GraphNode<T>> = D3DragEvent<SVGCircleElement, Node, Node>; type GraphHost = Selection<HTMLDivElement, undefined, null, undefined>; type GraphSimulation<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = Simulation<Node, Link>; type LinkSelection<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = Selection<SVGGElement, Link, SVGGElement, undefined>; type MarkerSelection = Selection<SVGMarkerElement, string, SVGGElement, undefined>; type NodeSelection<T extends NodeTypeToken, Node extends GraphNode<T>> = Selection<SVGGElement, Node, SVGGElement, undefined>; type Zoom = ZoomBehavior<SVGSVGElement, undefined>; //#endregion //#region src/config/modifiers.d.ts /** * Modifier for the drag. */ type DragModifier<T extends NodeTypeToken, Node extends GraphNode<T>> = (drag: Drag<T, Node>) => void; /** * Modifier for node circles. */ type NodeModifier<T extends NodeTypeToken, Node extends GraphNode<T>> = (selection: Selection<SVGCircleElement, Node, SVGGElement, undefined>) => void; /** * Modifier for node labels. */ type NodeLabelModifier<T extends NodeTypeToken, Node extends GraphNode<T>> = (selection: Selection<SVGTextElement, Node, SVGGElement, undefined>) => void; /** * Modifier for link paths. */ type LinkModifier<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = (selection: Selection<SVGPathElement, Link, SVGGElement, undefined>) => void; /** * Modifier for link labels. */ type LinkLabelModifier<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = (selection: Selection<SVGTextElement, Link, SVGGElement, undefined>) => void; /** * Modifier for the simulation. */ type SimulationModifier<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> = (simulation: GraphSimulation<T, Node, Link>) => void; /** * Modifier for the zoom. */ type ZoomModifier = (zoom: Zoom) => void; /** * Low-level callbacks for modifying the underlying d3-selection.wd */ interface Modifiers<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> { /** * Modify the drag. * @param drag - The drag. */ readonly drag?: DragModifier<T, Node>; /** * Modify the node selection. * @param selection - The selection of nodes. */ readonly node?: NodeModifier<T, Node>; /** * Modify the node label selection. * @param selection - The selection of node labels. */ readonly nodeLabel?: NodeLabelModifier<T, Node>; /** * Modify the link selection. * @param selection - The selection of links. */ readonly link?: LinkModifier<T, Node, Link>; /** * Modify the link label selection. * @param selection - The selection of link labels. */ readonly linkLabel?: LinkLabelModifier<T, Node, Link>; /** * Modify the simulation. * @param simulation - The simulation. */ readonly simulation?: SimulationModifier<T, Node, Link>; /** * Modify the zoom. * @param zoom - The zoom. */ readonly zoom?: ZoomModifier; } //#endregion //#region src/config/position.d.ts /** * Initializes a node's position in context of a graph's width and height. */ type PositionInitializer<T extends NodeTypeToken, Node extends GraphNode<T>> = (node: Node, width: number, height: number) => [number, number]; declare function Stable<T extends NodeTypeToken, Node extends GraphNode<T>>(previousGraph: Graph<T, Node>): PositionInitializer<T, Node>; /** * Collection of built-in position initializers. */ declare const PositionInitializers: { /** * Initializes node positions to a graph's center. */ Centered: PositionInitializer<string, GraphNode<string>>; /** * Randomly initializes node positions within the visible area. */ Randomized: PositionInitializer<string, GraphNode<string>>; /** * Initializes node positions based on other graph. */ Stable: typeof Stable; }; //#endregion //#region src/config/forces.d.ts /** * Simulation force. */ interface Force<Subject> { /** * Whether the force is enabled. */ readonly enabled: boolean; /** * The strength of the force. * Can be a static number or a function receiving the force's subject and returning a number. */ readonly strength: number | ((subject: Subject) => number); } /** * Simulation force applied to nodes. */ type NodeForce<T extends NodeTypeToken, Node extends GraphNode<T>> = Force<Node>; /** * Collision force applied to nodes. */ interface CollisionForce<T extends NodeTypeToken, Node extends GraphNode<T>> extends NodeForce<T, Node> { /** * Multiplier of the node radius. * Tip: Large values can drastically reduce link intersection. */ readonly radiusMultiplier: number; } /** * Simulation force applied to links. */ interface LinkForce<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> extends Force<Link> { /** * Define the length of a link for the simulation. */ readonly length: number | ((link: Link) => number); } /** * Simulation force configuration. */ interface SimulationForceConfig<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> { /** * Centering force applied to nodes. */ readonly centering: false | NodeForce<T, Node>; /** * Charge force applied to nodes. */ readonly charge: false | NodeForce<T, Node>; /** * Collision force applied to nodes. */ readonly collision: false | CollisionForce<T, Node>; /** * Link force applied to links. */ readonly link: false | LinkForce<T, Node, Link>; } /** * Create the default force configuration. */ declare function createDefaultForceConfig<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>>(): SimulationForceConfig<T, Node, Link>; //#endregion //#region src/config/simulation.d.ts interface SimulationConfig<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> { /** * Alpha value configuration. */ readonly alphas: AlphaConfig<T, Node>; /** * Force configuration. */ readonly forces: SimulationForceConfig<T, Node, Link>; } //#endregion //#region src/config/zoom.d.ts /** * Zoom configuration. */ interface ZoomConfig { /** * The initial zoom. * Must be in range [min, max]. */ readonly initial: number; /** * Maximum zoom level. * May not be smaller than initial zoom. */ readonly max: number; /** * Minimum zoom level. * May not be larger than initial zoom or less than or equal to 0. */ readonly min: number; } //#endregion //#region src/config/config.d.ts interface GraphConfig<T extends NodeTypeToken, Node extends GraphNode<T>, Link extends GraphLink<T, Node>> { /** * Set to true to enable automatic resizing. * Warning: Do call shutdown(), once the controller is no longer required. */ readonly autoResize: boolean; /** * Callback configuration. */ readonly callbacks: Callbacks<T, Node>; readonly hooks: { afterZoom?: (scale: number, xOffset: number, yOffset: number) => void; }; /** * Initial settings of a controller. */ readonly initial: InitialGraphSettings<T, Node, Link>; /** * Marker configuration. */ readonly marker: MarkerConfig; /** * Low-level callbacks for modifying the underlying d3-selection. */ readonly modifiers: Modifiers<T, Node, Link>; /** * Define the radius of a node for the simulation and visualization. * Can be a static number or a function receiving a node as its parameter. */ readonly nodeRadius: number | ((node: Node) => number); /** * Initializes a node's position in context of a graph's width and height. */ readonly positionInitializer: PositionInitializer<T, Node>; /** * Simulation configuration. */ readonly simulation: SimulationConfig<T, Node, Link>; /** * Zoom configuration. */ readonly zoom: ZoomConfig; } /** * Utility type for deeply partial objects. */ type DeepPartial<T> = { readonly [P in keyof T]?: DeepPartial<T[P]> }; /** * Define the configuration of a controller. * Will be merged with the default configuration. * @param config - The partial configuration. * @returns The merged configuration. */ declare function defineGraphConfig<T extends NodeTypeToken = NodeTypeToken, Node extends GraphNode<T> = GraphNode<T>, Link extends GraphLink<T, Node> = GraphLink<T, Node>>(config?: DeepPartial<GraphConfig<T, Node, Link>>): GraphConfig<T, Node, Link>; //#endregion //#region src/controller.d.ts /** * Controller for a graph view. */ declare class GraphController<T extends NodeTypeToken = NodeTypeToken, Node extends GraphNode<T> = GraphNode<T>, Link extends GraphLink<T, Node> = GraphLink<T, Node>> { /** * Array of all node types included in the controller's graph. */ readonly nodeTypes: T[]; private _nodeTypeFilter; private _includeUnlinked; private _linkFilter; private _showLinkLabels; private _showNodeLabels; private filteredGraph; private width; private height; private simulation; private canvas; private linkSelection; private nodeSelection; private markerSelection; private zoom; private drag; private xOffset; private yOffset; private scale; private focusedNode; private resizeObserver?; private readonly container; private readonly graph; private readonly config; /** * Create a new controller and initialize the view. * @param container - The container the graph will be placed in. * @param graph - The graph of the controller. * @param config - The config of the controller. */ constructor(container: HTMLDivElement, graph: Graph<T, Node, Link>, config: GraphConfig<T, Node, Link>); /** * Get the current node type filter. * Only nodes whose type is included will be shown. */ get nodeTypeFilter(): T[]; /** * Get whether nodes without incoming or outgoing links will be shown or not. */ get includeUnlinked(): boolean; /** * Set whether nodes without incoming or outgoing links will be shown or not. * @param value - The value. */ set includeUnlinked(value: boolean); /** * Set a new link filter and update the controller's state. * @param value - The new link filter. */ set linkFilter(value: LinkFilter<T, Node, Link>); /** * Get the current link filter. * @returns - The current link filter. */ get linkFilter(): LinkFilter<T, Node, Link>; /** * Get whether node labels are shown or not. */ get showNodeLabels(): boolean; /** * Set whether node labels will be shown or not. * @param value - The value. */ set showNodeLabels(value: boolean); /** * Get whether link labels are shown or not. */ get showLinkLabels(): boolean; /** * Set whether link labels will be shown or not. * @param value - The value. */ set showLinkLabels(value: boolean); private get effectiveWidth(); private get effectiveHeight(); private get effectiveCenter(); /** * Resize the graph to fit its container. */ resize(): void; /** * Restart the controller. * @param alpha - The alpha value of the controller's simulation after the restart. */ restart(alpha: number): void; /** * Update the node type filter by either including or removing the specified type from the filter. * @param include - Whether the type will be included or removed from the filter. * @param nodeType - The type to be added or removed from the filter. */ filterNodesByType(include: boolean, nodeType: T): void; /** * Shut down the controller's simulation and (optional) automatic resizing. */ shutdown(): void; private initGraph; private onTick; private resetView; private onZoom; private applyZoom; private toggleNodeFocus; private focusNode; private filterGraph; } //#endregion export { AlphaConfig, Callbacks, Canvas, CollisionForce, DeepPartial, Drag, DragModifier, Force, Graph, GraphConfig, GraphController, GraphHost, GraphLink, GraphNode, GraphSimulation, InitialGraphSettings, Label, LabelAlphas, LinkFilter, LinkForce, LinkLabelModifier, LinkModifier, LinkSelection, MarkerConfig, MarkerSelection, Markers, Modifiers, NodeDragEvent, NodeForce, NodeLabelModifier, NodeModifier, NodeSelection, NodeTypeToken, PositionInitializer, PositionInitializers, ResizeContext, SimulationForceConfig, SimulationModifier, Zoom, ZoomConfig, ZoomModifier, createDefaultAlphaConfig, createDefaultForceConfig, createDefaultInitialGraphSettings, defineGraph, defineGraphConfig, defineLink, defineNode, defineNodeWithDefaults }; //# sourceMappingURL=index.d.mts.map