### Initialize and start the project Source: https://github.com/reaviz/reaflow/blob/master/docs/Contributing.mdx Commands to install dependencies and launch the Storybook documentation environment. ```bash npm i npm start ``` -------------------------------- ### useSelection Hook Setup Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Example implementation of the useSelection hook to manage nodes, edges, and selection state. ```ts import { NodeData, EdgeData, useSelection } from 'reaflow'; const [nodes, setNodes] = useState([ { id: '1', text: 'Node 1' }, { id: '2', text: 'Node 2' } ]); const [edges, setEdges] = useState([ { id: '1-2', from: '1', to: '2' } ]); const { selections, onCanvasClick, onClick, onKeyDown, clearSelections } = useSelection({ nodes, edges, onDataChange: (n, e) => { console.info('Data changed', n, e); setNodes(n); setEdges(e); }, onSelection: (s) => { console.info('Selection', s); } }); ``` -------------------------------- ### Install Reaflow via Yarn Source: https://github.com/reaviz/reaflow/blob/master/README.md Use this command to install the package using the Yarn package manager. ```bash yarn add reaflow ``` -------------------------------- ### Install Reaflow via NPM Source: https://github.com/reaviz/reaflow/blob/master/README.md Use this command to install the package using the NPM package manager. ```bash npm i reaflow --save ``` -------------------------------- ### Install REAFLOW via package managers Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/Installing.mdx Use these commands to add the REAFLOW dependency to your project. ```bash npm install reaflow --save ``` ```bash yarn add reaflow ``` -------------------------------- ### Implementing useUndo Hook Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Undo.mdx Example of integrating the useUndo hook into a React component to manage graph state. ```tsx import { useUndo, EdgeData, Canvas, NodeData } from 'reaflow'; const MyApp = () => { const [nodes, setNodes] = useState([]); const [edges, setEdges] = useState([]); const { undo, redo, canUndo, canRedo } = useUndo({ nodes, edges, onUndoRedo: (state: UndoRedoEvent) => { console.log('Undo / Redo', state); // Note: This is where YOUR state comes into play setEdges(state.edges); setNodes(state.nodes); } }); return ; } ``` -------------------------------- ### Inspect foreignObject rendering structure Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/CustomNodes.mdx An example of the generated SVG structure showing how foreignObject encapsulates custom HTML content within a node container. ```html
Node content
``` -------------------------------- ### Run development environment and build Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/Installing.mdx Commands for local development and production builds using the project's scripts. ```bash npm install ``` ```bash npm start ``` ```bash npm run build ``` -------------------------------- ### Configure package.json for linking Source: https://github.com/reaviz/reaflow/blob/master/docs/Contributing.mdx Suggested script to automate the linking of Reaflow and its peer dependencies. ```json "link:reaflow": "yarn link reaflow && yarn link react && yarn link react-dom" ``` -------------------------------- ### Run build in watch mode Source: https://github.com/reaviz/reaflow/blob/master/docs/Contributing.mdx Command to enable hot-reloading for local development changes. ```bash yarn build:watch ``` -------------------------------- ### Render a Basic Canvas Source: https://github.com/reaviz/reaflow/blob/master/README.md Import the Canvas component and provide nodes and edges to display a basic diagram. ```jsx import React from 'react'; import { Canvas } from 'reaflow'; export default () => ( ); ``` -------------------------------- ### UndoProps Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Undo.mdx Defines the configuration properties for the useUndo hook. ```ts export interface UndoProps { /** * Current node datas. */ nodes: NodeData[]; /** * Current edge datas. */ edges: EdgeData[]; /** * Max history count. */ maxHistory?: number; /** * Disabled or not. */ disabled?: boolean; /** * On undo/redo event handler. */ onUndoRedo: (state: UndoRedoEvent) => void; } ``` -------------------------------- ### Add Node and Edge in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Shortcut to add a node and an optional edge to the graph. ```js addNodeAndEdge( nodes: NodeData[], edges: EdgeData[], node: NodeData, toNode?: NodeData ) => { nodes: NodeData[]; edges: EdgeData[]; } ``` ```js import { addNodeAndEdge } from 'reaflow'; const result = addNodeAndEdge( nodes, edges, { id, text: id }, enteredNode ); setNodes(results.nodes); setEdges(results.edges); ``` -------------------------------- ### Clone State for Immutability Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/StateMgmt.mdx Shows the correct approach to updating state by cloning the existing data using a utility like lodash.clonedeep. ```tsx import cloneDeep from 'lodash.clonedeep'; const newNodes = nodes; // DO NOT DO THAT const newNodes = cloneDeep(nodes); // Do that instead ``` -------------------------------- ### useUndo(props: UndoProps) Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Undo.mdx The useUndo hook manages the history of nodes and edges. It accepts configuration properties and returns methods to control undo/redo operations. ```APIDOC ## useUndo(props: UndoProps) ### Description Initializes the undo/redo history management for nodes and edges. It returns an object containing control methods and state status. ### Parameters - **nodes** (NodeData[]) - Required - Current node data. - **edges** (EdgeData[]) - Required - Current edge data. - **maxHistory** (number) - Optional - Maximum number of history states to keep. - **disabled** (boolean) - Optional - Whether the undo/redo functionality is disabled. - **onUndoRedo** (function) - Required - Callback triggered on undo/redo events, receiving an UndoRedoEvent. ### Returns (UndoResult) - **canUndo** (boolean) - Whether an undo operation is possible. - **canRedo** (boolean) - Whether a redo operation is possible. - **count** (function) - Returns the number of existing changes in history. - **clear** (function) - Clears history and resets to the provided nodes and edges. - **history** (function) - Returns the full history of node and edge states. - **undo** (function) - Performs an undo operation. - **redo** (function) - Performs a redo operation. ``` -------------------------------- ### Add Node and Edge with Port Linking Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Extending.mdx Adds a node and an optional edge, automatically connecting the fromNode's EAST port to the newNode's WEST port. ```typescript export function addNodeAndEdgeThroughPorts( nodes: BaseNodeData[], edges: BaseEdgeData[], newNode: BaseNodeData, fromNode?: BaseNodeData, toNode?: BaseNodeData, fromPort?: BasePortData, toPort?: BasePortData, ): CanvasDataset { // The default destination node is the newly created node toNode = toNode || newNode; const newEdge: BaseEdgeData = createEdge( fromNode, toNode, getDefaultFromPort(fromNode, fromPort), getDefaultToPort(toNode, toPort), ); return { nodes: [...nodes, newNode], edges: [ ...edges, ...(fromNode ? [ newEdge, ] : []), ], }; } ``` -------------------------------- ### Customizing Canvas Elements Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/Styling.mdx Demonstrates how to override node, edge, and arrow properties using the Canvas component. ```jsx import { Canvas, Node, Edge, Port, MarkerArrow } from 'reaflow'; export const CustomCanvas: FC = () => ( } port={} /> } arrow={} edge={} /> ); ``` -------------------------------- ### SelectionProps Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Defines the configuration properties accepted by the useSelection hook. ```ts export interface SelectionProps { /** * Current selections. */ selections?: string[]; /** * Node datas. */ nodes?: NodeData[]; /** * Edge datas. */ edges?: EdgeData[]; /** * Hotkey types. */ hotkeys?: HotkeyTypes[]; /** * Disabled or not. */ disabled?: boolean; /** * On selection change. */ onSelection?: (value: string[]) => void; /** * On data change. */ onDataChange?: (nodes: NodeData[], edges: EdgeData[]) => void; } ``` -------------------------------- ### Implementing Node Linking with Canvas Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/LinkingNodes.mdx Uses onNodeLinkCheck to prevent duplicate links via the hasLink helper and onNodeLink to update the edge state. ```tsx import React, { useState } from 'react'; import { Canvas, hasLink, NodeData, EdgeData } from 'reaflow'; export default () => { const [nodes, setNodes] = useState([ { id: '1', text: '1' }, { id: '2', text: '2' } ]); const [edges, setEdges] = useState([]); return ( { return !hasLink(edges, from, to); }} onNodeLink={(event, from, to) => { const id = `${from.id}-${to.id}`; setEdges([ ...edges, { id, from: from.id, to: to.id } ]); }} /> ) }; ``` -------------------------------- ### Manual Selection Canvas Implementation Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Manually handling selection events and state updates within the Canvas component. ```jsx { console.log('Selecting Node', event, node); setSelections([node.id]); }} /> } edge={ { console.log('Selecting Edge', event, edge); setSelections([edge.id]); }} /> } onCanvasClick={(event) => { console.log('Canvas Clicked', event); setSelections([]); }} onLayoutChange={layout => console.log('Layout', layout)} /> ``` -------------------------------- ### Implement useProximity with Framer Motion Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Proximity.mdx Integrates the useProximity hook with framer-motion drag controls to manage node proximity detection and canvas updates during drag operations. ```tsx import React, { useState, useRef } from 'react'; import { useProximity, CanvasRef, addNodeAndEdge, Canvas, EdgeData, NodeData } from 'reaflow'; import { useDragControls } from 'framer-motion'; const App = () => { // This is the controls from framer-motion for dragging const dragControls = useDragControls(); // We need to create a reference to the canvas so we can pass // it to the hook so it has knowledge about the canvas const canvasRef = useRef(null); // We need to determine if we can drop the element onto the canvas const [droppable, setDroppable] = useState(false); // Let's save the node that we have "entered" so that when the user // ends the drag we can link it const [enteredNode, setEnteredNode] = useState(null); // Just some empty arrays for demo purposes, this would normally // be whatever your graph contains const [edges, setEdges] = useState([]); const [nodes, setNodes] = useState([]); const { // Drag event handlers we need to hook into our drag onDragStart: onProximityDragStart, onDrag: onProximityDrag, onDragEnd: onProximityDragEnd } = useProximity({ // The ref we defined above canvasRef, onMatchChange: (match: string | null) => { // If there is a match, let's find the node in // our models here let matchNode: NodeData | null = null; if (match) { matchNode = nodes.find(n => n.id === match); } // Now let's set the matched node setEnteredNode(matchNode); // We set this seperately from the enteredNode because // you might want to do some validation on whether you can drop or not setDroppable(matchNode !== null); } }); const onDragStart = (event) => { // Call the hook's drag start onProximityDragStart(event); // Have the drag snap to our cursor dragControls.start(event, { snapToCursor: true }); }; const onDragEnd = (event) => { // Call our proximity to let it know we are done dragging onProximityDragEnd(event); // If its droppable let's add it to the canvas if (droppable) { // Let's use our addNodeAndEdge helper function const result = addNodeAndEdge( nodes, edges, // Make this whatever you want to drop { id: 'random', text: 'random' }, // Let's add it using the closest node enteredNode ); // Update our edges and nodes setNodes(result.nodes); setEdges(result.edges); } // Reset the drop state setDroppable(false); setEnteredNode(null); }; return (
Drag Me! {activeDrag && (
Dragger!
)}
) } ``` -------------------------------- ### useSelection Hook Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx The useSelection hook manages selection state, hotkeys, and event handlers for nodes and edges. ```APIDOC ## useSelection(props: SelectionProps) ### Description Initializes selection management for nodes and edges, providing state and event handlers for interaction. ### Parameters - **selections** (string[]) - Optional - Current selection IDs. - **nodes** (NodeData[]) - Optional - Array of node data. - **edges** (EdgeData[]) - Optional - Array of edge data. - **hotkeys** (HotkeyTypes[]) - Optional - Custom hotkey configurations. - **disabled** (boolean) - Optional - Whether selection is disabled. - **onSelection** (function) - Optional - Callback triggered on selection change: (value: string[]) => void. - **onDataChange** (function) - Optional - Callback triggered on data change: (nodes: NodeData[], edges: EdgeData[]) => void. ### Returns - **selections** (string[]) - Current selection IDs. - **clearSelections** (function) - Clears selections: (value?: string[]) => void. - **addSelection** (function) - Adds a selection: (value: string) => void. - **removeSelection** (function) - Removes a selection: (value: string) => void. - **toggleSelection** (function) - Toggles a selection: (value: string) => void. - **setSelections** (function) - Sets internal selections: (value: string[]) => void. - **onClick** (function) - Event handler for node/edge clicks. - **onCanvasClick** (function) - Event handler for canvas clicks. - **onKeyDown** (function) - Event handler for keyboard events. ``` -------------------------------- ### Fix broken links Source: https://github.com/reaviz/reaflow/blob/master/docs/Contributing.mdx Commands to reset node_modules and re-establish links when dependencies are updated. ```bash rm -rf node_modules && yarn && yarn link:reaflow ``` -------------------------------- ### Manual Selection State Definition Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Defining local state for manual selection management without the hook. ```jsx import { NodeData, EdgeData } from 'reaflow'; const [selections, setSelections] = useState([]); const [nodes] = useState([ { id: '1', text: 'Node 1' }, { id: '2', text: 'Node 2' } ]); const [edges] = useState([ { id: '1-2', from: '1', to: '2' } ]); ``` -------------------------------- ### Render Diagram with Canvas Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/Basics.mdx Pass the defined nodes and edges arrays to the Canvas component to render the diagram. ```jsx import React from 'react'; import { Canvas } from 'reaflow'; export const MyDiagram = () => ( ); ``` -------------------------------- ### Upsert Node into Edge with Port Linking Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Extending.mdx Splits an existing edge into two by inserting a node, automatically linking the new node's WEST and EAST ports to the respective edge segments. ```typescript export function upsertNodeThroughPorts( nodes: BaseNodeData[], edges: BaseEdgeData[], edge: BaseEdgeData, newNode: BaseNodeData, ): CanvasDataset { const oldEdgeIndex = edges.findIndex(e => e.id === edge.id); const edgeBeforeNewNode = { ...edge, id: `${edge.from}-${newNode.id}`, to: newNode.id, }; const edgeAfterNewNode = { ...edge, id: `${newNode.id}-${edge.to}`, from: newNode.id, }; if (edge.fromPort && edge.toPort) { const fromLeftNodeToWestPort: BasePortData | undefined = newNode?.ports?.find((port: BasePortData) => port?.side === 'WEST'); const fromRightNodeToEastPort: BasePortData | undefined = newNode?.ports?.find((port: BasePortData) => port?.side === 'EAST'); edgeBeforeNewNode.fromPort = edge.fromPort; edgeBeforeNewNode.toPort = fromLeftNodeToWestPort?.id || `${newNode.id}-to`; edgeAfterNewNode.fromPort = fromRightNodeToEastPort?.id || `${newNode.id}-from`; edgeAfterNewNode.toPort = edge.toPort; } edges.splice(oldEdgeIndex, 1, edgeBeforeNewNode, edgeAfterNewNode); return { nodes: [...nodes, newNode], edges: [...edges], }; } ``` -------------------------------- ### createEdgeFromNodes Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Creates an edge between two nodes. ```APIDOC ## createEdgeFromNodes(fromNode: NodeData, toNode: NodeData) => EdgeData ### Description The `createEdgeFromNodes` function simplifies creating an edge between two nodes. ``` -------------------------------- ### UndoResult Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Undo.mdx Properties and methods returned by the useUndo hook. ```ts export interface UndoResult { /** * Can undo or not. */ canUndo: boolean; /** * Can redo or not. */ canRedo: boolean; /** * Count of existing changes. */ count: () => number; /** * Clear state and save first element of new state. */ clear: (nodes: NodeData[]; edges: EdgeData[]) => void; /** * Get history of state. */ history: () => { nodes: NodeData[]; edges: EdgeData[] }[]; /** * Perform an redo. */ redo: () => void; /** * Perform a undo. */ undo: () => void; } ``` -------------------------------- ### Create Edge from Nodes in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Creates a new edge between two specified nodes. ```js createEdgeFromNodes( fromNode: NodeData, toNode: NodeData ) => EdgeData ``` ```js import { createEdgeFromNodes } from 'reaflow'; const newEdge = createEdgeFromNodes( fromNode, toNode ); setEdges([...edges, newEdge]); ``` -------------------------------- ### Define IconData Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/DataShapes.mdx Specifies the dimensions and source URL for node icons. ```ts export interface IconData { /** * URL for the icon. */ url: string; /** * Height of the icon. */ height: number; /** * Width of the icon. */ width: number; } ``` -------------------------------- ### ProximityProps Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Proximity.mdx Defines the configuration options for the useProximity hook, including distance thresholds and event callbacks. ```ts export interface ProximityProps { /** * Disable proximity or not. */ disabled?: boolean; /** * Min distance required before match is made. Default is 40. */ minDistance?: number; /** * Ref pointer to the canvas. */ canvasRef?: RefObject; /** * Distance from the match. */ onDistanceChange?: (distance: number | null) => void; /** * When a match state has changed. */ onMatchChange?: (matche: string | null, distance: number | null) => void; /** * When the pointer intersects a node. */ onIntersects?: (matche: string | null) => void; } ``` -------------------------------- ### Remove and Upsert Nodes in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Removes a node and links its child edges to the parent of the removed node. ```js removeAndUpsertNodes( nodes: NodeData[], edges: EdgeData[], removeNodes: NodeData | NodeData[], onNodeLinkCheck?: ( newNodes: NodeData[], newEdges: EdgeData[], from: NodeData, to: NodeData, port?: PortData ) => undefined | boolean ) => { nodes: NodeData[]; edges: EdgeData[]; } ``` ```js import { removeAndUpsertNodes } from 'reaflow'; const result = removeAndUpsertNodes(nodes, edges, node); setNodes(results.nodes); setEdges(results.edges); ``` -------------------------------- ### Retrieve Edges by Node Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Returns all edges associated with a node, categorized by incoming and outgoing connections. ```js getEdgesByNode( edges: EdgeData[], node: NodeData, ) => { all: EdgeData[], to: EdgeData[], from: EdgeData[] } ``` ```js import { getEdgesByNode } from 'reaflow'; const { all, to, from } = getEdgesByNode(edges, node); if (!all.length) { // Do something } ``` -------------------------------- ### Define PortData Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/DataShapes.mdx Defines connection points on a node, specifying their location and visual properties. ```ts export interface PortData { /** * Unique ID of the port. */ id: string; /** * Height of the port. */ height: number; /** * Width of the port. */ width: number; /** * Whether the port is visually hidden or not. */ hidden?: boolean; /** * Classname for the port. */ className?: string; /** * Alignment of the port. */ alignment?: 'CENTER'; /** * Side the port is located. */ side: 'NORTH' | 'SOUTH' | 'EAST' | 'WEST'; /** * Port is disabled. */ disabled?: boolean; } ``` -------------------------------- ### Check for Existing Links Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Checks if a link already exists between a source node and a target node. ```js hasLink( edges: EdgeData[], fromNode: NodeData, toNode: NodeData ) => boolean; ``` ```js import { hasLink } from 'reaflow'; const has = hasLink(edges, fromNode, toNode); if (!has) { // Do something } ``` -------------------------------- ### Detect Circular Dependencies Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Determines if connecting a source node to a target node creates a circular link. ```js detectCircular( nodes: NodeData[], edges: EdgeData[], fromNode: NodeData, toNode: NodeData ) => boolean; ``` ```js import { detectCircular } from 'reaflow'; const has = detectCircular(nodes, edges, fromNode, toNode); if (!has) { // Do something } ``` -------------------------------- ### SelectionResult Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Defines the methods and event handlers returned by the useSelection hook. ```ts export interface SelectionResult { /** * Selections id array. */ selections: string[]; /** * Clear selections method. */ clearSelections: (value?: string[]) => void; /** * A selection method. */ addSelection: (value: string) => void; /** * Remove selection method. */ removeSelection: (value: string) => void; /** * Toggle existing selection on/off method. */ toggleSelection: (value: string) => void; /** * Set internal selections. */ setSelections: (value: string[]) => void; /** * On click event pass through. */ onClick?: ( event: React.MouseEvent, data: any ) => void; /** * On canvas click event pass through. */ onCanvasClick?: (event?: React.MouseEvent) => void; /** * On keydown event pass through. */ onKeyDown?: (event: React.KeyboardEvent) => void; } ``` -------------------------------- ### Canvas Integration with useSelection Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Selection.mdx Passing hook-generated handlers and state to the Canvas component. ```jsx { const result = removeAndUpsertNodes(nodes, edges, node); setEdges(result.edges); setNodes(result.nodes); clearSelections(); }} /> } edge={ } onCanvasClick={onCanvasClick} /> ``` -------------------------------- ### Define NodeData Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/DataShapes.mdx Defines the structure for graph nodes, including layout, ports, and custom data. ```ts export interface NodeData { /** * Unique ID for the node. */ id: string; /** * Whether the node is disabled or not. */ disabled?: boolean; /** * Text label for the node. */ text?: any; /** * Optional height attribute. If not passed with calculate * default sizes using text. */ height?: number; /** * Optional width attribute. If not passed with calculate * default sizes using text. */ width?: number; /** * Parent node id for nesting. */ parent?: string; /** * List of ports. */ ports?: PortData[]; /** * Icon for the node. */ icon?: IconData; /** * Padding for the node. */ nodePadding?: number | [number, number] | [number, number, number, number]; /** * Data for the node. */ data?: T; /** * CSS classname for the node. */ className?: string; /** * ELK layout options. */ layoutOptions?: ElkNodeLayoutOptions; /** * Whether the node can be clicked. */ selectionDisabled?: boolean; } ``` -------------------------------- ### Conditional Canvas Rendering for SSR Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/SSRSupport.mdx Use a typeof window check to ensure the Canvas component only mounts on the client side. ```tsx import React from 'react'; import { Canvas } from 'reaflow'; const Page = () => (
{ // Don't render the Canvas on the server typeof window !== 'undefined' && ( ) }
); export default Page; ``` -------------------------------- ### Define Nodes and Edges Data Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/Basics.mdx Nodes require an id property and optional text or icon. Edges define relationships between nodes using from and to properties. ```js const nodes = [ { id: '1', text: '1' }, { id: '2', text: '2' } ]; const edges = [ { id: '1-2', from: '1', to: '2' } ]; ``` -------------------------------- ### upsertNode Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Inserts a new node between two other nodes. ```APIDOC ## upsertNode(nodes: NodeData[], edges: EdgeData[], edge: EdgeData, newNode: NodeData) => { nodes: NodeData[]; edges: EdgeData[]; } ### Description The `upsertNode` function helps you insert a new node between two other nodes. ``` -------------------------------- ### addNodeAndEdge Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Adds a node to a nodes array and an optional edge. ```APIDOC ## addNodeAndEdge(nodes: NodeData[], edges: EdgeData[], node: NodeData, toNode?: NodeData) => { nodes: NodeData[]; edges: EdgeData[]; } ### Description The `addNodeAndEdge` helper is a shortcut function to add a node to a nodes array and a optional edge. ``` -------------------------------- ### removeAndUpsertNodes Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Removes a node and links child edges to the parent of the removed node. ```APIDOC ## removeAndUpsertNodes(nodes: NodeData[], edges: EdgeData[], removeNodes: NodeData | NodeData[], onNodeLinkCheck?: (newNodes: NodeData[], newEdges: EdgeData[], from: NodeData, to: NodeData, port?: PortData) => undefined | boolean) => { nodes: NodeData[]; edges: EdgeData[]; } ### Description The `removeAndUpsertNodes` helper allows you to remove a node that has existing `to` and `from` edges and link the child edges from the node remove to the parent of the node removed. ``` -------------------------------- ### Upsert Node in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Inserts a new node between two existing nodes. ```js upsertNode( nodes: NodeData[], edges: EdgeData[], edge: EdgeData, newNode: NodeData ) => { nodes: NodeData[]; edges: EdgeData[]; } ``` ```js import { upsertNode} from 'reaflow'; const id = `node-${Math.random()}`; const newNode = { id, text: id }; const results = upsertNode(nodes, edges, edge, newNode); setNodes(results.nodes); setEdges(results.edges); ``` -------------------------------- ### ProximityResult Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Proximity.mdx Defines the return object of the useProximity hook, providing the current match ID and drag event handlers. ```ts export interface ProximityResult { /** * The matched id of the node. */ match: string | null; /** * Event for drag started. */ onDragStart: (event: PointerEvent) => void; /** * Event for active dragging. */ onDrag: (event: PointerEvent) => void; /** * Event for drag ended. */ onDragEnd: (event: PointerEvent) => void; } ``` -------------------------------- ### Traverse Parent Nodes Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Retrieves all parent nodes for a specified node ID. ```js getParentsForNodeId( nodes: NodeData[], edges: EdgeData[], nodeId: string ) => NodeData[]; ``` ```js import { getParentsForNodeId } from 'reaflow'; const nodes = getParentsForNodeId(nodes, edges, node.id); ``` -------------------------------- ### useProximity(props: ProximityProps) Source: https://github.com/reaviz/reaflow/blob/master/docs/Helpers/Proximity.mdx A React hook that calculates proximity between a pointer and nodes on a canvas. ```APIDOC ## useProximity(props: ProximityProps) ### Description Calculates the proximity of the mouse pointer to nodes on the canvas and triggers callbacks based on distance and intersection thresholds. ### Parameters - **disabled** (boolean) - Optional - Disable proximity detection. - **minDistance** (number) - Optional - Minimum distance required for a match (default: 40). - **canvasRef** (RefObject) - Optional - Reference pointer to the canvas. - **onDistanceChange** (function) - Optional - Callback triggered when distance changes: (distance: number | null) => void. - **onMatchChange** (function) - Optional - Callback triggered when match state changes: (match: string | null, distance: number | null) => void. - **onIntersects** (function) - Optional - Callback triggered when pointer intersects a node: (match: string | null) => void. ### Returns - **match** (string | null) - The ID of the currently matched node. - **onDragStart** (function) - Event handler for drag start: (event: PointerEvent) => void. - **onDrag** (function) - Event handler for active dragging: (event: PointerEvent) => void. - **onDragEnd** (function) - Event handler for drag end: (event: PointerEvent) => void. ``` -------------------------------- ### hasLink Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Checks if a link already exists between a source node and a target node. ```APIDOC ## hasLink(edges, fromNode, toNode) ### Description Determines if there is an existing edge connecting the source node to the target node. ### Signature `hasLink(edges: EdgeData[], fromNode: NodeData, toNode: NodeData) => boolean` ``` -------------------------------- ### CanvasRef Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/Refs.mdx The CanvasRef interface allows external control over the Canvas component instance. It provides access to internal DOM elements, layout data, and methods for manipulating the view. ```APIDOC ## CanvasRef Interface ### Properties - **svgRef** (RefObject) - Reference to the canvas SVG element. - **xy** ([number, number]) - Current X/Y offset. - **scrollXY** ([number, number]) - Current scroll offset. - **layout** (ElkRoot) - The ELK layout object. - **containerRef** (RefObject) - Reference to the container div. - **canvasHeight** (number) - Height of the svg. - **canvasWidth** (number) - Width of the svg. - **containerWidth** (number) - Width of the container div. - **containerHeight** (number) - Height of the container div. - **zoom** (number) - Current zoom factor. ### Methods - **positionCanvas**(position: CanvasPosition, animated?: boolean) - Positions the canvas to the viewport. - **fitCanvas**(animated?: boolean) - Fits the entire canvas to the viewport. - **fitNodes**(nodeIds: string | string[], animated?: boolean) - Fits a specific group of nodes to the viewport. - **setScrollXY**(xy: [number, number], animated?: boolean) - Scrolls the canvas to the specified X/Y coordinates. - **setZoom**(factor: number) - Sets the zoom factor of the canvas. - **zoomIn**(zoomFactor?: number) - Zooms in on the canvas. - **zoomOut**(zoomFactor?: number) - Zooms out on the canvas. ``` -------------------------------- ### Define EdgeData Interface Source: https://github.com/reaviz/reaflow/blob/master/docs/GettingStarted/DataShapes.mdx Defines the connection between nodes, including source/target references and port identifiers. ```ts export interface EdgeData { /** * Unique ID of the edge. */ id: string; /** * Whether the edge is disabled or not. */ disabled?: boolean; /** * Text label for the edge. */ text?: any; /** * ID of the from node. */ from?: string; /** * ID of the to node. */ to?: string; /** * Optional ID of the from port. */ fromPort?: string; /** * Optional ID of the to port. */ toPort?: string; /** * Data about the edge. */ data?: T; /** * CSS Classname for the edge. */ className?: string; /** * Optional arrow head type. */ arrowHeadType?: any; /** * Parent of the edge for nesting. */ parent?: string; /** * Whether the edge can be clicked. */ selectionDisabled?: boolean; } ``` -------------------------------- ### Avoid Direct State Mutation with React.useState Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/StateMgmt.mdx Demonstrates the incorrect approach of mutating state directly when using React.useState, which fails to trigger re-renders. ```tsx import React, { useState } from 'react'; import { NodeData } from 'reaflow'; const [nodes, setNodes] = useState([]); ... const newNodes = nodes; // DO NOT DO THAT newNodes[0] = { id: '1' }; console.log('updateCurrentNode new nodes', newNodes); // Will print the expected object setNodes(newNodes); // Will not crash, but won't actually mutate the state for real ``` -------------------------------- ### Accessing Canvas via useRef Source: https://github.com/reaviz/reaflow/blob/master/docs/Advanced/Refs.mdx Use the useRef hook to obtain a reference to the Canvas component for external manipulation. ```jsx export const MyCanvas: FC = () => { const ref = useRef(null); useEffect(() => { // Refs give you ability to do things like: // ref.current?.centerCanvas() }, [ref]); return ; }; ``` -------------------------------- ### Remove Node in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Removes a node and all associated edges. ```js removeNode( nodes: NodeData[], edges: EdgeData[], removeNodes: string | string[] ) => { nodes: NodeData[]; edges: EdgeData[]; } ``` ```js import { removeNode } from 'reaflow'; const results = removeNode(nodes, edges, nodeIds); setNodes(results.nodes); setEdges(results.edges); ``` -------------------------------- ### Remove Edges from Node in Reaflow Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Utils.mdx Removes all edges connected to a specific node. ```js removeEdgesFromNode( nodeId: string, edges: EdgeData[] ) => EdgeData[] ``` ```js import { removeEdgesFromNode } from 'reaflow'; const newEdges = removeEdgesFromNode( node.id, edges ); setEdges(newEdges); ``` -------------------------------- ### detectCircular Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Determines if connecting a source node to a target node will create a circular link. ```APIDOC ## detectCircular(nodes, edges, fromNode, toNode) ### Description Checks if a connection between two nodes would result in a circular dependency within the graph. ### Signature `detectCircular(nodes: NodeData[], edges: EdgeData[], fromNode: NodeData, toNode: NodeData) => boolean` ``` -------------------------------- ### Remove Node and Merge Edges Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Extending.mdx Removes one or more nodes and merges the surrounding edges, automatically linking the source and target nodes via their EAST and WEST ports. ```typescript export function removeAndUpsertNodesThroughPorts( nodes: BaseNodeData[], edges: BaseEdgeData[], removeNodes: BaseNodeData | BaseNodeData[], onNodeLinkCheck?: ( newNodes: BaseNodeData[], newEdges: BaseEdgeData[], from: BaseNodeData, to: BaseNodeData, port?: BasePortData, ) => undefined | boolean, ): CanvasDataset { if (!Array.isArray(removeNodes)) { removeNodes = [removeNodes]; } const nodeIds = removeNodes.map((n) => n.id); const newNodes = nodes.filter((n) => !nodeIds.includes(n.id)); const newEdges = edges.filter( (e: BaseEdgeData) => !nodeIds.includes(e?.from as string) && !nodeIds.includes(e?.to as string), ); for (const nodeId of nodeIds) { const sourceEdges = edges.filter((e) => e.to === nodeId); const targetEdges = edges.filter((e) => e.from === nodeId); for (const sourceEdge of sourceEdges) { for (const targetEdge of targetEdges) { const sourceNode = nodes.find((n) => n.id === sourceEdge.from); const targetNode = nodes.find((n) => n.id === targetEdge.to); if (sourceNode && targetNode) { const canLink = onNodeLinkCheck?.( newNodes, newEdges, sourceNode, targetNode, ); if (canLink === undefined || canLink) { const fromPort: BasePortData | undefined = sourceNode?.ports?.find((port: BasePortData) => port?.side === 'EAST'); const toPort: BasePortData | undefined = targetNode?.ports?.find((port: BasePortData) => port?.side === 'WEST'); newEdges.push({ id: `${sourceNode.id}-${targetNode.id}`, from: sourceNode.id, to: targetNode.id, parent: sourceNode?.parent, fromPort: fromPort?.id, toPort: toPort?.id, }); } } } } } return { edges: newEdges, nodes: newNodes, }; } ``` -------------------------------- ### getParentsForNodeId Source: https://github.com/reaviz/reaflow/blob/master/docs/Utils/Graph.mdx Retrieves all parent nodes for a specified node ID. ```APIDOC ## getParentsForNodeId(nodes, edges, nodeId) ### Description Finds and returns all parent nodes associated with the provided node ID. ### Signature `getParentsForNodeId(nodes: NodeData[], edges: EdgeData[], nodeId: string) => NodeData[]` ```