{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-code-runner",
  "type": "registry:component",
  "title": "Code runner",
  "description": "A snippet with a run button, and the output it produced attached below it.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/code-runner.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { Loader2Icon, PlayIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { codeScroll, codeSurface, ghostButton, mono, paper } from \"./surfaces\";\n\nexport type RunState = \"idle\" | \"running\" | \"ok\" | \"error\";\n\nexport function CodeRunner({\n  language,\n  code,\n  state,\n  output,\n  durationMs,\n  onRun,\n  className,\n  ...props\n}: Omit<\n  ComponentProps<\"div\">,\n  \"children\" | \"language\" | \"code\" | \"state\" | \"output\" | \"durationMs\" | \"onRun\"\n> & {\n  language: string;\n  code: string;\n  state: RunState;\n  output: readonly string[];\n  durationMs?: number;\n  onRun?: () => void;\n}) {\n  return (\n    <div\n      data-slot=\"code-runner\"\n      className={cn(\n        paper,\n        \"flex w-full max-w-md flex-col overflow-hidden rounded-2xl\",\n        className,\n      )}\n\n      {...props}\n    >\n      <div className=\"flex items-center gap-2 px-3.5 py-2\">\n        <span className={cn(mono, \"text-foreground/35 min-w-0 flex-1\")}>\n          {language}\n        </span>\n        {durationMs !== undefined && state !== \"running\" && (\n          <span\n            className={cn(mono, \"text-foreground/30 shrink-0 tabular-nums\")}\n          >\n            {durationMs}ms\n          </span>\n        )}\n        <button\n          type=\"button\"\n          aria-label=\"Run this snippet\"\n          onClick={onRun}\n          disabled={state === \"running\"}\n          className={cn(\n            ghostButton,\n            \"size-7 shrink-0 disabled:pointer-events-none\",\n          )}\n        >\n          {state === \"running\" ? (\n            <Loader2Icon className=\"size-3.5 animate-spin motion-reduce:animate-none\" />\n          ) : (\n            <PlayIcon className=\"size-3.5 translate-x-px\" />\n          )}\n        </button>\n      </div>\n\n      <pre className=\"border-foreground/[0.07] overflow-x-auto border-t px-3.5 py-2.5 font-mono text-xs leading-relaxed\">\n        <code className=\"text-foreground/75\">{code}</code>\n      </pre>\n\n      {state !== \"idle\" && (\n        <div className=\"border-foreground/[0.07] fade-in animate-in flex flex-col border-t px-3.5 py-2.5 duration-300\">\n          <span className={cn(mono, \"text-foreground/30 pb-1\")}>output</span>\n          <div className={codeScroll}>\n            <div className={cn(codeSurface, \"flex flex-col\")}>\n              {output.map((line, i) => (\n                <span\n                  key={`${i}-${line}`}\n                  className={cn(\n                    \"fade-in animate-in fill-mode-both font-mono text-xs leading-relaxed whitespace-pre\",\n                    state === \"error\"\n                      ? \"text-red-600 dark:text-red-400\"\n                      : \"text-foreground/70\",\n                  )}\n                  style={{ animationDelay: `${i * 80}ms` }}\n                >\n                  {line}\n                </span>\n              ))}\n            </div>\n          </div>\n          {state === \"running\" && (\n            <span\n              aria-hidden\n              className=\"bg-foreground/40 h-[1em] w-[2px] animate-pulse rounded-full motion-reduce:animate-none\"\n            />\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
    }
  ]
}