|
import { |
|
BaseEdge, |
|
EdgeLabelRenderer, |
|
EdgeProps, |
|
getBezierPath, |
|
} from 'reactflow'; |
|
import useGraphStore from '../../store'; |
|
|
|
import { useFetchFlow } from '@/hooks/flow-hooks'; |
|
import { useMemo } from 'react'; |
|
import styles from './index.less'; |
|
|
|
export function ButtonEdge({ |
|
id, |
|
sourceX, |
|
sourceY, |
|
targetX, |
|
targetY, |
|
sourcePosition, |
|
targetPosition, |
|
source, |
|
target, |
|
style = {}, |
|
markerEnd, |
|
selected, |
|
}: EdgeProps) { |
|
const deleteEdgeById = useGraphStore((state) => state.deleteEdgeById); |
|
const [edgePath, labelX, labelY] = getBezierPath({ |
|
sourceX, |
|
sourceY, |
|
sourcePosition, |
|
targetX, |
|
targetY, |
|
targetPosition, |
|
}); |
|
|
|
const selectedStyle = useMemo(() => { |
|
return selected ? { strokeWidth: 2, stroke: '#1677ff' } : {}; |
|
}, [selected]); |
|
|
|
const onEdgeClick = () => { |
|
deleteEdgeById(id); |
|
}; |
|
|
|
|
|
|
|
|
|
const { data: flowDetail } = useFetchFlow(); |
|
|
|
const graphPath = useMemo(() => { |
|
|
|
const path = flowDetail?.dsl?.path ?? []; |
|
|
|
const previousGraphPath: string[] = path.at(-2) ?? []; |
|
let graphPath: string[] = path.at(-1) ?? []; |
|
|
|
const previousLatestElement = previousGraphPath.at(-1); |
|
if (previousGraphPath.length > 0 && previousLatestElement) { |
|
graphPath = [previousLatestElement, ...graphPath]; |
|
} |
|
return graphPath; |
|
}, [flowDetail.dsl?.path]); |
|
|
|
const highlightStyle = useMemo(() => { |
|
const idx = graphPath.findIndex((x) => x === source); |
|
if (idx !== -1) { |
|
|
|
const slicedGraphPath = graphPath.slice(idx + 1); |
|
if (slicedGraphPath.some((x) => x === target)) { |
|
return { strokeWidth: 2, stroke: 'red' }; |
|
} |
|
} |
|
return {}; |
|
}, [source, target, graphPath]); |
|
|
|
return ( |
|
<> |
|
<BaseEdge |
|
path={edgePath} |
|
markerEnd={markerEnd} |
|
style={{ ...style, ...selectedStyle, ...highlightStyle }} |
|
/> |
|
<EdgeLabelRenderer> |
|
<div |
|
style={{ |
|
position: 'absolute', |
|
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`, |
|
fontSize: 12, |
|
// everything inside EdgeLabelRenderer has no pointer events by default |
|
// if you have an interactive element, set pointer-events: all |
|
pointerEvents: 'all', |
|
}} |
|
className="nodrag nopan" |
|
> |
|
<button |
|
className={styles.edgeButton} |
|
type="button" |
|
onClick={onEdgeClick} |
|
> |
|
× |
|
</button> |
|
</div> |
|
</EdgeLabelRenderer> |
|
</> |
|
); |
|
} |
|
|