{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "code-block",
  "title": "Code Block",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/code-block/CodeBlock.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { Check, ChevronDown, ChevronUp, Copy } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from '@/components/ui/button'\n\nexport interface CodeBlockProps {\n  /** Source code to display. */\n  code: string\n  /** Language label shown in the header. */\n  language?: string\n  /** Render line numbers in the gutter. */\n  showLineNumbers?: boolean\n  /** Maximum height of the code body before scrolling kicks in. */\n  maxHeight?: string\n  /** Render expanded on first paint. Default true. */\n  defaultExpanded?: boolean\n  /** Show the language label / copy / collapse header. */\n  showHeader?: boolean\n  className?: string\n}\n\nfunction CodeBlock({\n  code,\n  language = 'tsx',\n  showLineNumbers = true,\n  maxHeight = '400px',\n  defaultExpanded = true,\n  showHeader = true,\n  className,\n}: CodeBlockProps) {\n  const [isExpanded, setIsExpanded] = React.useState(defaultExpanded)\n  const [copied, setCopied] = React.useState(false)\n\n  const lines = React.useMemo(() => code.replace(/\\s+$/, '').split('\\n'), [code])\n\n  async function copyToClipboard() {\n    try {\n      await navigator.clipboard.writeText(code)\n      setCopied(true)\n      setTimeout(() => setCopied(false), 1600)\n    } catch (e) {\n      console.warn('Clipboard write failed', e)\n    }\n  }\n\n  return (\n    <div\n      data-uipkge=\"\"\n      data-slot=\"code-block\"\n      className={cn('group border-border bg-muted/20 relative overflow-hidden rounded-lg border', className)}\n    >\n      {/* Header */}\n      {showHeader && (\n        <div className=\"border-border bg-muted/40 flex items-center justify-between gap-2 border-b px-3 py-2\">\n          <span className=\"text-muted-foreground text-xs font-medium tracking-wide uppercase\">{language}</span>\n          <div className=\"flex items-center gap-1\">\n            <Button variant=\"ghost\" size=\"xs\" className=\"h-7 gap-1.5 px-2\" onClick={copyToClipboard}>\n              {copied ? (\n                <Check className=\"text-success size-3\" aria-hidden=\"true\" />\n              ) : (\n                <Copy className=\"size-3\" aria-hidden=\"true\" />\n              )}\n              <span className=\"text-xs\">{copied ? 'Copied' : 'Copy'}</span>\n            </Button>\n            <Button\n              variant=\"ghost\"\n              size=\"xs\"\n              className=\"h-7 gap-1.5 px-2\"\n              onClick={() => setIsExpanded((v) => !v)}\n            >\n              {isExpanded ? (\n                <ChevronUp className=\"size-3\" aria-hidden=\"true\" />\n              ) : (\n                <ChevronDown className=\"size-3\" aria-hidden=\"true\" />\n              )}\n              <span className=\"text-xs\">{isExpanded ? 'Hide' : 'Show'} code</span>\n            </Button>\n          </div>\n        </div>\n      )}\n\n      {/* Code body. We render line-by-line so the gutter and the code stay in\n          sync without measuring text height. The renderer is intentionally\n          plain: code is displayed as-is and the consumer can layer their own\n          syntax highlighter (shiki, prism, hljs) on top by replacing this\n          file or by wrapping it in their own component. */}\n      {isExpanded && (\n        <div\n          className=\"bg-background/40 overflow-auto font-mono text-sm leading-relaxed\"\n          style={{ maxHeight }}\n        >\n          <pre className=\"m-0 flex\">\n            {showLineNumbers && (\n              <div\n                aria-hidden=\"true\"\n                className=\"text-muted-foreground/60 sticky left-0 select-none border-r border-border/60 bg-muted/30 px-3 py-3 text-right tabular-nums\"\n              >\n                {lines.map((_, i) => (\n                  <div key={i}>{i + 1}</div>\n                ))}\n              </div>\n            )}\n            <code className=\"block flex-1 px-4 py-3\">\n              {lines.map((line, i) => (\n                <React.Fragment key={i}>\n                  <span>{line || ' '}</span>\n                  {i < lines.length - 1 && <br />}\n                </React.Fragment>\n              ))}\n            </code>\n          </pre>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport { CodeBlock }\n",
      "type": "registry:ui",
      "target": "~/components/ui/code-block/CodeBlock.tsx"
    },
    {
      "path": "packages/registry-react/components/code-block/index.ts",
      "content": "export { CodeBlock, type CodeBlockProps } from './CodeBlock'\n",
      "type": "registry:ui",
      "target": "~/components/ui/code-block/index.ts"
    }
  ],
  "dependencies": [
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/react/button.json"
  ],
  "description": "Read-only code preview with a header, optional filename, copy button, and `<pre>`-rendered content. Use for installation snippets, API examples, and snippets you want users to copy verbatim.",
  "categories": [
    "data-display"
  ]
}