File size: 2,890 Bytes
a8b3f00 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
import {
memo,
useCallback,
useState,
} from 'react'
import { intersection } from 'lodash-es'
import type { EdgeProps } from 'reactflow'
import {
BaseEdge,
EdgeLabelRenderer,
Position,
getBezierPath,
} from 'reactflow'
import {
useAvailableBlocks,
useNodesInteractions,
} from './hooks'
import BlockSelector from './block-selector'
import type {
Edge,
OnSelectBlock,
} from './types'
import { ITERATION_CHILDREN_Z_INDEX } from './constants'
import cn from '@/utils/classnames'
const CustomEdge = ({
id,
data,
source,
sourceHandleId,
target,
targetHandleId,
sourceX,
sourceY,
targetX,
targetY,
selected,
}: EdgeProps) => {
const [
edgePath,
labelX,
labelY,
] = getBezierPath({
sourceX: sourceX - 8,
sourceY,
sourcePosition: Position.Right,
targetX: targetX + 8,
targetY,
targetPosition: Position.Left,
curvature: 0.16,
})
const [open, setOpen] = useState(false)
const { handleNodeAdd } = useNodesInteractions()
const { availablePrevBlocks } = useAvailableBlocks((data as Edge['data'])!.targetType, (data as Edge['data'])?.isInIteration)
const { availableNextBlocks } = useAvailableBlocks((data as Edge['data'])!.sourceType, (data as Edge['data'])?.isInIteration)
const handleOpenChange = useCallback((v: boolean) => {
setOpen(v)
}, [])
const handleInsert = useCallback<OnSelectBlock>((nodeType, toolDefaultValue) => {
handleNodeAdd(
{
nodeType,
toolDefaultValue,
},
{
prevNodeId: source,
prevNodeSourceHandle: sourceHandleId || 'source',
nextNodeId: target,
nextNodeTargetHandle: targetHandleId || 'target',
},
)
}, [handleNodeAdd, source, sourceHandleId, target, targetHandleId])
return (
<>
<BaseEdge
id={id}
path={edgePath}
style={{
stroke: (selected || data?._connectedNodeIsHovering || data?._run) ? '#2970FF' : '#D0D5DD',
strokeWidth: 2,
}}
/>
<EdgeLabelRenderer>
<div
className={cn(
'nopan nodrag hover:scale-125',
data?._hovering ? 'block' : 'hidden',
open && '!block',
data.isInIteration && `z-[${ITERATION_CHILDREN_Z_INDEX}]`,
)}
style={{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
pointerEvents: 'all',
}}
>
<BlockSelector
open={open}
onOpenChange={handleOpenChange}
asChild
onSelect={handleInsert}
availableBlocksTypes={intersection(availablePrevBlocks, availableNextBlocks)}
triggerClassName={() => 'hover:scale-150 transition-all'}
/>
</div>
</EdgeLabelRenderer>
</>
)
}
export default memo(CustomEdge)
|