({
containerRef,
messages,
searchState,
pageId,
onMatchesChange
}: UseSearchHighlightOptions)
| 25 | * 搜索高亮 Hook |
| 26 | */ |
| 27 | export function useSearchHighlight({ |
| 28 | containerRef, |
| 29 | messages, |
| 30 | searchState, |
| 31 | pageId, |
| 32 | onMatchesChange |
| 33 | }: UseSearchHighlightOptions): UseSearchHighlightResult { |
| 34 | const rangesRef = useRef<Map<number, Range>>(new Map()) |
| 35 | |
| 36 | // 计算搜索选项 |
| 37 | const searchOptions: SearchOptions = useMemo( |
| 38 | () => ({ |
| 39 | matchCase: searchState.matchCase, |
| 40 | useRegex: searchState.useRegex, |
| 41 | matchWholeWord: searchState.matchWholeWord |
| 42 | }), |
| 43 | [searchState.matchCase, searchState.useRegex, searchState.matchWholeWord] |
| 44 | ) |
| 45 | |
| 46 | // 防抖后的查询 |
| 47 | const [debouncedQuery, setDebouncedQuery] = useState(searchState.query) |
| 48 | |
| 49 | // 防抖处理 |
| 50 | useEffect(() => { |
| 51 | const timer = setTimeout(() => { |
| 52 | setDebouncedQuery(searchState.query) |
| 53 | }, DEBOUNCE_DELAY) |
| 54 | |
| 55 | return () => clearTimeout(timer) |
| 56 | }, [searchState.query]) |
| 57 | |
| 58 | // 计算匹配结果(使用防抖后的查询) |
| 59 | const matches = useMemo(() => { |
| 60 | if (!searchState.isOpen || !debouncedQuery.trim()) { |
| 61 | return [] |
| 62 | } |
| 63 | return findAllMatches(messages, debouncedQuery, searchOptions) |
| 64 | }, [messages, searchState.isOpen, debouncedQuery, searchOptions]) |
| 65 | |
| 66 | // 通知匹配结果变化 |
| 67 | useEffect(() => { |
| 68 | onMatchesChange?.(matches) |
| 69 | }, [matches, onMatchesChange]) |
| 70 | |
| 71 | // 应用 CSS Custom Highlight - 当 matches 变化时重新创建所有 Range |
| 72 | useEffect(() => { |
| 73 | // 清除之前的高亮 |
| 74 | if ('highlights' in CSS) { |
| 75 | CSS.highlights.delete('search-highlight') |
| 76 | CSS.highlights.delete('search-current') |
| 77 | } |
| 78 | rangesRef.current.clear() |
| 79 | |
| 80 | const container = containerRef.current |
| 81 | if (!container || matches.length === 0 || !('highlights' in CSS)) { |
| 82 | return |
| 83 | } |
| 84 |
no test coverage detected