import React, { memo } from 'react'; import { CopyButton } from '@djangocfg/ui-core/components'; import PrettyCode from '../PrettyCode'; interface CodeBlockProps { code: string; language: string; isUser: boolean; isCompact?: boolean; /** * Code surface palette. Default `'dark'` — syntax highlighting * ships its own contrast model and reads washed out on a light * surface (GitHub / ChatGPT / VSCode convention). Pass `'light'` * to opt a host into a light code surface anyway. */ codeTheme?: 'dark' | 'light'; } /** * Markdown code block. Renders directly — its own * FloatingToolbar already carries the language tag and Copy action. * * Earlier versions stacked an extra here too, which * surfaced as two copy buttons on every code fence. The fallback * branch below still ships its own button because the plain
 * has no toolbar of its own.
 *
 * Memoised: re-renders only when `code`, `language`, `isUser` or
 * `isCompact` change. `code` is the main trigger — long code blocks
 * should not re-render when parent chat scrolls.
 */
function CodeBlockRaw({ code, language, codeTheme = 'dark' }: CodeBlockProps) {
  // Chat fences are always rendered in PrettyCode's compact mode:
  // 12px font, tighter padding, line-height 1.4. A fenced block in
  // a chat bubble shouldn't outweigh two paragraphs of body text —
  // the standalone PrettyCode story keeps the larger default for
  // docs/diff viewers.
  //
  // The surface defaults to dark: syntax highlighting ships its own
  // contrast model, so a light code surface in a light-theme bubble
  // renders washed out (GitHub / ChatGPT / VSCode convention). Hosts
  // can opt into a light surface via `codeTheme="light"`.
  return (
    
); } export const CodeBlock = memo(CodeBlockRaw); /** Simple `
` fallback used when CodeBlock throws (lazy module
 *  failure, missing PrettyCode peer, etc).
 *
 *  Memoised: re-renders only when `code`, `language`, `isUser` or
 *  `isCompact` change.
 */
function CodeBlockFallbackRaw({ code, codeTheme = 'dark' }: CodeBlockProps) {
  const isDark = codeTheme === 'dark';
  // On the dark surface the copy button is always light; on a light
  // surface it follows the semantic muted token.
  const copyButtonClass =
    `absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8 ` +
    (isDark
      ? 'text-white/70 hover:text-white hover:bg-white/15'
      : 'text-muted-foreground hover:text-foreground hover:bg-muted');

  return (
    
{isDark ? ( // Fixed dark surface to match PrettyCode's default.
          {code}
        
) : (
          {code}
        
)}
); } export const CodeBlockFallback = memo(CodeBlockFallbackRaw);