// Select component based on Base UI with Field-consistent styling
// https://base-ui.com/react/components/select
import { Select as BaseSelect } from "@base-ui-components/react/select" ;
import clsx from "clsx" ;
import { Check , ChevronDown } from "lucide-react" ;
import type { ReactNode } from "react" ;
import styles from "./Select.module.scss" ;
// Root component
const Root = BaseSelect . Root ;
// Trigger component
interface TriggerProps extends BaseSelect . Trigger . Props {
className ? : string ;
}
function Trigger ({ className , ... props }: TriggerProps ) {
return (
< BaseSelect.Trigger
className = { clsx ( styles . trigger , className ) }
{ ... props }
/>
);
}
// Value component
interface ValueProps extends BaseSelect . Value . Props {
className ? : string ;
}
function Value ({ className , ... props }: ValueProps ) {
return (
< BaseSelect.Value className = { clsx ( styles . value , className ) } { ... props } />
);
}
// Icon component
interface IconProps extends BaseSelect . Icon . Props {
className ? : string ;
}
function Icon ({ className , children , ... props }: IconProps ) {
return (
< BaseSelect.Icon className = { clsx ( styles . icon , className ) } { ... props } >
{ children || < ChevronDown size = { 16 } /> }
</ BaseSelect.Icon >
);
}
// Portal component
const Portal = BaseSelect . Portal ;
// Positioner component
interface PositionerProps extends BaseSelect . Positioner . Props {
className ? : string ;
}
function Positioner ({ className , ... props }: PositionerProps ) {
return (
< BaseSelect.Positioner
className = { clsx ( styles . positioner , className ) }
{ ... props }
/>
);
}
// Popup component
interface PopupProps extends BaseSelect . Popup . Props {
className ? : string ;
}
function Popup ({ className , ... props }: PopupProps ) {
return (
< BaseSelect.Popup className = { clsx ( styles . popup , className ) } { ... props } />
);
}
// Item component
interface ItemProps extends BaseSelect . Item . Props {
className ? : string ;
}
function Item ({ className , ... props }: ItemProps ) {
return (
< BaseSelect.Item className = { clsx ( styles . item , className ) } { ... props } />
);
}
// ItemIndicator component
interface ItemIndicatorProps extends BaseSelect . ItemIndicator . Props {
className ? : string ;
children ? : ReactNode ;
}
function ItemIndicator ({ className , children , ... props }: ItemIndicatorProps ) {
return (
< BaseSelect.ItemIndicator
className = { clsx ( styles . itemIndicator , className ) }
{ ... props }
>
{ children || < Check size = { 14 } /> }
</ BaseSelect.ItemIndicator >
);
}
// ItemText component
interface ItemTextProps extends BaseSelect . ItemText . Props {
className ? : string ;
}
function ItemText ({ className , ... props }: ItemTextProps ) {
return (
< BaseSelect.ItemText
className = { clsx ( styles . itemText , className ) }
{ ... props }
/>
);
}
// Group component
interface GroupProps extends BaseSelect . Group . Props {
className ? : string ;
}
function Group ({ className , ... props }: GroupProps ) {
return (
< BaseSelect.Group className = { clsx ( styles . group , className ) } { ... props } />
);
}
// GroupLabel component
interface GroupLabelProps extends BaseSelect . GroupLabel . Props {
className ? : string ;
}
function GroupLabel ({ className , ... props }: GroupLabelProps ) {
return (
< BaseSelect.GroupLabel
className = { clsx ( styles . groupLabel , className ) }
{ ... props }
/>
);
}
// Separator component
interface SeparatorProps extends BaseSelect . Separator . Props {
className ? : string ;
}
function Separator ({ className , ... props }: SeparatorProps ) {
return (
< BaseSelect.Separator
className = { clsx ( styles . separator , className ) }
{ ... props }
/>
);
}
// Backdrop component
const Backdrop = BaseSelect . Backdrop ;
const Select = {
Root ,
Trigger ,
Value ,
Icon ,
Portal ,
Backdrop ,
Positioner ,
Popup ,
Item ,
ItemIndicator ,
ItemText ,
Group ,
GroupLabel ,
Separator ,
};
export default Select ;