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, };