diff --git a/packages/core/src/components/Nodes/wrapNode.tsx b/packages/core/src/components/Nodes/wrapNode.tsx index afb1f761..1150c85d 100644 --- a/packages/core/src/components/Nodes/wrapNode.tsx +++ b/packages/core/src/components/Nodes/wrapNode.tsx @@ -81,6 +81,8 @@ export default (NodeComponent: ComponentType) => { const node = store.getState().nodeInternals.get(id)!; onClick(event, { ...node }); } + + event.stopPropagation(); }; const onKeyDown = (event: KeyboardEvent) => { diff --git a/packages/core/src/components/UserSelection/index.tsx b/packages/core/src/components/UserSelection/index.tsx index 65cb1d2d..d0aed2da 100644 --- a/packages/core/src/components/UserSelection/index.tsx +++ b/packages/core/src/components/UserSelection/index.tsx @@ -13,7 +13,6 @@ import type { XYPosition, ReactFlowState, NodeChange, EdgeChange, Rect } from '. type SelectionRect = Rect & { startX: number; startY: number; - draw: boolean; }; type UserSelectionProps = { @@ -36,32 +35,16 @@ const selector = (s: ReactFlowState) => ({ elementsSelectable: s.elementsSelectable, }); -const initialRect: SelectionRect = { - startX: 0, - startY: 0, - x: 0, - y: 0, - width: 0, - height: 0, - draw: false, -}; - const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWheel, children }: UserSelectionProps) => { const store = useStoreApi(); const prevSelectedNodesCount = useRef(0); const prevSelectedEdgesCount = useRef(0); const containerBounds = useRef(); - const [userSelectionRect, setUserSelectionRect] = useState(initialRect); + const [userSelectionRect, setUserSelectionRect] = useState(null); const { userSelectionActive, elementsSelectable } = useStore(selector, shallow); - const renderUserSelectionPane = userSelectionActive || selectionKeyPressed; - - if (!elementsSelectable || !renderUserSelectionPane) { - return null; - } - const resetUserSelection = () => { - setUserSelectionRect(initialRect); + setUserSelectionRect(null); store.setState({ userSelectionActive: false }); @@ -70,6 +53,10 @@ const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWhe }; const onMouseDown = (event: React.MouseEvent): void => { + if (!elementsSelectable || !selectionKeyPressed || event.button !== 0) { + return; + } + const reactFlowNode = (event.target as Element).closest('.react-flow')!; containerBounds.current = reactFlowNode.getBoundingClientRect(); @@ -82,12 +69,11 @@ const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWhe startY: mousePos.y, x: mousePos.x, y: mousePos.y, - draw: true, }); }; const onMouseMove = (event: React.MouseEvent): void => { - if (!selectionKeyPressed || !userSelectionRect.draw || !containerBounds.current) { + if (!selectionKeyPressed || !containerBounds.current || !userSelectionRect) { return; } @@ -103,6 +89,7 @@ const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWhe y: mousePos.y < startY ? mousePos.y : startY, width: Math.abs(mousePos.x - startX), height: Math.abs(mousePos.y - startY), + draw: true, }; const { nodeInternals, edges, transform, onNodesChange, onEdgesChange, nodeOrigin } = store.getState(); @@ -130,13 +117,9 @@ const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWhe setUserSelectionRect(nextUserSelectRect); }; - const onMouseUp = (event: React.MouseEvent) => { + const onMouseUp = () => { store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }); - if (!store.getState().userSelectionActive) { - onClick?.(event); - } - resetUserSelection(); }; @@ -145,18 +128,27 @@ const UserSelection = memo(({ selectionKeyPressed, onClick, onContextMenu, onWhe resetUserSelection(); }; + const eventHandlers = + elementsSelectable && (selectionKeyPressed || userSelectionActive) + ? { + onClick, + onContextMenu, + onWheel, + onMouseDown, + onMouseMove, + onMouseUp, + onMouseLeave, + } + : { + onClick, + onContextMenu, + onWheel, + }; + return ( -
+
{children} - {userSelectionRect.draw && ( + {userSelectionActive && userSelectionRect && (
{ @@ -92,7 +94,7 @@ const FlowRenderer = ({ panOnScrollSpeed={panOnScrollSpeed} panOnScrollMode={panOnScrollMode} zoomOnDoubleClick={zoomOnDoubleClick} - panOnDrag={panOnDrag} + panOnDrag={panOnDrag && !isSelectionMode} defaultViewport={defaultViewport} translateExtent={translateExtent} minZoom={minZoom} @@ -109,7 +111,7 @@ const FlowRenderer = ({ onMouseLeave={onPaneMouseLeave} onContextMenu={onContextMenu} onWheel={onWheel} - selectionKeyPressed={selectionKeyPressed || (selectBoxOnDrag && !panOnDrag)} + selectionKeyPressed={isSelectionMode} > {children} {nodesSelectionActive && ( diff --git a/packages/core/src/styles/init.css b/packages/core/src/styles/init.css index a500c17d..6f4c25e8 100644 --- a/packages/core/src/styles/init.css +++ b/packages/core/src/styles/init.css @@ -30,6 +30,10 @@ z-index: 5; } +.react-flow__selection { + z-index: 6; +} + .react-flow__nodesselection-rect:focus, .react-flow__nodesselection-rect:focus-visible { outline: none;