From dc89d1afad185a8e4044dea2c5431db75f74c2ab Mon Sep 17 00:00:00 2001 From: linus Date: Mon, 2 Dec 2024 12:05:56 +0100 Subject: [PATCH 1/4] Added support for rightclick connectionline and connection point to remove lines --- packages/react-pipelines/src/FlowBoard.tsx | 14 +++++++- .../react-pipelines/src/blocks/MidBlock.tsx | 6 ++-- .../react-pipelines/src/blocks/StartBlock.tsx | 6 ++-- .../src/connections/ConnectionLine.tsx | 8 +++-- .../src/connections/ConnectionPoint.tsx | 19 ++++++++--- .../src/hooks/useConnectionClick.tsx | 34 +++++++++++++++++++ .../src/hooks/useConnectionDrag.tsx | 6 +++- .../src/hooks/useConnectionDraw.tsx | 12 +++++-- .../react-pipelines/src/utils/BlockParser.tsx | 9 +++-- 9 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 packages/react-pipelines/src/hooks/useConnectionClick.tsx diff --git a/packages/react-pipelines/src/FlowBoard.tsx b/packages/react-pipelines/src/FlowBoard.tsx index e549366..db35563 100644 --- a/packages/react-pipelines/src/FlowBoard.tsx +++ b/packages/react-pipelines/src/FlowBoard.tsx @@ -8,6 +8,7 @@ import Toolbox from './toolbox/Toolbox' import { parseBlockData } from './utils/BlockParser' import { ToolBlockDefinition } from './toolbox/ToolBlock' import React from 'react' +import useConnectionRightClick from './hooks/useConnectionClick' interface FlowBoardProps { id: string @@ -49,6 +50,14 @@ const FlowBoard = ({ blockData, ...props }: FlowBoardProps) => { const { svgConnectionLines } = useConnectionDraw(connectionLinesData, blockData) + const { + handleConnectionLineRightClick, + handleOutputConnectionPointRightClick, + } = useConnectionRightClick( + props.connectionLineData, + props.onConnectionLineUpdate + ) + const dragBlock = (event: React.DragEvent) => { event.preventDefault() } @@ -122,6 +131,9 @@ const FlowBoard = ({ blockData, ...props }: FlowBoardProps) => { onDragBlockStart: () => { }, onDragBlockEnd: () => { }, }, + { + onConnectionPointRightClick: handleOutputConnectionPointRightClick + }, ), ) @@ -155,7 +167,7 @@ const FlowBoard = ({ blockData, ...props }: FlowBoardProps) => { ref={el => mainBoardRef.current = el} > {blocks} - + diff --git a/packages/react-pipelines/src/blocks/MidBlock.tsx b/packages/react-pipelines/src/blocks/MidBlock.tsx index ad53116..127a656 100644 --- a/packages/react-pipelines/src/blocks/MidBlock.tsx +++ b/packages/react-pipelines/src/blocks/MidBlock.tsx @@ -7,7 +7,7 @@ import { InputConnectionPoint, OutputConnectionPoint, } from '../connections/ConnectionPoint' -import { DragConnectionLineProps } from '../utils/BlockParser' +import { DragConnectionLineProps, ConnectionPointProps } from '../utils/BlockParser' import { TransformData } from '../utils/BlockUtils' interface MidBlockProps { @@ -17,7 +17,7 @@ interface MidBlockProps { transformData: TransformData } -const MidBlock = (props: MidBlockProps & DragConnectionLineProps) => { +const MidBlock = (props: MidBlockProps & DragConnectionLineProps & ConnectionPointProps) => { const { transformData, onDragStart, onDragEnd } = usePipelineDrag( props.transformData.translateX, props.transformData.translateY, @@ -38,6 +38,7 @@ const MidBlock = (props: MidBlockProps & DragConnectionLineProps) => { onDragStart={props.onConnectionLineDragStart} onDrag={props.onConnectionLineDrag} onDragEnd={props.onConnectionLineDragEnd} + onContextMenu= {(event) => props.onConnectionPointRightClick(`${props.id}-output`, event)} /> { onDragStart={props.onConnectionLineDragStart} onDrag={props.onConnectionLineDrag} onDragEnd={props.onConnectionLineDragEnd} + onContextMenu= {(event) => props.onConnectionPointRightClick(`${props.id}-erroroutput`, event)} /> { +const StartBlock = (props: StartBlockProps & DragConnectionLineProps & DragBlockProps & ConnectionPointProps) => { const { transformData, onDragStart, onDragEnd } = usePipelineDrag( props.transformData.translateX, props.transformData.translateY, @@ -33,6 +33,7 @@ const StartBlock = (props: StartBlockProps & DragConnectionLineProps & DragBlock onDragStart={props.onConnectionLineDragStart} onDrag={props.onConnectionLineDrag} onDragEnd={props.onConnectionLineDragEnd} + onContextMenu= {(event) => props.onConnectionPointRightClick(`${props.id}-output`, event)} /> props.onConnectionPointRightClick(`${props.id}-erroroutput`, event)} /> {props.children} diff --git a/packages/react-pipelines/src/connections/ConnectionLine.tsx b/packages/react-pipelines/src/connections/ConnectionLine.tsx index 375e43c..e10669c 100644 --- a/packages/react-pipelines/src/connections/ConnectionLine.tsx +++ b/packages/react-pipelines/src/connections/ConnectionLine.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components' interface ConnectionContainerProps { key: string lines: ConnectionSvgLineProps[] + onLineRightClick: (lineKey: string, event: React.MouseEvent) => void; } const StyledSvgContainer = styled.svg` @@ -19,10 +20,12 @@ const StyledSvgContainer = styled.svg` const StyledSvgLine = styled.line` position: absolute; - strokeWidth: 2px; + stroke-width: 2px; + transition: stroke-width 0.2s ease; &:hover { stroke: red; - } + stroke-width: 6px; + cursor: pointer; ` // const StyledSvgPath = styled.path` @@ -55,6 +58,7 @@ const ConnectionCanvas = (props: ConnectionContainerProps) => { y2={line.y2} stroke="steelblue" strokeWidth="2" + onContextMenu={(event) => props.onLineRightClick(line.key, event)} // markerEnd="url(#arrowhead)" /> ))} diff --git a/packages/react-pipelines/src/connections/ConnectionPoint.tsx b/packages/react-pipelines/src/connections/ConnectionPoint.tsx index 12fb121..25a25ad 100644 --- a/packages/react-pipelines/src/connections/ConnectionPoint.tsx +++ b/packages/react-pipelines/src/connections/ConnectionPoint.tsx @@ -6,33 +6,42 @@ const styledConnectionPoint = styled.div` height: 15px; background: white; border-radius: 50%; - cursor: crosshair; + cursor: grab; border: 1px solid black; z-index: 10; margin-bottom: 5px; + + &:hover { + border-color: lightblue; + } + + &:active { + cursor: grabbing; + border-color: lightblue; + } ` const styledInputConnectionPoint = styled(styledConnectionPoint)` left: -10px; - top: 20px; + top: 40px; background: green; ` const styledErrorInputConnectionPoint = styled(styledConnectionPoint)` left: -10px; - top: 50px; + top: 70px; background: red; ` const styledOutputConnectionPoint = styled(styledConnectionPoint)` right: -10px; -top: 20px; +top: 40px; background: green; ` const styledErrorOutputConnectionPoint = styled(styledConnectionPoint)` right: -10px; - top: 50px; + top: 70px; background: red; ` diff --git a/packages/react-pipelines/src/hooks/useConnectionClick.tsx b/packages/react-pipelines/src/hooks/useConnectionClick.tsx new file mode 100644 index 0000000..ae03b3c --- /dev/null +++ b/packages/react-pipelines/src/hooks/useConnectionClick.tsx @@ -0,0 +1,34 @@ +import { useCallback } from 'react'; +import { ConnectionLineData } from '../utils/ConnectionUtils' + +const useConnectionRightClick = ( + connectionLineData: ConnectionLineData[], + onConnectionLineUpdate: (connectionLineData: ConnectionLineData[]) => void = () => {}, +) => { + const handleConnectionLineRightClick = useCallback((lineKey: string, event: React.MouseEvent) => { + event.preventDefault() + + const updatedConnectionLineData = connectionLineData.filter( + (line) => line.key !== lineKey + ); + onConnectionLineUpdate(updatedConnectionLineData); +}, + [connectionLineData, onConnectionLineUpdate] +); + + const handleOutputConnectionPointRightClick = useCallback((connectionPointId: string, event: React.MouseEvent) => { + event.preventDefault(); + const updatedConnectionLineData = connectionLineData.filter( + (line) => line.originConnectionPointId !== connectionPointId + ); + onConnectionLineUpdate(updatedConnectionLineData); + }, + [connectionLineData, onConnectionLineUpdate] +); + return { + handleConnectionLineRightClick, + handleOutputConnectionPointRightClick, + }; +}; + +export default useConnectionRightClick; \ No newline at end of file diff --git a/packages/react-pipelines/src/hooks/useConnectionDrag.tsx b/packages/react-pipelines/src/hooks/useConnectionDrag.tsx index bb739cf..bb8ea90 100644 --- a/packages/react-pipelines/src/hooks/useConnectionDrag.tsx +++ b/packages/react-pipelines/src/hooks/useConnectionDrag.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react' +import { useState, useEffect } from 'react' import { BlockData } from '../utils/BlockUtils' import { ConnectionLineData, TemporaryConnectionLineData } from '../utils/ConnectionUtils' @@ -12,6 +12,10 @@ const useConnectionDrag = ( const [connectionLinesData, setConnectionLines] = useState<(ConnectionLineData | TemporaryConnectionLineData)[]>(connectionLineData) const [currentConnectionLine, setCurrentConnectionLine] = useState(null) + useEffect(() => { + setConnectionLines(connectionLineData); + }, [connectionLineData]); + const onOutputConnectionPointDragStart = (event: React.DragEvent) => { event.stopPropagation() event.dataTransfer.setData('originConnectionPoint', event.currentTarget.id) diff --git a/packages/react-pipelines/src/hooks/useConnectionDraw.tsx b/packages/react-pipelines/src/hooks/useConnectionDraw.tsx index 6802a33..5648203 100644 --- a/packages/react-pipelines/src/hooks/useConnectionDraw.tsx +++ b/packages/react-pipelines/src/hooks/useConnectionDraw.tsx @@ -97,7 +97,10 @@ const useConnectionDraw = ( [], ) - useEffect(() => { + useEffect(() => { + + setSvgConnectionLines([]); + const savedConnectionLines: ConnectionLineData[] = connectionLineData.filter( (connectionLine) => connectionLine.key !== 'xxx', ) as ConnectionLineData[] @@ -106,12 +109,15 @@ const useConnectionDraw = ( (connectionLine) => connectionLine.key === 'xxx', ) as TemporaryConnectionLineData[] - savedConnectionLines.forEach((connectionLine) => drawConnectionLine(connectionLine, calculatePosition, blockData)) + savedConnectionLines.forEach((connectionLine) => + drawConnectionLine(connectionLine, calculatePosition, blockData), + ); + tempConnectionLines.forEach((connectionLine) => drawTempConnectionLine(connectionLine, calculatePosition, blockData), ) }, [connectionLineData, blockData, drawConnectionLine, drawTempConnectionLine]) - + return { svgConnectionLines } } diff --git a/packages/react-pipelines/src/utils/BlockParser.tsx b/packages/react-pipelines/src/utils/BlockParser.tsx index aef94d9..0afaae4 100644 --- a/packages/react-pipelines/src/utils/BlockParser.tsx +++ b/packages/react-pipelines/src/utils/BlockParser.tsx @@ -17,21 +17,26 @@ export interface DragBlockProps { onDragBlockEnd: (event: React.DragEvent) => void } +export interface ConnectionPointProps { + onConnectionPointRightClick: (lineKey: string, event: React.MouseEvent) => void; +} + function parseBlockData( input: BlockData, connectionLinesProps: DragConnectionLineProps, dragBlockProps: DragBlockProps, + connectionPointProps: ConnectionPointProps ): React.ReactElement { switch (input.blockType) { case 'start': return ( - + {input.renderer && input.renderer()} ) case 'mid': return ( - + {input.renderer && input.renderer()} ) From fde478c0cecff1ce4d079c25efbd926d4791d7e7 Mon Sep 17 00:00:00 2001 From: linus Date: Mon, 2 Dec 2024 15:45:34 +0100 Subject: [PATCH 2/4] Added support to remove a connection line by right clicking - removed connectionPoint updates --- packages/react-pipelines/src/FlowBoard.tsx | 4 ---- .../react-pipelines/src/blocks/StartBlock.tsx | 6 ++---- .../src/connections/ConnectionLine.tsx | 3 --- .../src/connections/ConnectionPoint.tsx | 4 ---- .../src/hooks/useConnectionClick.tsx | 17 +++-------------- .../react-pipelines/src/utils/BlockParser.tsx | 9 ++------- 6 files changed, 7 insertions(+), 36 deletions(-) diff --git a/packages/react-pipelines/src/FlowBoard.tsx b/packages/react-pipelines/src/FlowBoard.tsx index db35563..5edf273 100644 --- a/packages/react-pipelines/src/FlowBoard.tsx +++ b/packages/react-pipelines/src/FlowBoard.tsx @@ -52,7 +52,6 @@ const FlowBoard = ({ blockData, ...props }: FlowBoardProps) => { const { handleConnectionLineRightClick, - handleOutputConnectionPointRightClick, } = useConnectionRightClick( props.connectionLineData, props.onConnectionLineUpdate @@ -131,9 +130,6 @@ const FlowBoard = ({ blockData, ...props }: FlowBoardProps) => { onDragBlockStart: () => { }, onDragBlockEnd: () => { }, }, - { - onConnectionPointRightClick: handleOutputConnectionPointRightClick - }, ), ) diff --git a/packages/react-pipelines/src/blocks/StartBlock.tsx b/packages/react-pipelines/src/blocks/StartBlock.tsx index 08389d2..2117bc6 100644 --- a/packages/react-pipelines/src/blocks/StartBlock.tsx +++ b/packages/react-pipelines/src/blocks/StartBlock.tsx @@ -2,7 +2,7 @@ import React from 'react' import BaseBlock from './BaseBlock' import { usePipelineDrag } from '../hooks/usePipelineDrag' import { ErrorOutputConnectionPoint, OutputConnectionPoint } from '../connections/ConnectionPoint' -import { DragBlockProps, DragConnectionLineProps, ConnectionPointProps } from '../utils/BlockParser' +import { DragBlockProps, DragConnectionLineProps } from '../utils/BlockParser' import { TransformData } from '../utils/BlockUtils' interface StartBlockProps { @@ -12,7 +12,7 @@ interface StartBlockProps { transformData: TransformData } -const StartBlock = (props: StartBlockProps & DragConnectionLineProps & DragBlockProps & ConnectionPointProps) => { +const StartBlock = (props: StartBlockProps & DragConnectionLineProps & DragBlockProps) => { const { transformData, onDragStart, onDragEnd } = usePipelineDrag( props.transformData.translateX, props.transformData.translateY, @@ -33,7 +33,6 @@ const StartBlock = (props: StartBlockProps & DragConnectionLineProps & DragBlock onDragStart={props.onConnectionLineDragStart} onDrag={props.onConnectionLineDrag} onDragEnd={props.onConnectionLineDragEnd} - onContextMenu= {(event) => props.onConnectionPointRightClick(`${props.id}-output`, event)} /> props.onConnectionPointRightClick(`${props.id}-erroroutput`, event)} /> {props.children} diff --git a/packages/react-pipelines/src/connections/ConnectionLine.tsx b/packages/react-pipelines/src/connections/ConnectionLine.tsx index e10669c..cd39f39 100644 --- a/packages/react-pipelines/src/connections/ConnectionLine.tsx +++ b/packages/react-pipelines/src/connections/ConnectionLine.tsx @@ -21,11 +21,8 @@ const StyledSvgContainer = styled.svg` const StyledSvgLine = styled.line` position: absolute; stroke-width: 2px; - transition: stroke-width 0.2s ease; &:hover { stroke: red; - stroke-width: 6px; - cursor: pointer; ` // const StyledSvgPath = styled.path` diff --git a/packages/react-pipelines/src/connections/ConnectionPoint.tsx b/packages/react-pipelines/src/connections/ConnectionPoint.tsx index 25a25ad..3ec81bb 100644 --- a/packages/react-pipelines/src/connections/ConnectionPoint.tsx +++ b/packages/react-pipelines/src/connections/ConnectionPoint.tsx @@ -11,10 +11,6 @@ const styledConnectionPoint = styled.div` z-index: 10; margin-bottom: 5px; - &:hover { - border-color: lightblue; - } - &:active { cursor: grabbing; border-color: lightblue; diff --git a/packages/react-pipelines/src/hooks/useConnectionClick.tsx b/packages/react-pipelines/src/hooks/useConnectionClick.tsx index ae03b3c..49c51a3 100644 --- a/packages/react-pipelines/src/hooks/useConnectionClick.tsx +++ b/packages/react-pipelines/src/hooks/useConnectionClick.tsx @@ -12,23 +12,12 @@ const useConnectionRightClick = ( (line) => line.key !== lineKey ); onConnectionLineUpdate(updatedConnectionLineData); -}, - [connectionLineData, onConnectionLineUpdate] -); + console.log(connectionLineData) - const handleOutputConnectionPointRightClick = useCallback((connectionPointId: string, event: React.MouseEvent) => { - event.preventDefault(); - const updatedConnectionLineData = connectionLineData.filter( - (line) => line.originConnectionPointId !== connectionPointId - ); - onConnectionLineUpdate(updatedConnectionLineData); - }, +}, [connectionLineData, onConnectionLineUpdate] ); - return { - handleConnectionLineRightClick, - handleOutputConnectionPointRightClick, - }; + return { handleConnectionLineRightClick }; }; export default useConnectionRightClick; \ No newline at end of file diff --git a/packages/react-pipelines/src/utils/BlockParser.tsx b/packages/react-pipelines/src/utils/BlockParser.tsx index 0afaae4..aef94d9 100644 --- a/packages/react-pipelines/src/utils/BlockParser.tsx +++ b/packages/react-pipelines/src/utils/BlockParser.tsx @@ -17,26 +17,21 @@ export interface DragBlockProps { onDragBlockEnd: (event: React.DragEvent) => void } -export interface ConnectionPointProps { - onConnectionPointRightClick: (lineKey: string, event: React.MouseEvent) => void; -} - function parseBlockData( input: BlockData, connectionLinesProps: DragConnectionLineProps, dragBlockProps: DragBlockProps, - connectionPointProps: ConnectionPointProps ): React.ReactElement { switch (input.blockType) { case 'start': return ( - + {input.renderer && input.renderer()} ) case 'mid': return ( - + {input.renderer && input.renderer()} ) From ce9ea2d1c394438ae0ff42f6815cafc63f9a48b2 Mon Sep 17 00:00:00 2001 From: linus Date: Mon, 2 Dec 2024 15:52:44 +0100 Subject: [PATCH 3/4] remove connectionpoint rightclick event --- packages/react-pipelines/src/blocks/MidBlock.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/react-pipelines/src/blocks/MidBlock.tsx b/packages/react-pipelines/src/blocks/MidBlock.tsx index 127a656..ad53116 100644 --- a/packages/react-pipelines/src/blocks/MidBlock.tsx +++ b/packages/react-pipelines/src/blocks/MidBlock.tsx @@ -7,7 +7,7 @@ import { InputConnectionPoint, OutputConnectionPoint, } from '../connections/ConnectionPoint' -import { DragConnectionLineProps, ConnectionPointProps } from '../utils/BlockParser' +import { DragConnectionLineProps } from '../utils/BlockParser' import { TransformData } from '../utils/BlockUtils' interface MidBlockProps { @@ -17,7 +17,7 @@ interface MidBlockProps { transformData: TransformData } -const MidBlock = (props: MidBlockProps & DragConnectionLineProps & ConnectionPointProps) => { +const MidBlock = (props: MidBlockProps & DragConnectionLineProps) => { const { transformData, onDragStart, onDragEnd } = usePipelineDrag( props.transformData.translateX, props.transformData.translateY, @@ -38,7 +38,6 @@ const MidBlock = (props: MidBlockProps & DragConnectionLineProps & ConnectionPoi onDragStart={props.onConnectionLineDragStart} onDrag={props.onConnectionLineDrag} onDragEnd={props.onConnectionLineDragEnd} - onContextMenu= {(event) => props.onConnectionPointRightClick(`${props.id}-output`, event)} /> props.onConnectionPointRightClick(`${props.id}-erroroutput`, event)} /> Date: Mon, 2 Dec 2024 16:15:03 +0100 Subject: [PATCH 4/4] more cleanup --- packages/react-pipelines/src/connections/ConnectionLine.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-pipelines/src/connections/ConnectionLine.tsx b/packages/react-pipelines/src/connections/ConnectionLine.tsx index cd39f39..0bf8389 100644 --- a/packages/react-pipelines/src/connections/ConnectionLine.tsx +++ b/packages/react-pipelines/src/connections/ConnectionLine.tsx @@ -23,6 +23,7 @@ const StyledSvgLine = styled.line` stroke-width: 2px; &:hover { stroke: red; + } ` // const StyledSvgPath = styled.path`