{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-image-generation",
  "type": "registry:component",
  "title": "Image generation",
  "description": "A dot grid holds the frame while the image resolves out of a blur.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/image-generation.tsx",
      "sourcePath": "packages/ui/src/components/react/assistant-ui/elements/image-generation.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { RefreshCwIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { ghostButton, mono, paper, ShimmerLabel } from \"./surfaces\";\n\nconst DOTS = Array.from({ length: 64 }, (_, i) => i);\n\nexport function ImageGeneration({\n  prompt,\n  generating,\n  className,\n  ...props\n}: Omit<ComponentProps<\"div\">, \"children\" | \"prompt\" | \"generating\"> & {\n  prompt: string;\n  generating: boolean;\n}) {\n  return (\n    <div\n      data-slot=\"image-generation\"\n      className={cn(\"flex w-52 flex-col gap-2.5\", className)}\n\n      {...props}\n    >\n      <div\n        className={cn(\n          paper,\n          \"relative aspect-square w-full overflow-hidden rounded-2xl\",\n        )}\n      >\n        <div\n          className=\"absolute inset-0 grid grid-cols-8 place-items-center p-6\"\n          aria-hidden\n        >\n          {DOTS.map((dot) => {\n            const row = Math.floor(dot / 8);\n            const col = dot % 8;\n            return (\n              <span\n                key={dot}\n                className={cn(\n                  \"bg-foreground/20 size-1 rounded-full transition-opacity duration-500\",\n                  generating\n                    ? \"animate-pulse motion-reduce:animate-none\"\n                    : \"opacity-0\",\n                )}\n                style={{ animationDelay: `${(row + col) * 90}ms` }}\n              />\n            );\n          })}\n        </div>\n        <div\n          aria-hidden\n          className={cn(\n            \"absolute inset-0 transition-[opacity,filter] duration-1000 ease-out motion-reduce:transition-none\",\n            generating ? \"opacity-0 blur-xl\" : \"blur-0 opacity-100\",\n          )}\n          style={{\n            background:\n              \"radial-gradient(120% 90% at 20% 100%, oklch(0.45 0.09 265) 0%, transparent 55%), radial-gradient(110% 80% at 85% 90%, oklch(0.62 0.1 300 / 0.8) 0%, transparent 60%), radial-gradient(130% 100% at 60% 0%, oklch(0.88 0.06 60) 0%, oklch(0.74 0.09 25 / 0.9) 45%, transparent 75%), linear-gradient(to top, oklch(0.35 0.06 275), oklch(0.82 0.07 50))\",\n          }}\n        />\n        <span\n          className={cn(\n            mono,\n            \"absolute end-2.5 top-2.5 tabular-nums\",\n            generating ? \"text-foreground/35\" : \"text-white/70\",\n          )}\n        >\n          1024 × 1024\n        </span>\n      </div>\n      <div className=\"flex items-center justify-between gap-2\">\n        <p className=\"text-foreground/45 min-w-0 flex-1 truncate text-xs\">\n          {generating ? (\n            <ShimmerLabel className=\"relative\">Generating</ShimmerLabel>\n          ) : (\n            prompt\n          )}\n        </p>\n        <button\n          type=\"button\"\n          aria-label=\"Regenerate image\"\n          className={cn(\n            ghostButton,\n            \"size-6 shrink-0\",\n            generating && \"pointer-events-none opacity-0\",\n          )}\n        >\n          <RefreshCwIcon className=\"size-3\" />\n        </button>\n      </div>\n    </div>\n  );\n}\n"
    }
  ]
}