'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.styles = undefined; var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); var _defineProperty3 = _interopRequireDefault(_defineProperty2); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties'); var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); 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 _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _warning = require('warning'); var _warning2 = _interopRequireDefault(_warning); var _keycode = require('keycode'); var _keycode2 = _interopRequireDefault(_keycode); var _inDOM = require('dom-helpers/util/inDOM'); var _inDOM2 = _interopRequireDefault(_inDOM); var _contains = require('dom-helpers/query/contains'); var _contains2 = _interopRequireDefault(_contains); var _activeElement = require('dom-helpers/activeElement'); var _activeElement2 = _interopRequireDefault(_activeElement); var _ownerDocument = require('dom-helpers/ownerDocument'); var _ownerDocument2 = _interopRequireDefault(_ownerDocument); var _addEventListener = require('../utils/addEventListener'); var _addEventListener2 = _interopRequireDefault(_addEventListener); var _helpers = require('../utils/helpers'); var _Fade = require('../transitions/Fade'); var _Fade2 = _interopRequireDefault(_Fade); var _withStyles = require('../styles/withStyles'); var _withStyles2 = _interopRequireDefault(_withStyles); var _modalManager = require('./modalManager'); var _modalManager2 = _interopRequireDefault(_modalManager); var _Backdrop = require('./Backdrop'); var _Backdrop2 = _interopRequireDefault(_Backdrop); var _Portal = require('./Portal'); var _Portal2 = _interopRequireDefault(_Portal); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var babelPluginFlowReactPropTypes_proptype_ElementType = require('react').babelPluginFlowReactPropTypes_proptype_ElementType || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_Element = require('react').babelPluginFlowReactPropTypes_proptype_Element || require('prop-types').any; // Modals don't open on the server so this won't break concurrency. // Could also put this on context. var babelPluginFlowReactPropTypes_proptype_TransitionCallback = require('../internal/transition').babelPluginFlowReactPropTypes_proptype_TransitionCallback || require('prop-types').any; var babelPluginFlowReactPropTypes_proptype_TransitionDuration = require('../internal/transition').babelPluginFlowReactPropTypes_proptype_TransitionDuration || require('prop-types').any; var modalManager = (0, _modalManager2.default)(); var styles = exports.styles = function styles(theme) { return { root: { display: 'flex', width: '100%', height: '100%', position: 'fixed', zIndex: theme.zIndex.dialog, top: 0, left: 0 }, hidden: { visibility: 'hidden' } }; }; var babelPluginFlowReactPropTypes_proptype_Props = { /** * The CSS class name of the backdrop element. */ BackdropClassName: require('prop-types').string, /** * Pass a component class to use as the backdrop. */ BackdropComponent: typeof babelPluginFlowReactPropTypes_proptype_ElementType === 'function' ? babelPluginFlowReactPropTypes_proptype_ElementType : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_ElementType), /** * If `true`, the backdrop is invisible. */ BackdropInvisible: require('prop-types').bool, /** * The duration for the backdrop transition, in milliseconds. * You may specify a single timeout for all transitions, or individually with an object. */ BackdropTransitionDuration: typeof babelPluginFlowReactPropTypes_proptype_TransitionDuration === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionDuration : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionDuration), /** * A single child content element. */ children: typeof babelPluginFlowReactPropTypes_proptype_Element === 'function' ? babelPluginFlowReactPropTypes_proptype_Element : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_Element), /** * Useful to extend the style applied to components. */ classes: require('prop-types').object, /** * @ignore */ className: require('prop-types').string, /** * Always keep the children in the DOM. * This property can be useful in SEO situation or * when you want to maximize the responsiveness of the Modal. */ keepMounted: require('prop-types').bool, /** * If `true`, the backdrop is disabled. */ disableBackdrop: require('prop-types').bool, /** * If `true`, clicking the backdrop will not fire the `onRequestClose` callback. */ ignoreBackdropClick: require('prop-types').bool, /** * If `true`, hitting escape will not fire the `onRequestClose` callback. */ ignoreEscapeKeyUp: require('prop-types').bool, /** * @ignore */ modalManager: require('prop-types').object, /** * Callback fires when the backdrop is clicked on. */ onBackdropClick: require('prop-types').func, /** * Callback fired before the modal is entering. */ onEnter: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fired when the modal is entering. */ onEntering: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fired when the modal has entered. */ onEntered: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fires when the escape key is pressed and the modal is in focus. */ onEscapeKeyUp: require('prop-types').func, /** * Callback fired before the modal is exiting. */ onExit: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fired when the modal is exiting. */ onExiting: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fired when the modal has exited. */ onExited: typeof babelPluginFlowReactPropTypes_proptype_TransitionCallback === 'function' ? babelPluginFlowReactPropTypes_proptype_TransitionCallback : require('prop-types').shape(babelPluginFlowReactPropTypes_proptype_TransitionCallback), /** * Callback fired when the component requests to be closed. * * @param {object} event The event source of the callback */ onRequestClose: require('prop-types').func, /** * If `true`, the Modal is visible. */ show: require('prop-types').bool }; /** * @ignore - internal component. */ var Modal = function (_React$Component) { (0, _inherits3.default)(Modal, _React$Component); function Modal() { var _ref; var _temp, _this, _ret; (0, _classCallCheck3.default)(this, Modal); 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 = Modal.__proto__ || (0, _getPrototypeOf2.default)(Modal)).call.apply(_ref, [this].concat(args))), _this), _initialiseProps.call(_this), _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); } (0, _createClass3.default)(Modal, [{ key: 'componentWillMount', value: function componentWillMount() { if (!this.props.show) { this.setState({ exited: true }); } } }, { key: 'componentDidMount', value: function componentDidMount() { this.mounted = true; if (this.props.show) { this.handleShow(); } } }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { if (nextProps.show && this.state.exited) { this.setState({ exited: false }); } } }, { key: 'componentWillUpdate', value: function componentWillUpdate(nextProps) { if (!this.props.show && nextProps.show) { this.checkForFocus(); } } }, { key: 'componentDidUpdate', value: function componentDidUpdate(prevProps) { if (!prevProps.show && this.props.show) { this.handleShow(); } // We are waiting for the onExited callback to call handleHide. } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (this.props.show || !this.state.exited) { this.handleHide(); } this.mounted = false; } }, { key: 'checkForFocus', value: function checkForFocus() { if (_inDOM2.default) { this.lastFocus = (0, _activeElement2.default)(); } } }, { key: 'restoreLastFocus', value: function restoreLastFocus() { if (this.lastFocus && this.lastFocus.focus) { this.lastFocus.focus(); this.lastFocus = undefined; } } }, { key: 'handleShow', value: function handleShow() { var doc = (0, _ownerDocument2.default)(_reactDom2.default.findDOMNode(this)); this.props.modalManager.add(this); this.onDocumentKeyUpListener = (0, _addEventListener2.default)(doc, 'keyup', this.handleDocumentKeyUp); this.onFocusListener = (0, _addEventListener2.default)(doc, 'focus', this.handleFocusListener, true); this.focus(); } }, { key: 'focus', value: function focus() { var currentFocus = (0, _activeElement2.default)((0, _ownerDocument2.default)(_reactDom2.default.findDOMNode(this))); var modalContent = this.modal && this.modal.lastChild; var focusInModal = currentFocus && (0, _contains2.default)(modalContent, currentFocus); if (modalContent && !focusInModal) { if (!modalContent.hasAttribute('tabIndex')) { modalContent.setAttribute('tabIndex', -1); process.env.NODE_ENV !== "production" ? (0, _warning2.default)(false, 'Material-UI: the modal content node does not accept focus. ' + 'For the benefit of assistive technologies, ' + 'the tabIndex of the node is being set to "-1".') : void 0; } modalContent.focus(); } } }, { key: 'handleHide', value: function handleHide() { this.props.modalManager.remove(this); if (this.onDocumentKeyUpListener) this.onDocumentKeyUpListener.remove(); if (this.onFocusListener) this.onFocusListener.remove(); this.restoreLastFocus(); } }, { key: 'renderBackdrop', value: function renderBackdrop() { var other = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _props = this.props, BackdropComponent = _props.BackdropComponent, BackdropClassName = _props.BackdropClassName, BackdropTransitionDuration = _props.BackdropTransitionDuration, BackdropInvisible = _props.BackdropInvisible, show = _props.show; return _react2.default.createElement( _Fade2.default, (0, _extends3.default)({ appear: true, 'in': show, timeout: BackdropTransitionDuration }, other), _react2.default.createElement(BackdropComponent, { invisible: BackdropInvisible, className: BackdropClassName, onClick: this.handleBackdropClick }) ); } }, { key: 'render', value: function render() { var _this2 = this; var _props2 = this.props, disableBackdrop = _props2.disableBackdrop, BackdropComponent = _props2.BackdropComponent, BackdropClassName = _props2.BackdropClassName, BackdropTransitionDuration = _props2.BackdropTransitionDuration, BackdropInvisible = _props2.BackdropInvisible, ignoreBackdropClick = _props2.ignoreBackdropClick, ignoreEscapeKeyUp = _props2.ignoreEscapeKeyUp, children = _props2.children, classes = _props2.classes, className = _props2.className, keepMounted = _props2.keepMounted, modalManagerProp = _props2.modalManager, onBackdropClick = _props2.onBackdropClick, onEscapeKeyUp = _props2.onEscapeKeyUp, onRequestClose = _props2.onRequestClose, onEnter = _props2.onEnter, onEntering = _props2.onEntering, onEntered = _props2.onEntered, onExit = _props2.onExit, onExiting = _props2.onExiting, onExited = _props2.onExited, show = _props2.show, other = (0, _objectWithoutProperties3.default)(_props2, ['disableBackdrop', 'BackdropComponent', 'BackdropClassName', 'BackdropTransitionDuration', 'BackdropInvisible', 'ignoreBackdropClick', 'ignoreEscapeKeyUp', 'children', 'classes', 'className', 'keepMounted', 'modalManager', 'onBackdropClick', 'onEscapeKeyUp', 'onRequestClose', 'onEnter', 'onEntering', 'onEntered', 'onExit', 'onExiting', 'onExited', 'show']); if (!keepMounted && !show && this.state.exited) { return null; } var transitionCallbacks = { onEnter: onEnter, onEntering: onEntering, onEntered: onEntered, onExit: onExit, onExiting: onExiting, onExited: this.handleTransitionExited }; var modalChild = _react2.default.Children.only(children); var _modalChild$props = modalChild.props, role = _modalChild$props.role, tabIndex = _modalChild$props.tabIndex; var childProps = {}; if (role === undefined) { childProps.role = role === undefined ? 'document' : role; } if (tabIndex === undefined) { childProps.tabIndex = tabIndex == null ? -1 : tabIndex; } var backdropProps = void 0; // It's a Transition like component if (modalChild.props.hasOwnProperty('in')) { (0, _keys2.default)(transitionCallbacks).forEach(function (key) { childProps[key] = (0, _helpers.createChainedFunction)(transitionCallbacks[key], modalChild.props[key]); }); } else { backdropProps = transitionCallbacks; } if ((0, _keys2.default)(childProps).length) { modalChild = _react2.default.cloneElement(modalChild, childProps); } return _react2.default.createElement( _Portal2.default, { open: true, ref: function ref(node) { _this2.mountNode = node ? node.getLayer() : null; } }, _react2.default.createElement( 'div', (0, _extends3.default)({ className: (0, _classnames2.default)(classes.root, className, (0, _defineProperty3.default)({}, classes.hidden, this.state.exited)) }, other, { ref: function ref(node) { _this2.modal = node; } }), !disableBackdrop && (!keepMounted || show || !this.state.exited) && this.renderBackdrop(backdropProps), modalChild ) ); } }]); return Modal; }(_react2.default.Component); Modal.defaultProps = { BackdropComponent: _Backdrop2.default, BackdropTransitionDuration: 300, BackdropInvisible: false, keepMounted: false, disableBackdrop: false, ignoreBackdropClick: false, ignoreEscapeKeyUp: false, modalManager: modalManager, show: false }; var _initialiseProps = function _initialiseProps() { var _this3 = this; this.state = { exited: false }; this.onDocumentKeyUpListener = null; this.onFocusListener = null; this.mounted = false; this.lastFocus = undefined; this.modal = null; this.mountNode = null; this.handleFocusListener = function () { if (!_this3.mounted || !_this3.props.modalManager.isTopModal(_this3)) { return; } var currentFocus = (0, _activeElement2.default)((0, _ownerDocument2.default)(_reactDom2.default.findDOMNode(_this3))); var modalContent = _this3.modal && _this3.modal.lastChild; if (modalContent && modalContent !== currentFocus && !(0, _contains2.default)(modalContent, currentFocus)) { modalContent.focus(); } }; this.handleDocumentKeyUp = function (event) { if (!_this3.mounted || !_this3.props.modalManager.isTopModal(_this3)) { return; } if ((0, _keycode2.default)(event) !== 'esc') { return; } var _props3 = _this3.props, onEscapeKeyUp = _props3.onEscapeKeyUp, onRequestClose = _props3.onRequestClose, ignoreEscapeKeyUp = _props3.ignoreEscapeKeyUp; if (onEscapeKeyUp) { onEscapeKeyUp(event); } if (onRequestClose && !ignoreEscapeKeyUp) { onRequestClose(event); } }; this.handleBackdropClick = function (event) { if (event.target !== event.currentTarget) { return; } var _props4 = _this3.props, onBackdropClick = _props4.onBackdropClick, onRequestClose = _props4.onRequestClose, ignoreBackdropClick = _props4.ignoreBackdropClick; if (onBackdropClick) { onBackdropClick(event); } if (onRequestClose && !ignoreBackdropClick) { onRequestClose(event); } }; this.handleTransitionExited = function () { if (_this3.props.onExited) { var _props5; (_props5 = _this3.props).onExited.apply(_props5, arguments); } _this3.setState({ exited: true }); _this3.handleHide(); }; }; exports.default = (0, _withStyles2.default)(styles, { flip: false, name: 'MuiModal' })(Modal);