@@ -101,6 +101,7 @@ export function WorkflowCanvas() {
101101 useReactFlow ( ) ;
102102
103103 const connectingNodeId = useRef < string | null > ( null ) ;
104+ const connectingHandleType = useRef < "source" | "target" | null > ( null ) ;
104105 const justCreatedNodeFromConnection = useRef ( false ) ;
105106 const viewportInitialized = useRef ( false ) ;
106107 const [ isCanvasReady , setIsCanvasReady ] = useState ( false ) ;
@@ -227,6 +228,18 @@ export function WorkflowCanvas() {
227228 [ ]
228229 ) ;
229230
231+ const nodeHasHandle = useCallback (
232+ ( nodeId : string , handleType : "source" | "target" ) => {
233+ const node = nodes . find ( ( node ) => node . id === nodeId ) ;
234+
235+ if ( ! node ) return false ;
236+ if ( handleType === "target" ) return node . type !== "trigger" ;
237+
238+ return node . type !== "add" ;
239+ } ,
240+ [ nodes ]
241+ ) ;
242+
230243 const isValidConnection = useCallback (
231244 ( connection : XYFlowConnection | XYFlowEdge ) => {
232245 // Ensure we have both source and target
@@ -272,6 +285,7 @@ export function WorkflowCanvas() {
272285 const onConnectStart = useCallback (
273286 ( _event : MouseEvent | TouchEvent , params : OnConnectStartParams ) => {
274287 connectingNodeId . current = params . nodeId ;
288+ connectingHandleType . current = params . handleType ;
275289 } ,
276290 [ ]
277291 ) ;
@@ -327,10 +341,36 @@ export function WorkflowCanvas() {
327341 return ;
328342 }
329343
330- const isNode = target . closest ( ".react-flow__node" ) ;
344+ const nodeElement = target . closest ( ".react-flow__node" ) ;
331345 const isHandle = target . closest ( ".react-flow__handle" ) ;
332346
333- if ( ! ( isNode || isHandle ) ) {
347+ // Create connection on edge dragged over node release
348+ if ( nodeElement && ! isHandle && connectingHandleType . current ) {
349+ const targetNodeId = nodeElement . getAttribute ( "data-id" ) ;
350+ const fromSource = connectingHandleType . current === "source" ;
351+ const requiredHandle = fromSource ? "target" : "source" ;
352+ const sourceId = fromSource ? connectingNodeId . current ! : targetNodeId ! ;
353+ const targetId = fromSource ? targetNodeId ! : connectingNodeId . current ! ;
354+
355+ if (
356+ targetNodeId &&
357+ targetNodeId !== connectingNodeId . current &&
358+ nodeHasHandle ( targetNodeId , requiredHandle )
359+ ) {
360+ onConnect ( {
361+ source : sourceId ,
362+ target : targetId ,
363+ sourceHandle : null ,
364+ targetHandle : null ,
365+ } ) ;
366+ }
367+
368+ connectingNodeId . current = null ;
369+ connectingHandleType . current = null ;
370+ return ;
371+ }
372+
373+ if ( ! nodeElement && ! isHandle ) {
334374 const { adjustedX, adjustedY } = calculateMenuPosition (
335375 event ,
336376 clientX ,
@@ -404,12 +444,15 @@ export function WorkflowCanvas() {
404444 }
405445
406446 connectingNodeId . current = null ;
447+ connectingHandleType . current = null ;
407448 } ,
408449 [
409450 getClientPosition ,
410451 calculateMenuPosition ,
411452 screenToFlowPosition ,
412453 addNode ,
454+ nodeHasHandle ,
455+ onConnect ,
413456 edges ,
414457 setEdges ,
415458 setNodes ,
0 commit comments