TextHighlighter.tsx43 lines · main
1'use client'
2
3import {
4 Children,
5 type DetailedHTMLProps,
6 type HTMLAttributes,
7 type PropsWithChildren,
8} from 'react'
9
10import { useQuery } from './hooks/queryHooks'
11
12interface TextHighlighterBaseProps extends PropsWithChildren<
13 DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>
14> {
15 query: string
16 text?: string
17}
18
19function TextHighlighterBase({ children, text, query, ...props }: TextHighlighterBaseProps) {
20 const child = text ?? Children.toArray(children)[0]
21 if (typeof child !== 'string') return child
22
23 const idx = child.toLowerCase().indexOf(query.toLowerCase())
24 if (idx === -1) {
25 return <span {...props}>{child}</span>
26 }
27
28 return (
29 <span {...props}>
30 {child.substring(0, idx)}
31 <span className="text-foreground">{child.substring(idx, idx + query.length)}</span>
32 {child.substring(idx + query.length)}
33 </span>
34 )
35}
36
37function TextHighlighter(props: Omit<TextHighlighterBaseProps, 'query'>) {
38 const query = useQuery()
39
40 return <TextHighlighterBase query={query} {...props} />
41}
42
43export { TextHighlighter, TextHighlighterBase }