{ "name": "liquid-blob", "type": "registry:ui", "dependencies": ["framer-motion"], "registryDependencies": [], "description": "Animated liquid morphing blob shapes with mouse interaction that create a beautiful organic background effect.", "files": [ { "path": "components/ui/liquid-blob.tsx", "content": "\"use client\"\n\nimport { motion, useMotionValue, useSpring } from \"framer-motion\"\nimport { useEffect, useRef } from \"react\"\nimport { cn } from \"@/lib/utils\"\n\ninterface LiquidBlobProps {\n className?: string\n color?: string\n secondaryColor?: string\n size?: number\n blur?: number\n speed?: number\n opacity?: number\n interactive?: boolean\n}\n\nexport function LiquidBlob({\n className,\n color = \"#8b5cf6\",\n secondaryColor = \"#ec4899\",\n size = 300,\n blur = 60,\n speed = 8,\n opacity = 0.7,\n interactive = true,\n}: LiquidBlobProps) {\n const containerRef = useRef(null)\n const mouseX = useMotionValue(0)\n const mouseY = useMotionValue(0)\n \n const springConfig = { damping: 25, stiffness: 150 }\n const smoothX = useSpring(mouseX, springConfig)\n const smoothY = useSpring(mouseY, springConfig)\n\n useEffect(() => {\n if (!interactive) return\n \n const container = containerRef.current\n if (!container) return\n\n const handleMouseMove = (e: MouseEvent) => {\n const rect = container.getBoundingClientRect()\n const x = e.clientX - rect.left - rect.width / 2\n const y = e.clientY - rect.top - rect.height / 2\n mouseX.set(x * 0.15)\n mouseY.set(y * 0.15)\n }\n\n const handleMouseLeave = () => {\n mouseX.set(0)\n mouseY.set(0)\n }\n\n container.addEventListener(\"mousemove\", handleMouseMove)\n container.addEventListener(\"mouseleave\", handleMouseLeave)\n\n return () => {\n container.removeEventListener(\"mousemove\", handleMouseMove)\n container.removeEventListener(\"mouseleave\", handleMouseLeave)\n }\n }, [interactive, mouseX, mouseY])\n\n return (\n
\n \n \n \n
\n )\n}\n", "type": "registry:ui" } ] }