"use client"; import { ChevronDown } from "lucide-react"; import React, { useEffect, useId, useRef, useState } from "react"; import { toggleFilterValue, type FilterOption, } from "../utils/overview-filters"; /** * Filter dropdown with a checkbox list (PM app style). An empty selection * means "Alle"; the "Alle" entry clears the selection. Closes on outside * click and Escape. */ export function MultiSelectDropdown({ label, options, selected, onChange, emptyLabel = "Keine Einträge vorhanden", }: { label: string; options: readonly FilterOption[]; selected: readonly string[]; onChange: (selected: string[]) => void; emptyLabel?: string; }) { const [isOpen, setIsOpen] = useState(false); const containerRef = useRef(null); const toggleRef = useRef(null); const labelId = useId(); const valueId = useId(); const panelId = useId(); useEffect(() => { if (!isOpen) { return; } function handlePointerDown(event: MouseEvent) { if ( containerRef.current && !containerRef.current.contains(event.target as Node) ) { setIsOpen(false); } } function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") { setIsOpen(false); toggleRef.current?.focus(); } } document.addEventListener("mousedown", handlePointerDown); document.addEventListener("keydown", handleKeyDown); return () => { document.removeEventListener("mousedown", handlePointerDown); document.removeEventListener("keydown", handleKeyDown); }; }, [isOpen]); const summary = selected.length === 0 ? "Alle" : selected.length === 1 ? options.find((option) => option.id === selected[0])?.label ?? "1 ausgewählt" : `${selected.length} ausgewählt`; return (
{label} {isOpen ? (
{options.length === 0 ? (
{emptyLabel}
) : ( <> {options.map((option) => ( ))} )}
) : null}
); }