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>
);
};
+5 -6
View File
@@ -26,8 +26,7 @@ interface EdgeRendererProps {
connectionMode?: ConnectionMode;
onElementClick?: (event: React.MouseEvent, element: Node | Edge) => void;
onEdgeDoubleClick?: (event: React.MouseEvent, edge: Edge) => void;
arrowHeadColor: string;
markerEndId?: string;
defaultMarkerColor: string;
onlyRenderVisibleElements: boolean;
onEdgeUpdate?: OnEdgeUpdateFunc;
onEdgeContextMenu?: (event: React.MouseEvent, edge: Edge) => void;
@@ -155,7 +154,8 @@ const Edge = ({
labelBgPadding={edge.labelBgPadding}
labelBgBorderRadius={edge.labelBgBorderRadius}
style={edge.style}
arrowHeadType={edge.arrowHeadType}
markerEnd={edge.markerEnd}
markerStart={edge.markerStart}
source={edge.source}
target={edge.target}
sourceHandleId={sourceHandleId}
@@ -167,7 +167,6 @@ const Edge = ({
sourcePosition={sourcePosition}
targetPosition={targetPosition}
elementsSelectable={elementsSelectable}
markerEndId={props.markerEndId}
isHidden={edge.isHidden}
onConnectEdge={onConnectEdge}
handleEdgeUpdate={typeof props.onEdgeUpdate !== 'undefined'}
@@ -203,7 +202,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
const {
connectionLineType,
arrowHeadColor,
defaultMarkerColor,
connectionLineStyle,
connectionLineComponent,
onlyRenderVisibleElements,
@@ -213,7 +212,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
return (
<svg width={width} height={height} className="react-flow__edges">
<MarkerDefinitions color={arrowHeadColor} />
<MarkerDefinitions defaultColor={defaultMarkerColor} />
<g transform={transformStyle}>
{edges.map((edge: Edge) => (
<Edge