{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "animated-grid-pattern",
  "title": "Animated Grid Pattern",
  "description": "A simple animated grid pattern",
  "files": [
    {
      "path": "src/components/ui/animated-grid-pattern.tsx",
      "content": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport { useEffect, useId, useRef, useState } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\ninterface AnimatedGridPatternProps {\n  width?: number;\n  height?: number;\n  x?: number;\n  y?: number;\n  strokeDasharray?: string | number;\n  numSquares?: number;\n  className?: string;\n  maxOpacity?: number;\n  duration?: number;\n}\n\nexport default function AnimatedGridPattern({\n  width = 40,\n  height = 40,\n  x = -1,\n  y = -1,\n  strokeDasharray = 0,\n  numSquares = 50,\n  className,\n  maxOpacity = 0.5,\n  duration = 4,\n  ...props\n}: AnimatedGridPatternProps) {\n  const id = useId();\n  const containerRef = useRef(null);\n  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });\n  const [squares, setSquares] = useState(() => generateSquares(numSquares));\n\n  function getPos() {\n    return [\n      Math.floor((Math.random() * dimensions.width) / width),\n      Math.floor((Math.random() * dimensions.height) / height),\n    ];\n  }\n\n  // Adjust the generateSquares function to return objects with an id, x, and y\n  function generateSquares(count: number) {\n    return Array.from({ length: count }, (_, i) => ({\n      id: i,\n      pos: getPos(),\n    }));\n  }\n\n  // Function to update a single square's position\n  const updateSquarePosition = (id: number) => {\n    setSquares((currentSquares) =>\n      currentSquares.map((sq) =>\n        sq.id === id\n          ? {\n              ...sq,\n              pos: getPos(),\n            }\n          : sq\n      )\n    );\n  };\n\n  // Update squares to animate in\n  useEffect(() => {\n    if (dimensions.width && dimensions.height) {\n      setSquares(generateSquares(numSquares));\n    }\n  }, [dimensions, numSquares]);\n\n  // Resize observer to update container dimensions\n  useEffect(() => {\n    const resizeObserver = new ResizeObserver((entries) => {\n      for (const entry of entries) {\n        setDimensions({\n          width: entry.contentRect.width,\n          height: entry.contentRect.height,\n        });\n      }\n    });\n\n    if (containerRef.current) {\n      resizeObserver.observe(containerRef.current);\n    }\n\n    return () => {\n      if (containerRef.current) {\n        resizeObserver.unobserve(containerRef.current);\n      }\n    };\n  }, [containerRef]);\n\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className={cn(\n        \"pointer-events-none absolute inset-0 h-full w-full fill-gray-400/30 stroke-gray-400/30\",\n        className\n      )}\n      ref={containerRef}\n      {...props}\n    >\n      <defs>\n        <pattern\n          height={height}\n          id={id}\n          patternUnits=\"userSpaceOnUse\"\n          width={width}\n          x={x}\n          y={y}\n        >\n          <path\n            d={`M.5 ${height}V.5H${width}`}\n            fill=\"none\"\n            strokeDasharray={strokeDasharray}\n          />\n        </pattern>\n      </defs>\n      <rect fill={`url(#${id})`} height=\"100%\" width=\"100%\" />\n      <svg className=\"overflow-visible\" x={x} y={y}>\n        {squares.map(({ pos: [x, y], id }, index) => (\n          <motion.rect\n            animate={{ opacity: maxOpacity }}\n            fill=\"currentColor\"\n            height={height - 1}\n            initial={{ opacity: 0 }}\n            key={`${x}-${y}-${index}`}\n            onAnimationComplete={() => updateSquarePosition(id)}\n            strokeWidth=\"0\"\n            transition={{\n              duration,\n              repeat: 1,\n              delay: index * 0.1,\n              repeatType: \"reverse\",\n            }}\n            width={width - 1}\n            x={x * width + 1}\n            y={y * height + 1}\n          />\n        ))}\n      </svg>\n    </svg>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}