{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"edge","type":"registry:component","title":"Edge","description":"AI-powered edge component.","files":[{"path":"registry/default/ai-elements/edge.tsx","type":"registry:component","content":"import {\n  BaseEdge,\n  type EdgeProps,\n  getBezierPath,\n  getSimpleBezierPath,\n  type InternalNode,\n  type Node,\n  Position,\n  useInternalNode,\n} from \"@xyflow/react\";\n\nconst Temporary = ({\n  id,\n  sourceX,\n  sourceY,\n  targetX,\n  targetY,\n  sourcePosition,\n  targetPosition,\n}: EdgeProps) => {\n  const [edgePath] = getSimpleBezierPath({\n    sourceX,\n    sourceY,\n    sourcePosition,\n    targetX,\n    targetY,\n    targetPosition,\n  });\n\n  return (\n    <BaseEdge\n      className=\"stroke-1 stroke-ring\"\n      id={id}\n      path={edgePath}\n      style={{\n        strokeDasharray: \"5, 5\",\n      }}\n    />\n  );\n};\n\nconst getHandleCoordsByPosition = (\n  node: InternalNode<Node>,\n  handlePosition: Position\n) => {\n  // Choose the handle type based on position - Left is for target, Right is for source\n  const handleType = handlePosition === Position.Left ? \"target\" : \"source\";\n\n  const handle = node.internals.handleBounds?.[handleType]?.find(\n    (h) => h.position === handlePosition\n  );\n\n  if (!handle) {\n    return [0, 0] as const;\n  }\n\n  let offsetX = handle.width / 2;\n  let offsetY = handle.height / 2;\n\n  // this is a tiny detail to make the markerEnd of an edge visible.\n  // The handle position that gets calculated has the origin top-left, so depending which side we are using, we add a little offset\n  // when the handlePosition is Position.Right for example, we need to add an offset as big as the handle itself in order to get the correct position\n  switch (handlePosition) {\n    case Position.Left:\n      offsetX = 0;\n      break;\n    case Position.Right:\n      offsetX = handle.width;\n      break;\n    case Position.Top:\n      offsetY = 0;\n      break;\n    case Position.Bottom:\n      offsetY = handle.height;\n      break;\n    default:\n      throw new Error(`Invalid handle position: ${handlePosition}`);\n  }\n\n  const x = node.internals.positionAbsolute.x + handle.x + offsetX;\n  const y = node.internals.positionAbsolute.y + handle.y + offsetY;\n\n  return [x, y] as const;\n};\n\nconst getEdgeParams = (\n  source: InternalNode<Node>,\n  target: InternalNode<Node>\n) => {\n  const sourcePos = Position.Right;\n  const [sx, sy] = getHandleCoordsByPosition(source, sourcePos);\n  const targetPos = Position.Left;\n  const [tx, ty] = getHandleCoordsByPosition(target, targetPos);\n\n  return {\n    sx,\n    sy,\n    tx,\n    ty,\n    sourcePos,\n    targetPos,\n  };\n};\n\nconst Animated = ({ id, source, target, markerEnd, style }: EdgeProps) => {\n  const sourceNode = useInternalNode(source);\n  const targetNode = useInternalNode(target);\n\n  if (!(sourceNode && targetNode)) {\n    return null;\n  }\n\n  const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(\n    sourceNode,\n    targetNode\n  );\n\n  const [edgePath] = getBezierPath({\n    sourceX: sx,\n    sourceY: sy,\n    sourcePosition: sourcePos,\n    targetX: tx,\n    targetY: ty,\n    targetPosition: targetPos,\n  });\n\n  return (\n    <>\n      <BaseEdge id={id} markerEnd={markerEnd} path={edgePath} style={style} />\n      <circle fill=\"var(--primary)\" r=\"4\">\n        <animateMotion dur=\"2s\" path={edgePath} repeatCount=\"indefinite\" />\n      </circle>\n    </>\n  );\n};\n\nexport const Edge = {\n  Temporary,\n  Animated,\n};\n","target":"components/ai-elements/edge.tsx"}],"dependencies":["@xyflow/react"],"devDependencies":[],"registryDependencies":[]}