The CrystalFlow React package provides components to create visual workflow builder interfaces powered by React Flow.
Overview
The @crystalflow/react package includes:
WorkflowBuilder
Complete workflow editor component
Custom Hooks
React hooks for workflow management
Node Components
Customizable node renderers
Panels & Controls
Property panels and toolbars
Installation
npm install @crystalflow/react @crystalflow/core reflect-metadata react react-dom
Basic Usage
import React from 'react';
import { WorkflowBuilder } from '@crystalflow/react';
import { AddNode, MultiplyNode } from './nodes';
function App() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<WorkflowBuilder
nodes={[AddNode, MultiplyNode]}
onWorkflowChange={(workflow) => {
console.log('Workflow updated:', workflow);
}}
/>
</div>
);
}
export default App;
WorkflowBuilder Props
Array of node classes to make available in the palette
Optional initial workflow to load
onWorkflowChange
(workflow: Workflow) => void
Callback when workflow changes
onExecute
(result: ExecutionResult) => void
Callback when workflow executes
Show/hide the node palette
Show/hide the property panel
Complete Example
import React, { useState } from 'react';
import { WorkflowBuilder } from '@crystalflow/react';
import {
NumberInputNode,
AddNode,
MultiplyNode,
DisplayNode
} from './nodes';
function App() {
const [workflow, setWorkflow] = useState(null);
return (
<div style={{ width: '100vw', height: '100vh' }}>
<WorkflowBuilder
nodes={[
NumberInputNode,
AddNode,
MultiplyNode,
DisplayNode
]}
onWorkflowChange={(wf) => {
setWorkflow(wf);
console.log('Workflow updated');
}}
onExecute={(result) => {
console.log('Execution result:', result);
if (result.status === 'success') {
alert('Workflow executed successfully!');
} else {
alert(`Execution failed: ${result.error?.message}`);
}
}}
showToolbar={true}
showNodePalette={true}
showPropertyPanel={true}
/>
</div>
);
}
export default App;
Using Custom Hooks
For more control, use the underlying hooks:
import React from 'react';
import {
useWorkflow,
useNodeRegistry,
useExecution
} from '@crystalflow/react';
function CustomWorkflowEditor() {
const { workflow, addNode, removeNode, connect } = useWorkflow();
const { registry } = useNodeRegistry([AddNode, MultiplyNode]);
const { execute, isExecuting, result } = useExecution();
const handleAddNode = (nodeType: string) => {
addNode(nodeType, {
position: { x: 100, y: 100 }
});
};
const handleExecute = async () => {
const executionResult = await execute(workflow);
console.log('Result:', executionResult);
};
return (
<div>
<button onClick={() => handleAddNode('math.add')}>
Add Math Node
</button>
<button onClick={handleExecute} disabled={isExecuting}>
{isExecuting ? 'Executing...' : 'Execute Workflow'}
</button>
{/* Render workflow canvas */}
</div>
);
}
Node Palette
The node palette allows users to drag and drop nodes:
import { NodePalette } from '@crystalflow/react';
<NodePalette
nodes={[AddNode, MultiplyNode]}
onNodeDrop={(nodeType, position) => {
workflow.addNodeByType(nodeType, { position });
}}
/>
Property Panel
The property panel displays node properties and inputs:
import { PropertyPanel } from '@crystalflow/react';
<PropertyPanel
node={selectedNode}
onChange={(propertyName, value) => {
selectedNode.setInputValue(propertyName, value);
}}
/>
Work in Progress: Some toolbar features are still under development.
import { Toolbar } from '@crystalflow/react';
<Toolbar
onSave={() => {
const json = serializeWorkflow(workflow.toJSON());
// Save to file/API
}}
onLoad={() => {
// Load from file/API
}}
onExecute={() => {
// Execute workflow
}}
onClear={() => {
// Clear workflow
}}
/>
Customizing Appearance
Custom Node Renderer
import { CustomNode } from '@crystalflow/react';
<WorkflowBuilder
nodeRenderer={(node) => (
<CustomNode
node={node}
className="my-custom-node"
style={{
background: '#f0f0f0',
border: '2px solid #333'
}}
/>
)}
nodes={[AddNode]}
/>
Styling
.crystalflow-node {
background: white;
border: 2px solid #3b82f6;
border-radius: 8px;
padding: 16px;
}
.crystalflow-node-header {
font-weight: bold;
margin-bottom: 12px;
}
.crystalflow-input-handle {
background: #10b981;
}
.crystalflow-output-handle {
background: #ef4444;
}
React Flow Integration
WorkflowBuilder is built on React Flow. Access React Flow features:
import { ReactFlowProvider } from 'reactflow';
import { WorkflowBuilder } from '@crystalflow/react';
<ReactFlowProvider>
<WorkflowBuilder nodes={[AddNode]} />
</ReactFlowProvider>
Event Handling
Handle workflow events:
<WorkflowBuilder
nodes={[AddNode]}
onNodeAdd={(node) => console.log('Node added:', node)}
onNodeRemove={(nodeId) => console.log('Node removed:', nodeId)}
onConnectionCreate={(conn) => console.log('Connected:', conn)}
onConnectionRemove={(conn) => console.log('Disconnected:', conn)}
onNodeSelect={(node) => console.log('Node selected:', node)}
/>
Keyboard Shortcuts
Work in Progress: Keyboard shortcuts are planned for a future release.
Planned keyboard shortcuts:
Delete - Remove selected nodes
Ctrl/Cmd + Z - Undo
Ctrl/Cmd + Shift + Z - Redo
Ctrl/Cmd + S - Save workflow
Ctrl/Cmd + E - Execute workflow
Persistence
Save and load workflows:
import { serializeWorkflow, deserializeWorkflow } from '@crystalflow/core';
// Save
const saveWorkflow = () => {
const json = serializeWorkflow(workflow.toJSON());
localStorage.setItem('workflow', json);
};
// Load
const loadWorkflow = () => {
const json = localStorage.getItem('workflow');
if (json) {
const workflowData = deserializeWorkflow(json);
const loadedWorkflow = Workflow.fromJSON(workflowData);
// Set workflow in UI
}
};
Monaco Editor Integration
Work in Progress: Monaco JSON editor integration is under development for dual-mode editing (visual + code).
Planned features:
- Side-by-side visual and JSON editing
- Real-time sync between modes
- JSON schema validation
- Syntax highlighting
Best Practices
Provide Clear Node Labels
Use descriptive labels and categories to help users find nodes.
Show user-friendly error messages when execution fails.
Implement auto-save to prevent data loss.
Validate workflows before execution and show validation errors.
Show execution progress and node states during workflow execution.
Example Projects
Check out complete example projects in the repository:
- Simple Math Workflow - Basic arithmetic operations
- Data Processing Pipeline - Fetch, filter, transform data
- API Integration - HTTP requests and response handling
Next Steps