chore(interactive-minimap): cleanup
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { MouseEvent } from 'react';
|
import { MouseEvent, useCallback } from 'react';
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
Background,
|
Background,
|
||||||
BackgroundVariant,
|
BackgroundVariant,
|
||||||
@@ -7,6 +7,7 @@ import ReactFlow, {
|
|||||||
Node,
|
Node,
|
||||||
Edge,
|
Edge,
|
||||||
useReactFlow,
|
useReactFlow,
|
||||||
|
XYPosition,
|
||||||
} from 'reactflow';
|
} from 'reactflow';
|
||||||
import { MiniMap } from '@reactflow/interactive-minimap';
|
import { MiniMap } from '@reactflow/interactive-minimap';
|
||||||
|
|
||||||
@@ -113,6 +114,10 @@ const BasicFlow = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMiniMapClick = useCallback((event: MouseEvent, pos: XYPosition) => {
|
||||||
|
console.log(pos);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
defaultNodes={initialNodes}
|
defaultNodes={initialNodes}
|
||||||
@@ -128,7 +133,7 @@ const BasicFlow = () => {
|
|||||||
fitView
|
fitView
|
||||||
>
|
>
|
||||||
<Background variant={BackgroundVariant.Dots} />
|
<Background variant={BackgroundVariant.Dots} />
|
||||||
<MiniMap />
|
<MiniMap onClick={onMiniMapClick} />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|
||||||
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
<div style={{ position: 'absolute', right: 10, top: 10, zIndex: 4 }}>
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { memo, MouseEvent, useEffect, useRef } from 'react';
|
import { memo, useEffect, useRef, MouseEvent } from 'react';
|
||||||
import cc from 'classcat';
|
import cc from 'classcat';
|
||||||
import shallow from 'zustand/shallow';
|
import shallow from 'zustand/shallow';
|
||||||
import { zoom, D3ZoomEvent, zoomIdentity } from 'd3-zoom';
|
import { zoom, D3ZoomEvent, zoomIdentity } from 'd3-zoom';
|
||||||
import { select, pointer } from 'd3-selection';
|
import { select, pointer } from 'd3-selection';
|
||||||
import {
|
|
||||||
useStore,
|
import { useStore, getRectOfNodes, ReactFlowState, Rect, Panel, getBoundsOfRects, useStoreApi } from '@reactflow/core';
|
||||||
getRectOfNodes,
|
|
||||||
ReactFlowState,
|
|
||||||
Rect,
|
|
||||||
Panel,
|
|
||||||
getBoundsOfRects,
|
|
||||||
useStoreApi,
|
|
||||||
useReactFlow,
|
|
||||||
} from '@reactflow/core';
|
|
||||||
|
|
||||||
import MiniMapNode from './MiniMapNode';
|
import MiniMapNode from './MiniMapNode';
|
||||||
import { MiniMapProps, GetMiniMapNodeAttribute } from './types';
|
import { MiniMapProps, GetMiniMapNodeAttribute } from './types';
|
||||||
@@ -56,6 +48,7 @@ function MiniMap({
|
|||||||
nodeStrokeWidth = 2,
|
nodeStrokeWidth = 2,
|
||||||
maskColor = 'rgb(200, 200, 200, 0.9)',
|
maskColor = 'rgb(200, 200, 200, 0.9)',
|
||||||
position = 'bottom-right',
|
position = 'bottom-right',
|
||||||
|
onClick,
|
||||||
}: MiniMapProps) {
|
}: MiniMapProps) {
|
||||||
const store = useStoreApi();
|
const store = useStoreApi();
|
||||||
const svg = useRef<SVGSVGElement>(null);
|
const svg = useRef<SVGSVGElement>(null);
|
||||||
@@ -77,16 +70,13 @@ function MiniMap({
|
|||||||
const height = viewHeight + offset * 2;
|
const height = viewHeight + offset * 2;
|
||||||
const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision';
|
const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision';
|
||||||
const labelledBy = `${ARIA_LABEL_KEY}-${rfId}`;
|
const labelledBy = `${ARIA_LABEL_KEY}-${rfId}`;
|
||||||
const { setCenter, setViewport, project } = useReactFlow();
|
|
||||||
const startTransform = useRef<[number, number]>([0, 0]);
|
|
||||||
const viewScaleRef = useRef(0);
|
const viewScaleRef = useRef(0);
|
||||||
|
|
||||||
viewScaleRef.current = Math.max(w / elementWidth, h / elementHeight);
|
viewScaleRef.current = Math.max(w / elementWidth, h / elementHeight);
|
||||||
|
|
||||||
const onClick = (event: MouseEvent) => {
|
const onSvgClick = (event: MouseEvent) => {
|
||||||
const rfCoord = pointer(event);
|
const rfCoord = pointer(event);
|
||||||
|
onClick?.(event, { x: rfCoord[0], y: rfCoord[1] });
|
||||||
console.log(rfCoord);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -94,11 +84,6 @@ function MiniMap({
|
|||||||
const selection = select(svg.current as Element);
|
const selection = select(svg.current as Element);
|
||||||
|
|
||||||
const zoomHandler = zoom()
|
const zoomHandler = zoom()
|
||||||
.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
|
||||||
const rfCoord = pointer(event);
|
|
||||||
|
|
||||||
startTransform.current = rfCoord;
|
|
||||||
})
|
|
||||||
.on('zoom.wheel', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
.on('zoom.wheel', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
||||||
const { transform, d3Selection, d3Zoom } = store.getState();
|
const { transform, d3Selection, d3Zoom } = store.getState();
|
||||||
|
|
||||||
@@ -112,25 +97,29 @@ function MiniMap({
|
|||||||
10;
|
10;
|
||||||
const zoom = transform[2] * Math.pow(2, pinchDelta);
|
const zoom = transform[2] * Math.pow(2, pinchDelta);
|
||||||
|
|
||||||
d3Zoom.scaleTo(d3Selection, zoom, startTransform.current);
|
d3Zoom.scaleTo(d3Selection, zoom);
|
||||||
})
|
})
|
||||||
.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
||||||
const { transform, d3Selection, d3Zoom } = store.getState();
|
const { transform, d3Selection, d3Zoom } = store.getState();
|
||||||
|
|
||||||
if (event.sourceEvent.type !== 'mousemove' || !d3Selection || !d3Zoom) {
|
if (event.sourceEvent.type !== 'mousemove' || !d3Selection || !d3Zoom) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let nextTransform = null;
|
||||||
|
|
||||||
const position = {
|
const position = {
|
||||||
x: transform[0] - event.sourceEvent.movementX * viewScaleRef.current * transform[2],
|
x: transform[0] - event.sourceEvent.movementX * viewScaleRef.current * transform[2],
|
||||||
y: transform[1] - event.sourceEvent.movementY * viewScaleRef.current * transform[2],
|
y: transform[1] - event.sourceEvent.movementY * viewScaleRef.current * transform[2],
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextTransform = zoomIdentity.translate(position.x, position.y).scale(transform[2]);
|
nextTransform = zoomIdentity.translate(position.x, position.y).scale(transform[2]);
|
||||||
|
|
||||||
d3Zoom.transform(d3Selection, nextTransform);
|
d3Zoom.transform(d3Selection, nextTransform);
|
||||||
});
|
});
|
||||||
selection.call(zoomHandler);
|
selection.call(zoomHandler);
|
||||||
}
|
}
|
||||||
}, [setCenter, setViewport, project]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel position={position} style={style} className={cc(['react-flow__minimap', className])}>
|
<Panel position={position} style={style} className={cc(['react-flow__minimap', className])}>
|
||||||
@@ -141,7 +130,7 @@ function MiniMap({
|
|||||||
role="img"
|
role="img"
|
||||||
aria-labelledby={labelledBy}
|
aria-labelledby={labelledBy}
|
||||||
ref={svg}
|
ref={svg}
|
||||||
onClick={onClick}
|
onClick={onSvgClick}
|
||||||
>
|
>
|
||||||
<title id={labelledBy}>React Flow mini map</title>
|
<title id={labelledBy}>React Flow mini map</title>
|
||||||
{nodes.map((node) => {
|
{nodes.map((node) => {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { HTMLAttributes } from 'react';
|
import { HTMLAttributes, MouseEvent } from 'react';
|
||||||
import { Node, PanelPosition } from '@reactflow/core';
|
import { Node, PanelPosition, XYPosition } from '@reactflow/core';
|
||||||
|
|
||||||
export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string;
|
export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string;
|
||||||
|
|
||||||
export interface MiniMapProps<NodeData = any> extends HTMLAttributes<SVGSVGElement> {
|
export type MiniMapProps<NodeData = any> = Omit<HTMLAttributes<SVGSVGElement>, 'onClick'> & {
|
||||||
nodeColor?: string | GetMiniMapNodeAttribute<NodeData>;
|
nodeColor?: string | GetMiniMapNodeAttribute<NodeData>;
|
||||||
nodeStrokeColor?: string | GetMiniMapNodeAttribute<NodeData>;
|
nodeStrokeColor?: string | GetMiniMapNodeAttribute<NodeData>;
|
||||||
nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>;
|
nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>;
|
||||||
@@ -12,4 +12,5 @@ export interface MiniMapProps<NodeData = any> extends HTMLAttributes<SVGSVGEleme
|
|||||||
nodeStrokeWidth?: number;
|
nodeStrokeWidth?: number;
|
||||||
maskColor?: string;
|
maskColor?: string;
|
||||||
position?: PanelPosition;
|
position?: PanelPosition;
|
||||||
}
|
onClick?: (event: MouseEvent, position: XYPosition) => void;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user