import React, { useState, useRef, useEffect } from 'react';
import { ChevronDown, Check } from 'lucide-react';
import { cn } from '@/lib/utils';
const Select = ({ children, value, onValueChange, disabled = false }) => {
const [open, setOpen] = useState(false);
const ref = useRef(null);
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
// Find the selected item's label
let selectedLabel = null;
// Process all children to find the selected item
React.Children.forEach(children, child => {
if (React.isValidElement(child) && child.type === SelectContent) {
// Check direct SelectItem children
React.Children.forEach(child.props.children, contentChild => {
if (React.isValidElement(contentChild)) {
if (contentChild.type === SelectItem && contentChild.props.value === value) {
selectedLabel = contentChild.props.children;
} else if (contentChild.type === SelectGroup) {
// Check SelectItems inside SelectGroups
React.Children.forEach(contentChild.props.children, groupChild => {
if (React.isValidElement(groupChild) &&
groupChild.type === SelectItem &&
groupChild.props.value === value) {
selectedLabel = groupChild.props.children;
}
});
}
}
});
}
});
// No need for context as we're passing values directly
return (
{React.Children.map(children, child => {
if (React.isValidElement(child)) {
if (child.type === SelectTrigger) {
// Clone the trigger with our props
return React.cloneElement(child, {
onClick: () => !disabled && setOpen(!open),
open,
disabled,
value: selectedLabel,
},
// Map the children of the trigger
React.Children.map(child.props.children, triggerChild => {
// If it's a SelectValue, replace its placeholder with the selected value
if (React.isValidElement(triggerChild) && triggerChild.type === SelectValue) {
return React.cloneElement(triggerChild, {
placeholder: selectedLabel || triggerChild.props.placeholder
});
}
return triggerChild;
}));
}
if (child.type === SelectContent) {
return open ? React.cloneElement(child, {
onSelect: (val) => {
onValueChange?.(val);
setOpen(false);
},
}) : null;
}
}
return child;
})}
);
};
const SelectTrigger = ({ className, children, open, disabled, onClick, value }) => (
);
const SelectValue = ({ placeholder, className }) => {
return {placeholder};
};
const SelectContent = ({ className, children, onSelect }) => {
return (
{React.Children.map(children, child => {
if (React.isValidElement(child)) {
if (child.type === SelectItem) {
return React.cloneElement(child, {
onSelect
});
} else if (child.type === SelectGroup) {
// Handle SelectGroup by recursively processing its children
return React.cloneElement(child, {
children: React.Children.map(child.props.children, groupChild => {
if (React.isValidElement(groupChild) && groupChild.type === SelectItem) {
return React.cloneElement(groupChild, {
onSelect
});
}
return groupChild;
})
});
}
}
return child;
})}
);
};
const SelectItem = ({ className, children, value, onSelect, disabled }) => {
return (
!disabled && onSelect?.(value)}
data-disabled={disabled || undefined}
>
{children}
);
};
const SelectGroup = ({ className, children }) => {
return {children}
;
};
const SelectLabel = ({ className, children }) => {
return {children}
;
};
const SelectSeparator = ({ className }) => {
return ;
};
// Export Select as default and named export
export default Select;
export {
Select,
SelectGroup,
SelectValue,
SelectTrigger,
SelectContent,
SelectLabel,
SelectItem,
SelectSeparator,
};