{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dot-matrix",
  "title": "Dot Matrix",
  "description": "An animated dot matrix background pattern.",
  "dependencies": [
    "clsx",
    "tailwind-merge"
  ],
  "files": [
    {
      "path": "registry/wise-ui/components/dot-matrix.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { cn } from \"@/registry/wise-ui/lib/utils\"\n\ninterface DotMatrixProps extends React.HTMLAttributes<HTMLDivElement> {\n  gap?: number\n  dotSize?: number\n  color?: string\n  activeColor?: string\n  influence?: number\n  maxScale?: number\n}\n\nfunction parseColor(color: string): [number, number, number] | null {\n  const ctx = typeof document !== \"undefined\"\n    ? document.createElement(\"canvas\").getContext(\"2d\")\n    : null\n  if (!ctx) return null\n  ctx.fillStyle = color\n  ctx.fillRect(0, 0, 1, 1)\n  const d = ctx.getImageData(0, 0, 1, 1).data\n  return [d[0], d[1], d[2]]\n}\n\nconst DotMatrix = React.forwardRef<HTMLDivElement, DotMatrixProps>(\n  (\n    {\n      gap = 24,\n      dotSize = 2,\n      color = \"currentColor\",\n      activeColor,\n      influence = 100,\n      maxScale = 3,\n      className,\n      children,\n      ...props\n    },\n    ref\n  ) => {\n    const canvasRef = React.useRef<HTMLCanvasElement>(null)\n    const containerRef = React.useRef<HTMLDivElement>(null)\n    const mouseRef = React.useRef({ x: -9999, y: -9999 })\n\n    React.useImperativeHandle(ref, () => containerRef.current!)\n\n    React.useEffect(() => {\n      const canvas = canvasRef.current\n      const container = containerRef.current\n      if (!canvas || !container) return\n\n      const ctx = canvas.getContext(\"2d\")\n      if (!ctx) return\n\n      let w = 0\n      let h = 0\n      let rafId = 0\n      let baseRgb: [number, number, number] = [128, 128, 128]\n      let activeRgb: [number, number, number] = [128, 128, 128]\n\n      function resolveColors() {\n        const computed = getComputedStyle(container!)\n        const resolvedColor = color === \"currentColor\" ? computed.color : color\n        const resolvedActive = activeColor\n          ? (activeColor === \"currentColor\" ? computed.color : activeColor)\n          : resolvedColor\n        baseRgb = parseColor(resolvedColor) ?? [128, 128, 128]\n        activeRgb = parseColor(resolvedActive) ?? baseRgb\n      }\n\n      function resize() {\n        const rect = container!.getBoundingClientRect()\n        const dpr = Math.min(window.devicePixelRatio, 2)\n        w = rect.width\n        h = rect.height\n        canvas!.width = w * dpr\n        canvas!.height = h * dpr\n        canvas!.style.width = `${w}px`\n        canvas!.style.height = `${h}px`\n        ctx!.setTransform(dpr, 0, 0, dpr, 0, 0)\n        resolveColors()\n      }\n\n      function draw() {\n        ctx!.clearRect(0, 0, w, h)\n        const mx = mouseRef.current.x\n        const my = mouseRef.current.y\n        const inf2 = influence * influence\n\n        for (let x = gap / 2; x < w; x += gap) {\n          for (let y = gap / 2; y < h; y += gap) {\n            const dx = x - mx\n            const dy = y - my\n            const dist2 = dx * dx + dy * dy\n            const t = dist2 < inf2 ? 1 - Math.sqrt(dist2) / influence : 0\n            const s = dotSize * (1 + (maxScale - 1) * t)\n\n            const r = Math.round(baseRgb[0] + (activeRgb[0] - baseRgb[0]) * t)\n            const g = Math.round(baseRgb[1] + (activeRgb[1] - baseRgb[1]) * t)\n            const b = Math.round(baseRgb[2] + (activeRgb[2] - baseRgb[2]) * t)\n            const alpha = 0.3 + 0.7 * t\n\n            ctx!.fillStyle = `rgba(${r},${g},${b},${alpha})`\n            ctx!.beginPath()\n            ctx!.arc(x, y, s, 0, Math.PI * 2)\n            ctx!.fill()\n          }\n        }\n\n        rafId = requestAnimationFrame(draw)\n      }\n\n      function handleMouseMove(e: MouseEvent) {\n        const rect = container!.getBoundingClientRect()\n        mouseRef.current.x = e.clientX - rect.left\n        mouseRef.current.y = e.clientY - rect.top\n      }\n\n      function handleMouseLeave() {\n        mouseRef.current.x = -9999\n        mouseRef.current.y = -9999\n      }\n\n      resize()\n      rafId = requestAnimationFrame(draw)\n\n      const ro = new ResizeObserver(resize)\n      ro.observe(container)\n      container.addEventListener(\"mousemove\", handleMouseMove)\n      container.addEventListener(\"mouseleave\", handleMouseLeave)\n\n      return () => {\n        cancelAnimationFrame(rafId)\n        ro.disconnect()\n        container.removeEventListener(\"mousemove\", handleMouseMove)\n        container.removeEventListener(\"mouseleave\", handleMouseLeave)\n      }\n    }, [gap, dotSize, color, activeColor, influence, maxScale])\n\n    return (\n      <div\n        ref={containerRef}\n        className={cn(\"relative overflow-hidden\", className)}\n        {...props}\n      >\n        <canvas ref={canvasRef} className=\"absolute inset-0\" />\n        {children && <div className=\"relative z-10\">{children}</div>}\n      </div>\n    )\n  }\n)\nDotMatrix.displayName = \"DotMatrix\"\n\nexport { DotMatrix }\nexport type { DotMatrixProps }\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}