refactor(zoom): move zoom methods into own hook, detatch from store
This commit is contained in:
@@ -50,6 +50,7 @@ const InteractionFlow = () => {
|
|||||||
onPaneClick={captureZoomClick ? onPaneClick : undefined}
|
onPaneClick={captureZoomClick ? onPaneClick : undefined}
|
||||||
onPaneScroll={captureZoomScroll ? onPaneScroll : undefined}
|
onPaneScroll={captureZoomScroll ? onPaneScroll : undefined}
|
||||||
onPaneContextMenu={captureZoomClick ? onPaneContextMenu : undefined}
|
onPaneContextMenu={captureZoomClick ? onPaneContextMenu : undefined}
|
||||||
|
onMoveEnd={(evt) => console.log('on move end', evt)}
|
||||||
>
|
>
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import LockIcon from '../../../assets/icons/lock.svg';
|
|||||||
import UnlockIcon from '../../../assets/icons/unlock.svg';
|
import UnlockIcon from '../../../assets/icons/unlock.svg';
|
||||||
|
|
||||||
import './style.css';
|
import './style.css';
|
||||||
|
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
||||||
|
|
||||||
export interface ControlProps extends React.HTMLAttributes<HTMLDivElement> {
|
export interface ControlProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
showZoom?: boolean;
|
showZoom?: boolean;
|
||||||
@@ -33,9 +34,7 @@ const Controls = ({
|
|||||||
className,
|
className,
|
||||||
}: ControlProps) => {
|
}: ControlProps) => {
|
||||||
const setInteractive = useStoreActions((actions) => actions.setInteractive);
|
const setInteractive = useStoreActions((actions) => actions.setInteractive);
|
||||||
const fitView = useStoreActions((actions) => actions.fitView);
|
const { zoomIn, zoomOut, fitView } = useZoomPanHelper();
|
||||||
const zoomIn = useStoreActions((actions) => actions.zoomIn);
|
|
||||||
const zoomOut = useStoreActions((actions) => actions.zoomOut);
|
|
||||||
|
|
||||||
const isInteractive = useStoreState((s) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable);
|
const isInteractive = useStoreState((s) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable);
|
||||||
const mapClasses = cc(['react-flow__controls', className]);
|
const mapClasses = cc(['react-flow__controls', className]);
|
||||||
@@ -44,20 +43,26 @@ const Controls = ({
|
|||||||
<div className={mapClasses} style={style}>
|
<div className={mapClasses} style={style}>
|
||||||
{showZoom && (
|
{showZoom && (
|
||||||
<>
|
<>
|
||||||
<div className="react-flow__controls-button react-flow__controls-zoomin" onClick={() => {
|
<div
|
||||||
zoomIn();
|
className="react-flow__controls-button react-flow__controls-zoomin"
|
||||||
if (onZoomIn) {
|
onClick={() => {
|
||||||
onZoomIn();
|
zoomIn();
|
||||||
}
|
if (onZoomIn) {
|
||||||
}}>
|
onZoomIn();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</div>
|
</div>
|
||||||
<div className="react-flow__controls-button react-flow__controls-zoomout" onClick={() => {
|
<div
|
||||||
zoomOut();
|
className="react-flow__controls-button react-flow__controls-zoomout"
|
||||||
if (onZoomOut) {
|
onClick={() => {
|
||||||
onZoomOut();
|
zoomOut();
|
||||||
}
|
if (onZoomOut) {
|
||||||
}}>
|
onZoomOut();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<MinusIcon />
|
<MinusIcon />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
OnConnectEndFunc,
|
OnConnectEndFunc,
|
||||||
TranslateExtent,
|
TranslateExtent,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
||||||
|
|
||||||
export interface GraphViewProps {
|
export interface GraphViewProps {
|
||||||
elements: Elements;
|
elements: Elements;
|
||||||
@@ -145,10 +146,8 @@ const GraphView = ({
|
|||||||
const setMinZoom = useStoreActions((actions) => actions.setMinZoom);
|
const setMinZoom = useStoreActions((actions) => actions.setMinZoom);
|
||||||
const setMaxZoom = useStoreActions((actions) => actions.setMaxZoom);
|
const setMaxZoom = useStoreActions((actions) => actions.setMaxZoom);
|
||||||
const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent);
|
const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent);
|
||||||
const fitView = useStoreActions((actions) => actions.fitView);
|
|
||||||
const zoom = useStoreActions((actions) => actions.zoom);
|
|
||||||
const zoomTo = useStoreActions((actions) => actions.zoomTo);
|
|
||||||
const currentStore = useStore();
|
const currentStore = useStore();
|
||||||
|
const { zoomIn, zoomOut, zoomTo, fitView } = useZoomPanHelper();
|
||||||
|
|
||||||
useElementUpdater(elements);
|
useElementUpdater(elements);
|
||||||
|
|
||||||
@@ -157,9 +156,9 @@ const GraphView = ({
|
|||||||
if (onLoad) {
|
if (onLoad) {
|
||||||
onLoad({
|
onLoad({
|
||||||
fitView: (params = { padding: 0.1 }) => fitView(params),
|
fitView: (params = { padding: 0.1 }) => fitView(params),
|
||||||
zoomIn: () => zoom(0.2),
|
zoomIn,
|
||||||
zoomOut: () => zoom(-0.2),
|
zoomOut,
|
||||||
zoomTo: (zoomLevel) => zoomTo(zoomLevel),
|
zoomTo,
|
||||||
project: onLoadProject(currentStore),
|
project: onLoadProject(currentStore),
|
||||||
getElements: onLoadGetElements(currentStore),
|
getElements: onLoadGetElements(currentStore),
|
||||||
setTransform: (transform: FlowTransform) =>
|
setTransform: (transform: FlowTransform) =>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { StoreProvider, useStore } from 'easy-peasy';
|
import { StoreProvider } from 'easy-peasy';
|
||||||
|
|
||||||
import store, { StoreModel } from '../../store';
|
import store from '../../store';
|
||||||
|
import { useStore } from '../../store/hooks';
|
||||||
|
|
||||||
const Wrapper: FC = ({ children }) => {
|
const Wrapper: FC = ({ children }) => {
|
||||||
const easyPeasyStore = useStore<StoreModel>();
|
const easyPeasyStore = useStore();
|
||||||
const isWrapepdWithReactFlowProvider = easyPeasyStore?.getState()?.reactFlowVersion;
|
const isWrapepdWithReactFlowProvider = easyPeasyStore?.getState()?.reactFlowVersion;
|
||||||
|
|
||||||
if (isWrapepdWithReactFlowProvider) {
|
if (isWrapepdWithReactFlowProvider) {
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import React, { useEffect, useRef, ReactNode } from 'react';
|
import React, { useEffect, useRef, ReactNode } from 'react';
|
||||||
|
|
||||||
|
import { zoom, zoomIdentity } from 'd3-zoom';
|
||||||
|
import { select } from 'd3-selection';
|
||||||
|
import { clamp } from '../../utils';
|
||||||
|
|
||||||
import useResizeHandler from '../../hooks/useResizeHandler';
|
import useResizeHandler from '../../hooks/useResizeHandler';
|
||||||
import { useStoreState, useStoreActions } from '../../store/hooks';
|
import { useStoreState, useStoreActions, useStore } from '../../store/hooks';
|
||||||
import { FlowTransform, TranslateExtent } from '../../types';
|
import { FlowTransform, TranslateExtent } from '../../types';
|
||||||
|
|
||||||
interface ZoomPaneProps {
|
interface ZoomPaneProps {
|
||||||
@@ -55,14 +59,36 @@ const ZoomPane = ({
|
|||||||
const d3Selection = useStoreState((s) => s.d3Selection);
|
const d3Selection = useStoreState((s) => s.d3Selection);
|
||||||
const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler);
|
const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler);
|
||||||
|
|
||||||
const initD3 = useStoreActions((actions) => actions.initD3);
|
const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom);
|
||||||
const updateTransform = useStoreActions((actions) => actions.updateTransform);
|
const updateTransform = useStoreActions((actions) => actions.updateTransform);
|
||||||
|
const store = useStore();
|
||||||
|
|
||||||
useResizeHandler(zoomPane);
|
useResizeHandler(zoomPane);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (zoomPane.current) {
|
if (zoomPane.current) {
|
||||||
initD3({ zoomPane: zoomPane.current, defaultPosition, defaultZoom, translateExtent });
|
// initD3: action((state, { zoomPane, defaultPosition, defaultZoom, translateExtent }) => {
|
||||||
|
const state = store.getState();
|
||||||
|
const currentTranslateExtent = typeof translateExtent !== 'undefined' ? translateExtent : state.translateExtent;
|
||||||
|
const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(currentTranslateExtent);
|
||||||
|
const selection = select(zoomPane.current as Element).call(d3ZoomInstance);
|
||||||
|
|
||||||
|
const clampedX = clamp(defaultPosition[0], currentTranslateExtent[0][0], currentTranslateExtent[1][0]);
|
||||||
|
const clampedY = clamp(defaultPosition[1], currentTranslateExtent[0][1], currentTranslateExtent[1][1]);
|
||||||
|
const clampedZoom = clamp(defaultZoom, state.minZoom, state.maxZoom);
|
||||||
|
|
||||||
|
const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom);
|
||||||
|
// selection.property('__zoom', updatedTransform);
|
||||||
|
|
||||||
|
const zoomHandler = selection.on('wheel.zoom');
|
||||||
|
|
||||||
|
d3ZoomInstance.transform(selection, updatedTransform);
|
||||||
|
|
||||||
|
initD3Zoom({
|
||||||
|
d3Zoom: d3ZoomInstance,
|
||||||
|
d3Selection: selection,
|
||||||
|
d3ZoomHandler: zoomHandler,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { zoomIdentity } from 'd3-zoom';
|
||||||
|
import { useStoreState, useStore } from '../store/hooks';
|
||||||
|
|
||||||
|
import { clamp } from '../utils';
|
||||||
|
import { getRectOfNodes } from '../utils/graph';
|
||||||
|
import { FitViewParams } from '../types';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const store = useStore();
|
||||||
|
const d3Zoom = useStoreState((s) => s.d3Zoom);
|
||||||
|
const d3Selection = useStoreState((s) => s.d3Selection);
|
||||||
|
|
||||||
|
const zoomIn = useCallback(() => {
|
||||||
|
if (d3Selection) {
|
||||||
|
d3Zoom?.scaleBy(d3Selection, 1.2);
|
||||||
|
}
|
||||||
|
}, [d3Zoom, d3Selection]);
|
||||||
|
|
||||||
|
const zoomOut = useCallback(() => {
|
||||||
|
if (d3Selection) {
|
||||||
|
d3Zoom?.scaleBy(d3Selection, 1 / 1.2);
|
||||||
|
}
|
||||||
|
}, [d3Zoom, d3Selection]);
|
||||||
|
|
||||||
|
const zoomTo = useCallback(
|
||||||
|
(zoomLevel: number) => {
|
||||||
|
if (d3Selection) {
|
||||||
|
d3Zoom?.scaleTo(d3Selection, zoomLevel);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[d3Zoom, d3Selection]
|
||||||
|
);
|
||||||
|
|
||||||
|
const fitView = useCallback(
|
||||||
|
(options: FitViewParams) => {
|
||||||
|
const { padding = 0.1 } = options;
|
||||||
|
const { nodes, width, height, minZoom, maxZoom } = store.getState();
|
||||||
|
|
||||||
|
if (!d3Selection || !nodes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bounds = getRectOfNodes(nodes);
|
||||||
|
const xZoom = width / (bounds.width * (1 + padding));
|
||||||
|
const yZoom = height / (bounds.height * (1 + padding));
|
||||||
|
const zoom = Math.min(xZoom, yZoom);
|
||||||
|
const clampedZoom = clamp(zoom, minZoom, maxZoom);
|
||||||
|
const boundsCenterX = bounds.x + bounds.width / 2;
|
||||||
|
const boundsCenterY = bounds.y + bounds.height / 2;
|
||||||
|
const x = width / 2 - boundsCenterX * clampedZoom;
|
||||||
|
const y = height / 2 - boundsCenterY * clampedZoom;
|
||||||
|
const k = clampedZoom;
|
||||||
|
const transform = zoomIdentity.translate(x, y).scale(k);
|
||||||
|
|
||||||
|
d3Zoom?.transform(d3Selection, transform);
|
||||||
|
},
|
||||||
|
[store, d3Zoom, d3Selection]
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
zoomIn,
|
||||||
|
zoomOut,
|
||||||
|
zoomTo,
|
||||||
|
fitView,
|
||||||
|
};
|
||||||
|
};
|
||||||
+11
-98
@@ -1,10 +1,9 @@
|
|||||||
import { createStore, Action, action, Thunk, thunk, computed, Computed } from 'easy-peasy';
|
import { createStore, Action, action, Thunk, thunk, computed, Computed } from 'easy-peasy';
|
||||||
import isEqual from 'fast-deep-equal';
|
import isEqual from 'fast-deep-equal';
|
||||||
import { Selection as D3Selection, ZoomBehavior } from 'd3';
|
import { Selection as D3Selection, ZoomBehavior } from 'd3';
|
||||||
import { zoom, zoomIdentity } from 'd3-zoom';
|
import { zoomIdentity } from 'd3-zoom';
|
||||||
import { select } from 'd3-selection';
|
|
||||||
|
|
||||||
import { getDimensions, clamp } from '../utils';
|
import { getDimensions } from '../utils';
|
||||||
import { getHandleBounds } from '../components/Nodes/utils';
|
import { getHandleBounds } from '../components/Nodes/utils';
|
||||||
|
|
||||||
import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph';
|
import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph';
|
||||||
@@ -26,7 +25,6 @@ import {
|
|||||||
SetConnectionId,
|
SetConnectionId,
|
||||||
NodePosUpdate,
|
NodePosUpdate,
|
||||||
NodeDiffUpdate,
|
NodeDiffUpdate,
|
||||||
FitViewParams,
|
|
||||||
TranslateExtent,
|
TranslateExtent,
|
||||||
SnapGrid,
|
SnapGrid,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
@@ -42,11 +40,10 @@ type NodeDimensionUpdate = {
|
|||||||
nodeElement: HTMLDivElement;
|
nodeElement: HTMLDivElement;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InitD3 = {
|
type InitD3Zoom = {
|
||||||
zoomPane: Element;
|
d3Zoom: ZoomBehavior<Element, unknown>;
|
||||||
defaultPosition: [number, number];
|
d3Selection: D3Selection<Element, unknown, null, undefined>;
|
||||||
defaultZoom: number;
|
d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined;
|
||||||
translateExtent?: TranslateExtent;
|
|
||||||
};
|
};
|
||||||
export interface StoreModel {
|
export interface StoreModel {
|
||||||
width: number;
|
width: number;
|
||||||
@@ -119,7 +116,7 @@ export interface StoreModel {
|
|||||||
|
|
||||||
updateSize: Action<StoreModel, Dimensions>;
|
updateSize: Action<StoreModel, Dimensions>;
|
||||||
|
|
||||||
initD3: Action<StoreModel, InitD3>;
|
initD3Zoom: Action<StoreModel, InitD3Zoom>;
|
||||||
|
|
||||||
setMinZoom: Action<StoreModel, number>;
|
setMinZoom: Action<StoreModel, number>;
|
||||||
setMaxZoom: Action<StoreModel, number>;
|
setMaxZoom: Action<StoreModel, number>;
|
||||||
@@ -142,12 +139,6 @@ export interface StoreModel {
|
|||||||
updateUserSelection: Action<StoreModel, XYPosition>;
|
updateUserSelection: Action<StoreModel, XYPosition>;
|
||||||
unsetUserSelection: Action<StoreModel>;
|
unsetUserSelection: Action<StoreModel>;
|
||||||
|
|
||||||
fitView: Action<StoreModel, FitViewParams>;
|
|
||||||
zoomTo: Action<StoreModel, number>;
|
|
||||||
zoom: Thunk<StoreModel, number, any, StoreModel>;
|
|
||||||
zoomIn: Thunk<StoreModel>;
|
|
||||||
zoomOut: Thunk<StoreModel>;
|
|
||||||
|
|
||||||
setMultiSelectionActive: Action<StoreModel, boolean>;
|
setMultiSelectionActive: Action<StoreModel, boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,26 +388,10 @@ export const storeModel: StoreModel = {
|
|||||||
state.height = size.height || 500;
|
state.height = size.height || 500;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
initD3: action((state, { zoomPane, defaultPosition, defaultZoom, translateExtent }) => {
|
initD3Zoom: action((state, { d3Zoom, d3Selection, d3ZoomHandler }) => {
|
||||||
const currentTranslateExtent = typeof translateExtent !== 'undefined' ? translateExtent : state.translateExtent;
|
state.d3Zoom = d3Zoom;
|
||||||
const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(currentTranslateExtent);
|
state.d3Selection = d3Selection;
|
||||||
const selection = select(zoomPane).call(d3ZoomInstance);
|
state.d3ZoomHandler = d3ZoomHandler;
|
||||||
|
|
||||||
const clampedX = clamp(defaultPosition[0], currentTranslateExtent[0][0], currentTranslateExtent[1][0]);
|
|
||||||
const clampedY = clamp(defaultPosition[1], currentTranslateExtent[0][1], currentTranslateExtent[1][1]);
|
|
||||||
const clampedZoom = clamp(defaultZoom, state.minZoom, state.maxZoom);
|
|
||||||
|
|
||||||
const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom);
|
|
||||||
selection.property('__zoom', updatedTransform);
|
|
||||||
|
|
||||||
const defaultHandler = selection.on('wheel.zoom');
|
|
||||||
|
|
||||||
state.transform[0] = clampedX;
|
|
||||||
state.transform[1] = clampedY;
|
|
||||||
state.transform[2] = clampedZoom;
|
|
||||||
state.d3Zoom = d3ZoomInstance;
|
|
||||||
state.d3Selection = selection;
|
|
||||||
state.d3ZoomHandler = defaultHandler;
|
|
||||||
state.d3Initialised = true;
|
state.d3Initialised = true;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@@ -481,68 +456,6 @@ export const storeModel: StoreModel = {
|
|||||||
state.elementsSelectable = elementsSelectable;
|
state.elementsSelectable = elementsSelectable;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
fitView: action((state, payload = { padding: 0.1 }) => {
|
|
||||||
const { padding } = payload;
|
|
||||||
const { nodes, width, height, d3Selection, minZoom, maxZoom } = state;
|
|
||||||
|
|
||||||
if (!d3Selection || !nodes.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bounds = getRectOfNodes(nodes);
|
|
||||||
const xZoom = width / (bounds.width * (1 + padding));
|
|
||||||
const yZoom = height / (bounds.height * (1 + padding));
|
|
||||||
const zoom = Math.min(xZoom, yZoom);
|
|
||||||
const clampedZoom = clamp(zoom, minZoom, maxZoom);
|
|
||||||
const boundsCenterX = bounds.x + bounds.width / 2;
|
|
||||||
const boundsCenterY = bounds.y + bounds.height / 2;
|
|
||||||
const transform = [width / 2 - boundsCenterX * clampedZoom, height / 2 - boundsCenterY * clampedZoom];
|
|
||||||
const fittedTransform = zoomIdentity.translate(transform[0], transform[1]).scale(clampedZoom);
|
|
||||||
|
|
||||||
// we need to sync the d3 zoom transform with the fitted transform
|
|
||||||
d3Selection.property('__zoom', fittedTransform);
|
|
||||||
|
|
||||||
state.transform[0] = fittedTransform.x;
|
|
||||||
state.transform[1] = fittedTransform.y;
|
|
||||||
state.transform[2] = fittedTransform.k;
|
|
||||||
}),
|
|
||||||
|
|
||||||
zoomTo: action((state, zoomLevel) => {
|
|
||||||
const { d3Selection, transform, minZoom, maxZoom } = state;
|
|
||||||
const nextZoom = clamp(zoomLevel, minZoom, maxZoom);
|
|
||||||
|
|
||||||
if (d3Selection) {
|
|
||||||
// we want to zoom in and out to the center of the zoom pane
|
|
||||||
const center = [state.width / 2, state.height / 2];
|
|
||||||
const centerInverted = [(center[0] - transform[0]) / transform[2], (center[1] - transform[1]) / transform[2]];
|
|
||||||
const x = center[0] - centerInverted[0] * nextZoom;
|
|
||||||
const y = center[1] - centerInverted[1] * nextZoom;
|
|
||||||
const zoomedTransform = zoomIdentity.translate(x, y).scale(nextZoom);
|
|
||||||
|
|
||||||
// we need to sync the d3 zoom transform with the zoomed transform
|
|
||||||
d3Selection.property('__zoom', zoomedTransform);
|
|
||||||
|
|
||||||
state.transform[0] = zoomedTransform.x;
|
|
||||||
state.transform[1] = zoomedTransform.y;
|
|
||||||
state.transform[2] = zoomedTransform.k;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
|
|
||||||
zoom: thunk((actions, amount, helpers) => {
|
|
||||||
const { transform } = helpers.getState();
|
|
||||||
const nextZoom = transform[2] + amount;
|
|
||||||
|
|
||||||
actions.zoomTo(nextZoom);
|
|
||||||
}),
|
|
||||||
|
|
||||||
zoomIn: thunk((actions) => {
|
|
||||||
actions.zoom(0.2);
|
|
||||||
}),
|
|
||||||
|
|
||||||
zoomOut: thunk((actions) => {
|
|
||||||
actions.zoom(-0.2);
|
|
||||||
}),
|
|
||||||
|
|
||||||
setMultiSelectionActive: action((state, isActive) => {
|
setMultiSelectionActive: action((state, isActive) => {
|
||||||
state.multiSelectionActive = isActive;
|
state.multiSelectionActive = isActive;
|
||||||
}),
|
}),
|
||||||
|
|||||||
+2
-27
@@ -1,7 +1,6 @@
|
|||||||
import { Store } from 'easy-peasy';
|
import { Store } from 'easy-peasy';
|
||||||
|
import { StoreModel } from '../store';
|
||||||
import store, { StoreModel } from '../store';
|
import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, Box, Connection } from '../types';
|
||||||
import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, FitViewParams, Box, Connection } from '../types';
|
|
||||||
|
|
||||||
export const isEdge = (element: Node | Connection | Edge): element is Edge =>
|
export const isEdge = (element: Node | Connection | Edge): element is Edge =>
|
||||||
'id' in element && 'source' in element && 'target' in element;
|
'id' in element && 'source' in element && 'target' in element;
|
||||||
@@ -106,12 +105,6 @@ export const onLoadProject = (currentStore: Store<StoreModel>) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const project = (position: XYPosition): XYPosition => {
|
|
||||||
const { transform, snapToGrid, snapGrid } = store.getState();
|
|
||||||
|
|
||||||
return pointToRendererPoint(position, transform, snapToGrid, snapGrid);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const parseElement = (element: Node | Edge): Node | Edge => {
|
export const parseElement = (element: Node | Edge): Node | Edge => {
|
||||||
if (!element.id) {
|
if (!element.id) {
|
||||||
throw new Error('All nodes and edges need to have an id.');
|
throw new Error('All nodes and edges need to have an id.');
|
||||||
@@ -227,18 +220,6 @@ export const getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[] => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fitView = (params: FitViewParams = { padding: 0.1 }): void => {
|
|
||||||
store.getActions().fitView(params);
|
|
||||||
};
|
|
||||||
|
|
||||||
const zoom = (amount: number): void => {
|
|
||||||
store.getActions().zoom(amount);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const zoomIn = (): void => zoom(0.2);
|
|
||||||
|
|
||||||
export const zoomOut = (): void => zoom(-0.2);
|
|
||||||
|
|
||||||
const parseElements = (nodes: Node[], edges: Edge[]): Elements => {
|
const parseElements = (nodes: Node[], edges: Edge[]): Elements => {
|
||||||
return [
|
return [
|
||||||
...nodes.map((node) => {
|
...nodes.map((node) => {
|
||||||
@@ -258,9 +239,3 @@ export const onLoadGetElements = (currentStore: Store<StoreModel>) => {
|
|||||||
return parseElements(nodes, edges);
|
return parseElements(nodes, edges);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getElements = (): Elements => {
|
|
||||||
const { nodes = [], edges = [] } = store.getState();
|
|
||||||
|
|
||||||
return parseElements(nodes, edges);
|
|
||||||
};
|
|
||||||
|
|||||||
Reference in New Issue
Block a user