CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/components/icon-select.tsx
Views: 687
1
/* Search through and select icons
2
3
See frontend/components/iconfont.cn/README.md for how to add anything from
4
the massive https://www.iconfont.cn/?lang=us
5
*/
6
7
import { Input } from "antd";
8
import { Icon, iconNames, IconName } from "./icon";
9
import { CSSProperties, useEffect, useState } from "react";
10
const { Search } = Input;
11
12
interface Props {
13
onSelect?: (name: IconName) => void;
14
onChange?: (search: string) => void;
15
defaultSearch?: string;
16
search?: string;
17
style?: CSSProperties;
18
fontSize?: string;
19
disabled?: boolean;
20
}
21
22
export default function IconSelect({
23
onSelect,
24
onChange,
25
defaultSearch,
26
search: search0,
27
style,
28
fontSize,
29
disabled,
30
}: Props) {
31
const [search, setSearch] = useState<string>(search0 ?? defaultSearch ?? "");
32
33
useEffect(() => {
34
if (search0 != null) {
35
setSearch(search0);
36
}
37
}, [search0]);
38
39
return (
40
<div style={{ fontSize: "24pt", ...style }}>
41
<Search
42
disabled={disabled}
43
placeholder="Search..."
44
value={search}
45
allowClear
46
onChange={(e) => {
47
setSearch(e.target.value);
48
onChange?.(e.target.value);
49
}}
50
style={{ maxWidth: "400px" }}
51
onPressEnter={() => {
52
// if there are any results, choose the first one
53
const search0 = search.trim().toLowerCase();
54
for (const name of iconNames) {
55
if (name.includes(search0)) {
56
setSearch(name);
57
onChange?.(name);
58
onSelect?.(name);
59
return;
60
}
61
}
62
}}
63
/>
64
<div
65
style={{
66
marginTop: "10px",
67
overflowY: "scroll",
68
border: "1px solid lightgrey",
69
}}
70
>
71
{icons(search, fontSize, (name) => {
72
setSearch(name);
73
onSelect?.(name);
74
})}
75
</div>
76
</div>
77
);
78
}
79
80
function icons(search, fontSize, onClick) {
81
search = search.trim().toLowerCase();
82
const v: JSX.Element[] = [];
83
for (const name of iconNames) {
84
if (!name.includes(search)) continue;
85
v.push(
86
<Match fontSize={fontSize} key={name} name={name} onClick={onClick} />
87
);
88
}
89
return v;
90
}
91
92
function Match({
93
name,
94
onClick,
95
fontSize = "11pt",
96
}: {
97
name: IconName;
98
onClick: (name: IconName) => void;
99
fontSize?;
100
}) {
101
return (
102
<div
103
style={{
104
display: "inline-block",
105
width: "100px",
106
cursor: "pointer",
107
whiteSpace: "nowrap",
108
overflow: "hidden",
109
textOverflow: "ellipsis",
110
textAlign: "center",
111
}}
112
onClick={() => onClick(name)}
113
>
114
<div style={{ margin: "0 10px" }}>
115
<Icon name={name} />
116
</div>
117
<div style={{ fontSize }}>{name}</div>
118
</div>
119
);
120
}
121
122