/* global React, Ic, Input */ // ============================================================ // GlassDropdown — shared custom dropdown component // // Props: // value — currently selected value (any) // onChange — (value) => void // options — [{ value, label, count?, hint? }] // count — optional badge / right-aligned number // hint — optional secondary text under label // placeholder — text shown when nothing is selected // searchable — boolean (default: auto — true if options.length > 6) // searchPlaceholder — string // emptyLabel — string shown when no options / filter empty // size — 'md' | 'lg' (default 'md') // minWidth — px number for popover min width // maxWidth — px for popover (default 420) // badgeValue — override count badge for the trigger (when value is set) // ============================================================ function GlassDropdown({ value, onChange, options, placeholder = 'Wybierz…', searchable, searchPlaceholder = 'Szukaj…', emptyLabel = 'Brak opcji.', size = 'md', minWidth = 260, maxWidth = 420, badgeValue, }) { const [open, setOpen] = React.useState(false); const [q, setQ] = React.useState(''); const wrapRef = React.useRef(null); React.useEffect(() => { function onDoc(e) { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); } document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); }, []); React.useEffect(() => { if (!open) setQ(''); }, [open]); const opts = Array.isArray(options) ? options : []; const autoSearch = typeof searchable === 'boolean' ? searchable : opts.length > 6; const list = opts.filter((o) => !q || (o.label || '').toLowerCase().includes(q.toLowerCase())); const selected = opts.find((o) => o.value === value); const triggerFont = size === 'lg' ? 18 : 13; const triggerPad = size === 'lg' ? '8px 14px' : '6px 12px'; return (
{open && (
{autoSearch && (
} placeholder={searchPlaceholder} value={q} onChange={(e) => setQ(e.target.value)} autoFocus />
)}
{list.length === 0 && (
{emptyLabel}
)} {list.map((o) => { const active = o.value === value; const hasCount = typeof o.count === 'number'; const dim = hasCount && o.count === 0; return (
{ onChange(o.value); setOpen(false); }} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 10px', borderRadius: 'var(--r-sm)', cursor: 'pointer', background: active ? 'var(--surface)' : 'transparent', border: active ? '1px solid var(--border-strong)' : '1px solid transparent', }} onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = 'var(--bg-sunken)'; }} onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = 'transparent'; }} > {hasCount && ( )} {o.label} {o.hint && ( {o.hint} )} {hasCount && ( {o.count} )}
); })}
)}
); } window.GlassDropdown = GlassDropdown;