33import { Box , css , Flex , VStack } from '@devup-ui/react'
44import clsx from 'clsx'
55import {
6+ Children ,
67 ComponentProps ,
78 createContext ,
9+ JSX ,
10+ JSXElementConstructor ,
11+ ReactElement ,
812 useContext ,
913 useEffect ,
1014 useRef ,
@@ -17,7 +21,7 @@ import { IconCheck } from './IconCheck'
1721type SelectType = 'default' | 'radio' | 'checkbox'
1822type SelectValue < T extends SelectType > = T extends 'radio' ? string : string [ ]
1923
20- interface SelectProps {
24+ interface SelectProps extends ComponentProps < 'div' > {
2125 open ?: boolean
2226 onOpenChange ?: ( open : boolean ) => void
2327 children : React . ReactNode
@@ -45,6 +49,7 @@ export function Select({
4549 children,
4650 open : openProp ,
4751 onOpenChange,
52+ ...props
4853} : SelectProps ) {
4954 const ref = useRef < HTMLDivElement > ( null )
5055 const [ open , setOpen ] = useState ( openProp ?? false )
@@ -90,28 +95,39 @@ export function Select({
9095 type,
9196 } }
9297 >
93- < Box ref = { ref } display = "inline-block" pos = "relative" >
98+ < Box ref = { ref } display = "inline-block" pos = "relative" { ... props } >
9499 { children }
95100 </ Box >
96101 </ SelectContext . Provider >
97102 )
98103}
99104
105+ interface SelectTriggerProps extends ComponentProps < typeof Button > {
106+ asChild ?: boolean
107+ }
100108export function SelectTrigger ( {
101109 className,
102110 children,
111+ asChild,
103112 ...props
104- } : ComponentProps < typeof Button > ) {
113+ } : SelectTriggerProps ) {
105114 const { open, setOpen } = useSelect ( )
106115 const handleClick = ( ) => {
107116 setOpen ( ! open )
108117 }
109118
119+ if ( asChild ) {
120+ const element = Children . only ( children ) as ReactElement <
121+ ComponentProps < keyof JSX . IntrinsicElements | JSXElementConstructor < any > >
122+ >
123+ const Comp = element . type
124+ return < Comp onClick = { handleClick } { ...element . props } />
125+ }
126+
110127 return (
111128 < Button
112129 className = { clsx (
113130 css ( {
114- pos : 'relative' ,
115131 borderRadius : '8px' ,
116132 } ) ,
117133 className ,
@@ -136,9 +152,9 @@ export function SelectContainer({ children, ...props }: ComponentProps<'div'>) {
136152 bottom = "-4px"
137153 boxShadow = "0 2px 2px 0 $base10"
138154 gap = "6px"
155+ h = "fit-content"
139156 p = "10px"
140157 pos = "absolute"
141- styleOrder = { 1 }
142158 transform = "translateY(100%)"
143159 userSelect = "none"
144160 w = "232px"
@@ -175,21 +191,23 @@ export function SelectOption({
175191 handleClose ( )
176192 }
177193
178- const isChecked = Array . isArray ( value )
194+ const isSelected = Array . isArray ( value )
179195 ? value . includes ( children as string )
180196 : value === children
181197
198+ const changesOnHover = ! disabled && ! ( type === 'radio' && isSelected )
199+
182200 return (
183201 < Flex
184202 _hover = {
185- ! disabled && {
203+ changesOnHover && {
186204 bg : '$primaryBg' ,
187205 }
188206 }
189207 alignItems = "center"
190208 borderRadius = "8px"
191- color = { disabled ? '$selectDisabled' : isChecked ? '$primary' : '$title' }
192- cursor = { disabled ? 'default ' : 'pointer ' }
209+ color = { disabled ? '$selectDisabled' : isSelected ? '$primary' : '$title' }
210+ cursor = { changesOnHover ? 'pointer ' : 'default ' }
193211 gap = {
194212 {
195213 checkbox : '10px' ,
@@ -202,20 +220,20 @@ export function SelectOption({
202220 px = "10px"
203221 styleOrder = { 1 }
204222 transition = "background-color 0.1s ease-in-out"
205- typography = { isChecked ? 'inputBold' : 'inputText' }
223+ typography = { isSelected ? 'inputBold' : 'inputText' }
206224 { ...props }
207225 >
208226 {
209227 {
210228 checkbox : (
211229 < Box
212- bg = { isChecked ? '$primary' : '$border' }
230+ bg = { isSelected ? '$primary' : '$border' }
213231 borderRadius = "4px"
214232 boxSize = "18px"
215233 pos = "relative"
216234 transition = "background-color 0.1s ease-in-out"
217235 >
218- { isChecked && (
236+ { isSelected && (
219237 < IconCheck
220238 className = { css ( {
221239 position : 'absolute' ,
@@ -229,7 +247,7 @@ export function SelectOption({
229247 ) ,
230248 radio : (
231249 < >
232- { isChecked && (
250+ { isSelected && (
233251 < Box
234252 borderRadius = "4px"
235253 boxSize = "18px"
0 commit comments