import { useEffect, useRef } from "react"; import { Terminal } from "xterm"; import { FitAddon } from "xterm-addon-fit"; import "xterm/css/xterm.css"; export default function XTerm({ onData, output }) { const termRef = useRef(null); const fitAddon = new FitAddon(); useEffect(() => { const term = new Terminal({ cursorBlink: true, fontSize: 14, theme: { background: "#1e1e1e", foreground: "#ffffff", }, }); termRef.current = term; term.loadAddon(fitAddon); term.open(document.getElementById("terminal-container")); fitAddon.fit(); term.onData((data) => { // Echo user input (like real terminals) term.write(data); // When ENTER pressed, send full line to parent if (data === "\r") { const line = term._core.buffer.xtermBuffer.active.getLine( term.buffer.active.cursorY ).translateToString().trim(); onData(line); } }); return () => term.dispose(); }, []); // Print backend output into terminal useEffect(() => { if (output) { termRef.current?.writeln("\r\n" + output); } }, [output]); return (
); }