{
  "name": "animated-beam",
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "ui/animated-beam.tsx",
      "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ninterface AnimatedBeamProps {\n  /** Reference to the container element */\n  containerRef: React.RefObject<HTMLElement | null>;\n  /** Reference to the start element */\n  fromRef: React.RefObject<HTMLElement | null>;\n  /** Reference to the end element */\n  toRef: React.RefObject<HTMLElement | null>;\n  /** Curvature of the beam (-1 to 1, 0 is straight) */\n  curvature?: number;\n  /** Animation duration in seconds */\n  duration?: number;\n  /** Delay before animation starts */\n  delay?: number;\n  /** Reverse the animation direction */\n  reverse?: boolean;\n  /** Width of the beam path */\n  pathWidth?: number;\n  /** Color of the beam gradient start */\n  gradientStartColor?: string;\n  /** Color of the beam gradient end */\n  gradientStopColor?: string;\n  /** Starting point offset */\n  startXOffset?: number;\n  startYOffset?: number;\n  /** Ending point offset */\n  endXOffset?: number;\n  endYOffset?: number;\n  className?: string;\n}\n\nconst AnimatedBeam = ({\n  containerRef,\n  fromRef,\n  toRef,\n  curvature = 0,\n  duration = 2,\n  delay = 0,\n  reverse = false,\n  pathWidth = 2,\n  gradientStartColor = \"#18181b\",\n  gradientStopColor = \"#18181b\",\n  startXOffset = 0,\n  startYOffset = 0,\n  endXOffset = 0,\n  endYOffset = 0,\n  className,\n}: AnimatedBeamProps) => {\n  const [pathD, setPathD] = React.useState(\"\");\n  const [svgDimensions, setSvgDimensions] = React.useState({\n    width: 0,\n    height: 0,\n  });\n  const uniqueId = React.useId();\n\n  const updatePath = React.useCallback(() => {\n    if (!containerRef.current || !fromRef.current || !toRef.current) return;\n\n    const containerRect = containerRef.current.getBoundingClientRect();\n    const fromRect = fromRef.current.getBoundingClientRect();\n    const toRect = toRef.current.getBoundingClientRect();\n\n    const startX =\n      fromRect.left - containerRect.left + fromRect.width / 2 + startXOffset;\n    const startY =\n      fromRect.top - containerRect.top + fromRect.height / 2 + startYOffset;\n    const endX =\n      toRect.left - containerRect.left + toRect.width / 2 + endXOffset;\n    const endY =\n      toRect.top - containerRect.top + toRect.height / 2 + endYOffset;\n\n    const midX = (startX + endX) / 2;\n    const midY = (startY + endY) / 2;\n\n    // Calculate control point for quadratic bezier curve\n    const dx = endX - startX;\n    const dy = endY - startY;\n    const controlX = midX - dy * curvature;\n    const controlY = midY + dx * curvature;\n\n    const path = `M ${startX},${startY} Q ${controlX},${controlY} ${endX},${endY}`;\n    setPathD(path);\n    setSvgDimensions({\n      width: containerRect.width,\n      height: containerRect.height,\n    });\n  }, [\n    containerRef,\n    fromRef,\n    toRef,\n    curvature,\n    startXOffset,\n    startYOffset,\n    endXOffset,\n    endYOffset,\n  ]);\n\n  React.useEffect(() => {\n    updatePath();\n\n    const resizeObserver = new ResizeObserver(updatePath);\n    if (containerRef.current) {\n      resizeObserver.observe(containerRef.current);\n    }\n\n    window.addEventListener(\"resize\", updatePath);\n\n    return () => {\n      resizeObserver.disconnect();\n      window.removeEventListener(\"resize\", updatePath);\n    };\n  }, [updatePath, containerRef]);\n\n  return (\n    <svg\n      className={cn(\n        \"pointer-events-none absolute top-0 left-0 h-full w-full\",\n        className,\n      )}\n      width={svgDimensions.width}\n      height={svgDimensions.height}\n      viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <defs>\n        {/* Background path gradient */}\n        <linearGradient\n          id={`beam-gradient-bg-${uniqueId}`}\n          gradientUnits=\"userSpaceOnUse\"\n          x1=\"0%\"\n          y1=\"0%\"\n          x2=\"100%\"\n          y2=\"0%\"\n        >\n          <stop offset=\"0%\" stopColor={gradientStartColor} stopOpacity=\"0.1\" />\n          <stop offset=\"50%\" stopColor={gradientStartColor} stopOpacity=\"0.2\" />\n          <stop offset=\"100%\" stopColor={gradientStopColor} stopOpacity=\"0.1\" />\n        </linearGradient>\n\n        {/* Animated beam gradient */}\n        <linearGradient\n          id={`beam-gradient-${uniqueId}`}\n          gradientUnits=\"userSpaceOnUse\"\n          x1=\"0%\"\n          y1=\"0%\"\n          x2=\"100%\"\n          y2=\"0%\"\n        >\n          <stop offset=\"0%\" stopColor={gradientStartColor} stopOpacity=\"0\" />\n          <stop offset=\"5%\" stopColor={gradientStartColor} stopOpacity=\"1\" />\n          <stop offset=\"50%\" stopColor={gradientStopColor} stopOpacity=\"1\" />\n          <stop offset=\"95%\" stopColor={gradientStopColor} stopOpacity=\"1\" />\n          <stop offset=\"100%\" stopColor={gradientStopColor} stopOpacity=\"0\" />\n        </linearGradient>\n\n        {/* Glow filter */}\n        <filter\n          id={`beam-glow-${uniqueId}`}\n          x=\"-50%\"\n          y=\"-50%\"\n          width=\"200%\"\n          height=\"200%\"\n        >\n          <feGaussianBlur in=\"SourceGraphic\" stdDeviation=\"2\" result=\"blur\" />\n          <feMerge>\n            <feMergeNode in=\"blur\" />\n            <feMergeNode in=\"SourceGraphic\" />\n          </feMerge>\n        </filter>\n\n        {/* Mask for animated beam */}\n        <mask id={`beam-mask-${uniqueId}`}>\n          <rect\n            className=\"beam-mask-rect\"\n            x=\"-100%\"\n            y=\"0\"\n            width=\"50%\"\n            height=\"100%\"\n            fill=\"url(#beam-mask-gradient)\"\n            style={{\n              animation: `beam-flow ${duration}s linear infinite`,\n              animationDelay: `${delay}s`,\n              animationDirection: reverse ? \"reverse\" : \"normal\",\n            }}\n          />\n        </mask>\n\n        <linearGradient\n          id=\"beam-mask-gradient\"\n          x1=\"0%\"\n          y1=\"0%\"\n          x2=\"100%\"\n          y2=\"0%\"\n        >\n          <stop offset=\"0%\" stopColor=\"black\" />\n          <stop offset=\"25%\" stopColor=\"white\" />\n          <stop offset=\"75%\" stopColor=\"white\" />\n          <stop offset=\"100%\" stopColor=\"black\" />\n        </linearGradient>\n      </defs>\n\n      {/* Background path */}\n      <path\n        d={pathD}\n        stroke={`url(#beam-gradient-bg-${uniqueId})`}\n        strokeWidth={pathWidth}\n        strokeLinecap=\"round\"\n        fill=\"none\"\n      />\n\n      {/* Animated glowing beam */}\n      <path\n        d={pathD}\n        stroke={`url(#beam-gradient-${uniqueId})`}\n        strokeWidth={pathWidth}\n        strokeLinecap=\"round\"\n        fill=\"none\"\n        filter={`url(#beam-glow-${uniqueId})`}\n        className=\"animated-beam-path\"\n        style={{\n          strokeDasharray: \"20 1000\",\n          strokeDashoffset: reverse ? \"-1000\" : \"1000\",\n          animation: `beam-dash ${duration}s linear infinite`,\n          animationDelay: `${delay}s`,\n          animationDirection: reverse ? \"reverse\" : \"normal\",\n        }}\n      />\n    </svg>\n  );\n};\n\ninterface BeamContainerProps extends React.HTMLAttributes<HTMLDivElement> {\n  children: React.ReactNode;\n}\n\nconst BeamContainer = React.forwardRef<HTMLDivElement, BeamContainerProps>(\n  ({ children, className, ...props }, ref) => {\n    return (\n      <div ref={ref} className={cn(\"relative\", className)} {...props}>\n        {children}\n      </div>\n    );\n  },\n);\nBeamContainer.displayName = \"BeamContainer\";\n\ninterface BeamNodeProps extends React.HTMLAttributes<HTMLDivElement> {\n  children: React.ReactNode;\n}\n\nconst BeamNode = React.forwardRef<HTMLDivElement, BeamNodeProps>(\n  ({ children, className, ...props }, ref) => {\n    return (\n      <div\n        ref={ref}\n        className={cn(\n          \"relative z-10 flex items-center justify-center rounded-xl border bg-background p-3 shadow-sm\",\n          className,\n        )}\n        {...props}\n      >\n        {children}\n      </div>\n    );\n  },\n);\nBeamNode.displayName = \"BeamNode\";\n\nexport {\n  AnimatedBeam,\n  BeamContainer,\n  BeamNode,\n  type AnimatedBeamProps,\n  type BeamContainerProps,\n  type BeamNodeProps,\n};\n",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}