{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "beams-upstream",
  "type": "registry:ui",
  "title": "Beams Upstream",
  "description": "Multiple background beams travel upstream, forming a hero section background",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": [],
  "dependencies": ["motion", "clsx", "tailwind-merge"],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/beams-upstream.tsx",
      "content": "'use client';\nimport React, { useState, useMemo } from 'react';\nimport { motion } from 'motion/react';\nimport { cn } from '@/lib/utils';\n\nexport const BeamsUpstream = React.memo(\n  ({ className }: { className?: string }) => {\n    const [paths] = useState(() => {\n      const pathsList: string[] = [];\n      const screenSections = 12;\n\n      for (let section = 0; section < screenSections; section++) {\n        const baseX = (section * 100) / (screenSections - 1);\n        for (let variation = 0; variation < 4; variation++) {\n          const startX = baseX + (Math.random() - 0.5) * 15;\n          const midX1 = startX + (Math.random() - 0.5) * 20;\n          const midX2 = startX + (Math.random() - 0.5) * 25;\n          const endX = startX + (Math.random() - 0.5) * 30;\n          const path = `M${startX} 100C${startX} 100 ${midX1} 75 ${midX1} 50C${midX1} 50 ${midX2} 25 ${midX2} 12C${midX2} 12 ${endX} 5 ${endX} 0`;\n          pathsList.push(path);\n          const altPath = `M${startX} 100C${startX} 100 ${\n            startX + 5\n          } 80 ${midX1} 60C${midX1} 60 ${midX2} 35 ${midX2} 15C${midX2} 15 ${endX} 3 ${endX} -2`;\n          pathsList.push(altPath);\n        }\n      }\n\n      return pathsList;\n    });\n\n    const [pathAnimations] = useState(() =>\n      paths.map(() => ({\n        duration: Math.random() * 3 + 2,\n        delay: Math.random() * 4,\n      })),\n    );\n\n    const [particleAnimations] = useState(() =>\n      paths.slice(0, 20).map(() => ({\n        duration: Math.random() * 8 + 6,\n        delay: Math.random() * 6,\n      })),\n    );\n\n    const [gradientAnimations] = useState(() =>\n      Array.from({ length: 20 }).map(() => ({\n        duration: Math.random() * 4 + 3,\n        delay: Math.random() * 5,\n      })),\n    );\n\n    return (\n      <div\n        className={cn(\n          'absolute inset-0 flex h-full w-full items-center justify-center overflow-hidden',\n          className,\n        )}\n      >\n        <svg\n          className='pointer-events-none absolute z-0 h-full w-full'\n          width='100%'\n          height='100%'\n          viewBox='0 0 100 100'\n          fill='none'\n          xmlns='http://www.w3.org/2000/svg'\n          preserveAspectRatio='none'\n        >\n          <rect\n            width='100%'\n            height='100%'\n            fill='url(#backgroundGradient)'\n            opacity='0.1'\n          />\n\n          <g opacity='0.2'>\n            {paths.map((path, index) => (\n              <path\n                key={`static-path-${index}`}\n                d={path}\n                stroke='url(#staticGradient)'\n                strokeOpacity='0.3'\n                strokeWidth='0.2'\n                fill='none'\n                vectorEffect='non-scaling-stroke'\n              />\n            ))}\n          </g>\n\n          {paths.map((path, index) => (\n            <motion.path\n              key={`path-${index}`}\n              d={path}\n              stroke={`url(#flowingGradient-${index % 20})`}\n              strokeOpacity='0.8'\n              strokeWidth='0.3'\n              fill='none'\n              vectorEffect='non-scaling-stroke'\n              initial={{ pathLength: 0 }}\n              animate={{ pathLength: 1 }}\n              transition={{\n                duration: pathAnimations[index].duration,\n                ease: 'easeInOut',\n                repeat: Infinity,\n                repeatType: 'loop',\n                delay: pathAnimations[index].delay,\n              }}\n            />\n          ))}\n\n          {paths.slice(0, 20).map((path, index) => (\n            <motion.circle\n              key={`particle-${index}`}\n              r='0.3'\n              fill={`url(#particleGradient-${index % 10})`}\n              initial={{ offsetDistance: '0%' }}\n              animate={{ offsetDistance: '100%' }}\n              transition={{\n                duration: particleAnimations[index].duration,\n                ease: 'linear',\n                repeat: Infinity,\n                delay: particleAnimations[index].delay,\n              }}\n              style={{\n                offsetPath: `path('${path}')`,\n                offsetRotate: '0deg',\n              }}\n            />\n          ))}\n\n          <defs>\n            <radialGradient\n              id='backgroundGradient'\n              cx='50%'\n              cy='80%'\n              r='60%'\n              gradientUnits='objectBoundingBox'\n            >\n              <stop offset='0%' stopColor='#6366F1' stopOpacity='0.3' />\n              <stop offset='50%' stopColor='#8B5CF6' stopOpacity='0.1' />\n              <stop offset='100%' stopColor='#EC4899' stopOpacity='0' />\n            </radialGradient>\n\n            <linearGradient\n              id='staticGradient'\n              x1='0%'\n              y1='100%'\n              x2='0%'\n              y2='0%'\n              gradientUnits='objectBoundingBox'\n            >\n              <stop offset='0%' stopColor='#6366F1' stopOpacity='0.8' />\n              <stop offset='50%' stopColor='#8B5CF6' stopOpacity='0.6' />\n              <stop offset='100%' stopColor='#EC4899' stopOpacity='0.4' />\n            </linearGradient>\n\n            {Array.from({ length: 20 }).map((_, index) => (\n              <motion.linearGradient\n                key={`flowingGradient-${index}`}\n                id={`flowingGradient-${index}`}\n                x1='0%'\n                y1='100%'\n                x2='0%'\n                y2='0%'\n                gradientUnits='objectBoundingBox'\n                initial={{\n                  y1: '100%',\n                  y2: '90%',\n                }}\n                animate={{\n                  y1: ['100%', '0%'],\n                  y2: ['90%', '-10%'],\n                }}\n                transition={{\n                  duration: gradientAnimations[index].duration,\n                  ease: 'linear',\n                  repeat: Infinity,\n                  delay: gradientAnimations[index].delay,\n                }}\n              >\n                <stop offset='0%' stopColor='#0EA5E9' stopOpacity='0' />\n                <stop offset='30%' stopColor='#3B82F6' stopOpacity='0.8' />\n                <stop offset='60%' stopColor='#8B5CF6' stopOpacity='1' />\n                <stop offset='100%' stopColor='#EC4899' stopOpacity='0' />\n              </motion.linearGradient>\n            ))}\n            <filter id='glow' x='-50%' y='-50%' width='200%' height='200%'>\n              <feGaussianBlur stdDeviation='1' result='coloredBlur' />\n              <feMerge>\n                <feMergeNode in='coloredBlur' />\n                <feMergeNode in='SourceGraphic' />\n              </feMerge>\n            </filter>\n          </defs>\n        </svg>\n      </div>\n    );\n  },\n);\n\nBeamsUpstream.displayName = 'BeamsUpstream';\n"
    },
    {
      "type": "registry:lib",
      "path": "lib/utils.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}"
    }
  ]
}
