1
- import React from 'react' ;
2
- import propTypes from 'prop-types' ;
3
-
1
+ import React , { forwardRef } from 'react' ;
4
2
import styled , { css } from 'styled-components' ;
5
- import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
6
- import { focusOutline } from '../common' ;
7
3
import { StyledButton } from '../Button/Button' ;
4
+ import { focusOutline } from '../common' ;
5
+ import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
6
+ import { noOp } from '../common/utils' ;
8
7
import { 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 ;
9
18
10
19
const Trigger = styled ( StyledButton ) `
11
20
padding-left: 8px;
@@ -33,7 +42,10 @@ export const StyledColorInput = styled.input`
33
42
` ;
34
43
35
44
// TODO replace with SVG icon
36
- const ColorPreview = styled . div `
45
+ const ColorPreview = styled . div < {
46
+ color : string ;
47
+ $disabled : boolean ;
48
+ } > `
37
49
box-sizing: border-box;
38
50
height: 19px;
39
51
display: inline-block;
@@ -42,8 +54,8 @@ const ColorPreview = styled.div`
42
54
43
55
background: ${ ( { color } ) => color } ;
44
56
45
- ${ ( { isDisabled } ) =>
46
- isDisabled
57
+ ${ ( { $disabled } ) =>
58
+ $disabled
47
59
? css `
48
60
border : 2px solid ${ ( { theme } ) => theme . materialTextDisabled } ;
49
61
filter : drop-shadow (
@@ -65,16 +77,20 @@ const ColorPreview = styled.div`
65
77
}
66
78
` ;
67
79
68
- const ChevronIcon = styled . span `
80
+ const ChevronIcon = styled . span <
81
+ Required < Pick < ColorInputProps , 'variant' > > & {
82
+ $disabled : boolean ;
83
+ }
84
+ > `
69
85
width: 0px;
70
86
height: 0px;
71
87
border-left: 6px solid transparent;
72
88
border-right: 6px solid transparent;
73
89
display: inline-block;
74
90
margin-left: 6px;
75
91
76
- ${ ( { isDisabled } ) =>
77
- isDisabled
92
+ ${ ( { $disabled } ) =>
93
+ $disabled
78
94
? css `
79
95
border-top : 6px solid ${ ( { theme } ) => theme . materialTextDisabled } ;
80
96
filter : drop-shadow (
@@ -96,66 +112,52 @@ const ChevronIcon = styled.span`
96
112
` ;
97
113
98
114
// 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
+ } ) ;
107
131
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 ) ;
112
135
onChange ( e ) ;
113
- }
114
- } ;
136
+ } ;
115
137
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
+ ) ;
153
162
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