123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- 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)
|