{"name":"beams-background","type":"registry:ui","dependencies":["motion"],"registryDependencies":[],"files":[{"path":"/components/ui/beams-background.tsx","content":"\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { motion } from \"motion/react\";\nimport { cn } from \"@/lib/utils\";\n\ninterface AnimatedGradientBackgroundProps {\n    className?: string;\n    children?: React.ReactNode;\n    intensity?: \"subtle\" | \"medium\" | \"strong\";\n}\n\ninterface Beam {\n    x: number;\n    y: number;\n    width: number;\n    length: number;\n    angle: number;\n    speed: number;\n    opacity: number;\n    hue: number;\n    pulse: number;\n    pulseSpeed: number;\n}\n\nfunction createBeam(width: number, height: number): Beam {\n    const angle = -35 + Math.random() * 10;\n    return {\n        x: Math.random() * width * 1.5 - width * 0.25,\n        y: Math.random() * height * 1.5 - height * 0.25,\n        width: 30 + Math.random() * 60,\n        length: height * 2.5,\n        angle: angle,\n        speed: 0.6 + Math.random() * 1.2,\n        opacity: 0.12 + Math.random() * 0.16,\n        hue: 190 + Math.random() * 70,\n        pulse: Math.random() * Math.PI * 2,\n        pulseSpeed: 0.02 + Math.random() * 0.03,\n    };\n}\n\nexport function BeamsBackground({\n    className,\n    intensity = \"strong\",\n}: AnimatedGradientBackgroundProps) {\n    const canvasRef = useRef<HTMLCanvasElement>(null);\n    const beamsRef = useRef<Beam[]>([]);\n    const animationFrameRef = useRef<number>(0);\n    const MINIMUM_BEAMS = 20;\n\n    const opacityMap = {\n        subtle: 0.7,\n        medium: 0.85,\n        strong: 1,\n    };\n\n    useEffect(() => {\n        const canvas = canvasRef.current;\n        if (!canvas) return;\n\n        const ctx = canvas.getContext(\"2d\");\n        if (!ctx) return;\n\n        const updateCanvasSize = () => {\n            const dpr = window.devicePixelRatio || 1;\n            canvas.width = window.innerWidth * dpr;\n            canvas.height = window.innerHeight * dpr;\n            canvas.style.width = `${window.innerWidth}px`;\n            canvas.style.height = `${window.innerHeight}px`;\n            ctx.scale(dpr, dpr);\n\n            const totalBeams = MINIMUM_BEAMS * 1.5;\n            beamsRef.current = Array.from({ length: totalBeams }, () =>\n                createBeam(canvas.width, canvas.height)\n            );\n        };\n\n        updateCanvasSize();\n        window.addEventListener(\"resize\", updateCanvasSize);\n\n        function resetBeam(beam: Beam, index: number, totalBeams: number) {\n            if (!canvas) return beam;\n            \n            const column = index % 3;\n            const spacing = canvas.width / 3;\n\n            beam.y = canvas.height + 100;\n            beam.x =\n                column * spacing +\n                spacing / 2 +\n                (Math.random() - 0.5) * spacing * 0.5;\n            beam.width = 100 + Math.random() * 100;\n            beam.speed = 0.5 + Math.random() * 0.4;\n            beam.hue = 190 + (index * 70) / totalBeams;\n            beam.opacity = 0.2 + Math.random() * 0.1;\n            return beam;\n        }\n\n        function drawBeam(ctx: CanvasRenderingContext2D, beam: Beam) {\n            ctx.save();\n            ctx.translate(beam.x, beam.y);\n            ctx.rotate((beam.angle * Math.PI) / 180);\n\n            // Calculate pulsing opacity\n            const pulsingOpacity =\n                beam.opacity *\n                (0.8 + Math.sin(beam.pulse) * 0.2) *\n                opacityMap[intensity];\n\n            const gradient = ctx.createLinearGradient(0, 0, 0, beam.length);\n\n            // Enhanced gradient with multiple color stops\n            gradient.addColorStop(0, `hsla(${beam.hue}, 85%, 65%, 0)`);\n            gradient.addColorStop(\n                0.1,\n                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity * 0.5})`\n            );\n            gradient.addColorStop(\n                0.4,\n                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity})`\n            );\n            gradient.addColorStop(\n                0.6,\n                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity})`\n            );\n            gradient.addColorStop(\n                0.9,\n                `hsla(${beam.hue}, 85%, 65%, ${pulsingOpacity * 0.5})`\n            );\n            gradient.addColorStop(1, `hsla(${beam.hue}, 85%, 65%, 0)`);\n\n            ctx.fillStyle = gradient;\n            ctx.fillRect(-beam.width / 2, 0, beam.width, beam.length);\n            ctx.restore();\n        }\n\n        function animate() {\n            if (!canvas || !ctx) return;\n\n            ctx.clearRect(0, 0, canvas.width, canvas.height);\n            ctx.filter = \"blur(35px)\";\n\n            const totalBeams = beamsRef.current.length;\n            beamsRef.current.forEach((beam, index) => {\n                beam.y -= beam.speed;\n                beam.pulse += beam.pulseSpeed;\n\n                // Reset beam when it goes off screen\n                if (beam.y + beam.length < -100) {\n                    resetBeam(beam, index, totalBeams);\n                }\n\n                drawBeam(ctx, beam);\n            });\n\n            animationFrameRef.current = requestAnimationFrame(animate);\n        }\n\n        animate();\n\n        return () => {\n            window.removeEventListener(\"resize\", updateCanvasSize);\n            if (animationFrameRef.current) {\n                cancelAnimationFrame(animationFrameRef.current);\n            }\n        };\n    }, [intensity]);\n\n    return (\n        <div\n            className={cn(\n                \"relative min-h-screen w-full overflow-hidden bg-neutral-950\",\n                className\n            )}\n        >\n            <canvas\n                ref={canvasRef}\n                className=\"absolute inset-0\"\n                style={{ filter: \"blur(15px)\" }}\n            />\n\n            <motion.div\n                className=\"absolute inset-0 bg-neutral-950/5\"\n                animate={{\n                    opacity: [0.05, 0.15, 0.05],\n                }}\n                transition={{\n                    duration: 10,\n                    ease: \"easeInOut\",\n                    repeat: Number.POSITIVE_INFINITY,\n                }}\n                style={{\n                    backdropFilter: \"blur(50px)\",\n                }}\n            />\n\n            <div className=\"relative z-10 flex h-screen w-full items-center justify-center\">\n                <div className=\"flex flex-col items-center justify-center gap-6 px-4 text-center\">\n                    <motion.h1\n                        className=\"text-6xl md:text-7xl lg:text-8xl font-semibold text-white tracking-tighter\"\n                        initial={{ opacity: 0, y: 20 }}\n                        animate={{ opacity: 1, y: 0 }}\n                        transition={{ duration: 0.8 }}\n                    >\n                        Beams\n                        <br />\n                        Background\n                    </motion.h1>\n                    <motion.p\n                        className=\"text-lg md:text-2xl lg:text-3xl text-white/70 tracking-tighter\"\n                        initial={{ opacity: 0, y: 20 }}\n                        animate={{ opacity: 1, y: 0 }}\n                        transition={{ duration: 0.8 }}\n                    >\n                        For your pleasure\n                    </motion.p>\n                </div>\n            </div>\n        </div>\n    );\n}\n","type":"registry:ui","target":""}],"tailwind":{"config":{}}}