'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.styles = exports.DELAY_RIPPLE = undefined; var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties'); var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _inherits2 = require('babel-runtime/helpers/inherits'); var _inherits3 = _interopRequireDefault(_inherits2); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _TransitionGroup = require('react-transition-group/TransitionGroup'); var _TransitionGroup2 = _interopRequireDefault(_TransitionGroup); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _withStyles = require('../styles/withStyles'); var _withStyles2 = _interopRequireDefault(_withStyles); var _Ripple = require('./Ripple'); var _Ripple2 = _interopRequireDefault(_Ripple); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // weak var DURATION = 550; var DELAY_RIPPLE = exports.DELAY_RIPPLE = 80; var styles = exports.styles = function styles(theme) { return { root: { display: 'block', position: 'absolute', overflow: 'hidden', borderRadius: 'inherit', width: '100%', height: '100%', left: 0, top: 0, pointerEvents: 'none', zIndex: 0 }, wrapper: { opacity: 1 }, wrapperLeaving: { opacity: 0, animation: 'mui-ripple-exit ' + DURATION + 'ms ' + theme.transitions.easing.easeInOut }, wrapperPulsating: { position: 'absolute', left: 0, top: 0, display: 'block', width: '100%', height: '100%', animation: 'mui-ripple-pulsate 1500ms ' + theme.transitions.easing.easeInOut + ' 200ms infinite', rippleVisible: { opacity: 0.2 } }, '@keyframes mui-ripple-enter': { '0%': { transform: 'scale(0)' }, '100%': { transform: 'scale(1)' } }, '@keyframes mui-ripple-exit': { '0%': { opacity: 1 }, '100%': { opacity: 0 } }, '@keyframes mui-ripple-pulsate': { '0%': { transform: 'scale(1)' }, '50%': { transform: 'scale(0.9)' }, '100%': { transform: 'scale(1)' } }, ripple: { width: 50, height: 50, left: 0, top: 0, opacity: 0, position: 'absolute', borderRadius: '50%', background: 'currentColor' }, rippleVisible: { opacity: 0.3, transform: 'scale(1)', animation: 'mui-ripple-enter ' + DURATION + 'ms ' + theme.transitions.easing.easeInOut }, rippleFast: { animationDuration: '200ms' } }; }; var babelPluginFlowReactPropTypes_proptype_Props = { /** * If `true`, the ripple starts at the center of the component * rather than at the point of interaction. */ center: require('prop-types').bool, /** * Useful to extend the style applied to components. */ classes: require('prop-types').object, /** * @ignore */ className: require('prop-types').string }; /** * @ignore - internal component. */ var TouchRipple = function (_React$Component) { (0, _inherits3.default)(TouchRipple, _React$Component); function TouchRipple() { var _ref; var _temp, _this, _ret; (0, _classCallCheck3.default)(this, TouchRipple); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = TouchRipple.__proto__ || (0, _getPrototypeOf2.default)(TouchRipple)).call.apply(_ref, [this].concat(args))), _this), _this.state = { nextKey: 0, ripples: [] }, _this.ignoringMouseDown = false, _this.startTimer = null, _this.startTimerCommit = null, _this.pulsate = function () { _this.start({}, { pulsate: true }); }, _this.start = function () { var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var cb = arguments[2]; var _options$pulsate = options.pulsate, pulsate = _options$pulsate === undefined ? false : _options$pulsate, _options$center = options.center, center = _options$center === undefined ? _this.props.center || options.pulsate : _options$center, _options$fakeElement = options.fakeElement, fakeElement = _options$fakeElement === undefined ? false : _options$fakeElement; if (event.type === 'mousedown' && _this.ignoringMouseDown) { _this.ignoringMouseDown = false; return; } if (event.type === 'touchstart') { _this.ignoringMouseDown = true; } var element = fakeElement ? null : _reactDom2.default.findDOMNode(_this); var rect = element ? // $FlowFixMe element.getBoundingClientRect() : { width: 0, height: 0, left: 0, top: 0 }; // Get the size of the ripple var rippleX = void 0; var rippleY = void 0; var rippleSize = void 0; if (center || event.clientX === 0 && event.clientY === 0 || !event.clientX && !event.touches) { rippleX = Math.round(rect.width / 2); rippleY = Math.round(rect.height / 2); } else { var clientX = event.clientX ? event.clientX : event.touches[0].clientX; var clientY = event.clientY ? event.clientY : event.touches[0].clientY; rippleX = Math.round(clientX - rect.left); rippleY = Math.round(clientY - rect.top); } if (center) { rippleSize = Math.sqrt((2 * Math.pow(rect.width, 2) + Math.pow(rect.height, 2)) / 3); // For some reason the animation is broken on Mobile Chrome if the size if even. if (rippleSize % 2 === 0) { rippleSize += 1; } } else { var sizeX = Math.max( // $FlowFixMe Math.abs((element ? element.clientWidth : 0) - rippleX), rippleX) * 2 + 2; var sizeY = Math.max( // $FlowFixMe Math.abs((element ? element.clientHeight : 0) - rippleY), rippleY) * 2 + 2; rippleSize = Math.sqrt(Math.pow(sizeX, 2) + Math.pow(sizeY, 2)); } // Touche devices if (event.touches) { // Prepare the ripple effect. _this.startTimerCommit = function () { _this.startCommit({ pulsate: pulsate, rippleX: rippleX, rippleY: rippleY, rippleSize: rippleSize, cb: cb }); }; // Deplay the execution of the ripple effect. _this.startTimer = setTimeout(function () { _this.startTimerCommit(); _this.startTimerCommit = null; }, DELAY_RIPPLE); // We have to make a tradeoff with this value. } else { _this.startCommit({ pulsate: pulsate, rippleX: rippleX, rippleY: rippleY, rippleSize: rippleSize, cb: cb }); } }, _this.startCommit = function (params) { var pulsate = params.pulsate, rippleX = params.rippleX, rippleY = params.rippleY, rippleSize = params.rippleSize, cb = params.cb; var ripples = _this.state.ripples; // Add a ripple to the ripples array ripples = [].concat((0, _toConsumableArray3.default)(ripples), [_react2.default.createElement(_Ripple2.default, { key: _this.state.nextKey, classes: _this.props.classes, timeout: { exit: DURATION, enter: DURATION }, pulsate: pulsate, rippleX: rippleX, rippleY: rippleY, rippleSize: rippleSize })]); _this.setState({ nextKey: _this.state.nextKey + 1, ripples: ripples }, cb); }, _this.stop = function (event, cb) { clearTimeout(_this.startTimer); var ripples = _this.state.ripples; // The touch interaction occures to quickly. // We still want to show ripple effect. if (event.type === 'touchend' && _this.startTimerCommit) { event.persist(); _this.startTimerCommit(); _this.startTimerCommit = null; _this.startTimer = setTimeout(function () { _this.stop(event, cb); }, 0); return; } _this.startTimerCommit = null; if (ripples && ripples.length) { _this.setState({ ripples: ripples.slice(1) }, cb); } }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); } (0, _createClass3.default)(TouchRipple, [{ key: 'componentWillUnmount', value: function componentWillUnmount() { clearTimeout(this.startTimer); } // Used to filter out mouse emulated events on mobile. // We use a timer in order to only show the ripples for touch "click" like events. // We don't want to display the ripple for touch scroll events. // This is the hook called once the previous timeout is ready. }, { key: 'render', value: function render() { var _props = this.props, center = _props.center, classes = _props.classes, className = _props.className, other = (0, _objectWithoutProperties3.default)(_props, ['center', 'classes', 'className']); return _react2.default.createElement( _TransitionGroup2.default, (0, _extends3.default)({ component: 'span', enter: true, exit: true, className: (0, _classnames2.default)(classes.root, className) }, other), this.state.ripples ); } }]); return TouchRipple; }(_react2.default.Component); TouchRipple.defaultProps = { center: false }; exports.default = (0, _withStyles2.default)(styles, { flip: false, name: 'MuiTouchRipple' })(TouchRipple);