* Terminal component based on Monaco Editor with ANSI color support. * Provides a read-only code viewer with search functionality, theme support, and ANSI color rendering. * Compatible with the existing Terminal component API.
({
className,
logs,
ref,
searchValue,
}: MonacoTerminalProps & { ref?: React.RefObject<MonacoTerminalRef | null> })
| 268 | * Compatible with the existing Terminal component API. |
| 269 | */ |
| 270 | function MonacoTerminal({ |
| 271 | className, |
| 272 | logs, |
| 273 | ref, |
| 274 | searchValue, |
| 275 | }: MonacoTerminalProps & { ref?: React.RefObject<MonacoTerminalRef | null> }) { |
| 276 | const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null); |
| 277 | const monacoRef = useRef<Monaco | null>(null); |
| 278 | const { theme } = useTheme(); |
| 279 | const [isEditorReady, setIsEditorReady] = useState(false); |
| 280 | const prevLogsLengthRef = useRef<number>(0); |
| 281 | const searchWidgetRef = useRef<null | { findNext: () => void; findPrevious: () => void }>(null); |
| 282 | const decorationsCollectionRef = useRef<monaco.editor.IEditorDecorationsCollection | null>(null); |
| 283 | |
| 284 | const parsedContent = useMemo(() => parseLogsWithCache(logs), [logs]); |
| 285 | |
| 286 | const content = useMemo(() => parsedContent.map((line) => line.text).join('\n'), [parsedContent]); |
| 287 | |
| 288 | const handleEditorDidMount: OnMount = useCallback((editor, monacoInstance) => { |
| 289 | editorRef.current = editor; |
| 290 | monacoRef.current = monacoInstance; |
| 291 | setIsEditorReady(true); |
| 292 | |
| 293 | editor.updateOptions({ |
| 294 | automaticLayout: true, |
| 295 | folding: false, |
| 296 | glyphMargin: false, |
| 297 | lineDecorationsWidth: 0, |
| 298 | lineNumbers: 'on', |
| 299 | lineNumbersMinChars: 5, |
| 300 | minimap: { enabled: false }, |
| 301 | overviewRulerLanes: 0, // Disable overview ruler for better performance |
| 302 | padding: { top: 4 }, |
| 303 | readOnly: true, |
| 304 | renderLineHighlight: 'none', |
| 305 | renderWhitespace: 'none', |
| 306 | scrollbar: { |
| 307 | alwaysConsumeMouseWheel: false, |
| 308 | horizontal: 'hidden', // Hide horizontal scrollbar completely |
| 309 | useShadows: false, |
| 310 | vertical: 'visible', |
| 311 | verticalScrollbarSize: 10, |
| 312 | }, |
| 313 | scrollBeyondLastLine: false, |
| 314 | selectOnLineNumbers: false, |
| 315 | wordWrap: 'on', // Enable word wrap (simple 'on' works better than 'bounded') |
| 316 | wrappingIndent: 'same', |
| 317 | wrappingStrategy: 'simple', // Use simple strategy for better performance |
| 318 | }); |
| 319 | |
| 320 | const ansiStyleId = 'monaco-terminal-ansi-styles'; |
| 321 | |
| 322 | if (!document.getElementById(ansiStyleId)) { |
| 323 | const ansiStyleElement = document.createElement('style'); |
| 324 | |
| 325 | ansiStyleElement.id = ansiStyleId; |
| 326 | ansiStyleElement.textContent = DECORATION_STYLES; |
| 327 | document.head.appendChild(ansiStyleElement); |
nothing calls this directly
no test coverage detected