Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit db6a6db

Browse files
codesukitraviskaufman
authored andcommitted
feat(framework-examples): Add ripple support to React checkbox example (#233)
Part of #211
1 parent 08ffe42 commit db6a6db

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

framework-examples/react/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
"react-scripts": "0.8.4"
1515
},
1616
"dependencies": {
17-
"@material/checkbox": "^0.1.0",
17+
"@material/checkbox": "^0.1.2",
1818
"@material/form-field": "^0.1.0",
19+
"@material/ripple": "^0.1.2",
1920
"classnames": "^2.2.5",
2021
"immutable": "^3.8.1",
2122
"react": "^15.4.1",

framework-examples/react/src/Checkbox.js

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,23 @@
2323
*/
2424

2525
import React, {PureComponent, PropTypes} from 'react';
26-
import {Set as ImmutableSet} from 'immutable';
26+
import {Set as ImmutableSet, Map as ImmutableMap} from 'immutable';
2727
// 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';
2830
import {MDCCheckboxFoundation} from '@material/checkbox/dist/mdc.checkbox';
2931
import '@material/checkbox/dist/mdc.checkbox.css';
3032

33+
function getMatchesProperty(HTMLElementPrototype) {
34+
return [
35+
'webkitMatchesSelector', 'msMatchesSelector', 'matches',
36+
].filter((p) => p in HTMLElementPrototype).pop();
37+
}
38+
3139
const {ANIM_END_EVENT_NAME} = MDCCheckboxFoundation.strings;
3240

41+
const MATCHES = getMatchesProperty(HTMLElement.prototype);
42+
3343
export default class Checkbox extends PureComponent {
3444
static propTypes = {
3545
id: PropTypes.string,
@@ -47,11 +57,10 @@ export default class Checkbox extends PureComponent {
4757

4858
state = {
4959
classes: new ImmutableSet(),
60+
rippleCss: new ImmutableMap(),
5061
checkedInternal: false,
5162
indeterminateInternal: false
5263
}
53-
classesToAdd = new ImmutableSet();
54-
classesToRemove = new ImmutableSet();
5564

5665
// Here we initialize a foundation class, passing it an adapter which tells it how to
5766
// work with the React component in an idiomatic way.
@@ -64,12 +73,12 @@ export default class Checkbox extends PureComponent {
6473
})),
6574
registerAnimationEndHandler: handler => {
6675
if (this.refs.root) {
67-
this.refs.root.addEventListener(ANIM_END_EVENT_NAME, handler);
76+
this.refs.root.addEventListener(getCorrectEventName(window, 'animationend'), handler);
6877
}
6978
},
7079
deregisterAnimationEndHandler: handler => {
7180
if (this.refs.root) {
72-
this.refs.root.removeEventListener(ANIM_END_EVENT_NAME, handler);
81+
this.refs.root.removeEventListener(getCorrectEventName(window, 'animationend'), handler)
7382
}
7483
},
7584
registerChangeHandler: handler => {
@@ -101,6 +110,45 @@ export default class Checkbox extends PureComponent {
101110
isAttachedToDOM: () => Boolean(this.refs.nativeCb),
102111
});
103112

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+
104152
render() {
105153
// Within render, we generate the html needed to render a proper MDC-Web checkbox.
106154
return (
@@ -138,8 +186,10 @@ export default class Checkbox extends PureComponent {
138186
// so that proper work can be performed.
139187
componentDidMount() {
140188
this.foundation.init();
189+
this.rippleFoundation.init();
141190
}
142191
componentWillUnmount() {
192+
this.rippleFoundation.destroy();
143193
this.foundation.destroy();
144194
}
145195

@@ -160,5 +210,11 @@ export default class Checkbox extends PureComponent {
160210
if (this.refs.nativeCb) {
161211
this.refs.nativeCb.indeterminate = this.state.indeterminateInternal;
162212
}
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+
}
163219
}
164220
}

0 commit comments

Comments
 (0)