23
23
*/
24
24
25
25
import React , { PureComponent , PropTypes } from 'react' ;
26
- import { Set as ImmutableSet } from 'immutable' ;
26
+ import { Set as ImmutableSet , Map as ImmutableMap } from 'immutable' ;
27
27
// Temporarily using relative reference until we publish on npm.
28
+ import { getCorrectEventName } from '@material/animation/dist/mdc.animation' ;
29
+ import { MDCRipple , MDCRippleFoundation } from '@material/ripple/dist/mdc.ripple' ;
28
30
import { MDCCheckboxFoundation } from '@material/checkbox/dist/mdc.checkbox' ;
29
31
import '@material/checkbox/dist/mdc.checkbox.css' ;
30
32
33
+ function getMatchesProperty ( HTMLElementPrototype ) {
34
+ return [
35
+ 'webkitMatchesSelector' , 'msMatchesSelector' , 'matches' ,
36
+ ] . filter ( ( p ) => p in HTMLElementPrototype ) . pop ( ) ;
37
+ }
38
+
31
39
const { ANIM_END_EVENT_NAME } = MDCCheckboxFoundation . strings ;
32
40
41
+ const MATCHES = getMatchesProperty ( HTMLElement . prototype ) ;
42
+
33
43
export default class Checkbox extends PureComponent {
34
44
static propTypes = {
35
45
id : PropTypes . string ,
@@ -47,11 +57,10 @@ export default class Checkbox extends PureComponent {
47
57
48
58
state = {
49
59
classes : new ImmutableSet ( ) ,
60
+ rippleCss : new ImmutableMap ( ) ,
50
61
checkedInternal : false ,
51
62
indeterminateInternal : false
52
63
}
53
- classesToAdd = new ImmutableSet ( ) ;
54
- classesToRemove = new ImmutableSet ( ) ;
55
64
56
65
// Here we initialize a foundation class, passing it an adapter which tells it how to
57
66
// work with the React component in an idiomatic way.
@@ -64,12 +73,12 @@ export default class Checkbox extends PureComponent {
64
73
} ) ) ,
65
74
registerAnimationEndHandler : handler => {
66
75
if ( this . refs . root ) {
67
- this . refs . root . addEventListener ( ANIM_END_EVENT_NAME , handler ) ;
76
+ this . refs . root . addEventListener ( getCorrectEventName ( window , 'animationend' ) , handler ) ;
68
77
}
69
78
} ,
70
79
deregisterAnimationEndHandler : handler => {
71
80
if ( this . refs . root ) {
72
- this . refs . root . removeEventListener ( ANIM_END_EVENT_NAME , handler ) ;
81
+ this . refs . root . removeEventListener ( getCorrectEventName ( window , 'animationend' ) , handler )
73
82
}
74
83
} ,
75
84
registerChangeHandler : handler => {
@@ -101,6 +110,45 @@ export default class Checkbox extends PureComponent {
101
110
isAttachedToDOM : ( ) => Boolean ( this . refs . nativeCb ) ,
102
111
} ) ;
103
112
113
+ // For browser compatibility we extend the default adapter which checks for css variable support.
114
+ rippleFoundation = new MDCRippleFoundation ( Object . assign ( MDCRipple . createAdapter ( this ) , {
115
+ isUnbounded : ( ) => true ,
116
+ isSurfaceActive : ( ) => this . refs . nativeCb [ MATCHES ] ( ':active' ) ,
117
+ addClass : className => {
118
+ this . setState ( prevState => ( {
119
+ classes : prevState . classes . add ( className )
120
+ } ) ) ;
121
+ } ,
122
+ removeClass : className => {
123
+ this . setState ( prevState => ( {
124
+ classes : prevState . classes . remove ( className )
125
+ } ) ) ;
126
+ } ,
127
+ registerInteractionHandler : ( evtType , handler ) => {
128
+ this . refs . nativeCb . addEventListener ( evtType , handler ) ;
129
+ } ,
130
+ deregisterInteractionHandler : ( evtType , handler ) => {
131
+ this . refs . nativeCb . removeEventListener ( evtType , handler ) ;
132
+ } ,
133
+ updateCssVariable : ( varName , value ) => {
134
+ this . setState ( prevState => ( {
135
+ rippleCss : prevState . rippleCss . set ( varName , value )
136
+ } ) ) ;
137
+ } ,
138
+ computeBoundingRect : ( ) => {
139
+ const { left, top} = this . refs . root . getBoundingClientRect ( ) ;
140
+ const DIM = 40 ;
141
+ return {
142
+ top,
143
+ left,
144
+ right : left + DIM ,
145
+ bottom : top + DIM ,
146
+ width : DIM ,
147
+ height : DIM ,
148
+ } ;
149
+ } ,
150
+ } ) ) ;
151
+
104
152
render ( ) {
105
153
// Within render, we generate the html needed to render a proper MDC-Web checkbox.
106
154
return (
@@ -138,8 +186,10 @@ export default class Checkbox extends PureComponent {
138
186
// so that proper work can be performed.
139
187
componentDidMount ( ) {
140
188
this . foundation . init ( ) ;
189
+ this . rippleFoundation . init ( ) ;
141
190
}
142
191
componentWillUnmount ( ) {
192
+ this . rippleFoundation . destroy ( ) ;
143
193
this . foundation . destroy ( ) ;
144
194
}
145
195
@@ -160,5 +210,11 @@ export default class Checkbox extends PureComponent {
160
210
if ( this . refs . nativeCb ) {
161
211
this . refs . nativeCb . indeterminate = this . state . indeterminateInternal ;
162
212
}
213
+ // To make the ripple animation work we update the css properties after React finished building the DOM.
214
+ if ( this . refs . root ) {
215
+ this . state . rippleCss . forEach ( ( v , k ) => {
216
+ this . refs . root . style . setProperty ( k , v ) ;
217
+ } ) ;
218
+ }
163
219
}
164
220
}
0 commit comments