-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathApp.tsx
107 lines (97 loc) · 2.61 KB
/
App.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
import React, { useCallback, useMemo, useState } from 'react'
import ReactCurse, { Input, Text, List, ListPos, useExit, useInput, useSize, useClipboard } from 'react-curse'
import icons from './icons.json'
const App = () => {
const { height } = useSize()
const [, setClipboard] = useClipboard()
const [value, setValue] = useState('')
const result = useMemo(() => {
const re = new RegExp(
value
.replace(/[^\da-z-]/gi, '')
.split('')
.join('.*')
)
const resIn = Object.keys(icons).filter(i => i.includes(value))
const resRe = Object.keys(icons).filter(i => !resIn.includes(i) && re.test(i))
const res = [...resIn, ...resRe]
return res.map(i => [String.fromCharCode(parseInt(icons[i], 16)), i])
}, [value, height])
const onSubmit = useCallback(
(pos: ListPos) => {
if (result.length === 0) return
setClipboard(`${result[pos.y][0]} `)
useExit()
},
[result]
)
useInput(
(input: string) => {
if (input === '\x1b') useExit()
},
[result]
)
const highlight = (str: string, q: string) => {
let index = -1
const indexes = q
.replace(/[^\da-z-]/gi, '')
.split('')
.map(letter => {
return (index = str.split('').findIndex((i, j) => {
return i === letter && j > index
}))
}, -1)
if (indexes.includes(-1)) return null
const res =
'x1b[0m' +
str
.split('')
.map((i, index) => {
return indexes.includes(index) ? `x1b[Greenm${i}x1b[0m` : i
})
.join('')
return (
<Text>
{res.split('x1b[').map((i, key) => {
const [color] = i.split('m', 2)
return (
<Text key={key} color={color !== '0' ? color : undefined}>
{i.substring(color.length + 1)}
</Text>
)
})}
</Text>
)
}
return (
<>
<Text block>
<Text>
<Text bold dim>
Search:{' '}
</Text>
<Input onChange={setValue} color="Green" />
<Text dim> ({result.length})</Text>
</Text>
</Text>
<List
data={result}
renderItem={({ item: [icon, name], selected, pass: value }) => (
<>
{selected && <Text color="Yellow"> </Text>}
<Text x={2}>{icon + ' '}</Text>
<Text dim>
<Text color="Cyan">nf-</Text>
{highlight(name, value)}
</Text>
</>
)}
height={height - 1}
vi={false}
pass={value}
onSubmit={onSubmit}
/>
</>
)
}
ReactCurse.render(<App />)