Skip to content

Commit 17614bd

Browse files
committed
refactor(callbacks): dont provide noops as defaults, but make cbs optional
1 parent 7324c79 commit 17614bd

File tree

8 files changed

+118
-78
lines changed

8 files changed

+118
-78
lines changed

src/components/Edges/wrapEdge.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interface EdgeWrapperProps {
1313
labelStyle?: CSSProperties;
1414
labelShowBg?: boolean;
1515
labelBgStyle: CSSProperties;
16-
onClick: (edge: Edge) => void;
16+
onClick?: (edge: Edge) => void;
1717
animated: boolean;
1818
selected: boolean;
1919
isInteractive: boolean;
@@ -46,7 +46,10 @@ export default (EdgeComponent: ComponentType<EdgeCompProps>) => {
4646
}
4747

4848
store.dispatch.setSelectedElements({ id, source, target });
49-
onClick({ id, source, target, type });
49+
50+
if (onClick) {
51+
onClick({ id, source, target, type });
52+
}
5053
};
5154

5255
return (

src/components/Nodes/wrapNode.tsx

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,27 @@ import { Node, XYPosition, Transform, ElementId, NodeComponentProps, WrapNodePro
1010
const getMouseEvent = (evt: MouseEvent | TouchEvent) =>
1111
typeof TouchEvent !== 'undefined' && evt instanceof TouchEvent ? evt.touches[0] : (evt as MouseEvent);
1212

13-
const onStart = (
14-
evt: MouseEvent | TouchEvent,
15-
onDragStart: (node: Node) => void,
16-
id: ElementId,
17-
type: string,
18-
data: any,
19-
setOffset: (pos: XYPosition) => void,
20-
transform: Transform,
21-
position: XYPosition
22-
): false | void => {
13+
interface OnDragStartParams {
14+
evt: MouseEvent | TouchEvent;
15+
id: ElementId;
16+
type: string;
17+
data: any;
18+
setOffset: (pos: XYPosition) => void;
19+
transform: Transform;
20+
position: XYPosition;
21+
onNodeDragStart?: (node: Node) => void;
22+
}
23+
24+
const onStart = ({
25+
evt,
26+
onNodeDragStart,
27+
id,
28+
type,
29+
data,
30+
setOffset,
31+
transform,
32+
position,
33+
}: OnDragStartParams): false | void => {
2334
const startEvt = getMouseEvent(evt);
2435

2536
const scaledClient: XYPosition = {
@@ -33,16 +44,21 @@ const onStart = (
3344

3445
store.dispatch.setSelectedElements({ id, type } as Node);
3546
setOffset({ x: offsetX, y: offsetY });
36-
onDragStart(node);
47+
48+
if (onNodeDragStart) {
49+
onNodeDragStart(node);
50+
}
3751
};
3852

39-
const onDrag = (
40-
evt: MouseEvent | TouchEvent,
41-
setDragging: (isDragging: boolean) => void,
42-
id: ElementId,
43-
offset: XYPosition,
44-
transform: Transform
45-
): void => {
53+
interface OnDragParams {
54+
evt: MouseEvent | TouchEvent;
55+
setDragging: (isDragging: boolean) => void;
56+
id: ElementId;
57+
offset: XYPosition;
58+
transform: Transform;
59+
}
60+
61+
const onDrag = ({ evt, setDragging, id, offset, transform }: OnDragParams): void => {
4662
const dragEvt = getMouseEvent(evt);
4763

4864
const scaledClient = {
@@ -60,29 +76,43 @@ const onDrag = (
6076
});
6177
};
6278

63-
const onStop = (
64-
onDragStop: (node: Node) => void,
65-
onClick: (node: Node) => void,
66-
isDragging: boolean,
67-
setDragging: (isDragging: boolean) => void,
68-
id: ElementId,
69-
type: string,
70-
position: XYPosition,
71-
data: any
72-
): void => {
79+
interface OnDragStopParams {
80+
isDragging: boolean;
81+
setDragging: (isDragging: boolean) => void;
82+
id: ElementId;
83+
type: string;
84+
position: XYPosition;
85+
data: any;
86+
onNodeDragStop?: (node: Node) => void;
87+
onClick?: (node: Node) => void;
88+
}
89+
90+
const onStop = ({
91+
onNodeDragStop,
92+
onClick,
93+
isDragging,
94+
setDragging,
95+
id,
96+
type,
97+
position,
98+
data,
99+
}: OnDragStopParams): void => {
73100
const node = {
74101
id,
75102
type,
76103
position,
77104
data,
78105
} as Node;
79106

80-
if (!isDragging) {
107+
if (!isDragging && onClick) {
81108
return onClick(node);
82109
}
83110

84111
setDragging(false);
85-
onDragStop(node);
112+
113+
if (onNodeDragStop) {
114+
onNodeDragStop(node);
115+
}
86116
};
87117

88118
export default (NodeComponent: ComponentType<NodeComponentProps>) => {
@@ -146,9 +176,11 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
146176

147177
return (
148178
<DraggableCore
149-
onStart={(evt) => onStart(evt as MouseEvent, onNodeDragStart, id, type, data, setOffset, transform, position)}
150-
onDrag={(evt) => onDrag(evt as MouseEvent, setDragging, id, offset, transform)}
151-
onStop={() => onStop(onNodeDragStop, onClick, isDragging, setDragging, id, type, position, data)}
179+
onStart={(evt) =>
180+
onStart({ evt: evt as MouseEvent, onNodeDragStart, id, type, data, setOffset, transform, position })
181+
}
182+
onDrag={(evt) => onDrag({ evt: evt as MouseEvent, setDragging, id, offset, transform })}
183+
onStop={() => onStop({ onNodeDragStop, onClick, isDragging, setDragging, id, type, position, data })}
152184
scale={transform[2]}
153185
disabled={!isInteractive}
154186
cancel=".nodrag"

src/container/GraphView/index.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ import { Elements, NodeTypesType, EdgeTypesType, OnLoadFunc, Node, Edge, Connect
1616

1717
export interface GraphViewProps {
1818
elements: Elements;
19-
onElementClick: (element: Node | Edge) => void;
20-
onElementsRemove: (elements: Elements) => void;
21-
onNodeDragStart: (node: Node) => void;
22-
onNodeDragStop: (node: Node) => void;
23-
onConnect: (connection: Connection | Edge) => void;
24-
onLoad: OnLoadFunc;
25-
onMove: () => void;
19+
onElementClick?: (element: Node | Edge) => void;
20+
onElementsRemove?: (elements: Elements) => void;
21+
onNodeDragStart?: (node: Node) => void;
22+
onNodeDragStop?: (node: Node) => void;
23+
onConnect?: (connection: Connection | Edge) => void;
24+
onLoad?: OnLoadFunc;
25+
onMove?: () => void;
2626
selectionKeyCode: number;
2727
nodeTypes: NodeTypesType;
2828
edgeTypes: EdgeTypesType;
@@ -92,26 +92,29 @@ const GraphView = memo(
9292

9393
useEffect(() => {
9494
updateDimensions();
95-
setOnConnect(onConnect);
9695
window.onresize = updateDimensions;
9796

97+
if (onConnect) {
98+
setOnConnect(onConnect);
99+
}
100+
98101
return () => {
99102
window.onresize = null;
100103
};
101104
}, []);
102105

103-
useD3Zoom(zoomPane, onMove, selectionKeyPressed);
106+
useD3Zoom({ zoomPane, onMove, selectionKeyPressed });
104107

105108
useEffect(() => {
106-
if (state.d3Initialised) {
109+
if (state.d3Initialised && onLoad) {
107110
onLoad({
108111
fitView,
109112
zoomIn,
110113
zoomOut,
111114
project,
112115
});
113116
}
114-
}, [state.d3Initialised]);
117+
}, [state.d3Initialised, onLoad]);
115118

116119
useEffect(() => {
117120
setSnapGrid({ snapToGrid, snapGrid });

src/container/NodeRenderer/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { Node, Transform, NodeTypesType, WrapNodeProps, Elements, Edge } from '.
66

77
interface NodeRendererProps {
88
nodeTypes: NodeTypesType;
9-
onElementClick: (element: Node | Edge) => void;
10-
onNodeDragStart: (node: Node) => void;
11-
onNodeDragStop: (node: Node) => void;
9+
onElementClick?: (element: Node | Edge) => void;
10+
onNodeDragStart?: (node: Node) => void;
11+
onNodeDragStop?: (node: Node) => void;
1212
onlyRenderVisibleNodes?: boolean;
1313
}
1414

@@ -22,7 +22,7 @@ function renderNode(
2222
const nodeType = node.type || 'default';
2323
const NodeComponent = (props.nodeTypes[nodeType] || props.nodeTypes.default) as ComponentType<WrapNodeProps>;
2424
if (!props.nodeTypes[nodeType]) {
25-
console.warn(`No node type found for type "${nodeType}". Using fallback type "default".`);
25+
console.warn(`Node type "${nodeType}" not found. Using fallback type "default".`);
2626
}
2727

2828
const isSelected = selectedElements ? selectedElements.some(({ id }) => id === node.id) : false;

src/container/ReactFlow/index.tsx

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ import '../../style.css';
2626

2727
export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onLoad'> {
2828
elements: Elements;
29-
onElementClick: (element: Node | Edge) => void;
30-
onElementsRemove: (elements: Elements) => void;
31-
onNodeDragStart: (node: Node) => void;
32-
onNodeDragStop: (node: Node) => void;
33-
onConnect: (connection: Edge | Connection) => void;
34-
onLoad: OnLoadFunc;
35-
onMove: () => void;
36-
onSelectionChange: (elements: Elements | null) => void;
29+
onElementClick?: (element: Node | Edge) => void;
30+
onElementsRemove?: (elements: Elements) => void;
31+
onNodeDragStart?: (node: Node) => void;
32+
onNodeDragStop?: (node: Node) => void;
33+
onConnect?: (connection: Edge | Connection) => void;
34+
onLoad?: OnLoadFunc;
35+
onMove?: () => void;
36+
onSelectionChange?: (elements: Elements | null) => void;
3737
nodeTypes: NodeTypesType;
3838
edgeTypes: EdgeTypesType;
3939
connectionLineType: string;
@@ -106,13 +106,6 @@ const ReactFlow = ({
106106
ReactFlow.displayName = 'ReactFlow';
107107

108108
ReactFlow.defaultProps = {
109-
onElementClick: () => {},
110-
onElementsRemove: () => {},
111-
onNodeDragStart: () => {},
112-
onNodeDragStop: () => {},
113-
onConnect: () => {},
114-
onLoad: () => {},
115-
onMove: () => {},
116109
nodeTypes: {
117110
input: InputNode,
118111
default: DefaultNode,

src/hooks/useD3Zoom.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,26 @@ import { select, event } from 'd3-selection';
44

55
import { useStoreState, useStoreActions } from '../store/hooks';
66

7+
interface UseD3ZoomParams {
8+
zoomPane: MutableRefObject<Element | null>;
9+
selectionKeyPressed: boolean;
10+
onMove?: () => void;
11+
}
12+
713
const d3ZoomInstance = d3Zoom
814
.zoom()
915
.scaleExtent([0.5, 2])
1016
.filter(() => !event.button);
1117

12-
export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void, shiftPressed: boolean): void => {
13-
const state = useStoreState(s => ({
18+
export default ({ zoomPane, onMove, selectionKeyPressed }: UseD3ZoomParams): void => {
19+
const state = useStoreState((s) => ({
1420
transform: s.transform,
1521
d3Selection: s.d3Selection,
1622
d3Zoom: s.d3Zoom,
1723
}));
1824

19-
const initD3 = useStoreActions(actions => actions.initD3);
20-
const updateTransform = useStoreActions(actions => actions.updateTransform);
25+
const initD3 = useStoreActions((actions) => actions.initD3);
26+
const updateTransform = useStoreActions((actions) => actions.updateTransform);
2127

2228
useEffect(() => {
2329
if (zoomPane.current) {
@@ -27,7 +33,7 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
2733
}, []);
2834

2935
useEffect(() => {
30-
if (shiftPressed) {
36+
if (selectionKeyPressed) {
3137
d3ZoomInstance.on('zoom', null);
3238
} else {
3339
d3ZoomInstance.on('zoom', () => {
@@ -37,7 +43,9 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
3743

3844
updateTransform(event.transform);
3945

40-
onMove();
46+
if (onMove) {
47+
onMove();
48+
}
4149
});
4250

4351
if (state.d3Selection && state.d3Zoom) {
@@ -53,5 +61,5 @@ export default (zoomPane: MutableRefObject<Element | null>, onMove: () => void,
5361
return () => {
5462
d3ZoomInstance.on('zoom', null);
5563
};
56-
}, [shiftPressed]);
64+
}, [selectionKeyPressed]);
5765
};

src/hooks/useGlobalKeyHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { Elements, Node } from '../types';
77

88
interface HookParams {
99
deleteKeyCode: number;
10-
onElementsRemove: (elements: Elements) => void;
10+
onElementsRemove?: (elements: Elements) => void;
1111
}
1212

1313
export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => {
@@ -19,7 +19,7 @@ export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => {
1919
const deleteKeyPressed = useKeyPress(deleteKeyCode);
2020

2121
useEffect(() => {
22-
if (deleteKeyPressed && state.selectedElements) {
22+
if (onElementsRemove && deleteKeyPressed && state.selectedElements) {
2323
let elementsToRemove = state.selectedElements;
2424

2525
// we also want to remove the edges if only one node is selected

src/types/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ export interface NodeComponentProps {
108108
yPos?: number;
109109
targetPosition?: Position;
110110
sourcePosition?: Position;
111-
onClick?: (node: Node) => void | undefined;
111+
onClick?: (node: Node) => void;
112+
onNodeDragStart?: (node: Node) => void;
112113
onNodeDragStop?: (node: Node) => void;
113114
style?: CSSProperties;
114115
}
@@ -122,9 +123,9 @@ export interface WrapNodeProps {
122123
xPos: number;
123124
yPos: number;
124125
isInteractive: boolean;
125-
onClick: (node: Node) => void | undefined;
126-
onNodeDragStart: (node: Node) => void;
127-
onNodeDragStop: (node: Node) => void;
126+
onClick?: (node: Node) => void;
127+
onNodeDragStart?: (node: Node) => void;
128+
onNodeDragStop?: (node: Node) => void;
128129
style?: CSSProperties;
129130
sourcePosition?: Position;
130131
targetPosition?: Position;

0 commit comments

Comments
 (0)