{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "rain",
  "title": "Map Rain",
  "description": "Animated rain effect layer.",
  "dependencies": ["mapbox-gl"],
  "devDependencies": ["@types/mapbox-gl"],
  "registryDependencies": ["https://www.terrae.dev/map.json"],
  "files": [
    {
      "path": "src/registry/map/rain.tsx",
      "content": "\"use client\"\n\nimport { useEffect, useRef } from \"react\"\nimport { useMap } from \"./hooks\"\n\ntype MapboxExpression = unknown[]\n\ntype MapRainProps = {\n  density?: number | MapboxExpression\n  intensity?: number\n  color?: string\n  opacity?: number\n  vignette?: number | MapboxExpression\n  vignetteColor?: string\n  direction?: [number, number]\n  dropletSize?: [number, number]\n  distortionStrength?: number\n  centerThinning?: number\n}\n\nexport const createZoomInterpolation = (\n  value: number,\n  minZoom: number = 11,\n  maxZoom: number = 13\n): MapboxExpression => {\n  return [\"interpolate\", [\"linear\"], [\"zoom\"], minZoom, 0.0, maxZoom, value]\n}\n\nconst clampValue = (value: number, min: number, max: number): number => {\n  return Math.min(Math.max(value, min), max)\n}\n\nconst applyRainEffect = (map: mapboxgl.Map, config: Record<string, unknown>): void => {\n  ;(map as unknown as { setRain: (config: Record<string, unknown> | null) => void }).setRain(config)\n}\n\nconst removeRainEffect = (map: mapboxgl.Map): void => {\n  ;(map as unknown as { setRain: (config: Record<string, unknown> | null) => void }).setRain(null)\n}\n\nconst hasRainSupport = (map: mapboxgl.Map): boolean => {\n  return typeof (map as unknown as Record<string, unknown>).setRain === \"function\"\n}\n\nconst DEFAULT_DIRECTION: [number, number] = [0, 80]\nconst DEFAULT_DROPLET_SIZE: [number, number] = [2.6, 18.2]\n\nexport const MapRain = ({\n  density = 0.5,\n  intensity = 1,\n  color = \"#a8adbc\",\n  opacity = 0.7,\n  vignette = 1,\n  vignetteColor = \"#464646\",\n  direction = DEFAULT_DIRECTION,\n  dropletSize = DEFAULT_DROPLET_SIZE,\n  distortionStrength = 0.7,\n  centerThinning = 0,\n}: MapRainProps) => {\n  const { map, isLoaded } = useMap()\n  const initializedRef = useRef(false)\n\n  useEffect(() => {\n    if (!isLoaded || !map || initializedRef.current) {\n      return\n    }\n\n    if (!hasRainSupport(map)) {\n      console.warn(\"Rain effect requires Mapbox GL JS v3.9 or higher. This feature is not available in MapLibre GL.\")\n      return\n    }\n\n    try {\n      const clampedDensity = typeof density === \"number\" ? clampValue(density, 0, 1) : density\n      const clampedVignette = typeof vignette === \"number\" ? clampValue(vignette, 0, 1) : vignette\n\n      applyRainEffect(map, {\n        density: clampedDensity,\n        intensity: clampValue(intensity, 0, 1),\n        color,\n        opacity: clampValue(opacity, 0, 1),\n        vignette: clampedVignette,\n        \"vignette-color\": vignetteColor,\n        direction,\n        \"droplet-size\": dropletSize,\n        \"distortion-strength\": clampValue(distortionStrength, 0, 1),\n        \"center-thinning\": centerThinning,\n      })\n\n      initializedRef.current = true\n    } catch (error) {\n      console.error(\"Error setting rain effect:\", error)\n    }\n\n    return () => {\n      if (map && hasRainSupport(map)) {\n        try {\n          removeRainEffect(map)\n        } catch (error) {\n          console.error(\"Error removing rain effect:\", error)\n        }\n      }\n      initializedRef.current = false\n    }\n  }, [\n    map,\n    isLoaded,\n    density,\n    intensity,\n    color,\n    opacity,\n    vignette,\n    vignetteColor,\n    direction,\n    dropletSize,\n    distortionStrength,\n    centerThinning,\n  ])\n\n  return null\n}\n",
      "type": "registry:ui",
      "target": "components/ui/map/rain.tsx"
    }
  ],
  "type": "registry:ui"
}
