UNPKG

react-ios-switch

Version:
338 lines (296 loc) 11.1 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _popmotion = require('popmotion'); var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _normalizeColor = require('./normalizeColor'); var _normalizeColor2 = _interopRequireDefault(_normalizeColor); var _prefixStyle = require('./prefixStyle'); var _prefixStyle2 = _interopRequireDefault(_prefixStyle); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var Switch = function (_React$Component) { _inherits(Switch, _React$Component); function Switch(props) { _classCallCheck(this, Switch); var _this = _possibleConstructorReturn(this, (Switch.__proto__ || Object.getPrototypeOf(Switch)).call(this, props)); _this.state = { isDragging: false, offset: null }; _this.handleChange = _this.handleChange.bind(_this); _this.handleClick = _this.handleClick.bind(_this); _this.handleHandleClick = _this.handleHandleClick.bind(_this); _this.handleMouseDown = _this.handleMouseDown.bind(_this); _this.handleMouseUp = _this.handleMouseUp.bind(_this); _this.setRef = _this.setRef.bind(_this); return _this; } _createClass(Switch, [{ key: 'clickChange', value: function clickChange(checked) { if (this.ref.parentNode && this.ref.parentNode.tagName.toLowerCase() === 'label') { // if the parent is a label, we don't need to emit the change event ourselves return; } this.props.onChange(checked); } }, { key: 'componentDidMount', value: function componentDidMount() { window.addEventListener('mouseup', this.handleMouseUp); } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { window.removeEventListener('mouseup', this.handleMouseUp); } }, { key: 'getHandleColor', value: function getHandleColor() { return (0, _normalizeColor2.default)(this.props.handleColor); } }, { key: 'getHandleCursor', value: function getHandleCursor() { if (this.isDisabled()) { return 'default'; } return this.state.isDragging ? 'grabbing' : 'grab'; } }, { key: 'getHandleLength', value: function getHandleLength() { return this.getHeight() - 2; } }, { key: 'getHeight', value: function getHeight() { return 30; } }, { key: 'getOffColor', value: function getOffColor() { return (0, _normalizeColor2.default)(this.props.offColor); } }, { key: 'getOffset', value: function getOffset() { if (this.state.isDragging) { return this.state.offset; } return this.props.checked ? this.getOffsetWidth() : 0; } }, { key: 'getOffsetProgress', value: function getOffsetProgress() { return this.getOffset() / this.getOffsetWidth(); } }, { key: 'getOffsetWidth', value: function getOffsetWidth(props) { return this.getWidth() - this.getHandleLength() - 2; } }, { key: 'getOnColor', value: function getOnColor() { return (0, _normalizeColor2.default)(this.props.onColor); } }, { key: 'getPendingColor', value: function getPendingColor(_ref) { var color = _ref.color, pendingColor = _ref.pendingColor; if (!pendingColor) { return color === 'white' ? // default pending color for white color '#dfdfdf' : (0, _normalizeColor2.default)(color); } return (0, _normalizeColor2.default)(pendingColor); } }, { key: 'getPendingOffColor', value: function getPendingOffColor() { return this.getPendingColor({ color: this.props.offColor, pendingColor: this.props.pendingOffColor }); } }, { key: 'getPendingOnColor', value: function getPendingOnColor() { return this.getPendingColor({ color: this.props.onColor, pendingColor: this.props.pendingOnColor }); } }, { key: 'getWidth', value: function getWidth() { return 50; } }, { key: 'handleChange', value: function handleChange(e) { this.props.onChange(e.target.checked); } }, { key: 'handleClick', value: function handleClick(e) { if (this.isDisabled()) { return; } // handle case when the switch is clicked this.clickChange(!this.props.checked); } }, { key: 'handleHandleClick', value: function handleHandleClick(e) { e.stopPropagation(); } }, { key: 'handleMouseDown', value: function handleMouseDown(e) { var _this2 = this; if (this.isDisabled()) { return; } this.pointerTracker = (0, _popmotion.pointer)(e).start(); this.offsetTracker = (0, _popmotion.trackOffset)(this.pointerTracker.x, { from: this.getOffset(), onUpdate: _popmotion.transform.pipe(_popmotion.transform.clamp(0, this.getOffsetWidth()), function (offset) { return _this2.setState({ offset: offset }); }) }).start(); this.setState({ isDragging: true, offset: this.getOffset() }); } }, { key: 'handleMouseUp', value: function handleMouseUp() { if (!this.state.isDragging) { return; } this.pointerTracker.stop(); this.offsetTracker.stop(); var prevOffset = this.props.checked ? this.getOffsetWidth() : 0; var checked = this.state.offset === prevOffset ? // handle case when the handle is clicked !this.props.checked : // handle case when the handle is dragged this.getOffsetProgress() >= 0.5; this.setState({ isDragging: false, offset: null }); this.clickChange(checked); } }, { key: 'isDisabled', value: function isDisabled() { return this.props.disabled || this.props.readOnly; } }, { key: 'render', value: function render() { var _props = this.props, checked = _props.checked, className = _props.className, disabled = _props.disabled, name = _props.name, onChange = _props.onChange, readOnly = _props.readOnly, style = _props.style; var isDragging = this.state.isDragging; var color = _popmotion.transform.pipe(_popmotion.easing.createExpoIn(2), _popmotion.transform.blendColor(this.getOffColor(), this.getOnColor()), _popmotion.transform.rgba)(this.getOffsetProgress()); var borderColor = _popmotion.transform.pipe(_popmotion.easing.createExpoIn(1), _popmotion.transform.blendColor(this.getPendingOffColor(), this.getPendingOnColor()), _popmotion.transform.rgba)(this.getOffsetProgress()); return _react2.default.createElement( 'span', { className: className, onClick: this.handleClick, ref: this.setRef, style: _extends({}, (0, _prefixStyle2.default)({ backgroundColor: color, border: '1px solid ' + borderColor, borderRadius: this.getHeight() / 2, boxShadow: 'inset 0 0 0 ' + this.getOffset() + 'px ' + borderColor, boxSizing: 'border-box', display: 'inline-block', height: this.getHeight(), opacity: this.isDisabled() ? 0.5 : 1, position: 'relative', transition: isDragging ? null : '0.2s', userSelect: 'none', width: this.getWidth() }), style) }, _react2.default.createElement('span', { onClick: this.handleHandleClick, onMouseDown: this.handleMouseDown, style: (0, _prefixStyle2.default)({ backgroundColor: this.getHandleColor(), borderRadius: '100%', boxShadow: '0 1px 3px rgba(0, 0, 0, 0.4)', cursor: this.getHandleCursor(), display: 'inline-block', height: this.getHandleLength(), left: this.getOffset(), position: 'absolute', top: 0, transition: isDragging ? null : '0.2s', width: this.getHandleLength() }) }), _react2.default.createElement('input', { checked: checked, disabled: disabled, name: name, onChange: this.handleChange, readOnly: readOnly, style: { display: 'none' }, type: 'checkbox' }) ); } }, { key: 'setRef', value: function setRef(ref) { this.ref = ref; } }]); return Switch; }(_react2.default.Component); Switch.propTypes = { checked: _propTypes2.default.bool, className: _propTypes2.default.string, disabled: _propTypes2.default.bool, handleColor: _propTypes2.default.string, name: _propTypes2.default.string, offColor: _propTypes2.default.string, onChange: _propTypes2.default.func, onColor: _propTypes2.default.string, pendingOffColor: _propTypes2.default.string, pendingOnColor: _propTypes2.default.string, readOnly: _propTypes2.default.bool, style: _propTypes2.default.object }; Switch.defaultProps = { handleColor: 'white', offColor: 'white', onChange: function onChange() {}, onColor: 'rgb(76, 217, 100)' }; exports.default = Switch;