import type { IBoxSize, ICoords, IProcessedGraphNode, LogicalArcGraph, RenderableContent, IARCProps, IEdgeRouterMode, IGraphEdge, GraphNodeId, IChartState } from '@adam-sv/arc'; import type { IConnectionCreationLogic } from './InteractionManager/NodeInteractionManager'; import type { IComputedGraphLayout } from './layouts'; export interface IGraphProps extends IARCProps { className?: string; graph: LogicalArcGraph; edgeMode?: IEdgeRouterMode; forceEdgesOnTop?: boolean; edgeSpacing?: number; edgeCreation?: IConnectionCreationLogic; gridSize?: number; gridLineOrDotThickness?: number; gridStyle?: 'grid' | 'dot-grid' | 'none'; hideScrollBars?: boolean; minHeight?: number; svgNodeContentRenderer?: IGraphNodeContentRenderer; htmlNodeContentRenderer?: IGraphNodeContentRenderer; scrollControls?: { left: number; top: number; onScrollUpdate?: (scrollLeft: number, scrollTop: number) => unknown; }; zoomControls?: { value?: number; min?: number; max?: number; onZoomUpdate?: (zoom: number) => unknown; }; mode?: IGraphStrategy; layoutOptions?: Partial; renderedLayout?: IComputedGraphLayout; onScrollUpdate?: (scrollLeft: number, scrollTop: number) => unknown; selectionActions?: IGraphSelectionActions; selectedNodeIds?: Set; selectedEdges?: Set>; connectionActions?: IGraphConnectionActions; nodeActions?: IGraphNodeActions; backgroundDragMode?: IGraphDragMode; onContextMenu?: (ev: React.MouseEvent, coordinateSpacePosition: ICoords) => unknown; onDrop?: (ev: React.DragEvent, coordinateSpacePosition: ICoords, data: string, chartState: IChartState) => unknown; invertDragControls?: boolean; /** `debug` mode results in EdgeRouter showing the nodes * in the WebCola coordinate space and writing additional logs.*/ debug?: boolean; } export interface IGraphRenderContext { graph: LogicalArcGraph; getPosition: (node: IProcessedGraphNode, flag?: boolean) => ICoords | undefined; getSize: (node: IProcessedGraphNode) => IBoxSize; getNodeConnectionLayout: (node: IProcessedGraphNode, useRelativePosition?: boolean) => IChildBoxPlacement | undefined; getNodeContentLayout: (node: IProcessedGraphNode, useAbsolutePosition?: boolean) => IChildBoxPlacement | undefined; layoutOptions: IGraphLayoutOptions; scaledPadding: { topLevel: ICoords; child: ICoords; }; zoom: number; } export interface IBoxPlacement { position: ICoords; size: IBoxSize; } export interface IChildBoxPlacement extends IBoxPlacement { isStrictSubset?: boolean; } export interface IGraphNodeContentRendererProps { node: IProcessedGraphNode; position: ICoords; size: IBoxSize; showContentBox?: boolean; graphContext: IGraphRenderContext; } export type IGraphNodeContentRenderer = (props: IGraphNodeContentRendererProps) => RenderableContent; export type IGraphChildNodeRenderer = (props: { node: IProcessedGraphNode; graphContext: IGraphRenderContext; childNodeRenderer?: IGraphChildNodeRenderer; contentRenderer?: IGraphNodeContentRenderer; }) => RenderableContent; export interface IGraphLayoutOptions { defaultNodeSize: IBoxSize; padding: number; childPadding: number; inputOutputHeight: number; inputOutputWidth: number | 'auto'; contentHeight: number; connectionTargetSize: number; } export type IGraphStrategy = 'flat' | 'hierarchical' | 'functional' | 'custom'; export type FlatGraphLayoutStrategy = { mode: 'flat'; padding: number; defaultNodeSize?: IBoxSize; }; export type HierarchicalGraphLayoutStrategy = { mode: 'hierarchical'; padding: number; defaultNodeSize?: IBoxSize; childPadding: number; inputOutputHeight?: number; inputOutputWidth?: number; contentHeight?: number; }; export type FunctionalLayoutOptions = { mode: 'functional'; connectionTargetSize?: number; childPadding?: number; }; export interface INodePlacement { node: IProcessedGraphNode; absolutePosition: ICoords; relativePosition: ICoords; size: IBoxSize; contentPlacement?: INodePortionPlacement; connectionTargetPlacement?: INodePortionPlacement; } export interface INodePortionPlacement { role: 'content-container' | 'connection-target'; position: ICoords; size: IBoxSize; } export type IGraphDragMode = 'move' | 'multi-select'; export interface IGraphDefaults { GRID_SIZE: number; GRID_LINE_OR_DOT_THICKNESS: number; MIN_HEIGHT: number; ZOOM_DEFAULTS: { value: number; min: number; max: number; }; LAYOUT_OPTIONS: { PADDING: number; CHILD_PADDING: number; DEFAULT_NODE_SIZE: IBoxSize; INPUT_OUTPUT_HEIGHT: number; INPUT_OUTPUT_WIDTH: number; CONTENT_HEIGHT: number; CONNECTION_TARGET_SIZE: number; }; } export interface IGraphConnectionActions { onClick?: (e: React.MouseEvent, edge: IGraphEdge) => unknown; onContextMenu?: (e: React.MouseEvent, edge: IGraphEdge) => unknown; onHover?: (e: React.MouseEvent, edge: IGraphEdge) => unknown; onUnhover?: (e: React.MouseEvent, edge: IGraphEdge) => unknown; } export interface IGraphNodeActions { onClick?: (e: React.MouseEvent, node: IProcessedGraphNode) => unknown; onDoubleClick?: (e: React.MouseEvent, node: IProcessedGraphNode) => unknown; onContextMenu?: (e: React.MouseEvent, node: IProcessedGraphNode) => unknown; onMove?: (node: IProcessedGraphNode, delta: ICoords) => unknown; } export interface IGraphSelectionActions { onContextMenu?: (e: React.MouseEvent, selection: IGraphSelection) => unknown; onSelectionMoved?: (selection: IGraphSelection, delta: ICoords) => unknown; onSelectionUpdated?: (selection: IGraphSelection) => unknown; onSelectionChanged?: (selectionDifference: { added?: Partial>; deleted?: Partial>; multiEvent?: boolean; }) => unknown; } export interface IGraphSelection { nodeIds: Set; edges: Set>; }