- onStart({
- event: event as MouseEvent,
- selectNodesOnDrag,
- isSelectable,
- onNodeDragStart,
- id,
- type,
- data,
- setOffset,
- transform,
- position,
- setSelectedElements,
- })
- }
- onDrag={(event) => onDrag({ event: event as MouseEvent, setDragging, id, offset, transform, updateNodePos })}
- onStop={(event) =>
- onStop({
- event: event as MouseEvent,
- onNodeDragStop,
- selectNodesOnDrag,
- isSelectable,
- onClick,
- isDragging,
- setDragging,
- id,
- type,
- position,
- data,
- setSelectedElements,
- })
- }
+ onStart={onDragStart}
+ onDrag={onDrag}
+ onStop={onDragStop}
scale={transform[2]}
disabled={!isDraggable}
cancel=".nodrag"
diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx
index 0baef218..88e2013c 100644
--- a/src/container/GraphView/index.tsx
+++ b/src/container/GraphView/index.tsx
@@ -24,6 +24,7 @@ import {
OnConnectStartFunc,
OnConnectStopFunc,
OnConnectEndFunc,
+ TranslateExtent,
} from '../../types';
export interface GraphViewProps {
@@ -67,6 +68,7 @@ export interface GraphViewProps {
maxZoom: number;
defaultZoom: number;
defaultPosition: [number, number];
+ translateExtent?: TranslateExtent;
arrowHeadColor: string;
markerEndId?: string;
zoomOnScroll: boolean;
@@ -112,6 +114,7 @@ const GraphView = ({
maxZoom,
defaultZoom,
defaultPosition,
+ translateExtent,
arrowHeadColor,
markerEndId,
zoomOnScroll,
@@ -137,6 +140,7 @@ const GraphView = ({
const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable);
const setInitTransform = useStoreActions((actions) => actions.setInitTransform);
const setMinMaxZoom = useStoreActions((actions) => actions.setMinMaxZoom);
+ const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent);
const fitView = useStoreActions((actions) => actions.fitView);
const zoom = useStoreActions((actions) => actions.zoom);
const zoomTo = useStoreActions((actions) => actions.zoomTo);
@@ -254,6 +258,12 @@ const GraphView = ({
setMinMaxZoom({ minZoom, maxZoom });
}, [minZoom, maxZoom]);
+ useEffect(() => {
+ if (typeof translateExtent !== 'undefined') {
+ setTranslateExtent(translateExtent);
+ }
+ }, [translateExtent]);
+
return (
, 'on
maxZoom: number;
defaultZoom: number;
defaultPosition: [number, number];
+ translateExtent?: TranslateExtent;
arrowHeadColor: string;
markerEndId?: string;
zoomOnScroll: boolean;
@@ -125,6 +127,7 @@ const ReactFlow = ({
maxZoom,
defaultZoom,
defaultPosition,
+ translateExtent,
arrowHeadColor,
markerEndId,
zoomOnScroll,
@@ -176,6 +179,7 @@ const ReactFlow = ({
maxZoom={maxZoom}
defaultZoom={defaultZoom}
defaultPosition={defaultPosition}
+ translateExtent={translateExtent}
arrowHeadColor={arrowHeadColor}
markerEndId={markerEndId}
zoomOnScroll={zoomOnScroll}
diff --git a/src/store/index.ts b/src/store/index.ts
index 913ba56e..9827092c 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -26,6 +26,7 @@ import {
SetConnectionId,
NodePosUpdate,
FitViewParams,
+ TranslateExtent,
} from '../types';
type TransformXYK = {
@@ -65,6 +66,7 @@ export interface StoreModel {
d3Initialised: boolean;
minZoom: number;
maxZoom: number;
+ translateExtent: TranslateExtent;
nodesSelectionActive: boolean;
selectionActive: boolean;
@@ -116,6 +118,8 @@ export interface StoreModel {
setMinMaxZoom: Action;
+ setTranslateExtent: Action;
+
setSnapGrid: Action;
setConnectionPosition: Action;
@@ -154,6 +158,10 @@ export const storeModel: StoreModel = {
d3Initialised: false,
minZoom: 0.5,
maxZoom: 2,
+ translateExtent: [
+ [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
+ [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],
+ ],
nodesSelectionActive: false,
selectionActive: false,
@@ -351,7 +359,7 @@ export const storeModel: StoreModel = {
}),
initD3: action((state, zoomPaneNode) => {
- const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]);
+ const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(state.translateExtent);
const selection = select(zoomPaneNode).call(d3ZoomInstance);
@@ -369,6 +377,14 @@ export const storeModel: StoreModel = {
}
}),
+ setTranslateExtent: action((state, translateExtent) => {
+ state.translateExtent = translateExtent;
+
+ if (state.d3Zoom) {
+ state.d3Zoom.translateExtent(translateExtent);
+ }
+ }),
+
setConnectionPosition: action((state, position) => {
state.connectionPosition = position;
}),
diff --git a/src/types/index.ts b/src/types/index.ts
index 8837c769..7d02712a 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -272,3 +272,5 @@ export type FlowTransform = {
y: number;
zoom: number;
};
+
+export type TranslateExtent = [[number, number], [number, number]];
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 165d0e2f..95130e1e 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,8 +1,6 @@
import { DraggableEvent } from 'react-draggable';
import { MouseEvent as ReactMouseEvent } from 'react';
-export const noop = () => {};
-
export const isInputDOMNode = (e: ReactMouseEvent | DraggableEvent | KeyboardEvent) => {
const target = e.target as HTMLElement;
return e && target && ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName);