{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "snowfall-animation",
  "type": "registry:component",
  "title": "Snowfall Animation",
  "author": "Toby Belhome",
  "description": "Enhance your website with the peaceful atmosphere of the Snowfall Animation Background. Create a captivating design with gently falling snowflakes for a serene and wintery experience.",
  "dependencies": [
    "next-themes"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "examples/motion/backgrounds/snowfall-animation/01/page.tsx",
      "content": "import { Button } from \"@/components/ui/button\";\nimport Snowfall from \"./snowfall\";\n\nexport default function SnowfallBackgroundExample() {\n  return (\n    <Snowfall className=\"flex aspect-4/2 items-center justify-center\">\n      <div className=\"z-10 space-y-4 text-center lg:space-y-6\">\n        <h4 className=\"text-2xl font-semibold text-black/80 lg:text-3xl dark:text-white/80\">\n          Bundui Components\n        </h4>\n        <Button>Discover Excellence</Button>\n      </div>\n    </Snowfall>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/snowfall-animation/snowfall-animation-example.tsx"
    },
    {
      "path": "examples/motion/backgrounds/snowfall-animation/01/snowfall.tsx",
      "content": "\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { useTheme } from \"next-themes\";\n\ninterface Snowflake {\n  x: number;\n  y: number;\n  radius: number;\n  speed: number;\n  opacity: number;\n  wind: number;\n  amplitude: number;\n  frequency: number;\n  angle: number;\n}\n\nexport default function SnowfallBackground({\n  children,\n  count = 100,\n  minRadius = 1,\n  maxRadius = 4,\n  minSpeed = 0.5,\n  maxSpeed = 2,\n  wind = 0.5,\n  className = \"\"\n}: {\n  children: React.ReactNode;\n  count?: number;\n  minRadius?: number;\n  maxRadius?: number;\n  minSpeed?: number;\n  maxSpeed?: number;\n  wind?: number;\n  className?: string;\n}) {\n  const canvasRef = useRef<HTMLCanvasElement>(null);\n  const { theme } = useTheme();\n  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });\n  const snowflakesRef = useRef<Snowflake[]>([]);\n  const animationFrameRef = useRef<number>(0);\n\n  const naturalDistribution = () => {\n    const r = Math.random();\n\n    if (r < 0.3) {\n      return 0.1 + Math.random() * 0.3;\n    } else if (r < 0.9) {\n      return 0.5 + Math.random() * 1.0;\n    } else {\n      return 1.6 + Math.random() * 1.4;\n    }\n  };\n\n  const initSnowflakes = (width: number, height: number) => {\n    const snowflakes: Snowflake[] = [];\n\n    const adjustedCount = Math.min(count, Math.floor((width * height) / 10000));\n\n    for (let i = 0; i < adjustedCount; i++) {\n      snowflakes.push({\n        x: Math.random() * width,\n        y: Math.random() * height,\n        radius: minRadius + Math.random() * (maxRadius - minRadius),\n        speed: minSpeed + Math.random() * (maxSpeed - minSpeed),\n        opacity: 0.3 + Math.random() * 0.7,\n        wind: (Math.random() - 0.5) * wind * 0.5,\n        amplitude: naturalDistribution(),\n        frequency: 0.001 + Math.random() * 0.008,\n        angle: Math.random() * Math.PI * 2\n      });\n    }\n\n    snowflakesRef.current = snowflakes;\n  };\n\n  useEffect(() => {\n    const handleResize = () => {\n      if (canvasRef.current && canvasRef.current.parentElement) {\n        const { width, height } = canvasRef.current.parentElement.getBoundingClientRect();\n        setDimensions({ width, height });\n        canvasRef.current.width = width;\n        canvasRef.current.height = height;\n        initSnowflakes(width, height);\n      }\n    };\n\n    handleResize();\n    window.addEventListener(\"resize\", handleResize);\n\n    return () => {\n      window.removeEventListener(\"resize\", handleResize);\n      if (animationFrameRef.current) {\n        cancelAnimationFrame(animationFrameRef.current);\n      }\n    };\n  }, []);\n\n  useEffect(() => {\n    if (!canvasRef.current || dimensions.width === 0 || dimensions.height === 0) return;\n\n    const canvas = canvasRef.current;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) return;\n\n    const animate = () => {\n      ctx.clearRect(0, 0, dimensions.width, dimensions.height);\n      const snowColor = theme === \"dark\" ? \"rgba(255, 255, 255,\" : \"rgba(220, 235, 255,\";\n\n      snowflakesRef.current.forEach((flake) => {\n        ctx.beginPath();\n        ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI * 2);\n        ctx.fillStyle = `${snowColor} ${flake.opacity})`;\n        ctx.fill();\n\n        flake.y += flake.speed;\n        flake.angle += flake.frequency;\n\n        flake.x += flake.wind + Math.sin(flake.angle) * flake.amplitude;\n\n        if (flake.y > dimensions.height) {\n          flake.y = -flake.radius;\n          flake.x = Math.random() * dimensions.width;\n          flake.amplitude = naturalDistribution();\n          flake.frequency = 0.001 + Math.random() * 0.008;\n        }\n\n        if (flake.x > dimensions.width) {\n          flake.x = 0;\n        } else if (flake.x < 0) {\n          flake.x = dimensions.width;\n        }\n      });\n\n      animationFrameRef.current = requestAnimationFrame(animate);\n    };\n\n    animate();\n\n    return () => {\n      if (animationFrameRef.current) {\n        cancelAnimationFrame(animationFrameRef.current);\n      }\n    };\n  }, [dimensions, theme]);\n\n  return (\n    <div className={cn(\"relative w-full\", className)}>\n      <canvas\n        ref={canvasRef}\n        className={`pointer-events-none absolute inset-0 ${className}`}\n        style={{ zIndex: 0 }}\n      />\n      <div className=\"z-10\">{children}</div>\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/snowfall-animation/snowfall.tsx"
    }
  ],
  "meta": {
    "isPro": false
  }
}