/* 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;