The primary interface for interacting with the workflow state.
const workflow = useWorkflow()| Property | Type | Description |
|---|---|---|
nodes |
WorkflowNode[] |
Array of all workflow nodes |
edges |
WorkflowEdge[] |
Array of all connections |
selectedNode |
string | null |
ID of currently selected node |
selectedEdge |
string | null |
ID of currently selected edge |
onNodesChange(changes: NodeChange[]): voidHandles node-related changes (position, selection, removal).
onEdgesChange(changes: EdgeChange[]): voidHandles edge-related changes (selection, removal).
onConnect(connection: Connection): voidCreates a new edge between nodes.
Parameters:
connection.source- Source node IDconnection.target- Target node IDconnection.sourceHandle- Source handle ID (optional)connection.targetHandle- Target handle ID (optional)
addNode(node: WorkflowNode): voidAdds a new node to the workflow.
Example:
addNode({
id: 'action-1',
type: 'action',
position: { x: 400, y: 300 },
data: {
label: 'Send Email',
type: 'action',
stepNumber: '2',
integrationName: 'Gmail',
},
})updateNode(nodeId: string, updates: Partial<WorkflowNode>): voidUpdates an existing node's properties.
deleteNode(nodeId: string): voidRemoves a node and its connected edges.
setSelectedNode(nodeId: string | null): voidSets the selected node for highlighting.
setSelectedEdge(edgeId: string | null): voidSets the selected edge for highlighting.
clearWorkflow(): voidRemoves all nodes and edges.
interface CustomNodeProps {
id: string
data: WorkflowNodeData
selected: boolean
type: string
dragging: boolean
zIndex: number
isConnectable: boolean
position: XYPosition
// ... other ReactFlow NodeProps
}Same as TriggerNode props.
interface EdgeProps {
id: string
source: string
target: string
sourceX: number
sourceY: number
targetX: number
targetY: number
sourcePosition: Position
targetPosition: Position
markerEnd?: string
// ... other ReactFlow EdgeProps
}type WorkflowNode = Node<WorkflowNodeData, NodeType>
interface WorkflowNodeData {
label: string // Display text
type: NodeType // Node variant
icon?: string // Icon identifier
description?: string // Tooltip/description
config?: Record<string, any> // Node-specific config
integrationLogo?: string // Logo URL
integrationName?: string // Integration display name
stepNumber?: string // Step sequence number
[key: string]: any // Additional properties
}type WorkflowEdge = Edge<{
label?: string // Edge label
condition?: any // Conditional logic
}>type NodeType = 'trigger' | 'action' | 'router' | 'branch'onNodeClick?: (event: React.MouseEvent, node: Node) => void
onNodeDoubleClick?: (event: React.MouseEvent, node: Node) => void
onNodeMouseEnter?: (event: React.MouseEvent, node: Node) => void
onNodeMouseLeave?: (event: React.MouseEvent, node: Node) => voidonEdgeClick?: (event: React.MouseEvent, edge: Edge) => void
onEdgeDoubleClick?: (event: React.MouseEvent, edge: Edge) => voidonPaneClick?: (event: React.MouseEvent) => void
onPaneScroll?: (event: React.WheelEvent) => void
onPaneContextMenu?: (event: React.MouseEvent) => void// Generate unique node ID
const generateNodeId = (): string => {
return `node_${Date.now()}`
}
// Create trigger node
const createTriggerNode = (position: XYPosition, data: Partial<WorkflowNodeData>): WorkflowNode => {
return {
id: generateNodeId(),
type: 'trigger',
position,
data: {
type: 'trigger',
stepNumber: '1',
...data,
},
}
}
// Create action node
const createActionNode = (position: XYPosition, data: Partial<WorkflowNodeData>): WorkflowNode => {
return {
id: generateNodeId(),
type: 'action',
position,
data: {
type: 'action',
...data,
},
}
}// Calculate node position in vertical layout
const calculateNodePosition = (index: number, startY: number = 100, spacing: number = 200): XYPosition => {
return {
x: 400, // Fixed X coordinate
y: startY + index * spacing,
}
}
// Get middle position between two nodes
const getMiddlePosition = (node1: Node, node2: Node): XYPosition => {
return {
x: (node1.position.x + node2.position.x) / 2,
y: (node1.position.y + node2.position.y) / 2,
}
}// Layout constants
export const LAYOUT = {
NODE_WIDTH: 350,
NODE_HEIGHT: 85,
NODE_SPACING: 200,
CENTER_X: 400,
START_Y: 100,
}
// Style constants
export const STYLES = {
TRIGGER_COLOR: '#6366f1',
ACTION_COLOR: '#9ca3af',
EDGE_COLOR: '#9ca3af',
SELECTED_COLOR: '#6366f1',
BACKGROUND_COLOR: '#fafafa',
}