{
  "$schema": "https://abackui.com/schema/registry-item.json",
  "name": "code-block",
  "type": "registry:ui",
  "title": "Code Block",
  "description": "A captioned, scrollable code sample with a copy button and optional line numbers.",
  "registryDependencies": [
    "https://abackui.com/r/utils.json",
    "https://abackui.com/r/copy-button.json"
  ],
  "categories": [
    "Data Display"
  ],
  "docs": "https://abackui.com/docs/components/code-block",
  "meta": {
    "status": "beta",
    "usedIn": [
      "aback-tools"
    ]
  },
  "files": [
    {
      "path": "components/ui/code-block.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { CopyButton } from \"@/components/ui/copy-button\";\n\nexport interface CodeBlockProps extends Omit<React.ComponentProps<\"figure\">, \"children\"> {\n  /** The exact source. It is what the copy button writes. */\n  code: string;\n  /** Shown in the caption bar, such as \"tsx\" or \"bash\". */\n  language?: string;\n  /** Shown in the caption bar and used to name the scroll region. */\n  filename?: string;\n  /** Show the copy button. */\n  copyable?: boolean;\n  /** Number the lines. Numbers are generated by CSS and never copied. */\n  showLineNumbers?: boolean;\n  /** Caps the height and scrolls, for long files. */\n  maxHeight?: number | string;\n  /** Accessible name of the copy button. */\n  copyLabel?: string;\n}\n\n/**\n * A captioned code sample with a copy button. The scroll region is focusable\n * so a keyboard can scroll a long line, and it has a name. No highlighter is\n * bundled; the block renders plain text so it stays light and safe.\n */\nfunction CodeBlock({\n  code,\n  language,\n  filename,\n  copyable = true,\n  showLineNumbers = false,\n  maxHeight,\n  copyLabel = \"Copy code\",\n  className,\n  ...props\n}: CodeBlockProps) {\n  const lines = React.useMemo(() => code.replace(/\\n$/, \"\").split(\"\\n\"), [code]);\n  const hasCaption = Boolean(filename || language || copyable);\n\n  return (\n    <figure\n      data-slot=\"code-block\"\n      className={cn(\"min-w-0 overflow-hidden border border-border bg-muted/30\", className)}\n      {...props}\n    >\n      {hasCaption ? (\n        <figcaption className=\"flex min-h-10 items-center justify-between gap-3 border-b border-border bg-muted px-4 py-1.5\">\n          <span className=\"flex min-w-0 items-center gap-3\">\n            {filename ? (\n              <span className=\"truncate font-mono text-xs text-foreground\">{filename}</span>\n            ) : null}\n            {language ? (\n              <span className=\"shrink-0 text-[10px] font-bold uppercase tracking-[0.12em] text-foreground\">\n                {language}\n              </span>\n            ) : null}\n          </span>\n          {copyable ? <CopyButton value={code} label={copyLabel} /> : null}\n        </figcaption>\n      ) : null}\n      <pre\n        tabIndex={0}\n        aria-label={filename ? `${filename} source` : \"Code sample\"}\n        className=\"overflow-auto p-4 text-[13px] leading-relaxed text-foreground outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-focus-ring\"\n        style={maxHeight !== undefined ? { maxHeight } : undefined}\n      >\n        <code className={cn(\"font-mono\", showLineNumbers && \"grid [counter-reset:line]\")}>\n          {showLineNumbers\n            ? lines.map((line, index) => (\n                <span\n                  key={index}\n                  className=\"[counter-increment:line] before:mr-4 before:inline-block before:w-6 before:select-none before:text-right before:text-muted-foreground before:content-[counter(line)]\"\n                >\n                  {line || \" \"}\n                </span>\n              ))\n            : code}\n        </code>\n      </pre>\n    </figure>\n  );\n}\n\nexport { CodeBlock };\n",
      "type": "registry:ui",
      "target": "components/ui/code-block.tsx"
    }
  ]
}
