3. Multiselect
by Vitalii_N
HTML
<div id="app"></div>
CSS
.container {
width: 300px;
margin: 20px;
}
.selected-display {
padding: 5px;
height: 20px;
border: 1px solid #ccc;
cursor: pointer;
}
.dropdown {
border: 1px solid #ccc;
list-style: none;
padding: 0;
}
React
// Your task is to implement multiselect from scratch (styling is not required)
// While closed it should show selected items separated by coma,
// on click it should open a list where you can check/uncheck items
const {createRoot} = ReactDOM;
const {useEffect, useState, useRef, useMemo, useCallback} = React;
const Component = () => {
const [items, setItems] = useState([
{ label: 'd', value: 'd' },
{ label: 'a', value: 'a' },
{ label: 'b', value: 'b' },
{ label: 'c', value: 'c' },
]);
const [selected, setSelected] = useState([]);
const [showDropdown, setShowDropdown] = useState(false);
const dropdownRef = useRef(null);
const selectedDisplayRef = useRef(null);
const handleClickOutsideDropdown = useCallback((event) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target) &&
!selectedDisplayRef.current.contains(event.target)) {
setShowDropdown(false);
}
}, [dropdownRef, selectedDisplayRef]);
useEffect(() => {
document.addEventListener('mousedown', handleClickOutsideDropdown);
return () => document.removeEventListener('mousedown', handleClickOutsideDropdown);
}, [handleClickOutsideDropdown]);
const handleToggleDropdown = () => {
setShowDropdown(!showDropdown);
};
const handleSelectChange = (value) => {
setSelected((prev) =>
prev.includes(value) ? prev.filter((item) => item !== value) : [...prev, value]
);
};
const dropdownItems = useMemo(() => (
<ul ref={dropdownRef} className="dropdown">
{items.map((item) => (
<li key={item.value}>
<label>
<input
type="checkbox"
checked={selected.includes(item.value)}
onChange={() => handleSelectChange(item.value)}
/>
{item.label}
</label>
</li>
))}
</ul>
), [items, selected]);
return (
<div className="container">
<div ref={selectedDisplayRef}...