@@ -27,6 +27,7 @@ import withRipple from '../ripple';
27
27
import { MDCChipFoundation } from '@material/chips/dist/mdc.chips' ;
28
28
29
29
export class Chip extends Component {
30
+ chipElement_ = null ;
30
31
foundation_ = null ;
31
32
state = {
32
33
classList : new Set ( ) ,
@@ -35,18 +36,28 @@ export class Chip extends Component {
35
36
componentDidMount ( ) {
36
37
this . foundation_ = new MDCChipFoundation ( this . adapter ) ;
37
38
this . foundation_ . init ( ) ;
39
+ this . foundation_ . setSelected ( this . props . selected ) ;
40
+ }
41
+
42
+ componentDidUpdate ( prevProps ) {
43
+ if ( this . props . selected !== prevProps . selected ) {
44
+ this . foundation_ . setSelected ( this . props . selected ) ;
45
+ }
38
46
}
39
47
40
48
componentWillUnmount ( ) {
41
49
this . foundation_ . destroy ( ) ;
42
50
}
43
51
52
+ init = ( el ) => {
53
+ this . chipElement_ = el ;
54
+ this . props . initRipple ( el ) ;
55
+ }
56
+
44
57
get classes ( ) {
45
58
const { classList} = this . state ;
46
- const { className, selected} = this . props ;
47
- return classnames ( 'mdc-chip' , Array . from ( classList ) , className , {
48
- 'mdc-chip--selected' : selected ,
49
- } ) ;
59
+ const { className} = this . props ;
60
+ return classnames ( 'mdc-chip' , Array . from ( classList ) , className ) ;
50
61
}
51
62
52
63
get adapter ( ) {
@@ -62,63 +73,126 @@ export class Chip extends Component {
62
73
this . setState ( { classList} ) ;
63
74
} ,
64
75
hasClass : ( className ) => this . classes . split ( ' ' ) . includes ( className ) ,
76
+ eventTargetHasClass : ( target , className ) => target . classList . contains ( className ) ,
77
+ getComputedStyleValue :
78
+ ( propertyName ) => window . getComputedStyle ( this . chipElement_ ) . getPropertyValue ( propertyName ) ,
79
+ setStyleProperty : ( propertyName , value ) => this . chipElement_ . style . setProperty ( propertyName , value ) ,
80
+ notifyRemoval : ( ) => this . props . handleRemove ( this . props . id ) ,
65
81
} ;
66
82
}
67
83
68
- handleClick = ( e ) => {
69
- if ( typeof this . props . onClick === 'function' ) {
70
- this . props . onClick ( e ) ;
71
- }
72
- this . props . handleSelect ( this . props . id ) ;
84
+ onClick = ( e ) => {
85
+ const { onClick, handleSelect, id} = this . props ;
86
+ onClick ( e ) ;
87
+ handleSelect ( id ) ;
73
88
}
74
89
90
+ handleRemoveIconClick = ( e ) => this . foundation_ . handleTrailingIconInteraction ( e ) ;
91
+
92
+ handleTransitionEnd = ( e ) => this . foundation_ . handleTransitionEnd ( e ) ;
93
+
94
+ renderLeadingIcon = ( leadingIcon ) => {
95
+ const {
96
+ className,
97
+ ...otherProps
98
+ } = leadingIcon . props ;
99
+
100
+ const props = {
101
+ className : classnames (
102
+ className ,
103
+ 'mdc-chip__icon' ,
104
+ 'mdc-chip__icon--leading' ,
105
+ ) ,
106
+ ...otherProps ,
107
+ } ;
108
+
109
+ return React . cloneElement ( leadingIcon , props ) ;
110
+ } ;
111
+
112
+ renderRemoveIcon = ( removeIcon ) => {
113
+ const {
114
+ className,
115
+ ...otherProps
116
+ } = removeIcon . props ;
117
+
118
+ const props = {
119
+ className : classnames (
120
+ className ,
121
+ 'mdc-chip__icon' ,
122
+ 'mdc-chip__icon--trailing' ,
123
+ ) ,
124
+ onClick : this . handleRemoveIconClick ,
125
+ onKeyDown : this . handleRemoveIconClick ,
126
+ tabIndex : 0 ,
127
+ role : 'button' ,
128
+ ...otherProps ,
129
+ } ;
130
+
131
+ return React . cloneElement ( removeIcon , props ) ;
132
+ } ;
133
+
75
134
render ( ) {
76
135
const {
77
- className, // eslint-disable-line no-unused-vars
78
- label,
79
- handleSelect, // eslint-disable-line no-unused-vars
80
- onClick, // eslint-disable-line no-unused-vars
81
- chipCheckmark,
82
- computeBoundingRect, // eslint-disable-line no-unused-vars
136
+ /* eslint-disable no-unused-vars */
137
+ id,
138
+ className,
139
+ selected,
140
+ handleSelect,
141
+ handleRemove,
142
+ onClick,
143
+ computeBoundingRect,
83
144
initRipple,
84
- unbounded, // eslint-disable-line no-unused-vars
145
+ unbounded,
146
+ /* eslint-enable no-unused-vars */
147
+ chipCheckmark,
148
+ leadingIcon,
149
+ removeIcon,
150
+ label,
85
151
...otherProps
86
152
} = this . props ;
87
153
88
154
return (
89
155
< div
156
+ tabIndex = '0'
90
157
className = { this . classes }
91
- onClick = { this . handleClick }
92
- ref = { initRipple }
158
+ onClick = { this . onClick }
159
+ onTransitionEnd = { this . handleTransitionEnd }
160
+ ref = { this . init }
93
161
{ ...otherProps }
94
162
>
163
+ { leadingIcon ? this . renderLeadingIcon ( leadingIcon ) : null }
95
164
{ chipCheckmark }
96
165
< div className = 'mdc-chip__text' > { label } </ div >
166
+ { removeIcon ? this . renderRemoveIcon ( removeIcon ) : null }
97
167
</ div >
98
168
) ;
99
169
}
100
170
}
101
171
102
172
Chip . propTypes = {
103
- id : PropTypes . number ,
173
+ id : PropTypes . string . isRequired ,
104
174
label : PropTypes . string ,
105
175
className : PropTypes . string ,
106
176
selected : PropTypes . bool ,
107
177
handleSelect : PropTypes . func ,
178
+ handleRemove : PropTypes . func ,
108
179
onClick : PropTypes . func ,
109
- // The following props are handled by withRipple and do not require defaults.
110
180
initRipple : PropTypes . func ,
111
181
unbounded : PropTypes . bool ,
112
182
chipCheckmark : PropTypes . node ,
183
+ leadingIcon : PropTypes . element ,
184
+ removeIcon : PropTypes . element ,
113
185
computeBoundingRect : PropTypes . func ,
114
186
} ;
115
187
116
188
Chip . defaultProps = {
117
- id : - 1 ,
118
189
label : '' ,
119
190
className : '' ,
120
191
selected : false ,
192
+ onClick : ( ) => { } ,
193
+ initRipple : ( ) => { } ,
121
194
handleSelect : ( ) => { } ,
195
+ handleRemove : ( ) => { } ,
122
196
} ;
123
197
124
198
export default withRipple ( Chip ) ;
0 commit comments