refactor(callbacks): dont provide noops as defaults, but make cbs optional

This commit is contained in:
moklick
2020-05-25 16:24:50 +02:00
parent 7324c79fd0
commit 17614bda6b
8 changed files with 118 additions and 78 deletions

View File

@@ -13,7 +13,7 @@ interface EdgeWrapperProps {
labelStyle?: CSSProperties;
labelShowBg?: boolean;
labelBgStyle: CSSProperties;
onClick: (edge: Edge) => void;
onClick?: (edge: Edge) => void;
animated: boolean;
selected: boolean;
isInteractive: boolean;
@@ -46,7 +46,10 @@ export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
}
store.dispatch.setSelectedElements({ id, source, target });
onClick({ id, source, target, type });
if (onClick) {
onClick({ id, source, target, type });
}
};
return (

View File

@@ -10,16 +10,27 @@ import { Node, XYPosition, Transform, ElementId, NodeComponentProps, WrapNodePro
const getMouseEvent = (evt: MouseEvent | TouchEvent) =>
typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent ? evt.touches[0] : (evt as MouseEvent);
const onStart = (
evt: MouseEvent | TouchEvent,
onDragStart: (node: Node) => void,
id: ElementId,
type: string,
data: any,
setOffset: (pos: XYPosition) => void,
transform: Transform,
position: XYPosition
): false | void => {
interface OnDragStartParams {
evt: MouseEvent | TouchEvent;
id: ElementId;
type: string;
data: any;
setOffset: (pos: XYPosition) => void;
transform: Transform;
position: XYPosition;
onNodeDragStart?: (node: Node) => void;
}
const onStart = ({
evt,
onNodeDragStart,
id,
type,
data,
setOffset,
transform,
position,
}: OnDragStartParams): false | void => {
const startEvt = getMouseEvent(evt);
const scaledClient: XYPosition = {
@@ -33,16 +44,21 @@ const onStart = (
store.dispatch.setSelectedElements({ id, type } as Node);
setOffset({ x: offsetX, y: offsetY });
onDragStart(node);
if (onNodeDragStart) {
onNodeDragStart(node);
}
};
const onDrag = (
evt: MouseEvent | TouchEvent,
setDragging: (isDragging: boolean) => void,
id: ElementId,
offset: XYPosition,
transform: Transform
): void => {
interface OnDragParams {
evt: MouseEvent | TouchEvent;
setDragging: (isDragging: boolean) => void;
id: ElementId;
offset: XYPosition;
transform: Transform;
}
const onDrag = ({ evt, setDragging, id, offset, transform }: OnDragParams): void => {
const dragEvt = getMouseEvent(evt);
const scaledClient = {
@@ -60,16 +76,27 @@ const onDrag = (
});
};
const onStop = (
onDragStop: (node: Node) => void,
onClick: (node: Node) => void,
isDragging: boolean,
setDragging: (isDragging: boolean) => void,
id: ElementId,
type: string,
position: XYPosition,
data: any
): void => {
interface OnDragStopParams {
isDragging: boolean;
setDragging: (isDragging: boolean) => void;
id: ElementId;
type: string;
position: XYPosition;
data: any;
onNodeDragStop?: (node: Node) => void;
onClick?: (node: Node) => void;
}
const onStop = ({
onNodeDragStop,
onClick,
isDragging,
setDragging,
id,
type,
position,
data,
}: OnDragStopParams): void => {
const node = {
id,
type,
@@ -77,12 +104,15 @@ const onStop = (
data,
} as Node;
if (!isDragging) {
if (!isDragging && onClick) {
return onClick(node);
}
setDragging(false);
onDragStop(node);
if (onNodeDragStop) {
onNodeDragStop(node);
}
};
export default (NodeComponent: ComponentType<NodeComponentProps>) => {
@@ -146,9 +176,11 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
return (
<DraggableCore
onStart={(evt) => onStart(evt as MouseEvent, onNodeDragStart, id, type, data, setOffset, transform, position)}
onDrag={(evt) => onDrag(evt as MouseEvent, setDragging, id, offset, transform)}
onStop={() => onStop(onNodeDragStop, onClick, isDragging, setDragging, id, type, position, data)}
onStart={(evt) =>
onStart({ evt: evt as MouseEvent, onNodeDragStart, id, type, data, setOffset, transform, position })
}
onDrag={(evt) => onDrag({ evt: evt as MouseEvent, setDragging, id, offset, transform })}
onStop={() => onStop({ onNodeDragStop, onClick, isDragging, setDragging, id, type, position, data })}
scale={transform[2]}
disabled={!isInteractive}
cancel=".nodrag"

View File

@@ -16,13 +16,13 @@ import { Elements, NodeTypesType, EdgeTypesType, OnLoadFunc, Node, Edge, Connect
export interface GraphViewProps {
elements: Elements;
onElementClick: (element: Node | Edge) => void;
onElementsRemove: (elements: Elements) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onConnect: (connection: Connection | Edge) => void;
onLoad: OnLoadFunc;
onMove: () => void;
onElementClick?: (element: Node | Edge) => void;
onElementsRemove?: (elements: Elements) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Connection | Edge) => void;
onLoad?: OnLoadFunc;
onMove?: () => void;
selectionKeyCode: number;
nodeTypes: NodeTypesType;
edgeTypes: EdgeTypesType;
@@ -92,18 +92,21 @@ const GraphView = memo(
useEffect(() => {
updateDimensions();
setOnConnect(onConnect);
window.onresize = updateDimensions;
if (onConnect) {
setOnConnect(onConnect);
}
return () => {
window.onresize = null;
};
}, []);
useD3Zoom(zoomPane, onMove, selectionKeyPressed);
useD3Zoom({ zoomPane, onMove, selectionKeyPressed });
useEffect(() => {
if (state.d3Initialised) {
if (state.d3Initialised && onLoad) {
onLoad({
fitView,
zoomIn,
@@ -111,7 +114,7 @@ const GraphView = memo(
project,
});
}
}, [state.d3Initialised]);
}, [state.d3Initialised, onLoad]);
useEffect(() => {
setSnapGrid({ snapToGrid, snapGrid });

View File

@@ -6,9 +6,9 @@ import { Node, Transform, NodeTypesType, WrapNodeProps, Elements, Edge } from '.
interface NodeRendererProps {
nodeTypes: NodeTypesType;
onElementClick: (element: Node | Edge) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onElementClick?: (element: Node | Edge) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
onlyRenderVisibleNodes?: boolean;
}
@@ -22,7 +22,7 @@ function renderNode(
const nodeType = node.type || 'default';
const NodeComponent = (props.nodeTypes[nodeType] || props.nodeTypes.default) as ComponentType<WrapNodeProps>;
if (!props.nodeTypes[nodeType]) {
console.warn(`No node type found for type "${nodeType}". Using fallback type "default".`);
console.warn(`Node type "${nodeType}" not found. Using fallback type "default".`);
}
const isSelected = selectedElements ? selectedElements.some(({ id }) => id === node.id) : false;

View File

@@ -26,14 +26,14 @@ import '../../style.css';
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> {
elements: Elements;
onElementClick: (element: Node | Edge) => void;
onElementsRemove: (elements: Elements) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onConnect: (connection: Edge | Connection) => void;
onLoad: OnLoadFunc;
onMove: () => void;
onSelectionChange: (elements: Elements | null) => void;
onElementClick?: (element: Node | Edge) => void;
onElementsRemove?: (elements: Elements) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
onConnect?: (connection: Edge | Connection) => void;
onLoad?: OnLoadFunc;
onMove?: () => void;
onSelectionChange?: (elements: Elements | null) => void;
nodeTypes: NodeTypesType;
edgeTypes: EdgeTypesType;
connectionLineType: string;
@@ -106,13 +106,6 @@ const ReactFlow = ({
ReactFlow.displayName = 'ReactFlow';
ReactFlow.defaultProps = {
onElementClick: () => {},
onElementsRemove: () => {},
onNodeDragStart: () => {},
onNodeDragStop: () => {},
onConnect: () => {},
onLoad: () => {},
onMove: () => {},
nodeTypes: {
input: InputNode,
default: DefaultNode,

View File

@@ -4,20 +4,26 @@ import { select, event } from 'd3-selection';
import { useStoreState, useStoreActions } from '../store/hooks';
interface UseD3ZoomParams {
zoomPane: MutableRefObject<Element | null>;
selectionKeyPressed: boolean;
onMove?: () => void;
}
const d3ZoomInstance = d3Zoom
.zoom()
.scaleExtent([0.5, 2])
.filter(() => !event.button);
export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void, shiftPressed: boolean): void => {
const state = useStoreState(s => ({
export default ({ zoomPane, onMove, selectionKeyPressed }: UseD3ZoomParams): void => {
const state = useStoreState((s) => ({
transform: s.transform,
d3Selection: s.d3Selection,
d3Zoom: s.d3Zoom,
}));
const initD3 = useStoreActions(actions => actions.initD3);
const updateTransform = useStoreActions(actions => actions.updateTransform);
const initD3 = useStoreActions((actions) => actions.initD3);
const updateTransform = useStoreActions((actions) => actions.updateTransform);
useEffect(() => {
if (zoomPane.current) {
@@ -27,7 +33,7 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
}, []);
useEffect(() => {
if (shiftPressed) {
if (selectionKeyPressed) {
d3ZoomInstance.on('zoom', null);
} else {
d3ZoomInstance.on('zoom', () => {
@@ -37,7 +43,9 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
updateTransform(event.transform);
onMove();
if (onMove) {
onMove();
}
});
if (state.d3Selection && state.d3Zoom) {
@@ -53,5 +61,5 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
return () => {
d3ZoomInstance.on('zoom', null);
};
}, [shiftPressed]);
}, [selectionKeyPressed]);
};

View File

@@ -7,7 +7,7 @@ import { Elements, Node } from '../types';
interface HookParams {
deleteKeyCode: number;
onElementsRemove: (elements: Elements) => void;
onElementsRemove?: (elements: Elements) => void;
}
export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => {
@@ -19,7 +19,7 @@ export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => {
const deleteKeyPressed = useKeyPress(deleteKeyCode);
useEffect(() => {
if (deleteKeyPressed && state.selectedElements) {
if (onElementsRemove && deleteKeyPressed && state.selectedElements) {
let elementsToRemove = state.selectedElements;
// we also want to remove the edges if only one node is selected

View File

@@ -108,7 +108,8 @@ export interface NodeComponentProps {
yPos?: number;
targetPosition?: Position;
sourcePosition?: Position;
onClick?: (node: Node) => void | undefined;
onClick?: (node: Node) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
style?: CSSProperties;
}
@@ -122,9 +123,9 @@ export interface WrapNodeProps {
xPos: number;
yPos: number;
isInteractive: boolean;
onClick: (node: Node) => void | undefined;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onClick?: (node: Node) => void;
onNodeDragStart?: (node: Node) => void;
onNodeDragStop?: (node: Node) => void;
style?: CSSProperties;
sourcePosition?: Position;
targetPosition?: Position;