Optimize MiniMapNodes like NodeRenderer
This commit is contained in:
@@ -1,21 +1,30 @@
|
|||||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { memo } from 'react';
|
import { ComponentType, memo, MouseEvent } from 'react';
|
||||||
import { shallow } from 'zustand/shallow';
|
import { shallow } from 'zustand/shallow';
|
||||||
import { getNodePositionWithOrigin } from '@xyflow/system';
|
import { NodeOrigin, getNodePositionWithOrigin } from '@xyflow/system';
|
||||||
|
|
||||||
import { useStore } from '../../hooks/useStore';
|
import { useStore } from '../../hooks/useStore';
|
||||||
import type { ReactFlowState } from '../../types';
|
import type { ReactFlowState } from '../../types';
|
||||||
import MiniMapNode from './MiniMapNode';
|
import MiniMapNode from './MiniMapNode';
|
||||||
import type { MiniMapNodes, GetMiniMapNodeAttribute } from './types';
|
import type { MiniMapNodes as MiniMapNodesProps, GetMiniMapNodeAttribute, MiniMapNodeProps } from './types';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
declare const window: any;
|
declare const window: any;
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => s.nodeOrigin;
|
const selector = (s: ReactFlowState) => s.nodeOrigin;
|
||||||
const selectorNodes = (s: ReactFlowState) =>
|
const selectorNodeIds = createSelector(
|
||||||
s.nodes.filter(
|
[(s: ReactFlowState) => s.nodes],
|
||||||
(node) => !node.hidden && (node.computed?.width || node.width) && (node.computed?.height || node.height)
|
(nodes) =>
|
||||||
);
|
nodes
|
||||||
|
.filter((node) => !node.hidden && (node.computed?.width || node.width) && (node.computed?.height || node.height))
|
||||||
|
.map((node) => node.id),
|
||||||
|
{
|
||||||
|
memoizeOptions: {
|
||||||
|
resultEqualityCheck: shallow,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func);
|
const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func);
|
||||||
|
|
||||||
function MiniMapNodes({
|
function MiniMapNodes({
|
||||||
@@ -28,8 +37,8 @@ function MiniMapNodes({
|
|||||||
// a component properly.
|
// a component properly.
|
||||||
nodeComponent: NodeComponent = MiniMapNode,
|
nodeComponent: NodeComponent = MiniMapNode,
|
||||||
onClick,
|
onClick,
|
||||||
}: MiniMapNodes) {
|
}: MiniMapNodesProps) {
|
||||||
const nodes = useStore(selectorNodes, shallow);
|
const nodes = useStore(selectorNodeIds);
|
||||||
const nodeOrigin = useStore(selector);
|
const nodeOrigin = useStore(selector);
|
||||||
const nodeColorFunc = getAttrFunction(nodeColor);
|
const nodeColorFunc = getAttrFunction(nodeColor);
|
||||||
const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
|
const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
|
||||||
@@ -39,33 +48,73 @@ function MiniMapNodes({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{nodes.map((node) => {
|
{nodes.map((nodeId) => (
|
||||||
const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute;
|
<NodeComponentWrapper
|
||||||
const color = nodeColor === undefined ? undefined : nodeColorFunc(node);
|
key={nodeId}
|
||||||
const strokeColor = nodeStrokeColor === undefined ? undefined : nodeStrokeColorFunc(node);
|
id={nodeId}
|
||||||
|
nodeOrigin={nodeOrigin}
|
||||||
return (
|
nodeColorFunc={nodeColorFunc}
|
||||||
<NodeComponent
|
nodeStrokeColorFunc={nodeStrokeColorFunc}
|
||||||
key={node.id}
|
nodeClassNameFunc={nodeClassNameFunc}
|
||||||
x={x}
|
nodeBorderRadius={nodeBorderRadius}
|
||||||
y={y}
|
nodeStrokeWidth={nodeStrokeWidth}
|
||||||
width={node.computed?.width ?? node.width ?? 0}
|
NodeComponent={NodeComponent}
|
||||||
height={node.computed?.height ?? node.height ?? 0}
|
onClick={onClick}
|
||||||
style={node.style}
|
shapeRendering={shapeRendering}
|
||||||
selected={!!node.selected}
|
/>
|
||||||
className={nodeClassNameFunc(node)}
|
))}
|
||||||
color={color}
|
|
||||||
borderRadius={nodeBorderRadius}
|
|
||||||
strokeColor={strokeColor}
|
|
||||||
strokeWidth={nodeStrokeWidth}
|
|
||||||
shapeRendering={shapeRendering}
|
|
||||||
onClick={onClick}
|
|
||||||
id={node.id}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NodeComponentWrapper = memo(function NodeComponentWrapper({
|
||||||
|
id,
|
||||||
|
nodeOrigin,
|
||||||
|
nodeColorFunc,
|
||||||
|
nodeStrokeColorFunc,
|
||||||
|
nodeClassNameFunc,
|
||||||
|
nodeBorderRadius,
|
||||||
|
nodeStrokeWidth,
|
||||||
|
shapeRendering,
|
||||||
|
NodeComponent,
|
||||||
|
onClick,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
nodeOrigin: NodeOrigin;
|
||||||
|
nodeColorFunc: GetMiniMapNodeAttribute;
|
||||||
|
nodeStrokeColorFunc: GetMiniMapNodeAttribute;
|
||||||
|
nodeClassNameFunc: GetMiniMapNodeAttribute;
|
||||||
|
nodeBorderRadius: number;
|
||||||
|
nodeStrokeWidth?: number;
|
||||||
|
NodeComponent: ComponentType<MiniMapNodeProps>;
|
||||||
|
onClick: MiniMapNodesProps['onClick'];
|
||||||
|
shapeRendering: string;
|
||||||
|
}) {
|
||||||
|
const node = useStore((s) => s.nodeLookup.get(id));
|
||||||
|
if (!node) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NodeComponent
|
||||||
|
x={x}
|
||||||
|
y={y}
|
||||||
|
width={node.computed?.width ?? node.width ?? 0}
|
||||||
|
height={node.computed?.height ?? node.height ?? 0}
|
||||||
|
style={node.style}
|
||||||
|
selected={!!node.selected}
|
||||||
|
className={nodeClassNameFunc(node)}
|
||||||
|
color={nodeColorFunc(node)}
|
||||||
|
borderRadius={nodeBorderRadius}
|
||||||
|
strokeColor={nodeStrokeColorFunc(node)}
|
||||||
|
strokeWidth={nodeStrokeWidth}
|
||||||
|
shapeRendering={shapeRendering}
|
||||||
|
onClick={onClick}
|
||||||
|
id={node.id}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export default memo(MiniMapNodes);
|
export default memo(MiniMapNodes);
|
||||||
|
|||||||
Reference in New Issue
Block a user