refactor(connection): cleanup
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port 3000 --open",
|
"dev": "vite --port 3000 --open --host",
|
||||||
"serve": "vite serve --port 3000",
|
"serve": "vite serve --port 3000",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"test:dev": "cypress open",
|
"test:dev": "cypress open",
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import type { MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
|
import type { MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
|
||||||
import { StoreApi } from 'zustand';
|
import { StoreApi } from 'zustand';
|
||||||
|
|
||||||
import { getHostForElement, calcAutoPan, getEventPosition, isMouseEvent } from '../../utils';
|
import { getHostForElement, calcAutoPan, getEventPosition } from '../../utils';
|
||||||
import type { OnConnect, HandleType, ReactFlowState } from '../../types';
|
import type { OnConnect, HandleType, ReactFlowState } from '../../types';
|
||||||
import { pointToRendererPoint, rendererPointToPoint } from '../../utils/graph';
|
import { pointToRendererPoint, rendererPointToPoint } from '../../utils/graph';
|
||||||
import { ConnectionHandle, getClosestHandle, getHandleLookup, isValidHandle, ValidConnectionFunc } from './utils';
|
import {
|
||||||
|
ConnectionHandle,
|
||||||
function resetRecentHandle(handleDomNode: Element): void {
|
getClosestHandle,
|
||||||
handleDomNode?.classList.remove('react-flow__handle-valid');
|
getHandleLookup,
|
||||||
handleDomNode?.classList.remove('react-flow__handle-connecting');
|
getHandleType,
|
||||||
}
|
isValidHandle,
|
||||||
|
resetRecentHandle,
|
||||||
|
ValidConnectionFunc,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
export function handlePointerDown({
|
export function handlePointerDown({
|
||||||
event,
|
event,
|
||||||
@@ -20,7 +23,7 @@ export function handlePointerDown({
|
|||||||
getState,
|
getState,
|
||||||
setState,
|
setState,
|
||||||
isValidConnection,
|
isValidConnection,
|
||||||
elementEdgeUpdaterType,
|
edgeUpdaterType,
|
||||||
onEdgeUpdateEnd,
|
onEdgeUpdateEnd,
|
||||||
}: {
|
}: {
|
||||||
event: ReactMouseEvent | ReactTouchEvent;
|
event: ReactMouseEvent | ReactTouchEvent;
|
||||||
@@ -31,27 +34,34 @@ export function handlePointerDown({
|
|||||||
getState: StoreApi<ReactFlowState>['getState'];
|
getState: StoreApi<ReactFlowState>['getState'];
|
||||||
setState: StoreApi<ReactFlowState>['setState'];
|
setState: StoreApi<ReactFlowState>['setState'];
|
||||||
isValidConnection: ValidConnectionFunc;
|
isValidConnection: ValidConnectionFunc;
|
||||||
elementEdgeUpdaterType?: HandleType;
|
edgeUpdaterType?: HandleType;
|
||||||
onEdgeUpdateEnd?: (evt: MouseEvent | TouchEvent) => void;
|
onEdgeUpdateEnd?: (evt: MouseEvent | TouchEvent) => void;
|
||||||
}): void {
|
}): void {
|
||||||
// when react-flow is used inside a shadow root we can't use document
|
// when react-flow is used inside a shadow root we can't use document
|
||||||
const doc = getHostForElement(event.target as HTMLElement);
|
const doc = getHostForElement(event.target as HTMLElement);
|
||||||
const { connectionMode, domNode, autoPanOnConnect, connectionRadius, onConnectStart, onConnectEnd, panBy, getNodes } =
|
const {
|
||||||
getState();
|
connectionMode,
|
||||||
|
domNode,
|
||||||
|
autoPanOnConnect,
|
||||||
|
connectionRadius,
|
||||||
|
onConnectStart,
|
||||||
|
onConnectEnd,
|
||||||
|
panBy,
|
||||||
|
getNodes,
|
||||||
|
cancelConnection,
|
||||||
|
} = getState();
|
||||||
let autoPanId = 0;
|
let autoPanId = 0;
|
||||||
let prevClosestHandle: ConnectionHandle | null;
|
let prevClosestHandle: ConnectionHandle | null;
|
||||||
|
|
||||||
const { clientX, clientY } = isMouseEvent(event) ? event : event.touches[0]!;
|
const { x, y } = getEventPosition(event);
|
||||||
const clickedElement = doc?.elementFromPoint(clientX, clientY);
|
const clickedHandle = doc?.elementFromPoint(x, y);
|
||||||
const elementIsTarget = clickedElement?.classList.contains('target');
|
const handleType = getHandleType(edgeUpdaterType, clickedHandle);
|
||||||
const elementIsSource = clickedElement?.classList.contains('source');
|
const containerBounds = domNode?.getBoundingClientRect();
|
||||||
|
|
||||||
if (!domNode || (!elementIsTarget && !elementIsSource && !elementEdgeUpdaterType)) {
|
if (!containerBounds || !handleType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementIsTarget ? 'target' : 'source';
|
|
||||||
const containerBounds = domNode.getBoundingClientRect();
|
|
||||||
let prevActiveHandle: Element;
|
let prevActiveHandle: Element;
|
||||||
let connectionPosition = getEventPosition(event, containerBounds);
|
let connectionPosition = getEventPosition(event, containerBounds);
|
||||||
let autoPanStarted = false;
|
let autoPanStarted = false;
|
||||||
@@ -154,17 +164,13 @@ export function handlePointerDown({
|
|||||||
|
|
||||||
onConnectEnd?.(event);
|
onConnectEnd?.(event);
|
||||||
|
|
||||||
if (elementEdgeUpdaterType) {
|
if (edgeUpdaterType) {
|
||||||
onEdgeUpdateEnd?.(event);
|
onEdgeUpdateEnd?.(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetRecentHandle(prevActiveHandle);
|
resetRecentHandle(prevActiveHandle);
|
||||||
|
|
||||||
setState({
|
cancelConnection();
|
||||||
connectionNodeId: null,
|
|
||||||
connectionHandleId: null,
|
|
||||||
connectionHandleType: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.removeEventListener('mousemove', onPointerMove as EventListener);
|
doc.removeEventListener('mousemove', onPointerMove as EventListener);
|
||||||
doc.removeEventListener('mouseup', onPointerUp as EventListener);
|
doc.removeEventListener('mouseup', onPointerUp as EventListener);
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onPointerDown = (event: ReactMouseEvent<HTMLDivElement> | ReactTouchEvent<HTMLDivElement>) => {
|
const onPointerDown = (event: ReactMouseEvent<HTMLDivElement> | ReactTouchEvent<HTMLDivElement>) => {
|
||||||
const isMouse = isMouseEvent(event);
|
const isMouseTriggered = isMouseEvent(event);
|
||||||
|
|
||||||
if ((isMouse && event.button === 0) || 'touches' in event) {
|
if ((isMouseTriggered && event.button === 0) || !isMouseTriggered) {
|
||||||
handlePointerDown({
|
handlePointerDown({
|
||||||
event,
|
event,
|
||||||
handleId,
|
handleId,
|
||||||
@@ -83,7 +83,7 @@ const Handle = forwardRef<HTMLDivElement, HandleComponentProps>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMouse) {
|
if (isMouseTriggered) {
|
||||||
onMouseDown?.(event);
|
onMouseDown?.(event);
|
||||||
} else {
|
} else {
|
||||||
onTouchStart?.(event);
|
onTouchStart?.(event);
|
||||||
|
|||||||
@@ -132,3 +132,23 @@ export function getHandleLookup({ nodes, nodeId, handleId, handleType }: GetHand
|
|||||||
return res;
|
return res;
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getHandleType(
|
||||||
|
edgeUpdaterType: HandleType | undefined,
|
||||||
|
handleDomNode: Element | null
|
||||||
|
): HandleType | null {
|
||||||
|
if (edgeUpdaterType) {
|
||||||
|
return edgeUpdaterType;
|
||||||
|
} else if (handleDomNode?.classList.contains('target')) {
|
||||||
|
return 'target';
|
||||||
|
} else if (handleDomNode?.classList.contains('source')) {
|
||||||
|
return 'source';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetRecentHandle(handleDomNode: Element): void {
|
||||||
|
handleDomNode?.classList.remove('react-flow__handle-valid');
|
||||||
|
handleDomNode?.classList.remove('react-flow__handle-connecting');
|
||||||
|
}
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ const createRFStore = () =>
|
|||||||
set({
|
set({
|
||||||
connectionNodeId: initialState.connectionNodeId,
|
connectionNodeId: initialState.connectionNodeId,
|
||||||
connectionHandleId: initialState.connectionHandleId,
|
connectionHandleId: initialState.connectionHandleId,
|
||||||
|
connectionHandleType: initialState.connectionHandleType,
|
||||||
}),
|
}),
|
||||||
reset: () => set({ ...initialState }),
|
reset: () => set({ ...initialState }),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -122,14 +122,14 @@ export const isMouseEvent = (
|
|||||||
|
|
||||||
export const getEventPosition = (
|
export const getEventPosition = (
|
||||||
event: MouseEvent | ReactMouseEvent | TouchEvent | ReactTouchEvent,
|
event: MouseEvent | ReactMouseEvent | TouchEvent | ReactTouchEvent,
|
||||||
bounds: DOMRect
|
bounds?: DOMRect
|
||||||
) => {
|
) => {
|
||||||
const isMouse = isMouseEvent(event);
|
const isMouseTriggered = isMouseEvent(event);
|
||||||
const evtX = isMouse ? event.clientX : event.touches?.[0].clientX;
|
const evtX = isMouseTriggered ? event.clientX : event.touches?.[0].clientX;
|
||||||
const evtY = isMouse ? event.clientY : event.touches?.[0].clientY;
|
const evtY = isMouseTriggered ? event.clientY : event.touches?.[0].clientY;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: evtX - bounds.left,
|
x: evtX - (bounds?.left ?? 0),
|
||||||
y: evtY - bounds.top,
|
y: evtY - (bounds?.top ?? 0),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user