-
Notifications
You must be signed in to change notification settings - Fork 19
/
Search.tsx
127 lines (119 loc) · 3.26 KB
/
Search.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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import React, { useState } from 'react';
import classNames from 'classnames/bind';
import { useMenus, useConfig, Link } from 'docz';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import styles from './Search.css';
const cx = classNames.bind(styles);
const highlightQuery = (query: string, text: string, color: string): string => {
const idx = text.toLowerCase().indexOf(query.toLowerCase());
if (idx < 0) {
if (query.length == 1) {
return text;
}
// Try using the first query character to search and highlight
const firstChar = query[0];
return highlightQuery(firstChar, text, color);
}
return idx < 0
? text
: text.substring(0, idx) +
`<span style="color: ${color}">${text.substring(
idx,
idx + query.length,
)}</span>` +
text.substring(idx + query.length);
};
const Search = () => {
const [query, setQuery] = useState('');
const menus = useMenus({ query });
const {
themeConfig: { colors, fonts },
} = useConfig();
const renderResult = () => {
if (!query || !menus) {
return null;
}
const result = menus.length
? menus.map(menu => {
const submenu = menu.menu;
if (!submenu) {
return (
<li key={menu.id}>
<Link
to={menu.route}
className={cx('item')}
dangerouslySetInnerHTML={{
__html: highlightQuery(query, menu.name, colors.highlight),
}}
/>
</li>
);
}
return (
<li key={menu.id}>
<span
className={cx('item', 'item--title')}
dangerouslySetInnerHTML={{
__html: highlightQuery(query, menu.name, colors.highlight),
}}
/>
<ul className={cx('submenu')}>
{submenu.map(menuItem => (
<li key={menuItem.id}>
<Link
to={menuItem.route}
className={cx('item', 'item--sub')}
dangerouslySetInnerHTML={{
__html: highlightQuery(
query,
menuItem.name,
colors.highlight,
),
}}
/>
</li>
))}
</ul>
</li>
);
})
: 'No docs found :(';
return (
<ul
className={cx('result')}
style={{
background: `linear-gradient(to right, ${colors.primary}, ${colors.secondary})`,
color: colors.whiteLight,
}}
>
{result}
</ul>
);
};
return (
<div
className={cx('container')}
style={{
fontFamily: fonts.body,
}}
>
<FontAwesomeIcon
icon="search"
style={{
color: colors.primary,
}}
/>
<input
type="text"
placeholder="Search docs..."
className={cx('input')}
value={query}
onChange={e => {
setQuery(e.currentTarget.value);
}}
/>
{renderResult()}
</div>
);
};
export default Search;