"use client" import { useEffect, useRef, useState, useCallback } from "react"; import { debounce, highlightHTML } from "@/lib/utils"; interface CodeEditorProps { code: string; isLoading?: boolean; onCodeChange?: (code: string) => void; } export function CodeEditor({ code, isLoading = false, onCodeChange }: CodeEditorProps) { const containerRef = useRef(null); const textareaRef = useRef(null); const highlightRef = useRef(null); const [isAtBottom, setIsAtBottom] = useState(true); const [localCode, setLocalCode] = useState(code); const debouncedSave = useCallback( debounce((newCode: string) => { if (onCodeChange) { onCodeChange(newCode); } }, 1000), [onCodeChange] ); useEffect(() => { setLocalCode(code); }, [code]); const handleCodeChange = (e: React.ChangeEvent) => { const newCode = e.target.value; setLocalCode(newCode); debouncedSave(newCode); }; // Sync scroll between textarea and highlight const handleScroll = (e: React.UIEvent) => { if (highlightRef.current && textareaRef.current) { highlightRef.current.scrollTop = textareaRef.current.scrollTop; highlightRef.current.scrollLeft = textareaRef.current.scrollLeft; } const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; const isNearBottom = scrollHeight - scrollTop - clientHeight < 30; setIsAtBottom(isNearBottom); }; useEffect(() => { if (isAtBottom && textareaRef.current && document.activeElement !== textareaRef.current) { textareaRef.current.scrollTop = textareaRef.current.scrollHeight; if (highlightRef.current) { highlightRef.current.scrollTop = highlightRef.current.scrollHeight; } } }, [localCode, isLoading, isAtBottom]); // Handle tab key for indentation const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Tab') { e.preventDefault(); const textarea = e.currentTarget; const start = textarea.selectionStart; const end = textarea.selectionEnd; const newValue = localCode.substring(0, start) + ' ' + localCode.substring(end); setLocalCode(newValue); debouncedSave(newValue); setTimeout(() => { textarea.selectionStart = textarea.selectionEnd = start + 2; }, 0); } }; const highlightedCode = highlightHTML(localCode); return (
{/* Syntax highlighted background - always visible */}
{/* Editable textarea - always transparent */}