11import * as React from "react"
2- import { merge } from "@element/shared"
32import { cva , type VariantProps } from "class-variance-authority"
43
4+ import { merge } from "@element/shared"
5+
56export const inputStyles = cva (
6- "focus:border-primary-500 rounded-xs focus:ring-primary-500 block w-full border text-base text-black placeholder-gray-500 ring-0 transition-colors focus:bg-transparent focus:ring-2 focus:ring-transparent dark:text-white" ,
7+ "focus:border-primary-500 dark:focus:border-primary-500 focus:ring-primary-500 rounded-xs block w-full border text-base text-black placeholder-gray-500 ring-0 transition-colors placeholder:font-thin focus:bg-transparent focus:ring-2 focus:ring-transparent read-only: focus:ring-transparent dark:text-white" ,
78 {
89 variants : {
910 variant : {
1011 solid : "border-transparent bg-black/5 hover:bg-black/10 dark:bg-white/5 dark:hover:bg-white/10" ,
11- outline : "border-black/10 bg-transparent hover:border-black/40 dark:border-white/10 dark:hover:border-white/20" ,
12+ outline : "border-black/10 bg-transparent hover:border-black/90 dark:border-white/10 dark:hover:border-white/20" ,
1213 ghost : "border-transparent bg-transparent hover:border-black/10 dark:hover:border-white/10" ,
1314 } ,
1415 size : {
1516 xs : "px-2 py-1 text-xs" ,
16- sm : "px-3 py-1.5 text-sm" ,
17- md : "text-md px-4 py-2 " ,
17+ sm : "px-3 py-1 text-sm" ,
18+ md : "px-4 py-1 text-base " ,
1819 lg : "px-5 py-3 text-lg" ,
1920 } ,
2021 } ,
@@ -29,9 +30,9 @@ export const inputSizeStyles = cva("", {
2930 variants : {
3031 size : {
3132 xs : "h-7" ,
32- sm : "h-9 " ,
33- md : "h-11 " ,
34- lg : "h-12 " ,
33+ sm : "h-8 " ,
34+ md : "h-9 " ,
35+ lg : "h-11 " ,
3536 } ,
3637 } ,
3738 defaultVariants : {
@@ -48,16 +49,39 @@ export interface InputProps
4849 InputStyleProps ,
4950 InputSizeStyleProps {
5051 name ?: string
52+ leftElement ?: React . ReactNode
53+ rightElement ?: React . ReactNode
54+ ref ?: React . Ref < HTMLInputElement >
5155}
52- export const Input = React . forwardRef < HTMLInputElement , InputProps > ( function _Input ( { size, variant, ...props } , ref ) {
56+ export const Input = React . forwardRef < HTMLInputElement , InputProps > ( function _Input (
57+ { size, variant, leftElement, rightElement, ...props } ,
58+ ref ,
59+ ) {
5360 return (
54- < input
55- type = "text"
56- ref = { ref }
57- id = { props . name }
58- { ...props }
59- className = { merge ( inputStyles ( { variant, size } ) , inputSizeStyles ( { size } ) , props . className ) }
60- />
61+ < div className = "flex flex-row" >
62+ { leftElement && (
63+ < div className = { merge ( inputSizeStyles ( { size } ) , "center rounded-l-xs border bg-gray-50 px-2 dark:bg-gray-900" ) } >
64+ { leftElement }
65+ </ div >
66+ ) }
67+ < input
68+ type = "text"
69+ ref = { ref }
70+ id = { props . name }
71+ { ...props }
72+ className = { merge (
73+ inputStyles ( { variant, size, className : props . className } ) ,
74+ inputSizeStyles ( { size } ) ,
75+ leftElement && "rounded-l-none" ,
76+ rightElement && "rounded-r-none" ,
77+ ) }
78+ />
79+ { rightElement && (
80+ < div className = { merge ( inputSizeStyles ( { size } ) , "center rounded-r-xs border bg-gray-50 px-2 dark:bg-gray-900" ) } >
81+ { rightElement }
82+ </ div >
83+ ) }
84+ </ div >
6185 )
6286} )
6387
@@ -66,48 +90,9 @@ export interface TextareaProps
6690 InputStyleProps {
6791 name ?: string
6892}
69- const paddingMap = {
70- xs : 4 ,
71- sm : 6 ,
72- md : 8 ,
73- lg : 12 ,
74- } as const
7593
76- const lineHeightMap = {
77- xs : 16 ,
78- sm : 20 ,
79- md : 24 ,
80- lg : 28 ,
81- }
8294export function Textarea ( { variant, size, ...props } : TextareaProps ) {
83- const ref = React . useRef < HTMLTextAreaElement > ( null )
84- // Dealing with Textarea Height
85- const calcHeight = React . useCallback (
86- ( value : string ) => {
87- if ( ! ref . current ) return
88- const numberOfLineBreaks = ( value . match ( / \n / g) || [ ] ) . length
89- const lineHeight = lineHeightMap [ size || "sm" ]
90- // min-height + lines x line-height + padding + border
91- const newHeight = lineHeight + numberOfLineBreaks * lineHeight + paddingMap [ size || "sm" ] * 2 + 2
92- ref . current . style . height = `${ newHeight } px`
93- } ,
94- [ size ] ,
95- )
96-
97- React . useEffect ( ( ) => {
98- if ( ! ref . current ) return
99- calcHeight ( ref . current . value )
100- } , [ calcHeight ] )
101-
102- return (
103- < textarea
104- ref = { ref }
105- id = { props . name }
106- { ...props }
107- onChange = { ( e ) => calcHeight ( e . currentTarget . value ) }
108- className = { merge ( inputStyles ( { variant, size } ) , "resize-none" , props . className ) }
109- />
110- )
95+ return < textarea id = { props . name } { ...props } className = { merge ( inputStyles ( { variant, size } ) , "resize-none" , props . className ) } />
11196}
11297
11398export interface SelectProps
@@ -121,7 +106,7 @@ export function Select({ variant, size, ...props }: SelectProps) {
121106 < select
122107 id = { props . name }
123108 { ...props }
124- className = { merge ( inputStyles ( { variant, size } ) , inputSizeStyles ( { size } ) , props . className ) }
109+ className = { merge ( inputStyles ( { variant, size } ) , inputSizeStyles ( { size } ) , "w-auto pr-8" , props . className ) }
125110 >
126111 { props . children }
127112 </ select >
@@ -131,30 +116,40 @@ export function Select({ variant, size, ...props }: SelectProps) {
131116export const checkboxSizeStyles = cva ( "" , {
132117 variants : {
133118 size : {
134- sm : "sq-5 " ,
135- md : "sq-7 " ,
136- lg : "sq-9 " ,
119+ sm : "sq-4 " ,
120+ md : "sq-5 " ,
121+ lg : "sq-7 " ,
137122 } ,
138123 } ,
139124 defaultVariants : {
140- size : "sm " ,
125+ size : "md " ,
141126 } ,
142127} )
143128export type CheckboxSizeStyleProps = VariantProps < typeof checkboxSizeStyles >
144129
145130export function Checkbox ( {
146- size = "sm" ,
131+ size = "md" ,
132+ isInderterminate,
147133 ...props
148134} : Omit < React . DetailedHTMLProps < React . InputHTMLAttributes < HTMLInputElement > , HTMLInputElement > , "size" > &
149- CheckboxSizeStyleProps ) {
135+ CheckboxSizeStyleProps & { isInderterminate ?: boolean } ) {
136+ const ref = React . useRef < HTMLInputElement > ( null )
137+ React . useEffect ( ( ) => {
138+ if ( ! ref . current ) return
139+ if ( isInderterminate ) {
140+ ref . current . indeterminate = ! props . checked && isInderterminate
141+ }
142+ } , [ isInderterminate , props . checked ] )
143+
150144 return (
151145 < input
146+ ref = { ref }
152147 type = "checkbox"
153148 { ...props }
154149 className = { merge (
155- inputStyles ( { variant : "outline" , size : "xs" } ) ,
150+ inputStyles ( { variant : "outline" } ) ,
156151 checkboxSizeStyles ( { size } ) ,
157- "text-primary-500 checked:bg-primary-500 hover:text-primary-600 focus:ring-primary-300 dark:checked:bg-primary-500 dark:hover:checked:bg-primary-600 dark:focus:ring-primary-300 cursor-pointer transition-all " ,
152+ "text-primary-500 checked:bg-primary-500 hover:text-primary-600 focus:ring-primary-300 dark:checked:bg-primary-500 dark:hover:checked:bg-primary-600 dark:focus:ring-primary-300 flex-shrink-0 cursor-pointer p-0 transition-all" ,
158153 props . className ,
159154 ) }
160155 />
0 commit comments