{
  "name": "code-block",
  "dependencies": [
    "lucide-react",
    "motion",
    "prism-react-renderer"
  ],
  "files": [
    {
      "path": "ui/code-block.tsx",
      "content": "import {\n  Check,\n  Copy,\n  Download,\n  FileCode,\n  Maximize2,\n  Minimize2,\n  Terminal,\n  WrapText,\n} from \"lucide-react\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { Highlight, type Language, themes } from \"prism-react-renderer\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\ntype CodeBlockVariant =\n  | \"default\"\n  | \"terminal\"\n  | \"minimal\"\n  | \"gradient\"\n  | \"glass\";\ntype AnimationType = \"none\" | \"fadeIn\" | \"slideIn\" | \"typewriter\" | \"highlight\";\ntype ThemeType =\n  | \"oneDark\"\n  | \"dracula\"\n  | \"github\"\n  | \"nightOwl\"\n  | \"oceanicNext\"\n  | \"palenight\"\n  | \"shadesOfPurple\"\n  | \"synthwave84\"\n  | \"vsDark\"\n  | \"vsLight\";\n\n// Theme mapping\nconst themeMap: Record<ThemeType, typeof themes.oneDark> = {\n  oneDark: themes.oneDark,\n  dracula: themes.dracula,\n  github: themes.github,\n  nightOwl: themes.nightOwl,\n  oceanicNext: themes.oceanicNext,\n  palenight: themes.palenight,\n  shadesOfPurple: themes.shadesOfPurple,\n  synthwave84: themes.synthwave84,\n  vsDark: themes.vsDark,\n  vsLight: themes.vsLight,\n};\n\n// Supported languages list\nconst supportedLanguages = [\n  \"javascript\",\n  \"typescript\",\n  \"jsx\",\n  \"tsx\",\n  \"python\",\n  \"bash\",\n  \"shell\",\n  \"css\",\n  \"scss\",\n  \"html\",\n  \"json\",\n  \"yaml\",\n  \"markdown\",\n  \"sql\",\n  \"graphql\",\n  \"rust\",\n  \"go\",\n  \"java\",\n  \"c\",\n  \"cpp\",\n  \"csharp\",\n  \"php\",\n  \"ruby\",\n  \"swift\",\n  \"kotlin\",\n  \"scala\",\n  \"r\",\n  \"lua\",\n  \"perl\",\n  \"haskell\",\n  \"elixir\",\n  \"clojure\",\n  \"dockerfile\",\n  \"toml\",\n  \"ini\",\n  \"xml\",\n  \"diff\",\n  \"makefile\",\n  \"regex\",\n] as const;\n\ninterface CodeBlockProps {\n  code: string;\n  language?: Language | string;\n  title?: string;\n  showLineNumbers?: boolean;\n  highlightLines?: number[];\n  addedLines?: number[];\n  removedLines?: number[];\n  variant?: CodeBlockVariant;\n  animation?: AnimationType;\n  animationDelay?: number;\n  className?: string;\n  copyable?: boolean;\n  downloadable?: boolean;\n  downloadFileName?: string;\n  maxHeight?: string;\n  theme?: ThemeType;\n  wrapLongLines?: boolean;\n  showLanguage?: boolean;\n  collapsible?: boolean;\n  defaultCollapsed?: boolean;\n  startingLineNumber?: number;\n  caption?: string;\n}\n\n// Copy button component\nconst CopyButton = ({\n  code,\n  className,\n}: {\n  code: string;\n  className?: string;\n}) => {\n  const [copied, setCopied] = React.useState(false);\n\n  const handleCopy = async () => {\n    try {\n      await navigator.clipboard.writeText(code);\n      setCopied(true);\n      setTimeout(() => setCopied(false), 2000);\n    } catch (err) {\n      console.error(\"Failed to copy:\", err);\n    }\n  };\n\n  return (\n    <motion.button\n      onClick={handleCopy}\n      className={cn(\n        \"rounded-md p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\",\n        className,\n      )}\n      whileHover={{ scale: 1.05 }}\n      whileTap={{ scale: 0.95 }}\n      aria-label={copied ? \"Copied!\" : \"Copy code\"}\n      title={copied ? \"Copied!\" : \"Copy code\"}\n    >\n      <AnimatePresence mode=\"wait\">\n        {copied ? (\n          <motion.div\n            key=\"check\"\n            initial={{ scale: 0, rotate: -180 }}\n            animate={{ scale: 1, rotate: 0 }}\n            exit={{ scale: 0, rotate: 180 }}\n            transition={{ duration: 0.2 }}\n          >\n            <Check className=\"h-4 w-4 text-green-500\" />\n          </motion.div>\n        ) : (\n          <motion.div\n            key=\"copy\"\n            initial={{ scale: 0 }}\n            animate={{ scale: 1 }}\n            exit={{ scale: 0 }}\n            transition={{ duration: 0.2 }}\n          >\n            <Copy className=\"h-4 w-4\" />\n          </motion.div>\n        )}\n      </AnimatePresence>\n    </motion.button>\n  );\n};\n\n// Download button component\nconst DownloadButton = ({\n  code,\n  fileName,\n  language,\n}: {\n  code: string;\n  fileName?: string;\n  language: string;\n}) => {\n  const handleDownload = () => {\n    const extension = getFileExtension(language);\n    const name = fileName || `code.${extension}`;\n    const blob = new Blob([code], { type: \"text/plain\" });\n    const url = URL.createObjectURL(blob);\n    const a = document.createElement(\"a\");\n    a.href = url;\n    a.download = name;\n    document.body.appendChild(a);\n    a.click();\n    document.body.removeChild(a);\n    URL.revokeObjectURL(url);\n  };\n\n  return (\n    <motion.button\n      onClick={handleDownload}\n      className=\"rounded-md p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n      whileHover={{ scale: 1.05 }}\n      whileTap={{ scale: 0.95 }}\n      aria-label=\"Download code\"\n      title=\"Download code\"\n    >\n      <Download className=\"h-4 w-4\" />\n    </motion.button>\n  );\n};\n\n// Get file extension from language\nconst getFileExtension = (language: string): string => {\n  const extensions: Record<string, string> = {\n    javascript: \"js\",\n    typescript: \"ts\",\n    jsx: \"jsx\",\n    tsx: \"tsx\",\n    python: \"py\",\n    bash: \"sh\",\n    shell: \"sh\",\n    css: \"css\",\n    scss: \"scss\",\n    html: \"html\",\n    json: \"json\",\n    yaml: \"yml\",\n    markdown: \"md\",\n    sql: \"sql\",\n    graphql: \"graphql\",\n    rust: \"rs\",\n    go: \"go\",\n    java: \"java\",\n    c: \"c\",\n    cpp: \"cpp\",\n    csharp: \"cs\",\n    php: \"php\",\n    ruby: \"rb\",\n    swift: \"swift\",\n    kotlin: \"kt\",\n    dockerfile: \"dockerfile\",\n    toml: \"toml\",\n    xml: \"xml\",\n  };\n  return extensions[language] || \"txt\";\n};\n\n// Language display names\nconst getLanguageDisplayName = (language: string): string => {\n  const names: Record<string, string> = {\n    javascript: \"JavaScript\",\n    typescript: \"TypeScript\",\n    jsx: \"JSX\",\n    tsx: \"TSX\",\n    python: \"Python\",\n    bash: \"Bash\",\n    shell: \"Shell\",\n    css: \"CSS\",\n    scss: \"SCSS\",\n    html: \"HTML\",\n    json: \"JSON\",\n    yaml: \"YAML\",\n    markdown: \"Markdown\",\n    sql: \"SQL\",\n    graphql: \"GraphQL\",\n    rust: \"Rust\",\n    go: \"Go\",\n    java: \"Java\",\n    c: \"C\",\n    cpp: \"C++\",\n    csharp: \"C#\",\n    php: \"PHP\",\n    ruby: \"Ruby\",\n    swift: \"Swift\",\n    kotlin: \"Kotlin\",\n    dockerfile: \"Dockerfile\",\n    toml: \"TOML\",\n    xml: \"XML\",\n    diff: \"Diff\",\n  };\n  return (\n    names[language] || language.charAt(0).toUpperCase() + language.slice(1)\n  );\n};\n\n// Typewriter code animation component\nconst TypewriterCode = ({\n  code,\n  language,\n  speed = 20,\n  showLineNumbers,\n  highlightLines = [],\n  startingLineNumber = 1,\n  theme,\n}: {\n  code: string;\n  language: Language;\n  speed?: number;\n  showLineNumbers: boolean;\n  highlightLines: number[];\n  startingLineNumber: number;\n  theme: typeof themes.oneDark;\n}) => {\n  const [displayedCode, setDisplayedCode] = React.useState(\"\");\n  const [currentIndex, setCurrentIndex] = React.useState(0);\n\n  React.useEffect(() => {\n    if (currentIndex >= code.length) return;\n\n    const timeout = setTimeout(() => {\n      setDisplayedCode(code.slice(0, currentIndex + 1));\n      setCurrentIndex((prev) => prev + 1);\n    }, speed);\n\n    return () => clearTimeout(timeout);\n  }, [currentIndex, code, speed]);\n\n  return (\n    <div className=\"relative\">\n      <Highlight theme={theme} code={displayedCode || \" \"} language={language}>\n        {({ className, style, tokens, getLineProps, getTokenProps }) => (\n          <pre\n            className={cn(\n              className,\n              \"!bg-transparent font-mono text-sm leading-relaxed\",\n            )}\n            style={{ ...style, background: \"transparent\" }}\n          >\n            {tokens.map((line, i) => {\n              const lineNumber = i + startingLineNumber;\n              const isHighlighted = highlightLines.includes(lineNumber);\n              return (\n                <div\n                  key={i}\n                  {...getLineProps({ line })}\n                  className={cn(\n                    \"flex\",\n                    isHighlighted &&\n                      \"-mx-4 border-primary border-l-2 bg-primary/10 px-4\",\n                  )}\n                >\n                  {showLineNumbers && (\n                    <span className=\"mr-4 inline-block w-8 shrink-0 select-none text-right text-muted-foreground/50\">\n                      {lineNumber}\n                    </span>\n                  )}\n                  <span className=\"flex-1\">\n                    {line.map((token, key) => (\n                      <span key={key} {...getTokenProps({ token })} />\n                    ))}\n                  </span>\n                </div>\n              );\n            })}\n          </pre>\n        )}\n      </Highlight>\n      {currentIndex < code.length && (\n        <motion.span\n          className=\"absolute inline-block h-4 w-2 bg-primary\"\n          animate={{ opacity: [1, 0] }}\n          transition={{ duration: 0.5, repeat: Infinity }}\n        />\n      )}\n    </div>\n  );\n};\n\n// Main CodeBlock component\nconst CodeBlock = React.forwardRef<HTMLDivElement, CodeBlockProps>(\n  (\n    {\n      code,\n      language = \"typescript\",\n      title,\n      showLineNumbers = true,\n      highlightLines = [],\n      addedLines = [],\n      removedLines = [],\n      variant = \"default\",\n      animation = \"fadeIn\",\n      animationDelay = 0,\n      className,\n      copyable = true,\n      downloadable = false,\n      downloadFileName,\n      maxHeight,\n      theme = \"oneDark\",\n      wrapLongLines = false,\n      showLanguage = true,\n      collapsible = false,\n      defaultCollapsed = false,\n      startingLineNumber = 1,\n      caption,\n    },\n    ref,\n  ) => {\n    const [isCollapsed, setIsCollapsed] = React.useState(defaultCollapsed);\n    const [isExpanded, setIsExpanded] = React.useState(false);\n    const [wordWrap, setWordWrap] = React.useState(wrapLongLines);\n    const trimmedCode = code.trim();\n    const selectedTheme = themeMap[theme] || themes.oneDark;\n\n    const variantStyles: Record<CodeBlockVariant, string> = {\n      default: \"bg-card border border-border shadow-sm\",\n      terminal: \"bg-[#1a1b26] border border-border shadow-lg\",\n      minimal: \"bg-muted/50\",\n      gradient:\n        \"bg-gradient-to-br from-card via-card to-primary/5 border border-border shadow-md\",\n      glass: \"bg-card/80 backdrop-blur-xl border border-border/50 shadow-xl\",\n    };\n\n    const headerStyles: Record<CodeBlockVariant, string> = {\n      default: \"border-b border-border bg-muted/50\",\n      terminal: \"border-b border-border bg-[#16161e]\",\n      minimal: \"border-b border-border/50\",\n      gradient: \"border-b border-border bg-muted/30\",\n      glass: \"border-b border-border/50 bg-muted/30 backdrop-blur-sm\",\n    };\n\n    const containerAnimation = {\n      fadeIn: {\n        initial: { opacity: 0, y: 20 },\n        animate: { opacity: 1, y: 0 },\n        transition: { duration: 0.4, delay: animationDelay },\n      },\n      slideIn: {\n        initial: { opacity: 0, x: -20 },\n        animate: { opacity: 1, x: 0 },\n        transition: { duration: 0.4, delay: animationDelay },\n      },\n      highlight: {\n        initial: { opacity: 0, scale: 0.98 },\n        animate: { opacity: 1, scale: 1 },\n        transition: { duration: 0.3, delay: animationDelay },\n      },\n      none: {\n        initial: {},\n        animate: {},\n        transition: {},\n      },\n      typewriter: {\n        initial: { opacity: 0 },\n        animate: { opacity: 1 },\n        transition: { duration: 0.2 },\n      },\n    };\n\n    const currentAnimation =\n      containerAnimation[animation] || containerAnimation.fadeIn;\n\n    return (\n      <motion.div\n        ref={ref}\n        className={cn(\n          \"overflow-hidden rounded-lg\",\n          variantStyles[variant],\n          isExpanded && \"fixed inset-4 z-50\",\n          className,\n        )}\n        initial={currentAnimation.initial}\n        animate={currentAnimation.animate}\n        transition={currentAnimation.transition}\n      >\n        {/* Header */}\n        <div\n          className={cn(\n            \"flex items-center justify-between px-4 py-2\",\n            headerStyles[variant],\n          )}\n        >\n          <div className=\"flex items-center gap-3\">\n            {/* Window controls */}\n            <div className=\"flex gap-1.5\">\n              <div className=\"h-3 w-3 rounded-full bg-red-500/80 transition-colors hover:bg-red-500\" />\n              <div className=\"h-3 w-3 rounded-full bg-yellow-500/80 transition-colors hover:bg-yellow-500\" />\n              <div className=\"h-3 w-3 rounded-full bg-green-500/80 transition-colors hover:bg-green-500\" />\n            </div>\n\n            {/* Title or language */}\n            <div className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n              {variant === \"terminal\" ? (\n                <Terminal className=\"h-4 w-4\" />\n              ) : (\n                <FileCode className=\"h-4 w-4\" />\n              )}\n              <span className=\"font-medium\">\n                {title || (showLanguage && getLanguageDisplayName(language))}\n              </span>\n            </div>\n          </div>\n\n          {/* Action buttons */}\n          <div className=\"flex items-center gap-1\">\n            {/* Word wrap toggle */}\n            <motion.button\n              onClick={() => setWordWrap(!wordWrap)}\n              className={cn(\n                \"rounded-md p-2 transition-colors hover:bg-muted\",\n                wordWrap\n                  ? \"text-primary\"\n                  : \"text-muted-foreground hover:text-foreground\",\n              )}\n              whileHover={{ scale: 1.05 }}\n              whileTap={{ scale: 0.95 }}\n              aria-label=\"Toggle word wrap\"\n              title=\"Toggle word wrap\"\n            >\n              <WrapText className=\"h-4 w-4\" />\n            </motion.button>\n\n            {/* Expand toggle */}\n            <motion.button\n              onClick={() => setIsExpanded(!isExpanded)}\n              className=\"rounded-md p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n              whileHover={{ scale: 1.05 }}\n              whileTap={{ scale: 0.95 }}\n              aria-label={isExpanded ? \"Minimize\" : \"Maximize\"}\n              title={isExpanded ? \"Minimize\" : \"Maximize\"}\n            >\n              {isExpanded ? (\n                <Minimize2 className=\"h-4 w-4\" />\n              ) : (\n                <Maximize2 className=\"h-4 w-4\" />\n              )}\n            </motion.button>\n\n            {/* Download button */}\n            {downloadable && (\n              <DownloadButton\n                code={trimmedCode}\n                fileName={downloadFileName}\n                language={language}\n              />\n            )}\n\n            {/* Copy button */}\n            {copyable && <CopyButton code={trimmedCode} />}\n\n            {/* Collapse toggle */}\n            {collapsible && (\n              <motion.button\n                onClick={() => setIsCollapsed(!isCollapsed)}\n                className=\"rounded-md px-2 py-1 text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground\"\n                whileHover={{ scale: 1.02 }}\n                whileTap={{ scale: 0.98 }}\n              >\n                {isCollapsed ? \"Expand\" : \"Collapse\"}\n              </motion.button>\n            )}\n          </div>\n        </div>\n\n        {/* Code content */}\n        <AnimatePresence>\n          {!isCollapsed && (\n            <motion.div\n              initial={{ height: 0, opacity: 0 }}\n              animate={{ height: \"auto\", opacity: 1 }}\n              exit={{ height: 0, opacity: 0 }}\n              transition={{ duration: 0.2 }}\n              className={cn(\n                \"overflow-auto p-4\",\n                wordWrap && \"whitespace-pre-wrap break-words\",\n              )}\n              style={maxHeight && !isExpanded ? { maxHeight } : undefined}\n            >\n              {animation === \"typewriter\" ? (\n                <TypewriterCode\n                  code={trimmedCode}\n                  language={language as Language}\n                  showLineNumbers={showLineNumbers}\n                  highlightLines={highlightLines}\n                  startingLineNumber={startingLineNumber}\n                  theme={selectedTheme}\n                />\n              ) : (\n                <Highlight\n                  theme={selectedTheme}\n                  code={trimmedCode}\n                  language={language as Language}\n                >\n                  {({\n                    className: preClassName,\n                    style,\n                    tokens,\n                    getLineProps,\n                    getTokenProps,\n                  }) => (\n                    <pre\n                      className={cn(\n                        preClassName,\n                        \"!bg-transparent font-mono text-sm leading-relaxed\",\n                      )}\n                      style={{ ...style, background: \"transparent\" }}\n                    >\n                      {tokens.map((line, i) => {\n                        const lineNumber = i + startingLineNumber;\n                        const isHighlighted =\n                          highlightLines.includes(lineNumber);\n                        const isAdded = addedLines.includes(lineNumber);\n                        const isRemoved = removedLines.includes(lineNumber);\n\n                        return (\n                          <motion.div\n                            key={i}\n                            {...getLineProps({ line })}\n                            className={cn(\n                              \"flex\",\n                              isHighlighted &&\n                                \"-mx-4 border-primary border-l-2 bg-primary/10 px-4\",\n                              isAdded &&\n                                \"-mx-4 border-green-500 border-l-2 bg-green-500/10 px-4\",\n                              isRemoved &&\n                                \"-mx-4 border-red-500 border-l-2 bg-red-500/10 px-4 line-through opacity-60\",\n                            )}\n                            initial={\n                              animation === \"slideIn\"\n                                ? { opacity: 0, x: -10 }\n                                : animation === \"highlight\"\n                                  ? {\n                                      backgroundColor:\n                                        \"hsl(var(--primary) / 0.2)\",\n                                    }\n                                  : {}\n                            }\n                            animate={\n                              animation === \"slideIn\"\n                                ? { opacity: 1, x: 0 }\n                                : animation === \"highlight\"\n                                  ? { backgroundColor: \"transparent\" }\n                                  : {}\n                            }\n                            transition={{\n                              duration: 0.3,\n                              delay: animationDelay + i * 0.03,\n                            }}\n                          >\n                            {showLineNumbers && (\n                              <span className=\"mr-4 inline-block w-8 shrink-0 select-none text-right text-muted-foreground/50\">\n                                {isAdded && (\n                                  <span className=\"mr-1 text-green-500\">+</span>\n                                )}\n                                {isRemoved && (\n                                  <span className=\"mr-1 text-red-500\">-</span>\n                                )}\n                                {lineNumber}\n                              </span>\n                            )}\n                            <span\n                              className={cn(\"flex-1\", wordWrap && \"break-all\")}\n                            >\n                              {line.map((token, key) => (\n                                <span key={key} {...getTokenProps({ token })} />\n                              ))}\n                            </span>\n                          </motion.div>\n                        );\n                      })}\n                    </pre>\n                  )}\n                </Highlight>\n              )}\n            </motion.div>\n          )}\n        </AnimatePresence>\n\n        {/* Caption */}\n        {caption && (\n          <div className=\"border-border border-t px-4 py-2 text-muted-foreground text-xs\">\n            {caption}\n          </div>\n        )}\n      </motion.div>\n    );\n  },\n);\n\nCodeBlock.displayName = \"CodeBlock\";\n\n// Inline code component\ninterface InlineCodeProps {\n  children: string;\n  className?: string;\n  variant?: \"default\" | \"primary\" | \"success\" | \"warning\" | \"error\";\n}\n\nconst InlineCode = React.forwardRef<HTMLSpanElement, InlineCodeProps>(\n  ({ children, className, variant = \"default\" }, ref) => {\n    const variantStyles: Record<string, string> = {\n      default: \"bg-muted text-foreground\",\n      primary: \"bg-primary/10 text-primary\",\n      success: \"bg-green-500/10 text-green-600 dark:text-green-400\",\n      warning: \"bg-yellow-500/10 text-yellow-600 dark:text-yellow-400\",\n      error: \"bg-red-500/10 text-red-600 dark:text-red-400\",\n    };\n\n    return (\n      <code\n        ref={ref}\n        className={cn(\n          \"rounded-md px-1.5 py-0.5 font-mono text-sm\",\n          variantStyles[variant],\n          className,\n        )}\n      >\n        {children}\n      </code>\n    );\n  },\n);\n\nInlineCode.displayName = \"InlineCode\";\n\n// Code comparison component\ninterface CodeCompareProps {\n  before: string;\n  after: string;\n  language?: string;\n  beforeTitle?: string;\n  afterTitle?: string;\n  className?: string;\n  theme?: ThemeType;\n  showDiff?: boolean;\n}\n\nconst CodeCompare = React.forwardRef<HTMLDivElement, CodeCompareProps>(\n  (\n    {\n      before,\n      after,\n      language = \"typescript\",\n      beforeTitle = \"Before\",\n      afterTitle = \"After\",\n      className,\n      theme = \"oneDark\",\n      showDiff = false,\n    },\n    ref,\n  ) => {\n    // Simple diff calculation for line additions/removals\n    const beforeLines = before.trim().split(\"\\n\");\n    const afterLines = after.trim().split(\"\\n\");\n\n    const removedLines = showDiff\n      ? beforeLines\n          .map((_, i) => i + 1)\n          .filter(\n            (_, i) => beforeLines[i] && !afterLines.includes(beforeLines[i]),\n          )\n      : [];\n    const addedLines = showDiff\n      ? afterLines\n          .map((_, i) => i + 1)\n          .filter(\n            (_, i) => afterLines[i] && !beforeLines.includes(afterLines[i]),\n          )\n      : [];\n\n    return (\n      <div ref={ref} className={cn(\"grid gap-4 md:grid-cols-2\", className)}>\n        <CodeBlock\n          code={before}\n          language={language}\n          title={beforeTitle}\n          variant=\"default\"\n          animation=\"slideIn\"\n          theme={theme}\n          removedLines={removedLines}\n        />\n        <CodeBlock\n          code={after}\n          language={language}\n          title={afterTitle}\n          variant=\"gradient\"\n          animation=\"slideIn\"\n          animationDelay={0.2}\n          theme={theme}\n          addedLines={addedLines}\n        />\n      </div>\n    );\n  },\n);\n\nCodeCompare.displayName = \"CodeCompare\";\n\n// Animated code tabs\ninterface CodeTabsProps {\n  tabs: Array<{\n    label: string;\n    code: string;\n    language?: string;\n    icon?: React.ReactNode;\n  }>;\n  className?: string;\n  theme?: ThemeType;\n  defaultTab?: number;\n}\n\nconst CodeTabs = React.forwardRef<HTMLDivElement, CodeTabsProps>(\n  ({ tabs, className, theme = \"oneDark\", defaultTab = 0 }, ref) => {\n    const [activeTab, setActiveTab] = React.useState(defaultTab);\n\n    return (\n      <div\n        ref={ref}\n        className={cn(\n          \"overflow-hidden rounded-lg border border-border bg-card shadow-sm\",\n          className,\n        )}\n      >\n        {/* Tab headers */}\n        <div className=\"flex overflow-x-auto border-border border-b bg-muted/50\">\n          {tabs.map((tab, index) => (\n            <motion.button\n              key={index}\n              onClick={() => setActiveTab(index)}\n              className={cn(\n                \"flex items-center gap-2 whitespace-nowrap px-4 py-2.5 font-medium text-sm transition-colors\",\n                activeTab === index\n                  ? \"border-primary border-b-2 bg-background/50 text-primary\"\n                  : \"text-muted-foreground hover:bg-muted/50 hover:text-foreground\",\n              )}\n              whileHover={{\n                backgroundColor:\n                  activeTab === index ? undefined : \"hsl(var(--muted) / 0.5)\",\n              }}\n              whileTap={{ scale: 0.98 }}\n            >\n              {tab.icon}\n              {tab.label}\n            </motion.button>\n          ))}\n        </div>\n\n        {/* Tab content */}\n        <AnimatePresence mode=\"wait\">\n          <motion.div\n            key={activeTab}\n            initial={{ opacity: 0, y: 10 }}\n            animate={{ opacity: 1, y: 0 }}\n            exit={{ opacity: 0, y: -10 }}\n            transition={{ duration: 0.2 }}\n          >\n            <CodeBlock\n              code={tabs[activeTab]?.code || \"\"}\n              language={tabs[activeTab]?.language || \"typescript\"}\n              showLineNumbers={true}\n              variant=\"minimal\"\n              animation=\"none\"\n              copyable={true}\n              className=\"rounded-none border-0\"\n              theme={theme}\n            />\n          </motion.div>\n        </AnimatePresence>\n      </div>\n    );\n  },\n);\n\nCodeTabs.displayName = \"CodeTabs\";\n\n// Terminal/Command component\ninterface TerminalBlockProps {\n  commands: Array<{\n    command: string;\n    output?: string;\n  }>;\n  title?: string;\n  className?: string;\n  animated?: boolean;\n}\n\nconst TerminalBlock = React.forwardRef<HTMLDivElement, TerminalBlockProps>(\n  ({ commands, title = \"Terminal\", className, animated = true }, ref) => {\n    return (\n      <motion.div\n        ref={ref}\n        className={cn(\n          \"overflow-hidden rounded-lg border border-border bg-[#1a1b26] shadow-lg\",\n          className,\n        )}\n        initial={animated ? { opacity: 0, y: 20 } : {}}\n        animate={animated ? { opacity: 1, y: 0 } : {}}\n        transition={{ duration: 0.4 }}\n      >\n        {/* Header */}\n        <div className=\"flex items-center gap-3 border-border border-b bg-[#16161e] px-4 py-2\">\n          <div className=\"flex gap-1.5\">\n            <div className=\"h-3 w-3 rounded-full bg-red-500/80\" />\n            <div className=\"h-3 w-3 rounded-full bg-yellow-500/80\" />\n            <div className=\"h-3 w-3 rounded-full bg-green-500/80\" />\n          </div>\n          <div className=\"flex items-center gap-2 text-muted-foreground text-sm\">\n            <Terminal className=\"h-4 w-4\" />\n            <span>{title}</span>\n          </div>\n        </div>\n\n        {/* Commands */}\n        <div className=\"p-4 font-mono text-sm\">\n          {commands.map((item, index) => (\n            <motion.div\n              key={index}\n              initial={animated ? { opacity: 0, x: -10 } : {}}\n              animate={animated ? { opacity: 1, x: 0 } : {}}\n              transition={{ delay: index * 0.1 }}\n              className=\"mb-2 last:mb-0\"\n            >\n              <div className=\"flex items-center gap-2\">\n                <span className=\"text-green-400\">$</span>\n                <span className=\"text-foreground\">{item.command}</span>\n              </div>\n              {item.output && (\n                <div className=\"mt-1 whitespace-pre-wrap pl-4 text-muted-foreground\">\n                  {item.output}\n                </div>\n              )}\n            </motion.div>\n          ))}\n        </div>\n      </motion.div>\n    );\n  },\n);\n\nTerminalBlock.displayName = \"TerminalBlock\";\n\nexport {\n  CodeBlock,\n  CodeCompare,\n  CodeTabs,\n  InlineCode,\n  supportedLanguages,\n  TerminalBlock,\n  themeMap,\n};\nexport type {\n  AnimationType,\n  CodeBlockProps,\n  CodeBlockVariant,\n  CodeCompareProps,\n  CodeTabsProps,\n  InlineCodeProps,\n  TerminalBlockProps,\n  ThemeType,\n};\n",
      "type": "registry:ui",
      "target": ""
    }
  ],
  "type": "registry:ui"
}