import { useMemo } from 'react'; import { AbstractAnchor, AnchorEnd, ColaLayout, ComponentFactory, DefaultEdge, DefaultNode, Graph, GraphComponent, Layer, Layout, LayoutFactory, Model, ModelKind, Node, NodeModel, Point, useAnchor, useSvgAnchor, Visualization, VisualizationProvider, VisualizationSurface, withDragNode, WithDragNodeProps } from '@patternfly/react-topology'; class RightAnchor extends AbstractAnchor { getLocation(): Point { return this.getReferencePoint(); } getReferencePoint(): Point { const bounds = this.owner.getBounds(); return new Point(bounds.right(), bounds.y + bounds.height / 2); } } type CustomNodeProps = { element: Node; } & WithDragNodeProps; const CustomNode: React.FC = ({ element, dragNodeRef }) => { const targetRef = useSvgAnchor(AnchorEnd.target, 'edge-point'); // overrides anchor for end points useAnchor(RightAnchor, AnchorEnd.source, 'edge-point'); // overrides anchor for end points const { width, height } = element.getDimensions(); return ( ); }; const customLayoutFactory: LayoutFactory = (type: string, graph: Graph): Layout | undefined => new ColaLayout(graph, { layoutOnDrag: false }); const customComponentFactory: ComponentFactory = (kind: ModelKind) => { switch (kind) { case ModelKind.graph: return GraphComponent; case ModelKind.node: return withDragNode()(CustomNode); case ModelKind.edge: return DefaultEdge; default: return undefined; } }; const NODE_DIAMETER = 75; const NODES: NodeModel[] = [ { id: 'node-0', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 250, y: 120 }, { id: 'node-1', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 350, y: 120 }, { id: 'node-2', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 450, y: 120 }, { id: 'node-3', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 250, y: 320 }, { id: 'node-4', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 350, y: 320 }, { id: 'node-5', type: 'node', width: NODE_DIAMETER, height: NODE_DIAMETER, x: 450, y: 320 } ]; const EDGES = [ { id: 'edge-node-0-node-1', type: 'edge-point', source: 'node-0', target: 'node-1' }, { id: 'edge-node-1-node-2', type: 'edge-point', source: 'node-1', target: 'node-2' }, { id: 'edge-node-3-node-4', type: 'edge-point', source: 'node-3', target: 'node-4' }, { id: 'edge-node-4-node-5', type: 'edge-point', source: 'node-4', target: 'node-5' } ]; export const TopologyCustomNodeDemo: React.FC = () => { const controller = useMemo(() => { const model: Model = { nodes: NODES, edges: EDGES, graph: { id: 'g1', type: 'graph', layout: 'Cola' } }; const newController = new Visualization(); newController.registerLayoutFactory(customLayoutFactory); newController.registerComponentFactory(customComponentFactory); newController.fromModel(model, false); return newController; }, []); return ( ); };