{
  "name": "wavy-background",
  "type": "registry:ui",
  "dependencies": [
    "simplex-noise"
  ],
  "files": [
    {
      "path": "components/ui/wavy-background.tsx",
      "content": "\"use client\";\nimport { cn } from \"@/lib/utils\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { createNoise3D } from \"simplex-noise\";\n\nexport const WavyBackground = ({\n  children,\n  className,\n  containerClassName,\n  colors,\n  waveWidth,\n  backgroundFill,\n  blur = 10,\n  speed = \"fast\",\n  waveOpacity = 0.5,\n  ...props\n}: {\n  children?: any;\n  className?: string;\n  containerClassName?: string;\n  colors?: string[];\n  waveWidth?: number;\n  backgroundFill?: string;\n  blur?: number;\n  speed?: \"slow\" | \"fast\";\n  waveOpacity?: number;\n  [key: string]: any;\n}) => {\n  const noise = createNoise3D();\n  let w: number,\n    h: number,\n    nt: number,\n    i: number,\n    x: number,\n    ctx: any,\n    canvas: any;\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const getSpeed = () => {\n    switch (speed) {\n      case \"slow\":\n        return 0.001;\n      case \"fast\":\n        return 0.002;\n      default:\n        return 0.001;\n    }\n  };\n\n  const init = () => {\n    canvas = canvasRef.current;\n    ctx = canvas.getContext(\"2d\");\n    w = ctx.canvas.width = window.innerWidth;\n    h = ctx.canvas.height = window.innerHeight;\n    ctx.filter = `blur(${blur}px)`;\n    nt = 0;\n    window.onresize = function () {\n      w = ctx.canvas.width = window.innerWidth;\n      h = ctx.canvas.height = window.innerHeight;\n      ctx.filter = `blur(${blur}px)`;\n    };\n    render();\n  };\n\n  const waveColors = colors ?? [\n    \"#38bdf8\",\n    \"#818cf8\",\n    \"#c084fc\",\n    \"#e879f9\",\n    \"#22d3ee\",\n  ];\n  const drawWave = (n: number) => {\n    nt += getSpeed();\n    for (i = 0; i < n; i++) {\n      ctx.beginPath();\n      ctx.lineWidth = waveWidth || 50;\n      ctx.strokeStyle = waveColors[i % waveColors.length];\n      for (x = 0; x < w; x += 5) {\n        var y = noise(x / 800, 0.3 * i, nt) * 100;\n        ctx.lineTo(x, y + h * 0.5); // adjust for height, currently at 50% of the container\n      }\n      ctx.stroke();\n      ctx.closePath();\n    }\n  };\n\n  let animationId: number;\n  const render = () => {\n    ctx.fillStyle = backgroundFill || \"black\";\n    ctx.globalAlpha = waveOpacity || 0.5;\n    ctx.fillRect(0, 0, w, h);\n    drawWave(5);\n    animationId = requestAnimationFrame(render);\n  };\n\n  useEffect(() => {\n    init();\n    return () => {\n      cancelAnimationFrame(animationId);\n    };\n  }, []);\n\n  const [isSafari, setIsSafari] = useState(false);\n  useEffect(() => {\n    // I'm sorry but i have got to support it on safari.\n    setIsSafari(\n      typeof window !== \"undefined\" &&\n        navigator.userAgent.includes(\"Safari\") &&\n        !navigator.userAgent.includes(\"Chrome\")\n    );\n  }, []);\n\n  return (\n    <div\n      className={cn(\n        \"h-screen flex flex-col items-center justify-center\",\n        containerClassName\n      )}\n    >\n      <canvas\n        className=\"absolute inset-0 z-0\"\n        ref={canvasRef}\n        id=\"canvas\"\n        style={{\n          ...(isSafari ? { filter: `blur(${blur}px)` } : {}),\n        }}\n      ></canvas>\n      <div className={cn(\"relative z-10\", className)} {...props}>\n        {children}\n      </div>\n    </div>\n  );\n};\n",
      "type": "registry:ui",
      "target": "components/ui/wavy-background.tsx"
    }
  ],
  "author": "Manu Arora <hi@manuarora.in>",
  "title": "Wavy Background"
}