Files
xyflow/packages/react/src/container/EdgeRenderer/MarkerDefinitions.tsx
2023-06-05 15:40:18 +02:00

86 lines
2.3 KiB
TypeScript

import { memo, useCallback } from 'react';
import { type MarkerProps, createMarkerIds } from '@xyflow/system';
import { useStore } from '../../hooks/useStore';
import { useMarkerSymbol } from './MarkerSymbols';
import type { ReactFlowState } from '../../types';
type MarkerDefinitionsProps = {
defaultColor: string;
rfId?: string;
};
const Marker = ({
id,
type,
color,
width = 12.5,
height = 12.5,
markerUnits = 'strokeWidth',
strokeWidth,
orient = 'auto-start-reverse',
}: MarkerProps) => {
const Symbol = useMarkerSymbol(type);
if (!Symbol) {
return null;
}
return (
<marker
className="react-flow__arrowhead"
id={id}
markerWidth={`${width}`}
markerHeight={`${height}`}
viewBox="-10 -10 20 20"
markerUnits={markerUnits}
orient={orient}
refX="0"
refY="0"
>
<Symbol color={color} strokeWidth={strokeWidth} />
</marker>
);
};
const markerSelector =
({ defaultColor, rfId }: { defaultColor: string; rfId?: string }) =>
(s: ReactFlowState) => {
const markers = createMarkerIds(s.edges, { id: rfId, defaultColor });
return markers;
};
// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore
// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper
// that we can then use for creating our unique marker ids
const MarkerDefinitions = ({ defaultColor, rfId }: MarkerDefinitionsProps) => {
const markers = useStore(
useCallback(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]),
// the id includes all marker options, so we just need to look at that part of the marker
(a, b) => !(a.length !== b.length || a.some((m, i) => m.id !== b[i].id))
);
return (
<defs>
{markers.map((marker: MarkerProps) => (
<Marker
id={marker.id}
key={marker.id}
type={marker.type}
color={marker.color}
width={marker.width}
height={marker.height}
markerUnits={marker.markerUnits}
strokeWidth={marker.strokeWidth}
orient={marker.orient}
/>
))}
</defs>
);
};
MarkerDefinitions.displayName = 'MarkerDefinitions';
export default memo(MarkerDefinitions);