Merge pull request #2906 from wbkd/feat/custom-minimap-nodes
feat: add prop to render custom node inside minimap
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@reactflow/minimap': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: add nodeComponent prop for passing custom component
|
||||||
@@ -5,6 +5,7 @@ import Basic from '../examples/Basic';
|
|||||||
import Backgrounds from '../examples/Backgrounds';
|
import Backgrounds from '../examples/Backgrounds';
|
||||||
import ControlledUncontrolled from '../examples/ControlledUncontrolled';
|
import ControlledUncontrolled from '../examples/ControlledUncontrolled';
|
||||||
import CustomConnectionLine from '../examples/CustomConnectionLine';
|
import CustomConnectionLine from '../examples/CustomConnectionLine';
|
||||||
|
import CustomMiniMapNode from '../examples/CustomMiniMapNode';
|
||||||
import CustomNode from '../examples/CustomNode';
|
import CustomNode from '../examples/CustomNode';
|
||||||
import DefaultNodes from '../examples/DefaultNodes';
|
import DefaultNodes from '../examples/DefaultNodes';
|
||||||
import DragHandle from '../examples/DragHandle';
|
import DragHandle from '../examples/DragHandle';
|
||||||
@@ -77,6 +78,11 @@ const routes: IRoute[] = [
|
|||||||
path: '/custom-connectionline',
|
path: '/custom-connectionline',
|
||||||
component: CustomConnectionLine,
|
component: CustomConnectionLine,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Custom Minimap Node',
|
||||||
|
path: '/custom-minimap-node',
|
||||||
|
component: CustomMiniMapNode,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Custom Node',
|
name: 'Custom Node',
|
||||||
path: '/custom-node',
|
path: '/custom-node',
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { MouseEvent, CSSProperties, useCallback } from 'react';
|
||||||
|
|
||||||
|
import ReactFlow, {
|
||||||
|
addEdge,
|
||||||
|
Background,
|
||||||
|
BackgroundVariant,
|
||||||
|
Connection,
|
||||||
|
Controls,
|
||||||
|
Edge,
|
||||||
|
MiniMap,
|
||||||
|
MiniMapNodeProps,
|
||||||
|
Node,
|
||||||
|
ReactFlowInstance,
|
||||||
|
useEdgesState,
|
||||||
|
useNodesState,
|
||||||
|
} from 'reactflow';
|
||||||
|
|
||||||
|
const onInit = (reactFlowInstance: ReactFlowInstance) => console.log('flow loaded:', reactFlowInstance);
|
||||||
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||||
|
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||||
|
|
||||||
|
const buttonStyle: CSSProperties = {
|
||||||
|
position: 'absolute',
|
||||||
|
left: 10,
|
||||||
|
top: 10,
|
||||||
|
zIndex: 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomMiniMapNode = ({ x, y, width, height, color }: MiniMapNodeProps) => (
|
||||||
|
<circle cx={x} cy={y} r={Math.max(width, height) / 2} fill={color} />
|
||||||
|
);
|
||||||
|
|
||||||
|
const CustomMiniMapNodeFlow = () => {
|
||||||
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
||||||
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||||
|
|
||||||
|
const onConnect = useCallback((params: Connection | Edge) => setEdges((els) => addEdge(params, els)), [setEdges]);
|
||||||
|
const addRandomNode = () => {
|
||||||
|
const nodeId = (nodes.length + 1).toString();
|
||||||
|
const newNode: Node = {
|
||||||
|
id: nodeId,
|
||||||
|
data: { label: `Node: ${nodeId}` },
|
||||||
|
position: {
|
||||||
|
x: Math.random() * window.innerWidth,
|
||||||
|
y: Math.random() * window.innerHeight,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
setNodes((nds) => nds.concat(newNode));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactFlow
|
||||||
|
nodes={nodes}
|
||||||
|
edges={edges}
|
||||||
|
onInit={onInit}
|
||||||
|
onNodesChange={onNodesChange}
|
||||||
|
onEdgesChange={onEdgesChange}
|
||||||
|
onNodeClick={onNodeClick}
|
||||||
|
onConnect={(p) => onConnect(p)}
|
||||||
|
onNodeDragStop={onNodeDragStop}
|
||||||
|
onlyRenderVisibleElements={false}
|
||||||
|
>
|
||||||
|
<Controls />
|
||||||
|
<Background variant={BackgroundVariant.Lines} />
|
||||||
|
<MiniMap nodeComponent={CustomMiniMapNode} />
|
||||||
|
|
||||||
|
<button type="button" onClick={addRandomNode} style={buttonStyle}>
|
||||||
|
add node
|
||||||
|
</button>
|
||||||
|
</ReactFlow>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CustomMiniMapNodeFlow;
|
||||||
@@ -55,6 +55,9 @@ function MiniMap({
|
|||||||
nodeClassName = '',
|
nodeClassName = '',
|
||||||
nodeBorderRadius = 5,
|
nodeBorderRadius = 5,
|
||||||
nodeStrokeWidth = 2,
|
nodeStrokeWidth = 2,
|
||||||
|
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
|
||||||
|
// a component properly.
|
||||||
|
nodeComponent: NodeComponent = MiniMapNode,
|
||||||
maskColor = 'rgb(240, 240, 240, 0.6)',
|
maskColor = 'rgb(240, 240, 240, 0.6)',
|
||||||
maskStrokeColor = 'none',
|
maskStrokeColor = 'none',
|
||||||
maskStrokeWidth = 1,
|
maskStrokeWidth = 1,
|
||||||
@@ -181,7 +184,7 @@ function MiniMap({
|
|||||||
const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
|
const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MiniMapNode
|
<NodeComponent
|
||||||
key={node.id}
|
key={node.id}
|
||||||
x={x}
|
x={x}
|
||||||
y={y}
|
y={y}
|
||||||
|
|||||||
@@ -1,23 +1,7 @@
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import type { CSSProperties, MouseEvent } from 'react';
|
import type { MiniMapNodeProps } from './types';
|
||||||
import cc from 'classcat';
|
import cc from 'classcat';
|
||||||
|
|
||||||
interface MiniMapNodeProps {
|
|
||||||
id: string;
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
borderRadius: number;
|
|
||||||
className: string;
|
|
||||||
color: string;
|
|
||||||
shapeRendering: string;
|
|
||||||
strokeColor: string;
|
|
||||||
strokeWidth: number;
|
|
||||||
style?: CSSProperties;
|
|
||||||
onClick?: (event: MouseEvent, id: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MiniMapNode = ({
|
const MiniMapNode = ({
|
||||||
id,
|
id,
|
||||||
x,
|
x,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import type { HTMLAttributes, MouseEvent } from 'react';
|
import type { ComponentType, CSSProperties, HTMLAttributes, MouseEvent } from 'react';
|
||||||
import type { Node, PanelPosition, XYPosition } from '@reactflow/core';
|
import type { Node, PanelPosition, XYPosition } from '@reactflow/core';
|
||||||
|
|
||||||
export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string;
|
export type GetMiniMapNodeAttribute<NodeData = any> = (node: Node<NodeData>) => string;
|
||||||
@@ -10,6 +10,7 @@ export type MiniMapProps<NodeData = any> = Omit<HTMLAttributes<SVGSVGElement>, '
|
|||||||
nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>;
|
nodeClassName?: string | GetMiniMapNodeAttribute<NodeData>;
|
||||||
nodeBorderRadius?: number;
|
nodeBorderRadius?: number;
|
||||||
nodeStrokeWidth?: number;
|
nodeStrokeWidth?: number;
|
||||||
|
nodeComponent?: ComponentType<MiniMapNodeProps>;
|
||||||
maskColor?: string;
|
maskColor?: string;
|
||||||
maskStrokeColor?: string;
|
maskStrokeColor?: string;
|
||||||
maskStrokeWidth?: number;
|
maskStrokeWidth?: number;
|
||||||
@@ -20,3 +21,19 @@ export type MiniMapProps<NodeData = any> = Omit<HTMLAttributes<SVGSVGElement>, '
|
|||||||
zoomable?: boolean;
|
zoomable?: boolean;
|
||||||
ariaLabel?: string | null;
|
ariaLabel?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface MiniMapNodeProps {
|
||||||
|
id: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
borderRadius: number;
|
||||||
|
className: string;
|
||||||
|
color: string;
|
||||||
|
shapeRendering: string;
|
||||||
|
strokeColor: string;
|
||||||
|
strokeWidth: number;
|
||||||
|
style?: CSSProperties;
|
||||||
|
onClick?: (event: MouseEvent, id: string) => void;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user