refactor(callbacks): dont provide noops as defaults, but make cbs optional
This commit is contained in:
@@ -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 (
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user