{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "edge",
  "dependencies": [
    "@xyflow/react"
  ],
  "files": [
    {
      "path": "registry/new-york/ai-elements/edge.tsx",
      "content": "import {\n  BaseEdge,\n  getBezierPath,\n  getSimpleBezierPath,\n  Position,\n  useInternalNode,\n  type EdgeProps,\n  type InternalNode,\n  type Node,\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-ring stroke-1\"\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]\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]\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",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}