{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block",
  "type": "registry:ui",
  "title": "Code block",
  "description": "React code block with zero dependency syntax coloring, a language tag, optional filename and line numbers, and a copy button that confirms Copied.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/code-block.tsx",
      "type": "registry:ui",
      "target": "components/ui/code-block.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { CheckIcon, CopyIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/** An ink-well code block in both themes, with lightweight token colouring (strings, keywords, JSX tags, comments) and a copy button. */\nconst KEYWORDS = new Set([\n  \"import\", \"from\", \"export\", \"default\", \"function\", \"return\", \"const\", \"let\", \"var\",\n  \"if\", \"else\", \"await\", \"async\", \"new\", \"type\", \"interface\", \"extends\", \"as\", \"npm\",\n  \"npx\", \"pnpm\", \"yarn\", \"bun\", \"true\", \"false\", \"null\", \"undefined\",\n])\n\nfunction highlight(code: string) {\n  const out: React.ReactNode[] = []\n  const re = /((?<![:\\w])\\/\\/[^\\n]*|(?<![\\w&])#(?![\\da-fA-F]{3,8}\\b)[^\\n]*$|\\/\\*[^\\n]*?\\*\\/)|(\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|`(?:[^`\\\\]|\\\\.)*`)|(<\\/?[A-Za-z][\\w.]*)|(\\b[A-Za-z_]\\w*\\b)|(\\d+(?:\\.\\d+)?)/gm\n  let last = 0\n  let m: RegExpExecArray | null\n  let k = 0\n  while ((m = re.exec(code))) {\n    if (m.index > last) out.push(code.slice(last, m.index))\n    const [t, comment, str, tag, word, num] = m\n    if (comment) out.push(<span key={k++} className=\"text-[color-mix(in_oklch,var(--code-fg)_45%,transparent)] italic\">{t}</span>)\n    else if (str) out.push(<span key={k++} className=\"text-[var(--code-str)]\">{t}</span>)\n    else if (tag) out.push(<span key={k++} className=\"text-[var(--code-tag)]\">{t}</span>)\n    else if (word && KEYWORDS.has(word)) out.push(<span key={k++} className=\"text-[var(--code-kw)]\">{t}</span>)\n    else if (word && /^[A-Z]/.test(word)) out.push(<span key={k++} className=\"text-[var(--code-type)]\">{t}</span>)\n    else if (num) out.push(<span key={k++} className=\"text-[var(--code-num)]\">{t}</span>)\n    else out.push(t)\n    last = m.index + t.length\n  }\n  if (last < code.length) out.push(code.slice(last))\n  return out\n}\n\nconst SAMPLE_CODE = `import { lumen } from \"@/lib/lumen\"\n\n// Create an invoice for Northwind and send it\nexport async function POST(req: Request) {\n  const { customerId, amount } = await req.json()\n  const invoice = await lumen.invoices.create({\n    customerId,\n    amount: Math.round(amount * 100), // cents\n    dueInDays: 30,\n  })\n  return Response.json({ id: invoice.id, status: \"open\" })\n}\n`\n\ntype CodeBlockProps = {\n  code?: string\n  language?: string\n  filename?: string\n  className?: string\n  showLineNumbers?: boolean\n}\n\nfunction CodeBlock({\n  code = SAMPLE_CODE,\n  language = \"tsx\",\n  filename,\n  className,\n  showLineNumbers = false,\n}: CodeBlockProps) {\n  const [copied, setCopied] = React.useState(false)\n  const lines = React.useMemo(() => code.replace(/\\n$/, \"\").split(\"\\n\"), [code])\n  return (\n    <div\n      data-slot=\"code-block\"\n      className={cn(\n        \"group/code relative overflow-hidden rounded-xl border border-[var(--code-border)] bg-[var(--code-bg)] text-[var(--code-fg)] shadow-md\",\n        \"[--code-bg:oklch(0.17_0.008_270)] [--code-border:oklch(0.26_0.008_270)] [--code-fg:oklch(0.9_0.006_270)]\",\n        \"[--code-kw:oklch(0.76_0.13_300)] [--code-str:oklch(0.8_0.11_160)] [--code-tag:oklch(0.78_0.11_230)] [--code-type:oklch(0.84_0.1_80)] [--code-num:oklch(0.8_0.12_40)]\",\n        \"dark:[--code-bg:oklch(0.12_0.005_270)] dark:[--code-border:oklch(0.24_0.006_270)]\",\n        className\n      )}\n    >\n      <div className=\"flex h-10 items-center justify-between gap-3 border-b border-[var(--code-border)] pr-2 pl-4\">\n        <div className=\"flex min-w-0 items-center gap-2 font-mono text-[11px] text-[color-mix(in_oklch,var(--code-fg)_55%,transparent)]\">\n          {filename ? <span className=\"truncate\">{filename}</span> : null}\n          <span className=\"rounded border border-[var(--code-border)] px-1.5 py-px uppercase tracking-[0.06em]\">{language}</span>\n        </div>\n        <button\n          type=\"button\"\n          aria-label={copied ? \"Copied\" : \"Copy code\"}\n          onClick={async () => {\n            try { await navigator.clipboard.writeText(code) } catch {}\n            setCopied(true)\n            setTimeout(() => setCopied(false), 1400)\n          }}\n          className=\"inline-flex h-7 items-center gap-1.5 rounded-md px-2 text-[11px] font-medium text-[color-mix(in_oklch,var(--code-fg)_65%,transparent)] outline-none transition-[color,background-color] duration-[70ms] hover:bg-white/8 hover:text-[var(--code-fg)] focus-visible:ring-2 focus-visible:ring-accent\"\n        >\n          {copied ? <CheckIcon className=\"size-3.5 text-[var(--code-str)]\" /> : <CopyIcon className=\"size-3.5\" />}\n          {copied ? \"Copied\" : \"Copy\"}\n        </button>\n      </div>\n      <pre className=\"overflow-x-auto py-3.5 font-mono text-[12.5px] leading-[1.7]\">\n        <code className=\"grid\">\n          {lines.map((line, i) => (\n            <span key={i} className=\"px-4\">\n              {showLineNumbers ? (\n                <span className=\"mr-4 inline-block w-5 text-right text-[color-mix(in_oklch,var(--code-fg)_28%,transparent)] select-none\">{i + 1}</span>\n              ) : null}\n              {highlight(line)}\n              {\"\\n\"}\n            </span>\n          ))}\n        </code>\n      </pre>\n    </div>\n  )\n}\nexport { CodeBlock }\nexport type { CodeBlockProps }\n"
    }
  ]
}
