{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "spinner",
  "title": "Spinner",
  "description": "Pixel spinner that steps at about 10 fps and holds still under reduced motion.",
  "dependencies": [
    "cn"
  ],
  "registryDependencies": [
    "@ui95/theme"
  ],
  "files": [
    {
      "path": "components/ui/spinner.tsx",
      "content": "\"use client\"\n\nimport { cn } from \"cn\"\nimport * as React from \"react\"\n\nconst FRAME_MS = 100\nconst TAIL_LENGTH = 5\n\nconst RING: readonly (readonly [number, number])[] = [\n  [0, 0],\n  [1, 0],\n  [2, 0],\n  [3, 0],\n  [4, 0],\n  [4, 1],\n  [4, 2],\n  [4, 3],\n  [4, 4],\n  [3, 4],\n  [2, 4],\n  [1, 4],\n  [0, 4],\n  [0, 3],\n  [0, 2],\n  [0, 1],\n]\n\nfunction usePixelFrame() {\n  const [frame, setFrame] = React.useState(0)\n\n  React.useEffect(() => {\n    if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return\n    const id = window.setInterval(\n      () => setFrame((current) => (current + 1) % RING.length),\n      FRAME_MS\n    )\n    return () => window.clearInterval(id)\n  }, [])\n\n  return frame\n}\n\nfunction Spinner({ className, ...props }: React.ComponentProps<\"svg\">) {\n  const frame = usePixelFrame()\n\n  return (\n    <svg\n      viewBox=\"0 0 5 5\"\n      shapeRendering=\"crispEdges\"\n      fill=\"currentColor\"\n      data-slot=\"spinner\"\n      role=\"status\"\n      aria-label=\"Loading\"\n      className={cn(\"size-4\", className)}\n      {...props}\n    >\n      {Array.from({ length: TAIL_LENGTH }, (_, offset) => {\n        const [x, y] = RING[(frame + RING.length - offset) % RING.length]\n        return <rect key={offset} x={x} y={y} width=\"1\" height=\"1\" />\n      })}\n    </svg>\n  )\n}\n\nexport { Spinner }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ui"
  ],
  "type": "registry:ui"
}