feat(markers): implement more generic api for markerEnd and markerStart handling

This commit is contained in:
Christopher Möller
2021-10-14 17:53:50 +02:00
parent eed5717821
commit d3b1148bca
18 changed files with 192 additions and 120 deletions
@@ -1,52 +1,98 @@
import React, { ReactNode } from 'react';
import React, { useMemo } from 'react';
import { useStoreState } from '../../store/hooks';
import { EdgeMarker, ArrowHeadType } from '../../types';
import { getMarkerId } from '../../utils/graph';
interface MarkerProps {
id: string;
children: ReactNode;
type: ArrowHeadType;
color: string;
}
interface MarkerDefinitionsProps {
defaultColor: string;
}
const Marker = ({ id, children }: MarkerProps) => (
<marker
className="react-flow__arrowhead"
id={id}
markerWidth="12.5"
markerHeight="12.5"
viewBox="-10 -10 20 20"
orient="auto"
refX="0"
refY="0"
>
{children}
</marker>
);
interface MarkerDefinitionsProps {
interface SymbolProps {
color: string;
}
const MarkerDefinitions = ({ color }: MarkerDefinitionsProps) => {
interface EdgeMarkerExtended extends EdgeMarker {
id: string;
}
const ArrowSymbol = ({ color }: SymbolProps) => {
return (
<polyline
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1"
fill={color}
points="-5,-4 0,0 -5,4 -5,-4"
/>
);
};
const ArrowClosedSymbol = ({ color }: SymbolProps) => {
return (
<polyline
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1"
fill={color}
points="-5,-4 0,0 -5,4 -5,-4"
/>
);
};
const markerSymbols = {
[ArrowHeadType.Arrow]: ArrowSymbol,
[ArrowHeadType.ArrowClosed]: ArrowClosedSymbol,
};
const Marker = ({ id, type, color }: MarkerProps) => {
const Symbol = markerSymbols[type];
return (
<marker
className="react-flow__arrowhead"
id={id}
markerWidth="12.5"
markerHeight="12.5"
viewBox="-10 -10 20 20"
orient="auto"
refX="0"
refY="0"
>
<Symbol color={color} />
</marker>
);
};
const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
const edges = useStoreState((state) => state.edges);
const markers = useMemo(() => {
const ids: string[] = [];
return edges.reduce<EdgeMarkerExtended[]>((markers, edge) => {
[edge.markerStart, edge.markerEnd].forEach((marker) => {
if (marker && typeof marker === 'object') {
const markerId = getMarkerId(marker);
if (!ids.includes(markerId)) {
markers.push({ id: markerId, ...marker });
ids.push(markerId);
}
}
});
return markers.sort((a, b) => a.id.localeCompare(b.id));
}, []);
}, [edges]);
return (
<defs>
<Marker id="react-flow__arrowclosed">
<polyline
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1"
fill={color}
points="-5,-4 0,0 -5,4 -5,-4"
/>
</Marker>
<Marker id="react-flow__arrow">
<polyline
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
fill="none"
points="-5,-4 0,0 -5,4"
/>
</Marker>
{markers.map((marker: EdgeMarkerExtended) => (
<Marker id={marker.id} key={marker.id} type={marker.type} color={marker.color || defaultColor} />
))}
</defs>
);
};