41 lines
2.3 KiB
TypeScript
41 lines
2.3 KiB
TypeScript
import { useState } from "react";
|
||
import type { FacetItem } from "../analysis/facets.ts";
|
||
import { Dropdown } from "../../ui/index.ts";
|
||
|
||
// мультиселект с поиском: пустой выбор = без фильтра (строки 913–938)
|
||
export function MultiSelect({ items, selected, allLabel, onChange }: {
|
||
items: FacetItem[]; selected: Set<string>; allLabel: string; onChange(next: Set<string>): void;
|
||
}) {
|
||
const [q, setQ] = useState("");
|
||
const sel = items.filter((i) => selected.has(i.value));
|
||
const label = !sel.length ? allLabel : sel.length === 1 ? sel[0].label : `${sel[0].label} +${sel.length - 1}`;
|
||
const shown = items.filter((i) => !q || i.label.toLowerCase().includes(q.toLowerCase()) || i.value.toLowerCase().includes(q.toLowerCase()));
|
||
const flip = (v: string, on: boolean) => { const n = new Set(selected); if (on) n.add(v); else n.delete(v); onChange(n); };
|
||
return (
|
||
<Dropdown onOpen={() => setQ("")} button={({ open, toggle }) => (
|
||
<button type="button" className="btn dd-btn" aria-expanded={open} title={sel.map((i) => i.label).join(", ")} onClick={toggle}>
|
||
<span className="lbl">{label}</span><span className="car">▼</span>
|
||
</button>
|
||
)}>
|
||
{() => (
|
||
<>
|
||
<input type="search" placeholder="Поиск…" aria-label="Поиск" autoFocus value={q} onChange={(e) => setQ(e.target.value)} />
|
||
<div className="dd-list" role="group" aria-label={allLabel}>
|
||
{!shown.length && <div className="dd-empty">ничего не найдено</div>}
|
||
{shown.map((i) => (
|
||
<label key={i.value} className={"dd-item" + (i.cls ? " " + i.cls : "")} title={i.title || i.label}>
|
||
<input type="checkbox" checked={selected.has(i.value)} onChange={(e) => flip(i.value, e.target.checked)} />
|
||
<span>{i.label}</span><span className="n">{i.count}</span>
|
||
</label>
|
||
))}
|
||
</div>
|
||
<div className="dd-foot">
|
||
<button type="button" className="btn all" onClick={() => onChange(new Set(items.map((i) => i.value)))}>Выбрать все</button>
|
||
<button type="button" className="btn clear" onClick={() => onChange(new Set())}>Снять выбор</button>
|
||
</div>
|
||
</>
|
||
)}
|
||
</Dropdown>
|
||
);
|
||
}
|