import { forwardRef } from "react"; import { cn } from "@/lib/utils"; import { cva, type VariantProps } from "class-variance-authority"; /** * Code Block component for displaying code snippets and inline code * * @example * ```tsx * const greeting = "Hello, world!"; * * const x = 10; * * * def hello_world(): * print("Hello, world!") * * ``` */ const codeBlockVariants = cva( "font-mono text-sm rounded-md", { variants: { variant: { default: "bg-muted text-foreground p-4 overflow-x-auto", inline: "bg-muted px-1.5 py-0.5 text-primary-foreground", terminal: "bg-black text-white p-4", }, language: { none: "", js: "", ts: "", jsx: "", tsx: "", html: "", css: "", python: "", ruby: "", java: "", csharp: "", go: "", rust: "", php: "", swift: "", shell: "", sql: "", markdown: "", json: "", yaml: "", }, }, defaultVariants: { variant: "default", language: "none", }, } ); export interface CodeBlockProps extends React.HTMLAttributes, VariantProps { /** * Whether to show line numbers */ showLineNumbers?: boolean; /** * Whether this is a single line of code (uses inline styling) */ inline?: boolean; /** * Optional title for the code block */ title?: string; } const CodeBlock = forwardRef( ({ className, variant = "default", language, showLineNumbers = false, inline = false, title, children, ...props }, ref) => { // If inline is true, override variant to "inline" const actualVariant = inline ? "inline" : variant; // If inline, render as inline code element if (inline) { return ( {children} ); } // Process code content for line numbers if needed let codeContent = children; if (showLineNumbers && typeof children === 'string') { const lines = children.toString().trim().split('\n'); const lineCount = lines.length; const lineNumberWidth = lineCount.toString().length; codeContent = (
{lines.map((_, idx) => (
{(idx + 1).toString().padStart(lineNumberWidth, ' ')}
))}
{lines.map((line, idx) => (
{line || ' '}
))}
); } return (
{title && (
{title}
)}
          {language && (
            
{language}
)} {codeContent}
); } ); CodeBlock.displayName = "CodeBlock"; export { CodeBlock, codeBlockVariants };