@@ -6,6 +6,8 @@ A reusable React library for building serverless workflow editors using React Fl
66
77- ** 🎯 Pre-built Node Components** : Ready-to-use React Flow nodes for different workflow states (Start, Operation, Switch, Event, Sleep, End)
88- ** 🔄 State Management Hooks** : Comprehensive hooks for workflow state, history management, and edge connections
9+ - ** 🚀 Programmatic Node Creation** : Add, remove, and manipulate workflow nodes programmatically with useWorkflowActions hook
10+ - ** 🏭 Node Factory Utilities** : Low-level utilities for creating workflow nodes with custom configurations
911- ** 📊 Workflow Conversion** : Bidirectional conversion between React Flow data and Serverless Workflow specification
1012- ** 🎨 Smart Edge Styling** : Automatic edge styling with animations, colors, and labels based on node types
1113- ** ⏮️ Undo/Redo Support** : Built-in history management with undo/redo functionality
@@ -39,6 +41,7 @@ import {
3941 useHistory ,
4042 useWorkflowState ,
4143 useEdgeConnection ,
44+ useWorkflowActions ,
4245 createServerlessWorkflow ,
4346 convertWorkflowToReactFlow ,
4447} from ' serverless-workflow-builder-lib' ;
@@ -83,6 +86,12 @@ function WorkflowEditor() {
8386 workflowMetadata
8487 );
8588
89+ // Initialize workflow actions for programmatic node creation
90+ const workflowActions = useWorkflowActions (
91+ { nodes, edges, workflowMetadata, updateNodes, updateEdges },
92+ setHistoryState
93+ );
94+
8695 // Convert current workflow to Serverless Workflow JSON
8796 const exportWorkflow = () => {
8897 const workflow = createServerlessWorkflow (nodes, edges, workflowMetadata);
@@ -611,6 +620,210 @@ const stats = getWorkflowStats();
611620console .log (` Total nodes: ${ stats .totalNodes } ` );
612621```
613622
623+ ### useWorkflowActions
624+
625+ Provides functions to programmatically add, remove, and manipulate workflow nodes.
626+
627+ ``` jsx
628+ import { useWorkflowActions } from ' serverless-workflow-builder-lib' ;
629+
630+ const workflowActions = useWorkflowActions (workflowState, historyCallback);
631+
632+ const {
633+ // Add specific node types
634+ addOperationNode, // Add operation node
635+ addSleepNode, // Add sleep node
636+ addEventNode, // Add event node
637+ addSwitchNode, // Add switch node
638+ addEndNode, // Add end node
639+ addStartNode, // Add start node
640+
641+ // Generic functions
642+ addNode, // Add any node type
643+ removeNode, // Remove node by ID
644+ duplicateNode, // Duplicate existing node
645+ clearAllNodes, // Clear all nodes
646+
647+ // Utility
648+ getDefaultPosition // Get default position for new nodes
649+ } = workflowActions;
650+ ```
651+
652+ #### Parameters
653+ - ` workflowState ` : The workflow state object from useWorkflowState
654+ - ` historyCallback ` : Optional callback to update history state
655+
656+ #### Example
657+
658+ ``` jsx
659+ function WorkflowEditor () {
660+ const { nodes , edges , workflowMetadata , updateNodes , updateEdges } = useWorkflowState (
661+ defaultInitialNodes,
662+ defaultInitialEdges,
663+ workflowMetadata
664+ );
665+
666+ const { setState: setHistoryState } = useHistory ({
667+ nodes: defaultInitialNodes,
668+ edges: defaultInitialEdges,
669+ workflowMetadata
670+ });
671+
672+ const workflowActions = useWorkflowActions (
673+ { nodes, edges, workflowMetadata, updateNodes, updateEdges },
674+ setHistoryState
675+ );
676+
677+ return (
678+ < div>
679+ {/* Add state buttons */ }
680+ < div style= {{ padding: ' 10px' , display: ' flex' , gap: ' 10px' }}>
681+ < button onClick= {() => workflowActions .addOperationNode ()}>
682+ + Operation
683+ < / button>
684+ < button onClick= {() => workflowActions .addSleepNode ()}>
685+ + Sleep
686+ < / button>
687+ < button onClick= {() => workflowActions .addEventNode ()}>
688+ + Event
689+ < / button>
690+ < button onClick= {() => workflowActions .addSwitchNode ()}>
691+ + Switch
692+ < / button>
693+ < button onClick= {() => workflowActions .addEndNode ()}>
694+ + End
695+ < / button>
696+ < / div>
697+
698+ {/* Custom positioned node */ }
699+ < button
700+ onClick= {() => workflowActions .addOperationNode ({
701+ position: { x: 200 , y: 300 },
702+ name: ' Custom Operation' ,
703+ actions: [{ name: ' customAction' , functionRef: ' myFunction' }]
704+ })}
705+ >
706+ Add Custom Operation
707+ < / button>
708+
709+ {/* Remove node */ }
710+ < button onClick= {() => workflowActions .removeNode (' node-id' )}>
711+ Remove Node
712+ < / button>
713+
714+ {/* Duplicate node */ }
715+ < button onClick= {() => workflowActions .duplicateNode (' node-id' )}>
716+ Duplicate Node
717+ < / button>
718+
719+ {/* React Flow component */ }
720+ < ReactFlow
721+ nodes= {nodes}
722+ edges= {edges}
723+ nodeTypes= {nodeTypes}
724+ // ... other props
725+ / >
726+ < / div>
727+ );
728+ }
729+ ```
730+
731+ #### Node Creation Options
732+
733+ Each add function accepts an optional options object:
734+
735+ ``` jsx
736+ // Basic usage
737+ workflowActions .addOperationNode ();
738+
739+ // With custom options
740+ workflowActions .addOperationNode ({
741+ position: { x: 100 , y: 200 }, // Custom position
742+ name: ' My Operation' , // Custom name
743+ actions: [ // Custom actions
744+ { name: ' action1' , functionRef: ' func1' }
745+ ],
746+ metadata: { custom: ' data' } // Custom metadata
747+ });
748+
749+ // Sleep node with duration
750+ workflowActions .addSleepNode ({
751+ name: ' Wait 5 seconds' ,
752+ duration: ' PT5S'
753+ });
754+
755+ // Event node with events
756+ workflowActions .addEventNode ({
757+ name: ' Wait for Order' ,
758+ onEvents: [{
759+ eventRefs: [' order.created' ]
760+ }]
761+ });
762+ ```
763+
764+ ## Node Factory Utilities
765+
766+ Low-level utilities for creating workflow nodes programmatically.
767+
768+ ``` jsx
769+ import {
770+ createOperationNode ,
771+ createSleepNode ,
772+ createEventNode ,
773+ createSwitchNode ,
774+ createEndNode ,
775+ createStartNode ,
776+ createNode ,
777+ generateNodeId ,
778+ getDefaultPosition
779+ } from ' serverless-workflow-builder-lib' ;
780+ ```
781+
782+ ### Individual Node Creators
783+
784+ ``` jsx
785+ // Create specific node types
786+ const operationNode = createOperationNode ({
787+ position: { x: 100 , y: 200 },
788+ name: ' Process Order' ,
789+ actions: [{ name: ' processOrder' , functionRef: ' orderProcessor' }]
790+ });
791+
792+ const sleepNode = createSleepNode ({
793+ position: { x: 200 , y: 300 },
794+ name: ' Wait' ,
795+ duration: ' PT30S'
796+ });
797+
798+ const eventNode = createEventNode ({
799+ position: { x: 300 , y: 400 },
800+ name: ' Wait for Event' ,
801+ onEvents: [{ eventRefs: [' user.action' ] }]
802+ });
803+ ```
804+
805+ ### Generic Node Creator
806+
807+ ``` jsx
808+ // Create any node type
809+ const node = createNode (' operation' , {
810+ position: { x: 100 , y: 200 },
811+ name: ' My Node' ,
812+ // ... type-specific options
813+ });
814+ ```
815+
816+ ### Utility Functions
817+
818+ ``` jsx
819+ // Generate unique node ID
820+ const nodeId = generateNodeId (); // Returns: 'node-1234567890'
821+
822+ // Get default position for new nodes
823+ const position = getDefaultPosition (existingNodes);
824+ // Returns: { x: number, y: number }
825+ ```
826+
614827## Utilities
615828
616829### Workflow Conversion
0 commit comments