UNPKG

material-ui

Version:

Material Design UI components built with React

471 lines (399 loc) 15.7 kB
'use strict'; 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; }; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _keyCode = require('./utils/key-code'); var _keyCode2 = _interopRequireDefault(_keyCode); var _stylePropable = require('./mixins/style-propable'); var _stylePropable2 = _interopRequireDefault(_stylePropable); var _transitions = require('./styles/transitions'); var _transitions2 = _interopRequireDefault(_transitions); var _uniqueId = require('./utils/unique-id'); var _uniqueId2 = _interopRequireDefault(_uniqueId); var _windowListenable = require('./mixins/window-listenable'); var _windowListenable2 = _interopRequireDefault(_windowListenable); var _clearfix = require('./clearfix'); var _clearfix2 = _interopRequireDefault(_clearfix); var _focusRipple = require('./ripples/focus-ripple'); var _focusRipple2 = _interopRequireDefault(_focusRipple); var _touchRipple = require('./ripples/touch-ripple'); var _touchRipple2 = _interopRequireDefault(_touchRipple); var _paper = require('./paper'); var _paper2 = _interopRequireDefault(_paper); var _lightRawTheme = require('./styles/raw-themes/light-raw-theme'); var _lightRawTheme2 = _interopRequireDefault(_lightRawTheme); var _themeManager = require('./styles/theme-manager'); var _themeManager2 = _interopRequireDefault(_themeManager); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } var EnhancedSwitch = _react2.default.createClass({ displayName: 'EnhancedSwitch', propTypes: { checked: _react2.default.PropTypes.bool, /** * The css class name of the root element. */ className: _react2.default.PropTypes.string, defaultSwitched: _react2.default.PropTypes.bool, disableFocusRipple: _react2.default.PropTypes.bool, disableTouchRipple: _react2.default.PropTypes.bool, disabled: _react2.default.PropTypes.bool, iconStyle: _react2.default.PropTypes.object, id: _react2.default.PropTypes.string, inputType: _react2.default.PropTypes.string.isRequired, label: _react2.default.PropTypes.node, labelPosition: _react2.default.PropTypes.oneOf(['left', 'right']), labelStyle: _react2.default.PropTypes.object, name: _react2.default.PropTypes.string, onBlur: _react2.default.PropTypes.func, onFocus: _react2.default.PropTypes.func, onMouseDown: _react2.default.PropTypes.func, onMouseLeave: _react2.default.PropTypes.func, onMouseUp: _react2.default.PropTypes.func, onParentShouldUpdate: _react2.default.PropTypes.func.isRequired, onSwitch: _react2.default.PropTypes.func, onTouchEnd: _react2.default.PropTypes.func, onTouchStart: _react2.default.PropTypes.func, required: _react2.default.PropTypes.bool, rippleColor: _react2.default.PropTypes.string, rippleStyle: _react2.default.PropTypes.object, /** * Override the inline-styles of the root element. */ style: _react2.default.PropTypes.object, switchElement: _react2.default.PropTypes.element.isRequired, switched: _react2.default.PropTypes.bool.isRequired, thumbStyle: _react2.default.PropTypes.object, trackStyle: _react2.default.PropTypes.object, value: _react2.default.PropTypes.string }, contextTypes: { muiTheme: _react2.default.PropTypes.object }, //for passing default theme context to children childContextTypes: { muiTheme: _react2.default.PropTypes.object }, mixins: [_windowListenable2.default, _stylePropable2.default], getInitialState: function getInitialState() { return { isKeyboardFocused: false, parentWidth: 100, muiTheme: this.context.muiTheme ? this.context.muiTheme : _themeManager2.default.getMuiTheme(_lightRawTheme2.default) }; }, getChildContext: function getChildContext() { return { muiTheme: this.state.muiTheme }; }, componentDidMount: function componentDidMount() { var inputNode = _reactDom2.default.findDOMNode(this.refs.checkbox); if (!this.props.switched || inputNode.checked !== this.props.switched) { this.props.onParentShouldUpdate(inputNode.checked); } window.addEventListener('resize', this._handleResize); this._handleResize(); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps, nextContext) { var hasCheckedLinkProp = nextProps.hasOwnProperty('checkedLink'); var hasCheckedProp = nextProps.hasOwnProperty('checked'); var hasToggledProp = nextProps.hasOwnProperty('toggled'); var hasNewDefaultProp = nextProps.hasOwnProperty('defaultSwitched') && nextProps.defaultSwitched !== this.props.defaultSwitched; var newState = {}; newState.muiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; if (hasCheckedProp) { newState.switched = nextProps.checked; } else if (hasToggledProp) { newState.switched = nextProps.toggled; } else if (hasCheckedLinkProp) { newState.switched = nextProps.checkedLink.value; } else if (hasNewDefaultProp) { newState.switched = nextProps.defaultSwitched; } if (newState.switched !== undefined && newState.switched !== this.props.switched) { this.props.onParentShouldUpdate(newState.switched); } this.setState(newState); }, componentWillUnmount: function componentWillUnmount() { window.removeEventListener('resize', this._handleResize); }, windowListeners: { keydown: '_handleWindowKeydown', keyup: '_handleWindowKeyup' }, getEvenWidth: function getEvenWidth() { return parseInt(window.getComputedStyle(_reactDom2.default.findDOMNode(this.refs.root)).getPropertyValue('width'), 10); }, getTheme: function getTheme() { return this.state.muiTheme.rawTheme.palette; }, getStyles: function getStyles() { var spacing = this.state.muiTheme.rawTheme.spacing; var switchWidth = 60 - spacing.desktopGutterLess; var labelWidth = 'calc(100% - 60px)'; var styles = { root: { position: 'relative', cursor: this.props.disabled ? 'default' : 'pointer', overflow: 'visible', display: 'table', height: 'auto', width: '100%' }, input: { position: 'absolute', cursor: this.props.disabled ? 'default' : 'pointer', pointerEvents: 'all', opacity: 0, width: '100%', height: '100%', zIndex: 2, left: 0, boxSizing: 'border-box', padding: 0, margin: 0 }, controls: { width: '100%', height: '100%' }, label: { float: 'left', position: 'relative', display: 'block', width: labelWidth, lineHeight: '24px', color: this.getTheme().textColor, fontFamily: this.state.muiTheme.rawTheme.fontFamily }, wrap: { transition: _transitions2.default.easeOut(), float: 'left', position: 'relative', display: 'block', width: switchWidth, marginRight: this.props.labelPosition === 'right' ? spacing.desktopGutterLess : 0, marginLeft: this.props.labelPosition === 'left' ? spacing.desktopGutterLess : 0 }, ripple: { height: '200%', width: '200%', top: -12, left: -12 } }; return styles; }, isSwitched: function isSwitched() { return _reactDom2.default.findDOMNode(this.refs.checkbox).checked; }, // no callback here because there is no event setSwitched: function setSwitched(newSwitchedValue) { if (!this.props.hasOwnProperty('checked') || this.props.checked === false) { this.props.onParentShouldUpdate(newSwitchedValue); _reactDom2.default.findDOMNode(this.refs.checkbox).checked = newSwitchedValue; } else if (process.env.NODE_ENV !== 'production') { var message = 'Cannot call set method while checked is defined as a property.'; console.error(message); } }, getValue: function getValue() { return _reactDom2.default.findDOMNode(this.refs.checkbox).value; }, isKeyboardFocused: function isKeyboardFocused() { return this.state.isKeyboardFocused; }, _handleChange: function _handleChange(e) { this._tabPressed = false; this.setState({ isKeyboardFocused: false }); var isInputChecked = _reactDom2.default.findDOMNode(this.refs.checkbox).checked; if (!this.props.hasOwnProperty('checked')) { this.props.onParentShouldUpdate(isInputChecked); } if (this.props.onSwitch) { this.props.onSwitch(e, isInputChecked); } }, // Checkbox inputs only use SPACE to change their state. Using ENTER will // update the ui but not the input. _handleWindowKeydown: function _handleWindowKeydown(e) { if (e.keyCode === _keyCode2.default.TAB) { this._tabPressed = true; } if (e.keyCode === _keyCode2.default.SPACE && this.state.isKeyboardFocused) { this._handleChange(e); } }, _handleWindowKeyup: function _handleWindowKeyup(e) { if (e.keyCode === _keyCode2.default.SPACE && this.state.isKeyboardFocused) { this._handleChange(e); } }, /** * Because both the ripples and the checkbox input cannot share pointer * events, the checkbox input takes control of pointer events and calls * ripple animations manually. */ _handleMouseDown: function _handleMouseDown(e) { //only listen to left clicks if (e.button === 0) { this.refs.touchRipple.start(e); } }, _handleMouseUp: function _handleMouseUp() { this.refs.touchRipple.end(); }, _handleMouseLeave: function _handleMouseLeave() { this.refs.touchRipple.end(); }, _handleTouchStart: function _handleTouchStart(e) { this.refs.touchRipple.start(e); }, _handleTouchEnd: function _handleTouchEnd() { this.refs.touchRipple.end(); }, _handleBlur: function _handleBlur(e) { this.setState({ isKeyboardFocused: false }); if (this.props.onBlur) { this.props.onBlur(e); } }, _handleFocus: function _handleFocus(e) { var _this = this; //setTimeout is needed becuase the focus event fires first //Wait so that we can capture if this was a keyboard focus //or touch focus setTimeout(function () { if (_this._tabPressed) { _this.setState({ isKeyboardFocused: true }); } }, 150); if (this.props.onFocus) { this.props.onFocus(e); } }, _handleResize: function _handleResize() { this.setState({ parentWidth: this.getEvenWidth() }); }, render: function render() { var _props = this.props; var name = _props.name; var value = _props.value; var label = _props.label; var onSwitch = _props.onSwitch; var defaultSwitched = _props.defaultSwitched; var onBlur = _props.onBlur; var onFocus = _props.onFocus; var onMouseUp = _props.onMouseUp; var onMouseDown = _props.onMouseDown; var onMouseLeave = _props.onMouseLeave; var onTouchStart = _props.onTouchStart; var onTouchEnd = _props.onTouchEnd; var disableTouchRipple = _props.disableTouchRipple; var disableFocusRipple = _props.disableFocusRipple; var className = _props.className; var other = _objectWithoutProperties(_props, ['name', 'value', 'label', 'onSwitch', 'defaultSwitched', 'onBlur', 'onFocus', 'onMouseUp', 'onMouseDown', 'onMouseLeave', 'onTouchStart', 'onTouchEnd', 'disableTouchRipple', 'disableFocusRipple', 'className']); var styles = this.getStyles(); var wrapStyles = this.prepareStyles(styles.wrap, this.props.iconStyle); var rippleStyle = this.prepareStyles(styles.ripple, this.props.rippleStyle); var rippleColor = this.props.hasOwnProperty('rippleColor') ? this.props.rippleColor : this.getTheme().primary1Color; if (this.props.thumbStyle) { wrapStyles.marginLeft /= 2; wrapStyles.marginRight /= 2; } var inputId = this.props.id || _uniqueId2.default.generate(); var labelStyle = this.prepareStyles(styles.label, this.props.labelStyle); var labelElement = this.props.label ? _react2.default.createElement( 'label', { style: labelStyle, htmlFor: inputId }, this.props.label ) : null; var inputProps = { ref: 'checkbox', type: this.props.inputType, style: this.prepareStyles(styles.input), name: this.props.name, value: this.props.value, defaultChecked: this.props.defaultSwitched, onBlur: this._handleBlur, onFocus: this._handleFocus }; var hideTouchRipple = this.props.disabled || disableTouchRipple; if (!hideTouchRipple) { inputProps.onMouseUp = this._handleMouseUp; inputProps.onMouseDown = this._handleMouseDown; inputProps.onMouseLeave = this._handleMouseLeave; inputProps.onTouchStart = this._handleTouchStart; inputProps.onTouchEnd = this._handleTouchEnd; } if (!this.props.hasOwnProperty('checkedLink')) { inputProps.onChange = this._handleChange; } var inputElement = _react2.default.createElement('input', _extends({}, other, inputProps)); var touchRipple = _react2.default.createElement(_touchRipple2.default, { ref: 'touchRipple', key: 'touchRipple', style: rippleStyle, color: rippleColor, centerRipple: true }); var focusRipple = _react2.default.createElement(_focusRipple2.default, { key: 'focusRipple', innerStyle: rippleStyle, color: rippleColor, show: this.state.isKeyboardFocused }); var ripples = [hideTouchRipple ? null : touchRipple, this.props.disabled || disableFocusRipple ? null : focusRipple]; // If toggle component (indicated by whether the style includes thumb) manually lay out // elements in order to nest ripple elements var switchElement = !this.props.thumbStyle ? _react2.default.createElement( 'div', { style: wrapStyles }, this.props.switchElement, ripples ) : _react2.default.createElement( 'div', { style: wrapStyles }, _react2.default.createElement('div', { style: this.prepareStyles(this.props.trackStyle) }), _react2.default.createElement( _paper2.default, { style: this.props.thumbStyle, zDepth: 1, circle: true }, ' ', ripples, ' ' ) ); var labelPositionExist = this.props.labelPosition; // Position is left if not defined or invalid. var elementsInOrder = labelPositionExist && this.props.labelPosition.toUpperCase() === 'RIGHT' ? _react2.default.createElement( _clearfix2.default, { style: styles.controls }, switchElement, labelElement ) : _react2.default.createElement( _clearfix2.default, { style: styles.controls }, labelElement, switchElement ); return _react2.default.createElement( 'div', { ref: 'root', className: className, style: this.prepareStyles(styles.root, this.props.style) }, inputElement, elementsInOrder ); } }); exports.default = EnhancedSwitch; module.exports = exports['default'];