blob: ca3bdab1461d6d4b5d56cfea3db2d7db17ee80dd (
plain)
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
128
129
130
|
import * as Uebersicht from "uebersicht";
import * as Icons from "../icons/icons.jsx";
import { SuspenseIcon } from "../icons/icon.jsx";
const { React } = Uebersicht;
/**
* IconPicker component allows users to select an icon from a list of available icons.
*
* @param {Object} props - The component props.
* @param {Function} props.callback - The callback function to be called when an icon is selected.
* @param {number} props.index - The index of the icon picker.
* @param {string} props.selectedIcon - The initially selected icon.
* @returns {JSX.Element} The IconPicker component.
*/
export default function IconPicker({ callback, index, selectedIcon }) {
// State to manage the open/close state of the icon picker dropdown
const [open, setOpen] = React.useState(false);
// State to manage the currently selected icon
const [selected, setSelected] = React.useState(selectedIcon);
// State to manage the search term for filtering icons
const [searchTerm, setSearchTerm] = React.useState("");
// Get the selected icon component
const Icon = Icons[selected];
// Get the list of all available icon keys
const keys = Object.keys(Icons);
// Filter icons based on search term
const filteredKeys = React.useMemo(() => {
if (!searchTerm.trim()) {
return keys;
}
return keys.filter((key) =>
key.toLowerCase().includes(searchTerm.toLowerCase()),
);
}, [keys, searchTerm]);
/**
* Toggles the open state of the icon picker dropdown.
*/
const onClick = () => setOpen(!open);
/**
* Handles search input changes.
*
* @param {React.ChangeEvent<HTMLInputElement>} e - The input change event.
*/
const onSearchChange = (e) => {
setSearchTerm(e.target.value);
};
/**
* Clears the search term.
*/
const clearSearch = () => {
setSearchTerm("");
};
return (
<div className="icon-picker">
<button className="icon-picker__button" onClick={onClick}>
<SuspenseIcon>
<Icon />
</SuspenseIcon>
</button>
{open && (
<div className="icon-picker__dropdown">
<div
className="icon-picker__search"
onClick={(e) => e.stopPropagation()}
>
<button
className="icon-picker__back"
onClick={() => setOpen(false)}
type="button"
>
<Icons.ChevronLeft />
Back
</button>
<input
type="text"
placeholder="Search icons..."
value={searchTerm}
onChange={onSearchChange}
className="icon-picker__search-input"
autoFocus
/>
{searchTerm && (
<button
className="icon-picker__search-clear"
onClick={clearSearch}
type="button"
>
✕
</button>
)}
</div>
<div className="icon-picker__icons" onClick={() => setOpen(false)}>
{filteredKeys.length > 0 ? (
filteredKeys.map((key) => {
/**
* Handles the icon selection.
*
* @param {React.MouseEvent} e - The click event.
*/
const onClick = (e) => {
e.stopPropagation();
setSelected(key);
callback?.(index, "icon", key);
setOpen(false);
};
const Icon = Icons[key];
return (
<button key={key} onClick={onClick} title={key}>
<Icon />
</button>
);
})
) : (
<div className="icon-picker__no-results">
No icons found for "{searchTerm}"
</div>
)}
</div>
</div>
)}
</div>
);
}
|