{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "matrix",
  "title": "Matrix",
  "description": "A grid of cells lit from the bottom by a level, which reads as a piece of hardware rather than as a chart.",
  "registryDependencies": [
    "utils",
    "https://ui.tinkererslabs.com/r/render-surface.json"
  ],
  "files": [
    {
      "path": "registry/default/matrix/matrix.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport {\n  RenderSurface,\n  useThemeColors,\n  type SurfaceColor,\n} from \"@/registry/default/render-surface/render-surface\"\nimport { cn } from \"@/lib/utils\"\n\nexport type MatrixProps = Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"children\"\n> & {\n  /** Cells across. Rows are worked out from the box. */\n  columns?: number\n  /** Nought to one. Lights the grid from the middle out. */\n  level?: number\n  /** Keeps moving with nothing to show, at a low idle. */\n  idle?: boolean\n  color?: string\n  gap?: number\n  label?: string\n}\n\ntype Cell = { x: number; y: number; seed: number }\n\n/**\n * A grid of cells lit by a level: an equaliser that reads as hardware rather\n * than as a chart. Loud lights the middle rows outward, quiet leaves a low\n * shimmer along the floor.\n */\nexport function Matrix({\n  columns = 24,\n  level = 0,\n  idle = true,\n  color = \"--primary\",\n  gap = 2,\n  label,\n  className,\n  ...rootProps\n}: MatrixProps) {\n  const rootRef = React.useRef<HTMLDivElement>(null)\n  const tokens = React.useMemo(\n    () => (color.startsWith(\"--\") ? [color] : []),\n    [color]\n  )\n  const resolved = useThemeColors(rootRef, tokens)\n  const ink = color.startsWith(\"--\") ? resolved[color] : undefined\n\n  const live = React.useRef({ level, idle })\n  React.useEffect(() => {\n    live.current = { level, idle }\n  })\n\n  const setup = React.useCallback(\n    ({ size }: { size: { width: number; height: number } }): Cell[] => {\n      const step = size.width / Math.max(columns, 1)\n      const rows = Math.max(1, Math.round(size.height / step))\n      const made: Cell[] = []\n\n      for (let x = 0; x < columns; x += 1) {\n        for (let y = 0; y < rows; y += 1) {\n          made.push({ x, y, seed: (x * 7 + y * 13) % 17 })\n        }\n      }\n\n      return made\n    },\n    [columns]\n  )\n\n  const draw = React.useCallback(\n    ({\n      context,\n      size: box,\n      state: cells,\n      time,\n    }: {\n      context: CanvasRenderingContext2D\n      size: { width: number; height: number; dpr: number }\n      state: Cell[]\n      time: number\n    }) => {\n      if (!ink) return\n\n      context.setTransform(box.dpr, 0, 0, box.dpr, 0, 0)\n      context.clearRect(0, 0, box.width, box.height)\n\n      const step = box.width / Math.max(columns, 1)\n      const rows = Math.max(1, Math.round(box.height / step))\n      const size = Math.max(step - gap, 1)\n      const [r, g, b] = ink as SurfaceColor\n      const rgb = `${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(b * 255)}`\n\n      const loud = Math.min(Math.max(live.current.level, 0), 1)\n      const floor = live.current.idle ? 0.12 : 0\n\n      for (const cell of cells) {\n        // Height from the bottom, so the grid reads as a level meter rather\n        // than as noise scattered over a rectangle.\n        const column =\n          Math.sin(time * 1.6 + cell.x * 0.5 + cell.seed) * 0.5 + 0.5\n        const reach = Math.max(loud * (0.55 + column * 0.45), floor * column)\n        const lit = 1 - cell.y / rows <= reach\n\n        context.fillStyle = `rgba(${rgb}, ${lit ? 0.25 + reach * 0.6 : 0.06})`\n        context.fillRect(\n          cell.x * step + gap / 2,\n          cell.y * step + gap / 2,\n          size,\n          size\n        )\n      }\n    },\n    [columns, gap, ink]\n  )\n\n  return (\n    <div\n      ref={rootRef}\n      data-slot=\"matrix\"\n      className={cn(\"relative isolate overflow-hidden\", className)}\n      {...rootProps}\n    >\n      {ink !== undefined && (\n        <RenderSurface<Cell[], \"2d\">\n          setup={setup}\n          draw={draw}\n          rebuildOnResize\n          className=\"absolute inset-0\"\n          label={label}\n        />\n      )}\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ai",
    "agent",
    "canvas",
    "audio",
    "meter"
  ],
  "type": "registry:ui"
}