1- import React from 'react' ;
2- import propTypes from 'prop-types' ;
3-
1+ import React , { forwardRef } from 'react' ;
42import styled , { css } from 'styled-components' ;
5- import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
6- import { focusOutline } from '../common' ;
73import { StyledButton } from '../Button/Button' ;
4+ import { focusOutline } from '../common' ;
5+ import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
6+ import { noOp } from '../common/utils' ;
87import { Divider } from '../Divider/Divider' ;
8+ import { CommonStyledProps } from '../types' ;
9+
10+ type ColorInputProps = {
11+ value ?: string ;
12+ defaultValue ?: string ;
13+ onChange ?: React . ChangeEventHandler < HTMLInputElement > ;
14+ disabled ?: boolean ;
15+ variant ?: 'default' | 'flat' ;
16+ } & React . InputHTMLAttributes < HTMLInputElement > &
17+ CommonStyledProps ;
918
1019const Trigger = styled ( StyledButton ) `
1120 padding-left: 8px;
@@ -33,7 +42,10 @@ export const StyledColorInput = styled.input`
3342` ;
3443
3544// TODO replace with SVG icon
36- const ColorPreview = styled . div `
45+ const ColorPreview = styled . div < {
46+ color : string ;
47+ $disabled : boolean ;
48+ } > `
3749 box-sizing: border-box;
3850 height: 19px;
3951 display: inline-block;
@@ -42,8 +54,8 @@ const ColorPreview = styled.div`
4254
4355 background: ${ ( { color } ) => color } ;
4456
45- ${ ( { isDisabled } ) =>
46- isDisabled
57+ ${ ( { $disabled } ) =>
58+ $disabled
4759 ? css `
4860 border : 2px solid ${ ( { theme } ) => theme . materialTextDisabled } ;
4961 filter : drop-shadow (
@@ -65,16 +77,20 @@ const ColorPreview = styled.div`
6577 }
6678` ;
6779
68- const ChevronIcon = styled . span `
80+ const ChevronIcon = styled . span <
81+ Required < Pick < ColorInputProps , 'variant' > > & {
82+ $disabled : boolean ;
83+ }
84+ > `
6985 width: 0px;
7086 height: 0px;
7187 border-left: 6px solid transparent;
7288 border-right: 6px solid transparent;
7389 display: inline-block;
7490 margin-left: 6px;
7591
76- ${ ( { isDisabled } ) =>
77- isDisabled
92+ ${ ( { $disabled } ) =>
93+ $disabled
7894 ? css `
7995 border-top : 6px solid ${ ( { theme } ) => theme . materialTextDisabled } ;
8096 filter : drop-shadow (
@@ -96,66 +112,52 @@ const ChevronIcon = styled.span`
96112` ;
97113
98114// TODO make sure all aria and role attributes are in place
99- const ColorInput = React . forwardRef ( function ColorInput ( props , ref ) {
100- const { value, defaultValue, onChange, disabled, variant, ...otherProps } =
101- props ;
102-
103- const [ valueDerived , setValueState ] = useControlledOrUncontrolled ( {
104- value,
105- defaultValue
106- } ) ;
115+ const ColorInput = forwardRef < HTMLInputElement , ColorInputProps > (
116+ function ColorInput (
117+ {
118+ value,
119+ defaultValue,
120+ onChange = noOp ,
121+ disabled = false ,
122+ variant = 'default' ,
123+ ...otherProps
124+ } ,
125+ ref
126+ ) {
127+ const [ valueDerived , setValueState ] = useControlledOrUncontrolled ( {
128+ value,
129+ defaultValue
130+ } ) ;
107131
108- const handleChange = e => {
109- const color = e . target . value ;
110- setValueState ( color ) ;
111- if ( onChange ) {
132+ const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
133+ const color = e . target . value ;
134+ setValueState ( color ) ;
112135 onChange ( e ) ;
113- }
114- } ;
136+ } ;
115137
116- return (
117- // we only need button styles, so we display
118- // it as a div and reset type attribute
119- < Trigger
120- isDisabled = { disabled }
121- as = 'div'
122- type = { null }
123- variant = { variant }
124- size = 'md'
125- >
126- < StyledColorInput
127- onChange = { handleChange }
128- readOnly = { disabled }
129- disabled = { disabled }
130- value = { valueDerived || '#008080' }
131- type = 'color'
132- ref = { ref }
133- { ...otherProps }
134- />
135- < ColorPreview
136- color = { valueDerived }
137- isDisabled = { disabled }
138- role = 'presentation'
139- />
140- { variant === 'default' && < StyledDivider orientation = 'vertical' /> }
141- < ChevronIcon isDisabled = { disabled } variant = { variant } />
142- </ Trigger >
143- ) ;
144- } ) ;
145-
146- ColorInput . defaultProps = {
147- value : undefined ,
148- defaultValue : undefined ,
149- disabled : false ,
150- variant : 'default' ,
151- onChange : ( ) => { }
152- } ;
138+ return (
139+ // we only need button styles, so we display
140+ // it as a div and reset type attribute
141+ < Trigger disabled = { disabled } as = 'div' variant = { variant } size = 'md' >
142+ < StyledColorInput
143+ onChange = { handleChange }
144+ readOnly = { disabled }
145+ disabled = { disabled }
146+ value = { valueDerived || '#008080' }
147+ type = 'color'
148+ ref = { ref }
149+ { ...otherProps }
150+ />
151+ < ColorPreview
152+ $disabled = { disabled }
153+ color = { valueDerived }
154+ role = 'presentation'
155+ />
156+ { variant === 'default' && < StyledDivider orientation = 'vertical' /> }
157+ < ChevronIcon $disabled = { disabled } variant = { variant } />
158+ </ Trigger >
159+ ) ;
160+ }
161+ ) ;
153162
154- ColorInput . propTypes = {
155- value : propTypes . string ,
156- defaultValue : propTypes . string ,
157- onChange : propTypes . func ,
158- disabled : propTypes . bool ,
159- variant : propTypes . oneOf ( [ 'default' , 'flat' ] )
160- } ;
161- export default ColorInput ;
163+ export { ColorInput , ColorInputProps } ;
0 commit comments