import React, { useState, useRef, useEffect, useCallback } from 'react'; import type { Block } from '../../types'; import { copyTextToClipboard } from '../../utils/clipboard'; import { applyHighlight, codeBlockClassName, codeBlockKeepsLayout } from '../../utils/codeHighlight'; import { useFenceTheme } from '../../hooks/useFenceTheme'; interface CodeBlockProps { block: Block; onHover?: (element: HTMLElement) => void; onLeave?: () => void; isHovered: boolean; } export const CodeBlock: React.FC = ({ block, onHover, onLeave }) => { const [copied, setCopied] = useState(false); const containerRef = useRef(null); const codeRef = useRef(null); const fenceTheme = useFenceTheme(); // Highlight on mount, on content/language change, and whenever the palette // changes. Language-less fences stay plain text (#1212) — nothing is guessed. useEffect(() => { if (codeRef.current) { codeRef.current.className = codeBlockClassName(block.language); applyHighlight(codeRef.current, block.content, block.language, fenceTheme); } }, [block.content, block.language, fenceTheme]); const handleCopy = useCallback(async () => { if (await copyTextToClipboard(block.content)) { setCopied(true); setTimeout(() => setCopied(false), 2000); } else { console.error('Failed to copy'); } }, [block.content]); const handleMouseEnter = () => { if (containerRef.current && onHover) { onHover(containerRef.current); } }; // Build className for code element const codeClassName = codeBlockClassName(block.language); return (
        {block.content}
      
); };