summaryrefslogtreecommitdiffhomepage
path: root/app/components/Switch.js
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@codeispoetry.ru>2017-07-03 12:06:05 +0300
committerAndrej Mihajlov <and@codeispoetry.ru>2017-07-03 12:06:05 +0300
commit4e8f44c7ef6ffee09d9d3abd70bfd093f87d6b18 (patch)
treea0b84c64f77fb3316f33bc031760172fce0fd0cc /app/components/Switch.js
parentab9d8b2471dbcd54bb882b3b6722626f81b71053 (diff)
parent5b5c897152a2208e546e56d6bdd731e2bb04ae80 (diff)
downloadmullvadvpn-4e8f44c7ef6ffee09d9d3abd70bfd093f87d6b18.tar.xz
mullvadvpn-4e8f44c7ef6ffee09d9d3abd70bfd093f87d6b18.zip
Merge branch 'feature/flow-typed/components'
Diffstat (limited to 'app/components/Switch.js')
-rw-r--r--app/components/Switch.js89
1 files changed, 58 insertions, 31 deletions
diff --git a/app/components/Switch.js b/app/components/Switch.js
index 4cb0ea34c3..46baeb8b22 100644
--- a/app/components/Switch.js
+++ b/app/components/Switch.js
@@ -1,27 +1,32 @@
+// @flow
import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+
+import type { Point2d } from '../types';
const CLICK_TIMEOUT = 1000;
const MOVE_THRESHOLD = 10;
export default class Switch extends Component {
+ props: {
+ isOn: boolean;
+ onChange: ?((isOn: boolean) => void);
+ }
- static propTypes = {
- isOn: PropTypes.bool,
- onChange: PropTypes.func
+ defaultProps = {
+ isOn: false
}
- constructor(props) {
- super(props);
- this.state = {
- isTracking: false,
- ignoreChange: false,
- initialPos: null,
- startTime: null
- };
+ ref: ?HTMLInputElement;
+ onRef = (e: HTMLInputElement) => this.ref = e;
+
+ state = {
+ isTracking: false,
+ ignoreChange: false,
+ initialPos: (null: ?Point2d),
+ startTime: (null: ?number)
}
- handleMouseDown(e) {
+ handleMouseDown = (e: MouseEvent) => {
const { pageX: x, pageY: y } = e;
this.setState({
isTracking: true,
@@ -30,14 +35,19 @@ export default class Switch extends Component {
});
}
- handleMouseMove(e) {
- if(!this.state.isTracking) { return; }
+ handleMouseMove = (e: MouseEvent) => {
+ if(!this.state.isTracking) {
+ return;
+ }
+ const inputElement = this.ref;
const { x: x0 } = this.state.initialPos;
const { pageX: x, pageY: y } = e;
const dx = Math.abs(x0 - x);
- if(dx < MOVE_THRESHOLD) { return; }
+ if(dx < MOVE_THRESHOLD) {
+ return;
+ }
const isOn = !!this.props.isOn;
let nextOn = isOn;
@@ -53,12 +63,16 @@ export default class Switch extends Component {
initialPos: { x, y },
ignoreChange: true
});
- this.refs.input.checked = nextOn;
+
+ if(inputElement) {
+ inputElement.checked = nextOn;
+ }
+
this.notify(nextOn);
}
}
- handleMouseUp() {
+ handleMouseUp = () => {
if(this.state.isTracking) {
this.setState({
isTracking: false,
@@ -67,8 +81,19 @@ export default class Switch extends Component {
}
}
- handleChange(e) {
- const dt = e.timeStamp - this.state.startTime;
+ handleChange = (e: Event) => {
+ const startTime = this.state.startTime;
+ const eventTarget = e.target;
+
+ if(typeof(startTime) !== 'number') {
+ throw new Error('startTime must be a number.');
+ }
+
+ if(!(eventTarget instanceof HTMLInputElement)) {
+ throw new Error('e.target must be an instance of HTMLInputElement.');
+ }
+
+ const dt = e.timeStamp - startTime;
if(this.state.ignoreChange) {
this.setState({ ignoreChange: false });
@@ -76,30 +101,32 @@ export default class Switch extends Component {
} else if(dt > CLICK_TIMEOUT) {
e.preventDefault();
} else {
- this.notify(e.target.checked);
+ this.notify(eventTarget.checked);
}
}
- notify(isOn) {
- if(this.props.onChange) {
- this.props.onChange(isOn);
+ notify(isOn: boolean) {
+ const onChange = this.props.onChange;
+ if(onChange) {
+ onChange(isOn);
}
}
componentDidMount() {
- document.addEventListener('mousemove', ::this.handleMouseMove);
- document.addEventListener('mouseup', ::this.handleMouseUp);
+ document.addEventListener('mousemove', this.handleMouseMove);
+ document.addEventListener('mouseup', this.handleMouseUp);
}
componentWillUnmount() {
- document.removeEventListener('mousemove', ::this.handleMouseMove);
- document.removeEventListener('mouseup', ::this.handleMouseUp);
+ document.removeEventListener('mousemove', this.handleMouseMove);
+ document.removeEventListener('mouseup', this.handleMouseUp);
}
- render() {
+ render(): React.Element<*> {
return (
- <input type="checkbox" ref="input" className="switch" checked={ this.props.isOn }
- onMouseDown={ ::this.handleMouseDown } onChange={ ::this.handleChange } />
+ <input type="checkbox" ref={ this.onRef } className="switch" checked={ this.props.isOn }
+ onMouseDown={ this.handleMouseDown }
+ onChange={ this.handleChange } />
);
}
}