-
Notifications
You must be signed in to change notification settings - Fork 9.3k
/
highlight-text.tsx
40 lines (38 loc) · 1.05 KB
/
highlight-text.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import * as React from 'react'
interface IHighlightTextProps {
/** The text to render */
readonly text: string
/** The characters in `text` to highlight */
readonly highlight: ReadonlyArray<number>
}
export const HighlightText: React.FunctionComponent<IHighlightTextProps> = ({
text,
highlight,
}) => (
<span>
{
text
.split('')
.map((ch, i): [string, boolean] => [ch, highlight.includes(i)])
.concat([['', false]])
.reduce(
(state, [ch, matched], i, arr) => {
if (matched === state.matched && i < arr.length - 1) {
state.str += ch
} else {
const Component = state.matched ? 'mark' : 'span'
state.result.push(<Component key={i}>{state.str}</Component>)
state.str = ch
state.matched = matched
}
return state
},
{
matched: false,
str: '',
result: new Array<React.ReactElement<any>>(),
}
).result
}
</span>
)