bug fix: only handle mouse events that were targeted at the selection pane.

This commit is contained in:
Jack Fishwick
2022-11-22 10:55:06 +00:00
parent 45dfcfd4ee
commit f0baf64725
2 changed files with 34 additions and 13 deletions
@@ -81,8 +81,6 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
const node = store.getState().nodeInternals.get(id)!; const node = store.getState().nodeInternals.get(id)!;
onClick(event, { ...node }); onClick(event, { ...node });
} }
event.stopPropagation();
}; };
const onKeyDown = (event: KeyboardEvent) => { const onKeyDown = (event: KeyboardEvent) => {
@@ -15,6 +15,8 @@ type SelectionRect = Rect & {
startY: number; startY: number;
}; };
type EventHandlers = { [key: string]: React.MouseEventHandler | React.WheelEventHandler | undefined };
type UserSelectionProps = { type UserSelectionProps = {
isSelectionMode: boolean; isSelectionMode: boolean;
onClick?: (e: React.MouseEvent) => void; 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<HTMLDivElement | null>
): React.MouseEventHandler => {
return (event: React.MouseEvent) => {
if (event.target !== containerRef.current) {
return;
}
handler?.(event);
};
};
const wrapHandlers = (
handlers: EventHandlers,
containerRef: React.MutableRefObject<HTMLDivElement | null>
): EventHandlers =>
Object.keys(handlers).reduce((hls, key) => ({ ...hls, [key]: wrapHandler(handlers[key], containerRef) }), {});
const selector = (s: ReactFlowState) => ({ const selector = (s: ReactFlowState) => ({
userSelectionActive: s.userSelectionActive, userSelectionActive: s.userSelectionActive,
elementsSelectable: s.elementsSelectable, elementsSelectable: s.elementsSelectable,
}); });
const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, children }: UserSelectionProps) => { const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel, children }: UserSelectionProps) => {
const container = useRef<HTMLDivElement | null>(null);
const store = useStoreApi(); const store = useStoreApi();
const prevSelectedNodesCount = useRef<number>(0); const prevSelectedNodesCount = useRef<number>(0);
const prevSelectedEdgesCount = useRef<number>(0); const prevSelectedEdgesCount = useRef<number>(0);
@@ -53,7 +74,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel,
}; };
const onMouseDown = (event: React.MouseEvent): void => { const onMouseDown = (event: React.MouseEvent): void => {
if (!elementsSelectable || !isSelectionMode || event.button !== 0) { if (!elementsSelectable || !isSelectionMode || event.button !== 0 || event.target !== container.current) {
return; return;
} }
@@ -75,7 +96,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel,
}; };
const onMouseMove = (event: React.MouseEvent): void => { const onMouseMove = (event: React.MouseEvent): void => {
if (!isSelectionMode || !containerBounds.current || !userSelectionRect) { if (!isSelectionMode || !containerBounds.current || !userSelectionRect || event.target !== container.current) {
return; return;
} }
@@ -122,7 +143,7 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel,
const onMouseUp = (event: React.MouseEvent) => { const onMouseUp = (event: React.MouseEvent) => {
// We only want to trigger click functions when in selection mode if // We only want to trigger click functions when in selection mode if
// the user did not move the mouse. // the user did not move the mouse.
if (!userSelectionActive && userSelectionRect) { if (!userSelectionActive && userSelectionRect && event.target === container.current) {
onClick?.(event); onClick?.(event);
} }
@@ -141,21 +162,23 @@ const UserSelection = memo(({ isSelectionMode, onClick, onContextMenu, onWheel,
const eventHandlers = const eventHandlers =
elementsSelectable && (isSelectionMode || userSelectionActive) elementsSelectable && (isSelectionMode || userSelectionActive)
? { ? {
onContextMenu, ...wrapHandlers({ onContextMenu, onWheel }, container),
onWheel,
onMouseDown, onMouseDown,
onMouseMove, onMouseMove,
onMouseUp, onMouseUp,
onMouseLeave, onMouseLeave,
} }
: { : wrapHandlers(
onClick, {
onContextMenu, onClick,
onWheel, onContextMenu,
}; onWheel,
},
container
);
return ( return (
<div className="react-flow__selectionpane react-flow__container" {...eventHandlers}> <div className="react-flow__selectionpane react-flow__container" {...eventHandlers} ref={container}>
{children} {children}
{userSelectionActive && userSelectionRect && ( {userSelectionActive && userSelectionRect && (
<div <div