|
| 1 | +import { memo } from "react"; |
| 2 | +import React from "react"; |
| 3 | +import { BaseEdge, Edge, EdgeProps, EdgeText, getBezierPath, getEdgeCenter } from "@xyflow/react"; |
| 4 | + |
| 5 | +import { IntentTypes } from "../../../common/Intent"; |
| 6 | +import { nodeContentUtils } from "../nodes/NodeContent"; |
| 7 | +import { NodeHighlightColor } from "../nodes/sharedTypes"; |
| 8 | + |
| 9 | +import { edgeDefaultUtils } from "./EdgeDefault"; |
| 10 | + |
| 11 | +export type EdgeDefaultV12DataProps = Record<string, unknown> & { |
| 12 | + /** |
| 13 | + * Overwrites the default style how the edge stroke is displayed. |
| 14 | + */ |
| 15 | + strokeType?: "solid" | "dashed" | "dotted" | "double" | "doubledashed"; |
| 16 | + /** |
| 17 | + * Feedback state of the node. |
| 18 | + */ |
| 19 | + intent?: IntentTypes; |
| 20 | + /** |
| 21 | + * Set the color of used highlights to mark the edge. |
| 22 | + */ |
| 23 | + highlightColor?: NodeHighlightColor | [NodeHighlightColor, NodeHighlightColor]; |
| 24 | + /** |
| 25 | + * Size of the "glow" effect when the edge is hovered. |
| 26 | + */ |
| 27 | + pathGlowWidth?: number; |
| 28 | + /* |
| 29 | + * Direction of the SVG path is inversed. |
| 30 | + * This is important for the placement of the markers and the animation movement. |
| 31 | + */ |
| 32 | + inversePath?: boolean; |
| 33 | + /** |
| 34 | + * Callback handler that returns a React element used as edge title. |
| 35 | + */ |
| 36 | + renderLabel?: (edgeCenter: [number, number, number, number]) => React.ReactNode; |
| 37 | + /** |
| 38 | + * Properties are forwarded to the internally used SVG `g` element. |
| 39 | + * Data attributes for test ids coud be included here. |
| 40 | + */ |
| 41 | + edgeSvgProps?: React.SVGProps<SVGGElement>; |
| 42 | +}; |
| 43 | + |
| 44 | +export const EdgeDefaultV12 = memo( |
| 45 | + ({ |
| 46 | + id, |
| 47 | + sourceX, |
| 48 | + sourceY, |
| 49 | + targetX, |
| 50 | + targetY, |
| 51 | + sourcePosition, |
| 52 | + targetPosition, |
| 53 | + label, |
| 54 | + labelStyle, |
| 55 | + labelShowBg, |
| 56 | + labelBgStyle, |
| 57 | + labelBgPadding = [5, 5], |
| 58 | + labelBgBorderRadius = 3, |
| 59 | + data = {}, |
| 60 | + ...edgeOriginalProperties |
| 61 | + }: EdgeProps<Edge<EdgeDefaultV12DataProps>>) => { |
| 62 | + const { pathGlowWidth = 10, highlightColor, renderLabel, edgeSvgProps, intent, inversePath, strokeType } = data; |
| 63 | + |
| 64 | + const [edgePath, labelX, labelY] = getBezierPath({ |
| 65 | + sourceX, |
| 66 | + sourceY, |
| 67 | + sourcePosition, |
| 68 | + targetX, |
| 69 | + targetY, |
| 70 | + targetPosition, |
| 71 | + }); |
| 72 | + |
| 73 | + const edgeStyle = edgeOriginalProperties.style ?? {}; |
| 74 | + const { highlightCustomPropertySettings } = nodeContentUtils.evaluateHighlightColors( |
| 75 | + "--edge-highlight", |
| 76 | + highlightColor |
| 77 | + ); |
| 78 | + |
| 79 | + const edgeCenter = getEdgeCenter({ |
| 80 | + sourceX, |
| 81 | + sourceY, |
| 82 | + targetX, |
| 83 | + targetY, |
| 84 | + }); |
| 85 | + |
| 86 | + const renderedLabel = |
| 87 | + renderLabel?.([labelX, labelY, sourceX, targetX]) ?? |
| 88 | + (label ? ( |
| 89 | + <EdgeText |
| 90 | + x={edgeCenter[0]} |
| 91 | + y={edgeCenter[1]} |
| 92 | + label={label} |
| 93 | + labelStyle={labelStyle} |
| 94 | + labelShowBg={labelShowBg} |
| 95 | + labelBgStyle={labelBgStyle} |
| 96 | + labelBgPadding={labelBgPadding || [5, 5]} |
| 97 | + labelBgBorderRadius={labelBgBorderRadius || 3} |
| 98 | + /> |
| 99 | + ) : null); |
| 100 | + |
| 101 | + return ( |
| 102 | + <g |
| 103 | + className={ |
| 104 | + "react-flow__edge " + |
| 105 | + edgeDefaultUtils.createEdgeDefaultClassName( |
| 106 | + { intent }, |
| 107 | + `${edgeOriginalProperties.selected ? "selected" : ""}` |
| 108 | + ) |
| 109 | + } |
| 110 | + tabIndex={0} |
| 111 | + role="button" |
| 112 | + data-id={id} |
| 113 | + aria-label={`Edge from ${edgeOriginalProperties.source} to ${edgeOriginalProperties.target}`} |
| 114 | + aria-describedby={`react-flow__edge-desc-${id}`} |
| 115 | + > |
| 116 | + <g className={edgeSvgProps?.className ?? ""}> |
| 117 | + {highlightColor && ( |
| 118 | + <path |
| 119 | + d={edgePath} |
| 120 | + className={edgeDefaultUtils.createEdgeDefaultClassName( |
| 121 | + { highlightColor }, |
| 122 | + "react-flow__edge-path-highlight" |
| 123 | + )} |
| 124 | + strokeWidth={10} |
| 125 | + style={{ |
| 126 | + ...highlightCustomPropertySettings, |
| 127 | + }} |
| 128 | + /> |
| 129 | + )} |
| 130 | + |
| 131 | + <BaseEdge |
| 132 | + id={id} |
| 133 | + path={edgePath} |
| 134 | + markerStart={inversePath ? "url(#arrow-closed-reverse)" : undefined} |
| 135 | + markerEnd={!inversePath ? "url(#arrow-closed)" : undefined} |
| 136 | + className={edgeDefaultUtils.createEdgeDefaultClassName({ strokeType })} |
| 137 | + interactionWidth={pathGlowWidth} |
| 138 | + style={{ |
| 139 | + ...edgeSvgProps?.style, |
| 140 | + ...edgeStyle, |
| 141 | + color: edgeStyle.color || edgeStyle.stroke, |
| 142 | + }} |
| 143 | + /> |
| 144 | + </g> |
| 145 | + {renderedLabel} |
| 146 | + </g> |
| 147 | + ); |
| 148 | + } |
| 149 | +); |
0 commit comments