import React, { useEffect, useRef, useCallback, useMemo } from 'react'; import ReactJson from 'react-json-view-ssr'; import CodeMirror from '@uiw/react-codemirror'; import { python } from '@codemirror/lang-python'; import { vscodeDark } from '@uiw/codemirror-theme-vscode'; const HighlightedValueInSearch = ({ value, searchTerm, theme }) => { const containerRef = useRef(null); const preRef = useRef(null); const scrollTimeoutRef = useRef(null); const isJson = useCallback((str) => { if (typeof str === 'object' && str !== null) return true; if (typeof str !== 'string') return false; const trimmed = str.trim(); if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return false; try { JSON.parse(trimmed); return true; } catch { return false; } }, []); const getJsonValue = useCallback((val) => { try { return typeof val === 'object' ? val : JSON.parse(val.trim()); } catch { return null; } }, []); const highlightInJson = useCallback((jsonStr, term) => { if (!term) return jsonStr; try { const escapedTerm = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); const regex = new RegExp(`(${escapedTerm})`, 'gi'); const highlightId = `highlight-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; return jsonStr.replace(regex, `$1`); } catch { return jsonStr; } }, []); const isPythonCode = useCallback((str) => { if (typeof str !== 'string') return false; const pythonPatterns = [ 'import ', 'from ', 'def ', 'class ', 'if __name__', 'print(', 'return ', 'elif ', 'except:', 'try:', 'with ', 'lambda ', 'yield ', 'async def', 'await ' ]; const trimmed = str.trim(); return pythonPatterns.some(pattern => trimmed.includes(pattern)) && (trimmed.includes('def') || trimmed.includes('class')); }, []); useEffect(() => { if (!searchTerm || !containerRef.current || !preRef.current) return; if (scrollTimeoutRef.current) { clearTimeout(scrollTimeoutRef.current); } scrollTimeoutRef.current = setTimeout(() => { try { const container = containerRef.current; const firstHighlight = preRef.current?.querySelector('mark'); if (firstHighlight && container) { const containerRect = container.getBoundingClientRect(); const highlightRect = firstHighlight.getBoundingClientRect(); const scrollTop = highlightRect.top - containerRect.top + container.scrollTop - (container.clientHeight / 2); container.scrollTo({ top: Math.max(0, scrollTop), behavior: 'smooth' }); } } catch (error) { console.warn('Auto-scroll failed:', error); } }, 100); return () => { if (scrollTimeoutRef.current) { clearTimeout(scrollTimeoutRef.current); } }; }, [searchTerm, value]); const RegularText = useCallback(({ value: textValue, searchTerm: term }) => { if (!textValue) return No content; const stringValue = String(textValue); // Check if it's Python code if (isPythonCode(stringValue)) { const lines = stringValue.split('\n'); const isNodeView = lines[0]?.startsWith('Node:'); const nodeTitle = isNodeView ? lines[0] : null; const codeContent = isNodeView ? lines.slice(1).join('\n') : stringValue; return (