{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "reactive-background-grid-shadcnui",
  "type": "registry:ui",
  "title": "Reactive Background Grid",
  "description": "Background pattern that reacts to mouse movement and click ripples",
  "dependencies": [
    "framer-motion",
    "react"
  ],
  "files": [
    {
      "path": "@uitripled/react-shadcn/src/components/motion-core/reactive-background-grid.tsx",
      "content": "\"use client\";\n\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { MouseEvent, useState } from \"react\";\n\ntype ReactiveBackgroundGridProps = {\n  dots?: boolean;\n  density?: number;\n};\n\nexport function ReactiveBackgroundGrid({\n  dots = true,\n  density = 20,\n}: ReactiveBackgroundGridProps) {\n  const [ripples, setRipples] = useState<\n    Array<{ id: number; x: number; y: number }>\n  >([]);\n  const [hoveredDot, setHoveredDot] = useState<{ x: number; y: number } | null>(\n    null\n  );\n\n  const handleClick = (e: MouseEvent<HTMLDivElement>) => {\n    const rect = e.currentTarget.getBoundingClientRect();\n    const x = e.clientX - rect.left;\n    const y = e.clientY - rect.top;\n\n    const newRipple = {\n      id: Date.now(),\n      x,\n      y,\n    };\n\n    setRipples((prev) => [...prev, newRipple]);\n    setTimeout(() => {\n      setRipples((prev) => prev.filter((r) => r.id !== newRipple.id));\n    }, 600);\n  };\n\n  const [containerSize, setContainerSize] = useState({\n    width: 400,\n    height: 400,\n  });\n\n  const handleMouseMove = (e: MouseEvent<HTMLDivElement>) => {\n    const rect = e.currentTarget.getBoundingClientRect();\n    const x = e.clientX - rect.left;\n    const y = e.clientY - rect.top;\n    setHoveredDot({ x, y });\n    setContainerSize({ width: rect.width, height: rect.height });\n  };\n\n  const gridSize = density;\n  const dotsArray = Array.from({ length: gridSize * gridSize });\n\n  return (\n    <div\n      onClick={handleClick}\n      onMouseMove={handleMouseMove}\n      onMouseLeave={() => setHoveredDot(null)}\n      className=\"relative h-96 w-full overflow-hidden rounded-2xl border border-border bg-card\"\n    >\n      <div\n        className=\"absolute inset-0\"\n        style={{\n          backgroundImage: dots\n            ? \"radial-gradient(circle, currentColor 1px, transparent 1px)\"\n            : \"linear-gradient(to right, currentColor 1px, transparent 1px), linear-gradient(to bottom, currentColor 1px, transparent 1px)\",\n          backgroundSize: `${100 / gridSize}% ${100 / gridSize}%`,\n          backgroundPosition: \"0 0\",\n          color: \"rgba(99, 102, 241, 0.1)\",\n        }}\n      />\n\n      {dots &&\n        dotsArray.map((_, index) => {\n          const row = Math.floor(index / gridSize);\n          const col = index % gridSize;\n          const x = (col / gridSize) * 100;\n          const y = (row / gridSize) * 100;\n\n          const distance = hoveredDot\n            ? Math.sqrt(\n                Math.pow(x - (hoveredDot.x / containerSize.width) * 100, 2) +\n                  Math.pow(y - (hoveredDot.y / containerSize.height) * 100, 2)\n              )\n            : Infinity;\n\n          const scale = hoveredDot && distance < 30 ? 1.5 : 1;\n          const opacity = hoveredDot && distance < 30 ? 0.6 : 0.2;\n\n          return (\n            <motion.div\n              key={index}\n              animate={{\n                scale,\n                opacity,\n              }}\n              transition={{\n                type: \"spring\",\n                stiffness: 300,\n                damping: 25,\n              }}\n              className=\"absolute rounded-full bg-primary\"\n              style={{\n                left: `${x}%`,\n                top: `${y}%`,\n                width: \"4px\",\n                height: \"4px\",\n                transform: \"translate(-50%, -50%)\",\n              }}\n            />\n          );\n        })}\n\n      <AnimatePresence>\n        {ripples.map((ripple) => (\n          <motion.div\n            key={ripple.id}\n            initial={{ scale: 0, opacity: 0.8 }}\n            animate={{ scale: 4, opacity: 0 }}\n            exit={{ scale: 4, opacity: 0 }}\n            transition={{ duration: 0.6 }}\n            className=\"absolute rounded-full border-2 border-primary\"\n            style={{\n              left: ripple.x,\n              top: ripple.y,\n              width: \"100px\",\n              height: \"100px\",\n              transform: \"translate(-50%, -50%)\",\n            }}\n          />\n        ))}\n      </AnimatePresence>\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/uitripled/reactive-background-grid-shadcnui.tsx"
    }
  ]
}