import { BaseEdge, Edge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, Position, useReactFlow, } from '@xyflow/react' import { ArrowLeft, ArrowRight } from 'lucide-react' import { memo, useCallback, useState } from 'react' import { Badge, cn } from 'ui' import { useSchemaGraphContext } from './SchemaGraphContext' import { EdgeData } from './Schemas.constants' import { useQuerySchemaState } from '@/hooks/misc/useSchemaQueryState' const DefaultEdgeComponent = ({ id, animated, data, deletable, selectable, source, sourceX, sourceY, sourceHandleId, sourcePosition = Position.Bottom, target, targetX, targetY, targetHandleId, targetPosition = Position.Top, selected, pathOptions, ...props }: EdgeProps>) => { const { isDownloading } = useSchemaGraphContext() const [edgePath, labelX, labelY] = getSmoothStepPath({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, borderRadius: pathOptions?.borderRadius, offset: pathOptions?.offset, stepPosition: pathOptions?.stepPosition, }) return ( <> {data && selected ? ( ) : null} ) } export const DefaultEdge = memo(DefaultEdgeComponent) const EdgeRelationInfo = ({ data, source, target, labelX, labelY, targetX, sourceX, }: { data: EdgeData edgePath: string source: string target: string labelX: number labelY: number sourceX: number targetX: number }) => { const [show, setShow] = useState(false) const reactFlowInstance = useReactFlow() const checkIfShouldBeDisplayed = useCallback( (relationInfoElement: HTMLDivElement | null) => { if (!relationInfoElement) return const sourceNode = reactFlowInstance.getNode(source) const targetNode = reactFlowInstance.getNode(target) if (!sourceNode || !targetNode) return const relationInfoRect = relationInfoElement.getBoundingClientRect() // Get the origin position of the relation information badge in the ReactFlow coordinates const relationInfoOriginPositionInReactFlow = reactFlowInstance.screenToFlowPosition({ x: relationInfoRect.x, y: relationInfoRect.y, }) // Get the end position (origin + dimensions) of the relation information badge in the ReactFlow coordinates const relationInfoTargetPositionInReactFlow = reactFlowInstance.screenToFlowPosition({ x: relationInfoRect.x + relationInfoRect.width, y: relationInfoRect.y + relationInfoRect.height, }) // Create a ReactFlow Rect from the computed position above const relationInfoReactFlowRect = { x: relationInfoOriginPositionInReactFlow.x, y: relationInfoOriginPositionInReactFlow.y, width: relationInfoTargetPositionInReactFlow.x - relationInfoOriginPositionInReactFlow.x, height: relationInfoTargetPositionInReactFlow.y - relationInfoOriginPositionInReactFlow.y, } // Check whether the relation information badge is intersecting with either the source or target node const isNodeIntersectingWithSource = reactFlowInstance.isNodeIntersecting( sourceNode, relationInfoReactFlowRect ) const isNodeIntersectingWithTarget = reactFlowInstance.isNodeIntersecting( targetNode, relationInfoReactFlowRect ) // If it is, hide it as they are too close setShow(!isNodeIntersectingWithSource && !isNodeIntersectingWithTarget) }, [reactFlowInstance, source, target] ) return ( { // Show the columns in the order of the schema instead of the Postgre relation order sourceX < targetX ? ( <> ) : ( <> ) } ) } const EdgeNodeData = ({ schema, table, column, }: { schema: string table: string column: string }) => { const { selectedSchema } = useQuerySchemaState() return ( {selectedSchema === schema ? '' : `${schema}.`} {table}.{column} ) }