1
+ import { type ReactNode , useMemo , useState } from "react" ;
2
+ import uFuzzy from "ufuzzy" ;
1
3
import { CopyableValue } from "components/CopyableValue/CopyableValue" ;
2
4
import { Margins } from "components/Margins/Margins" ;
3
5
import { Stack } from "components/Stack/Stack" ;
4
6
import { colors } from "theme/colors" ;
5
7
import icons from "theme/icons.json" ;
6
8
9
+ const iconsWithoutSuffix = icons . map ( ( icon ) => icon . split ( "." ) [ 0 ] ) ;
10
+ const fuzzyFinder = new uFuzzy ( {
11
+ intraMode : 1 ,
12
+ intraIns : 1 ,
13
+ intraSub : 1 ,
14
+ intraTrn : 1 ,
15
+ intraDel : 1 ,
16
+ } ) ;
17
+
7
18
export default function ( ) {
19
+ const [ searchText , setSearchText ] = useState ( "" ) ;
20
+
21
+ const searchedIcons = useMemo ( ( ) => {
22
+ if ( ! searchText . trim ( ) ) {
23
+ return icons . map ( ( icon ) => ( { url : `/icon/${ icon } ` , description : icon } ) ) ;
24
+ }
25
+
26
+ const [ map , info , sorted ] = fuzzyFinder . search (
27
+ iconsWithoutSuffix ,
28
+ searchText ,
29
+ ) ;
30
+
31
+ // We hit an invalid state somehow
32
+ if ( ! map || ! info || ! sorted ) {
33
+ return [ ] ;
34
+ }
35
+
36
+ return sorted . map ( ( i ) => {
37
+ const iconName = icons [ info . idx [ i ] ] ;
38
+ const ranges = info . ranges [ i ] ;
39
+
40
+ const nodes : ReactNode [ ] = [ ] ;
41
+ let cursor = 0 ;
42
+ for ( let j = 0 ; j < ranges . length ; j += 2 ) {
43
+ nodes . push ( iconName . slice ( cursor , ranges [ j ] ) ) ;
44
+ nodes . push (
45
+ < mark key = { j + 1 } > { iconName . slice ( ranges [ j ] , ranges [ j + 1 ] ) } </ mark > ,
46
+ ) ;
47
+ cursor = ranges [ j + 1 ] ;
48
+ }
49
+ nodes . push ( iconName . slice ( cursor ) ) ;
50
+ return { url : `/icon/${ iconName } ` , description : nodes } ;
51
+ } ) ;
52
+ } , [ searchText . trim ( ) ] ) ;
53
+
8
54
return (
9
55
< Margins >
56
+ < input
57
+ type = "search"
58
+ onChange = { ( event ) => setSearchText ( event . target . value ) }
59
+ />
10
60
< Stack direction = "row" wrap = "wrap" spacing = { 1 } justifyContent = "center" >
11
- { icons . map ( ( icon ) => (
12
- < CopyableValue value = { `/ icon/ $ {icon } ` } placement = "bottom" >
61
+ { searchedIcons . map ( ( icon ) => (
62
+ < CopyableValue key = { icon . url } value = { icon . url } placement = "bottom" >
13
63
< Stack
14
64
alignItems = "center"
15
65
css = { ( theme ) => ( { margin : theme . spacing ( 1.5 ) } ) }
16
66
>
17
67
< img
18
- src = { `/ icon/ ${ icon } ` }
68
+ src = { icon . url }
19
69
css = { {
20
70
width : 64 ,
21
71
height : 64 ,
@@ -35,7 +85,7 @@ export default function () {
35
85
overflow : "hidden" ,
36
86
} }
37
87
>
38
- { icon }
88
+ { icon . description }
39
89
</ p >
40
90
</ Stack >
41
91
</ CopyableValue >
0 commit comments