From f0baf6472542ac7fb2016976b99c3b5da1043e53 Mon Sep 17 00:00:00 2001 From: Jack Fishwick Date: Tue, 27 Sep 2022 15:03:02 +0100 Subject: [PATCH] bug fix: only handle mouse events that were targeted at the selection pane. --- .../core/src/components/Nodes/wrapNode.tsx | 2 - .../src/components/UserSelection/index.tsx | 45 ++++++++++++++----- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/packages/core/src/components/Nodes/wrapNode.tsx b/packages/core/src/components/Nodes/wrapNode.tsx index 1150c85d..afb1f761 100644 --- a/packages/core/src/components/Nodes/wrapNode.tsx +++ b/packages/core/src/components/Nodes/wrapNode.tsx @@ -81,8 +81,6 @@ 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 0c0e871a..152e7115 100644 --- a/packages/core/src/components/UserSelection/index.tsx +++ b/packages/core/src/components/UserSelection/index.tsx @@ -15,6 +15,8 @@ type SelectionRect = Rect & { startY: number; }; +type EventHandlers = { [key: string]: React.MouseEventHandler | React.WheelEventHandler | undefined }; + type UserSelectionProps = { isSelectionMode: boolean; onClick?: (e: React.MouseEvent) => void; @@ -30,12 +32,31 @@ function getMousePosition(event: React.MouseEvent, containerBounds: DOMRect): XY }; } +const wrapHandler = ( + handler: React.MouseEventHandler | undefined, + containerRef: React.MutableRefObject +): React.MouseEventHandler => { + return (event: React.MouseEvent) => { + if (event.target !== containerRef.current) { + return; + } + handler?.(event); + }; +}; + +const wrapHandlers = ( + handlers: EventHandlers, + containerRef: React.MutableRefObject +): EventHandlers => + Object.keys(handlers).reduce((hls, key) => ({ ...hls, [key]: wrapHandler(handlers[key], containerRef) }), {}); + const selector = (s: ReactFlowState) => ({ userSelectionActive: s.userSelectionActive, elementsSelectable: s.elementsSelectable, }); const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, children }: UserSelectionProps) => { + const container = useRef(null); const store = useStoreApi(); const prevSelectedNodesCount = useRef(0); const prevSelectedEdgesCount = useRef(0); @@ -53,7 +74,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, }; const onMouseDown = (event: React.MouseEvent): void => { - if (!elementsSelectable || !isSelectionMode || event.button !== 0) { + if (!elementsSelectable || !isSelectionMode || event.button !== 0 || event.target !== container.current) { return; } @@ -75,7 +96,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, }; const onMouseMove = (event: React.MouseEvent): void => { - if (!isSelectionMode || !containerBounds.current || !userSelectionRect) { + if (!isSelectionMode || !containerBounds.current || !userSelectionRect || event.target !== container.current) { return; } @@ -122,7 +143,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, const onMouseUp = (event: React.MouseEvent) => { // We only want to trigger click functions when in selection mode if // the user did not move the mouse. - if (!userSelectionActive && userSelectionRect) { + if (!userSelectionActive && userSelectionRect && event.target === container.current) { onClick?.(event); } @@ -141,21 +162,23 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, const eventHandlers = elementsSelectable && (isSelectionMode || userSelectionActive) ? { - onContextMenu, - onWheel, + ...wrapHandlers({ onContextMenu, onWheel }, container), onMouseDown, onMouseMove, onMouseUp, onMouseLeave, } - : { - onClick, - onContextMenu, - onWheel, - }; + : wrapHandlers( + { + onClick, + onContextMenu, + onWheel, + }, + container + ); return ( -
+
{children} {userSelectionActive && userSelectionRect && (