@@ -5,6 +5,7 @@ import * as React from "react";
5
5
import { SelectGroup } from "@radix-ui/react-select" ;
6
6
import { tv } from "tailwind-variants" ;
7
7
8
+ import { cn } from "@/lib/utils" ;
8
9
import { IconType } from "@/primitives/Icon" ;
9
10
import {
10
11
Select as ShadcnSelect ,
@@ -13,9 +14,10 @@ import {
13
14
SelectLabel ,
14
15
SelectItem ,
15
16
SelectSeparator ,
16
- SelectValue ,
17
17
} from "@/ui-shadcn/select" ;
18
18
19
+ import { Label } from "./Label" ;
20
+
19
21
export interface SelectProps {
20
22
options : {
21
23
groupLabel ?: string ;
@@ -30,6 +32,7 @@ export interface SelectProps {
30
32
} [ ] ;
31
33
placeholder ?: React . ReactNode ;
32
34
onValueChange ?: ( value : string ) => void ;
35
+ value ?: string ;
33
36
defaultValue ?: string ;
34
37
variant ?: "default" | "outlined" | "filled" ;
35
38
size ?: "sm" | "md" | "lg" ;
@@ -38,16 +41,47 @@ export interface SelectProps {
38
41
39
42
const selectStyles = tv ( {
40
43
base : "h-10 rounded-md border text-sm" ,
44
+ slots : {
45
+ trigger : "h-10 rounded-md border text-sm" ,
46
+ item : "" ,
47
+ label : "" ,
48
+ } ,
41
49
variants : {
42
50
variant : {
43
- default : "border-transparent bg-white " ,
44
- outlined : "border-transparent bg-transparent" ,
45
- filled : "bg-grey-200" ,
51
+ default : {
52
+ trigger : "border-transparent bg-white " ,
53
+ content : "" ,
54
+ item : "" ,
55
+ label : "" ,
56
+ } ,
57
+ outlined : {
58
+ trigger : "border-transparent bg-transparent" ,
59
+ item : "" ,
60
+ label : "" ,
61
+ } ,
62
+ filled : {
63
+ trigger : " bg-grey-200 text-grey-900" ,
64
+ content : "" ,
65
+ item : "" ,
66
+ label : "" ,
67
+ } ,
46
68
} ,
47
69
size : {
48
- sm : "h-8 text-xs" ,
49
- md : "h-10 text-sm" ,
50
- lg : "h-12 text-base" ,
70
+ sm : {
71
+ trigger : "h-8 gap-1 text-xs" ,
72
+ item : "h-8 text-xs" ,
73
+ label : "text-xs" ,
74
+ } ,
75
+ md : {
76
+ trigger : "h-10 px-3 py-2 text-sm" ,
77
+ item : "text-sm" ,
78
+ label : "text-sm" ,
79
+ } ,
80
+ lg : {
81
+ trigger : "h-12 gap-2 text-base" ,
82
+ item : "text-base" ,
83
+ label : "" ,
84
+ } ,
51
85
} ,
52
86
} ,
53
87
defaultVariants : {
@@ -56,33 +90,59 @@ const selectStyles = tv({
56
90
} ,
57
91
} ) ;
58
92
93
+ export const getSelectedItem = (
94
+ options : SelectProps [ "options" ] ,
95
+ value ?: string ,
96
+ defaultValue ?: string ,
97
+ onValueChange ?: ( value : string ) => void ,
98
+ ) => {
99
+ const itemValue = value || defaultValue ;
100
+ const item = options
101
+ . find ( ( option ) => option . items . find ( ( item ) => item . value === itemValue ) )
102
+ ?. items . find ( ( item ) => item . value === itemValue ) ;
103
+ if ( item ) {
104
+ onValueChange ?.( item . value ) ;
105
+ }
106
+ return item ;
107
+ } ;
108
+
59
109
export const Select = ( {
60
110
options,
61
111
placeholder = "Select an option" ,
62
112
onValueChange,
63
113
defaultValue,
114
+ value,
64
115
variant,
65
116
size,
66
117
className,
67
118
} : SelectProps ) => {
119
+ const item = getSelectedItem ( options , value , defaultValue , onValueChange ) ;
120
+ const { trigger, item : selectItem , label } = selectStyles ( { variant, size, className } ) ;
68
121
return (
69
- < ShadcnSelect defaultValue = { defaultValue } onValueChange = { onValueChange } >
70
- < SelectTrigger className = { selectStyles ( { variant, size, className } ) } >
71
- < SelectValue placeholder = { defaultValue ?? placeholder } />
122
+ < ShadcnSelect
123
+ defaultValue = { defaultValue }
124
+ onValueChange = { onValueChange }
125
+ value = { value || defaultValue }
126
+ >
127
+ < SelectTrigger className = { cn ( trigger ( ) , className ) } >
128
+ { item ? < Label { ...item } /> : placeholder }
72
129
</ SelectTrigger >
73
130
< SelectContent >
74
131
{ options . map ( ( group , index ) => (
75
132
< React . Fragment key = { index } >
76
133
{ group . groupLabel && (
77
134
< SelectGroup >
78
- < SelectLabel > { group . groupLabel } </ SelectLabel >
135
+ < SelectLabel className = { label ( ) } > { group . groupLabel } </ SelectLabel >
79
136
</ SelectGroup >
80
137
) }
81
138
{ group . items . map ( ( item ) => (
82
- < SelectItem key = { item . value } value = { item . value } className = "flex items-center gap-2" >
83
- { item . icon && item . iconPosition === "left" && item . icon }
84
- { item . label }
85
- { item . icon && item . iconPosition === "right" && item . icon }
139
+ < SelectItem key = { item . value } value = { item . value } >
140
+ < Label
141
+ label = { item . label }
142
+ icon = { item . icon }
143
+ iconPosition = { item . iconPosition }
144
+ className = { selectItem ( ) }
145
+ />
86
146
</ SelectItem >
87
147
) ) }
88
148
{ group . separator && < SelectSeparator /> }
0 commit comments