/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { ComponentType, memo } from 'react';
import { NodeOrigin, getNodePositionWithOrigin } from '@xyflow/system';
import { shallow } from 'zustand/shallow';
import { useStore } from '../../hooks/useStore';
import { MiniMapNode } from './MiniMapNode';
import type { ReactFlowState } from '../../types';
import type { MiniMapNodes as MiniMapNodesProps, GetMiniMapNodeAttribute, MiniMapNodeProps } from './types';
declare const window: any;
const selector = (s: ReactFlowState) => s.nodeOrigin;
const selectorNodeIds = (s: ReactFlowState) => s.nodes.map((node) => node.id);
const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func);
function MiniMapNodes({
nodeStrokeColor,
nodeColor,
nodeClassName = '',
nodeBorderRadius = 5,
nodeStrokeWidth,
// We need to rename the prop to be `CapitalCase` so that JSX will render it as
// a component properly.
nodeComponent: NodeComponent = MiniMapNode,
onClick,
}: MiniMapNodesProps) {
const nodeIds = useStore(selectorNodeIds, shallow);
const nodeOrigin = useStore(selector);
const nodeColorFunc = getAttrFunction(nodeColor);
const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor);
const nodeClassNameFunc = getAttrFunction(nodeClassName);
const shapeRendering = typeof window === 'undefined' || !!window.chrome ? 'crispEdges' : 'geometricPrecision';
return (
<>
{nodeIds.map((nodeId) => (
// The split of responsibilities between MiniMapNodes and
// NodeComponentWrapper may appear weird. However, it’s designed to
// minimize the cost of updates when individual nodes change.
//
// For more details, see a similar commit in `NodeRenderer/index.tsx`.
))}
>
);
}
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;
onClick: MiniMapNodesProps['onClick'];
shapeRendering: string;
}) {
const { node, x, y } = useStore((s) => {
const node = s.nodeLookup.get(id);
const { x, y } = getNodePositionWithOrigin(node, node?.origin || nodeOrigin).positionAbsolute;
return {
node,
x,
y,
};
}, shallow);
if (!node || node.hidden || !(node.computed?.width || node.width) || !(node.computed?.height || node.height)) {
return null;
}
return (
);
});
export default memo(MiniMapNodes);