import { useEffect, useRef, useState } from 'react'; import type { SearchAddon } from '@xterm/addon-search'; import { ChevronDown, ChevronUp, X } from 'lucide-react'; import { type TermTheme } from './theme'; // ============================================================ // SearchBar — kept from v1.10.4 // ============================================================ interface SearchBarProps { searchRef: React.MutableRefObject; theme: TermTheme; onClose: () => void; } export function SearchBar({ searchRef, theme, onClose }: SearchBarProps) { const [q, setQ] = useState(''); const [counts, setCounts] = useState<{ idx: number; total: number }>({ idx: -1, total: 0 }); const inputRef = useRef(null); useEffect(() => { inputRef.current?.focus(); }, []); useEffect(() => { const addon = searchRef.current; if (!addon) return; const sub = addon.onDidChangeResults(({ resultIndex, resultCount }) => { setCounts({ idx: resultIndex, total: resultCount }); }); return () => sub.dispose(); }, [searchRef]); useEffect(() => { const addon = searchRef.current; if (!addon) return; if (q.length === 0) { addon.clearDecorations?.(); setCounts({ idx: -1, total: 0 }); return; } addon.findNext(q, { incremental: true, decorations: { matchBackground: theme.selectionBackground, matchOverviewRuler: theme.cursor, activeMatchBackground: theme.cursor, activeMatchColorOverviewRuler: theme.cursor, }, }); }, [q, searchRef, theme]); function findNext(): void { if (!q) return; searchRef.current?.findNext(q); } function findPrev(): void { if (!q) return; searchRef.current?.findPrevious(q); } function onKey(ev: React.KeyboardEvent): void { if (ev.key === 'Escape') { ev.preventDefault(); onClose(); return; } if (ev.key === 'Enter') { ev.preventDefault(); if (ev.shiftKey) findPrev(); else findNext(); } } return (
setQ(ev.target.value)} onKeyDown={onKey} placeholder="Search…" style={{ background: 'transparent', border: 0, outline: 'none', color: '#d6deeb', padding: '8px 8px', fontSize: 13, width: 160, minHeight: 36, }} /> {q.length > 0 && ( {counts.total === 0 ? 'No match' : counts.idx === -1 ? `${counts.total}+` : `${counts.idx + 1} of ${counts.total}`} )}
); } const iconBtnStyle: React.CSSProperties = { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 44, height: 44, background: 'transparent', border: 0, color: '#d6deeb', cursor: 'pointer', borderRadius: 6, };