@@ -18,6 +18,10 @@ export type SelectProps<T = string> = {
1818 value ?: T
1919}
2020
21+ // Avoid throwing an error if <Select.Item /> has an empty string value.
22+ // https://github.com/radix-ui/primitives/blob/main/packages/react/select/src/select.tsx#L1277
23+ const EMPTY_VALUE_PLACEHOLDER = '__empty__'
24+
2125export const Select = < T extends string = string > ( {
2226 className,
2327 defaultValue,
@@ -28,24 +32,43 @@ export const Select = <T extends string = string>({
2832 placeholder = 'Select an option' ,
2933 value,
3034} : SelectProps < T > ) => {
35+ const normalizeValue = ( val : T | undefined ) => {
36+ if ( val === '' ) return EMPTY_VALUE_PLACEHOLDER
37+ return val
38+ }
39+
40+ const denormalizeValue = ( val : string ) : T => {
41+ if ( val === EMPTY_VALUE_PLACEHOLDER ) return '' as T
42+ return val as T
43+ }
44+
45+ const handleValueChange = ( newValue : string ) => {
46+ if ( handleChange ) {
47+ handleChange ( denormalizeValue ( newValue ) )
48+ }
49+ }
50+
3151 return (
3252 < div className = { cn ( 'space-y-2' , className ) } >
3353 { label && < Label > { label } </ Label > }
3454 < BaseSelect
35- value = { value as string }
36- onValueChange = { handleChange as ( ( value : string ) => void ) | undefined }
37- defaultValue = { defaultValue as string }
55+ value = { normalizeValue ( value ) }
56+ onValueChange = { handleValueChange }
57+ defaultValue = { normalizeValue ( defaultValue ) }
3858 disabled = { disabled }
3959 >
4060 < SelectTrigger className = "text-foreground font-medium data-[size=default]:h-10 w-full bg-background focus-visible:ring-ring/20" >
4161 < SelectValue placeholder = { placeholder } />
4262 </ SelectTrigger >
4363 < SelectContent >
44- { options . map ( option => (
45- < SelectItem key = { String ( option . value ) } value = { String ( option . value ) } >
46- { option . label }
47- </ SelectItem >
48- ) ) }
64+ { options . map ( option => {
65+ const itemValue = option . value === '' ? EMPTY_VALUE_PLACEHOLDER : String ( option . value )
66+ return (
67+ < SelectItem key = { itemValue } value = { itemValue } >
68+ { option . label }
69+ </ SelectItem >
70+ )
71+ } ) }
4972 </ SelectContent >
5073 </ BaseSelect >
5174 </ div >
0 commit comments