Initial commit
This commit is contained in:
619
node_modules/react-overlays/lib/Modal.js
generated
vendored
Normal file
619
node_modules/react-overlays/lib/Modal.js
generated
vendored
Normal file
@@ -0,0 +1,619 @@
|
||||
'use strict';
|
||||
|
||||
exports.__esModule = 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 _activeElement = require('dom-helpers/activeElement');
|
||||
|
||||
var _activeElement2 = _interopRequireDefault(_activeElement);
|
||||
|
||||
var _contains = require('dom-helpers/query/contains');
|
||||
|
||||
var _contains2 = _interopRequireDefault(_contains);
|
||||
|
||||
var _inDOM = require('dom-helpers/util/inDOM');
|
||||
|
||||
var _inDOM2 = _interopRequireDefault(_inDOM);
|
||||
|
||||
var _propTypes = require('prop-types');
|
||||
|
||||
var _propTypes2 = _interopRequireDefault(_propTypes);
|
||||
|
||||
var _componentOrElement = require('prop-types-extra/lib/componentOrElement');
|
||||
|
||||
var _componentOrElement2 = _interopRequireDefault(_componentOrElement);
|
||||
|
||||
var _deprecated = require('prop-types-extra/lib/deprecated');
|
||||
|
||||
var _deprecated2 = _interopRequireDefault(_deprecated);
|
||||
|
||||
var _elementType = require('prop-types-extra/lib/elementType');
|
||||
|
||||
var _elementType2 = _interopRequireDefault(_elementType);
|
||||
|
||||
var _react = require('react');
|
||||
|
||||
var _react2 = _interopRequireDefault(_react);
|
||||
|
||||
var _reactDom = require('react-dom');
|
||||
|
||||
var _reactDom2 = _interopRequireDefault(_reactDom);
|
||||
|
||||
var _warning = require('warning');
|
||||
|
||||
var _warning2 = _interopRequireDefault(_warning);
|
||||
|
||||
var _ModalManager = require('./ModalManager');
|
||||
|
||||
var _ModalManager2 = _interopRequireDefault(_ModalManager);
|
||||
|
||||
var _Portal = require('./Portal');
|
||||
|
||||
var _Portal2 = _interopRequireDefault(_Portal);
|
||||
|
||||
var _RefHolder = require('./RefHolder');
|
||||
|
||||
var _RefHolder2 = _interopRequireDefault(_RefHolder);
|
||||
|
||||
var _addEventListener = require('./utils/addEventListener');
|
||||
|
||||
var _addEventListener2 = _interopRequireDefault(_addEventListener);
|
||||
|
||||
var _addFocusListener = require('./utils/addFocusListener');
|
||||
|
||||
var _addFocusListener2 = _interopRequireDefault(_addFocusListener);
|
||||
|
||||
var _getContainer = require('./utils/getContainer');
|
||||
|
||||
var _getContainer2 = _interopRequireDefault(_getContainer);
|
||||
|
||||
var _ownerDocument = require('./utils/ownerDocument');
|
||||
|
||||
var _ownerDocument2 = _interopRequireDefault(_ownerDocument);
|
||||
|
||||
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; } /* eslint-disable react/prop-types */
|
||||
|
||||
var modalManager = new _ModalManager2.default();
|
||||
|
||||
/**
|
||||
* Love them or hate them, `<Modal/>` provides a solid foundation for creating dialogs, lightboxes, or whatever else.
|
||||
* The Modal component renders its `children` node in front of a backdrop component.
|
||||
*
|
||||
* The Modal offers a few helpful features over using just a `<Portal/>` component and some styles:
|
||||
*
|
||||
* - Manages dialog stacking when one-at-a-time just isn't enough.
|
||||
* - Creates a backdrop, for disabling interaction below the modal.
|
||||
* - It properly manages focus; moving to the modal content, and keeping it there until the modal is closed.
|
||||
* - It disables scrolling of the page content while open.
|
||||
* - Adds the appropriate ARIA roles are automatically.
|
||||
* - Easily pluggable animations via a `<Transition/>` component.
|
||||
*
|
||||
* Note that, in the same way the backdrop element prevents users from clicking or interacting
|
||||
* with the page content underneath the Modal, Screen readers also need to be signaled to not to
|
||||
* interact with page content while the Modal is open. To do this, we use a common technique of applying
|
||||
* the `aria-hidden='true'` attribute to the non-Modal elements in the Modal `container`. This means that for
|
||||
* a Modal to be truly modal, it should have a `container` that is _outside_ your app's
|
||||
* React hierarchy (such as the default: document.body).
|
||||
*/
|
||||
|
||||
var Modal = function (_React$Component) {
|
||||
_inherits(Modal, _React$Component);
|
||||
|
||||
function Modal() {
|
||||
var _temp, _this, _ret;
|
||||
|
||||
_classCallCheck(this, Modal);
|
||||
|
||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
return _ret = (_temp = (_this = _possibleConstructorReturn(this, _React$Component.call.apply(_React$Component, [this].concat(args))), _this), _initialiseProps.call(_this), _temp), _possibleConstructorReturn(_this, _ret);
|
||||
}
|
||||
|
||||
Modal.prototype.omitProps = function omitProps(props, propTypes) {
|
||||
|
||||
var keys = Object.keys(props);
|
||||
var newProps = {};
|
||||
keys.map(function (prop) {
|
||||
if (!Object.prototype.hasOwnProperty.call(propTypes, prop)) {
|
||||
newProps[prop] = props[prop];
|
||||
}
|
||||
});
|
||||
|
||||
return newProps;
|
||||
};
|
||||
|
||||
Modal.prototype.render = function render() {
|
||||
var _props = this.props,
|
||||
show = _props.show,
|
||||
container = _props.container,
|
||||
children = _props.children,
|
||||
Transition = _props.transition,
|
||||
backdrop = _props.backdrop,
|
||||
className = _props.className,
|
||||
style = _props.style,
|
||||
onExit = _props.onExit,
|
||||
onExiting = _props.onExiting,
|
||||
onEnter = _props.onEnter,
|
||||
onEntering = _props.onEntering,
|
||||
onEntered = _props.onEntered;
|
||||
|
||||
|
||||
var dialog = _react2.default.Children.only(children);
|
||||
var filteredProps = this.omitProps(this.props, Modal.propTypes);
|
||||
|
||||
var mountModal = show || Transition && !this.state.exited;
|
||||
if (!mountModal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var _dialog$props = dialog.props,
|
||||
role = _dialog$props.role,
|
||||
tabIndex = _dialog$props.tabIndex;
|
||||
|
||||
|
||||
if (role === undefined || tabIndex === undefined) {
|
||||
dialog = (0, _react.cloneElement)(dialog, {
|
||||
role: role === undefined ? 'document' : role,
|
||||
tabIndex: tabIndex == null ? '-1' : tabIndex
|
||||
});
|
||||
}
|
||||
|
||||
if (Transition) {
|
||||
dialog = _react2.default.createElement(
|
||||
Transition,
|
||||
{
|
||||
appear: true,
|
||||
unmountOnExit: true,
|
||||
'in': show,
|
||||
onExit: onExit,
|
||||
onExiting: onExiting,
|
||||
onExited: this.handleHidden,
|
||||
onEnter: onEnter,
|
||||
onEntering: onEntering,
|
||||
onEntered: onEntered
|
||||
},
|
||||
dialog
|
||||
);
|
||||
}
|
||||
|
||||
return _react2.default.createElement(
|
||||
_Portal2.default,
|
||||
{
|
||||
ref: this.setMountNode,
|
||||
container: container,
|
||||
onRendered: this.onPortalRendered
|
||||
},
|
||||
_react2.default.createElement(
|
||||
'div',
|
||||
_extends({
|
||||
ref: this.setModalNodeRef,
|
||||
role: role || 'dialog'
|
||||
}, filteredProps, {
|
||||
style: style,
|
||||
className: className
|
||||
}),
|
||||
backdrop && this.renderBackdrop(),
|
||||
_react2.default.createElement(
|
||||
_RefHolder2.default,
|
||||
{ ref: this.setDialogRef },
|
||||
dialog
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
Modal.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.show) {
|
||||
this.setState({ exited: false });
|
||||
} else if (!nextProps.transition) {
|
||||
// Otherwise let handleHidden take care of marking exited.
|
||||
this.setState({ exited: true });
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.componentWillUpdate = function componentWillUpdate(nextProps) {
|
||||
if (!this.props.show && nextProps.show) {
|
||||
this.checkForFocus();
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.componentDidMount = function componentDidMount() {
|
||||
this._isMounted = true;
|
||||
if (this.props.show) {
|
||||
this.onShow();
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.componentDidUpdate = function componentDidUpdate(prevProps) {
|
||||
var transition = this.props.transition;
|
||||
|
||||
|
||||
if (prevProps.show && !this.props.show && !transition) {
|
||||
// Otherwise handleHidden will call this.
|
||||
this.onHide();
|
||||
} else if (!prevProps.show && this.props.show) {
|
||||
this.onShow();
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.componentWillUnmount = function componentWillUnmount() {
|
||||
var _props2 = this.props,
|
||||
show = _props2.show,
|
||||
transition = _props2.transition;
|
||||
|
||||
|
||||
this._isMounted = false;
|
||||
|
||||
if (show || transition && !this.state.exited) {
|
||||
this.onHide();
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.autoFocus = function autoFocus() {
|
||||
if (!this.props.autoFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dialogElement = this.getDialogElement();
|
||||
var currentActiveElement = (0, _activeElement2.default)((0, _ownerDocument2.default)(this));
|
||||
|
||||
if (dialogElement && !(0, _contains2.default)(dialogElement, currentActiveElement)) {
|
||||
this.lastFocus = currentActiveElement;
|
||||
|
||||
if (!dialogElement.hasAttribute('tabIndex')) {
|
||||
(0, _warning2.default)(false, 'The modal content node does not accept focus. For the benefit of ' + 'assistive technologies, the tabIndex of the node is being set ' + 'to "-1".');
|
||||
|
||||
dialogElement.setAttribute('tabIndex', -1);
|
||||
}
|
||||
|
||||
dialogElement.focus();
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.restoreLastFocus = function restoreLastFocus() {
|
||||
// Support: <=IE11 doesn't support `focus()` on svg elements (RB: #917)
|
||||
if (this.lastFocus && this.lastFocus.focus) {
|
||||
this.lastFocus.focus();
|
||||
this.lastFocus = null;
|
||||
}
|
||||
};
|
||||
|
||||
Modal.prototype.getDialogElement = function getDialogElement() {
|
||||
return _reactDom2.default.findDOMNode(this.dialog);
|
||||
};
|
||||
|
||||
Modal.prototype.isTopModal = function isTopModal() {
|
||||
return this.props.manager.isTopModal(this);
|
||||
};
|
||||
|
||||
return Modal;
|
||||
}(_react2.default.Component);
|
||||
|
||||
Modal.propTypes = _extends({}, _Portal2.default.propTypes, {
|
||||
|
||||
/**
|
||||
* Set the visibility of the Modal
|
||||
*/
|
||||
show: _propTypes2.default.bool,
|
||||
|
||||
/**
|
||||
* A Node, Component instance, or function that returns either. The Modal is appended to it's container element.
|
||||
*
|
||||
* For the sake of assistive technologies, the container should usually be the document body, so that the rest of the
|
||||
* page content can be placed behind a virtual backdrop as well as a visual one.
|
||||
*/
|
||||
container: _propTypes2.default.oneOfType([_componentOrElement2.default, _propTypes2.default.func]),
|
||||
|
||||
/**
|
||||
* A callback fired when the Modal is opening.
|
||||
*/
|
||||
onShow: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* A callback fired when either the backdrop is clicked, or the escape key is pressed.
|
||||
*
|
||||
* The `onHide` callback only signals intent from the Modal,
|
||||
* you must actually set the `show` prop to `false` for the Modal to close.
|
||||
*/
|
||||
onHide: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Include a backdrop component.
|
||||
*/
|
||||
backdrop: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.oneOf(['static'])]),
|
||||
|
||||
/**
|
||||
* A function that returns a backdrop component. Useful for custom
|
||||
* backdrop rendering.
|
||||
*
|
||||
* ```js
|
||||
* renderBackdrop={props => <MyBackdrop {...props} />}
|
||||
* ```
|
||||
*/
|
||||
renderBackdrop: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* A callback fired when the escape key, if specified in `keyboard`, is pressed.
|
||||
*/
|
||||
onEscapeKeyDown: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Support for this function will be deprecated. Please use `onEscapeKeyDown` instead
|
||||
* A callback fired when the escape key, if specified in `keyboard`, is pressed.
|
||||
* @deprecated
|
||||
*/
|
||||
onEscapeKeyUp: (0, _deprecated2.default)(_propTypes2.default.func, 'Please use onEscapeKeyDown instead for consistency'),
|
||||
|
||||
/**
|
||||
* A callback fired when the backdrop, if specified, is clicked.
|
||||
*/
|
||||
onBackdropClick: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* A style object for the backdrop component.
|
||||
*/
|
||||
backdropStyle: _propTypes2.default.object,
|
||||
|
||||
/**
|
||||
* A css class or classes for the backdrop component.
|
||||
*/
|
||||
backdropClassName: _propTypes2.default.string,
|
||||
|
||||
/**
|
||||
* A css class or set of classes applied to the modal container when the modal is open,
|
||||
* and removed when it is closed.
|
||||
*/
|
||||
containerClassName: _propTypes2.default.string,
|
||||
|
||||
/**
|
||||
* Close the modal when escape key is pressed
|
||||
*/
|
||||
keyboard: _propTypes2.default.bool,
|
||||
|
||||
/**
|
||||
* A `react-transition-group@2.0.0` `<Transition/>` component used
|
||||
* to control animations for the dialog component.
|
||||
*/
|
||||
transition: _elementType2.default,
|
||||
|
||||
/**
|
||||
* A `react-transition-group@2.0.0` `<Transition/>` component used
|
||||
* to control animations for the backdrop components.
|
||||
*/
|
||||
backdropTransition: _elementType2.default,
|
||||
|
||||
/**
|
||||
* When `true` The modal will automatically shift focus to itself when it opens, and
|
||||
* replace it to the last focused element when it closes. This also
|
||||
* works correctly with any Modal children that have the `autoFocus` prop.
|
||||
*
|
||||
* Generally this should never be set to `false` as it makes the Modal less
|
||||
* accessible to assistive technologies, like screen readers.
|
||||
*/
|
||||
autoFocus: _propTypes2.default.bool,
|
||||
|
||||
/**
|
||||
* When `true` The modal will prevent focus from leaving the Modal while open.
|
||||
*
|
||||
* Generally this should never be set to `false` as it makes the Modal less
|
||||
* accessible to assistive technologies, like screen readers.
|
||||
*/
|
||||
enforceFocus: _propTypes2.default.bool,
|
||||
|
||||
/**
|
||||
* When `true` The modal will restore focus to previously focused element once
|
||||
* modal is hidden
|
||||
*/
|
||||
restoreFocus: _propTypes2.default.bool,
|
||||
|
||||
/**
|
||||
* Callback fired before the Modal transitions in
|
||||
*/
|
||||
onEnter: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Callback fired as the Modal begins to transition in
|
||||
*/
|
||||
onEntering: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Callback fired after the Modal finishes transitioning in
|
||||
*/
|
||||
onEntered: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Callback fired right before the Modal transitions out
|
||||
*/
|
||||
onExit: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Callback fired as the Modal begins to transition out
|
||||
*/
|
||||
onExiting: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* Callback fired after the Modal finishes transitioning out
|
||||
*/
|
||||
onExited: _propTypes2.default.func,
|
||||
|
||||
/**
|
||||
* A ModalManager instance used to track and manage the state of open
|
||||
* Modals. Useful when customizing how modals interact within a container
|
||||
*/
|
||||
manager: _propTypes2.default.object.isRequired
|
||||
});
|
||||
Modal.defaultProps = {
|
||||
show: false,
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
autoFocus: true,
|
||||
enforceFocus: true,
|
||||
restoreFocus: true,
|
||||
onHide: function onHide() {},
|
||||
manager: modalManager,
|
||||
renderBackdrop: function renderBackdrop(props) {
|
||||
return _react2.default.createElement('div', props);
|
||||
}
|
||||
};
|
||||
|
||||
var _initialiseProps = function _initialiseProps() {
|
||||
var _this2 = this;
|
||||
|
||||
this.state = { exited: !this.props.show };
|
||||
|
||||
this.renderBackdrop = function () {
|
||||
var _props3 = _this2.props,
|
||||
backdropStyle = _props3.backdropStyle,
|
||||
backdropClassName = _props3.backdropClassName,
|
||||
renderBackdrop = _props3.renderBackdrop,
|
||||
Transition = _props3.backdropTransition;
|
||||
|
||||
|
||||
var backdropRef = function backdropRef(ref) {
|
||||
return _this2.backdrop = ref;
|
||||
};
|
||||
|
||||
var backdrop = renderBackdrop({
|
||||
ref: backdropRef,
|
||||
style: backdropStyle,
|
||||
className: backdropClassName,
|
||||
onClick: _this2.handleBackdropClick
|
||||
});
|
||||
|
||||
if (Transition) {
|
||||
backdrop = _react2.default.createElement(
|
||||
Transition,
|
||||
{
|
||||
appear: true,
|
||||
'in': _this2.props.show
|
||||
},
|
||||
backdrop
|
||||
);
|
||||
}
|
||||
|
||||
return backdrop;
|
||||
};
|
||||
|
||||
this.onPortalRendered = function () {
|
||||
_this2.autoFocus();
|
||||
|
||||
if (_this2.props.onShow) {
|
||||
_this2.props.onShow();
|
||||
}
|
||||
};
|
||||
|
||||
this.onShow = function () {
|
||||
var doc = (0, _ownerDocument2.default)(_this2);
|
||||
var container = (0, _getContainer2.default)(_this2.props.container, doc.body);
|
||||
|
||||
_this2.props.manager.add(_this2, container, _this2.props.containerClassName);
|
||||
|
||||
_this2._onDocumentKeydownListener = (0, _addEventListener2.default)(doc, 'keydown', _this2.handleDocumentKeyDown);
|
||||
|
||||
_this2._onDocumentKeyupListener = (0, _addEventListener2.default)(doc, 'keyup', _this2.handleDocumentKeyUp);
|
||||
|
||||
_this2._onFocusinListener = (0, _addFocusListener2.default)(_this2.enforceFocus);
|
||||
};
|
||||
|
||||
this.onHide = function () {
|
||||
_this2.props.manager.remove(_this2);
|
||||
|
||||
_this2._onDocumentKeydownListener.remove();
|
||||
|
||||
_this2._onDocumentKeyupListener.remove();
|
||||
|
||||
_this2._onFocusinListener.remove();
|
||||
|
||||
if (_this2.props.restoreFocus) {
|
||||
_this2.restoreLastFocus();
|
||||
}
|
||||
};
|
||||
|
||||
this.setMountNode = function (ref) {
|
||||
_this2.mountNode = ref ? ref.getMountNode() : ref;
|
||||
};
|
||||
|
||||
this.setModalNodeRef = function (ref) {
|
||||
_this2.modalNode = ref;
|
||||
};
|
||||
|
||||
this.setDialogRef = function (ref) {
|
||||
_this2.dialog = ref;
|
||||
};
|
||||
|
||||
this.handleHidden = function () {
|
||||
_this2.setState({ exited: true });
|
||||
_this2.onHide();
|
||||
|
||||
if (_this2.props.onExited) {
|
||||
var _props4;
|
||||
|
||||
(_props4 = _this2.props).onExited.apply(_props4, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
this.handleBackdropClick = function (e) {
|
||||
if (e.target !== e.currentTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_this2.props.onBackdropClick) {
|
||||
_this2.props.onBackdropClick(e);
|
||||
}
|
||||
|
||||
if (_this2.props.backdrop === true) {
|
||||
_this2.props.onHide();
|
||||
}
|
||||
};
|
||||
|
||||
this.handleDocumentKeyDown = function (e) {
|
||||
if (_this2.props.keyboard && e.keyCode === 27 && _this2.isTopModal()) {
|
||||
if (_this2.props.onEscapeKeyDown) {
|
||||
_this2.props.onEscapeKeyDown(e);
|
||||
}
|
||||
|
||||
_this2.props.onHide();
|
||||
}
|
||||
};
|
||||
|
||||
this.handleDocumentKeyUp = function (e) {
|
||||
if (_this2.props.keyboard && e.keyCode === 27 && _this2.isTopModal()) {
|
||||
if (_this2.props.onEscapeKeyUp) {
|
||||
_this2.props.onEscapeKeyUp(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.checkForFocus = function () {
|
||||
if (_inDOM2.default) {
|
||||
_this2.lastFocus = (0, _activeElement2.default)();
|
||||
}
|
||||
};
|
||||
|
||||
this.enforceFocus = function () {
|
||||
if (!_this2.props.enforceFocus || !_this2._isMounted || !_this2.isTopModal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dialogElement = _this2.getDialogElement();
|
||||
var currentActiveElement = (0, _activeElement2.default)((0, _ownerDocument2.default)(_this2));
|
||||
|
||||
if (dialogElement && !(0, _contains2.default)(dialogElement, currentActiveElement)) {
|
||||
dialogElement.focus();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Modal.Manager = _ModalManager2.default;
|
||||
|
||||
exports.default = Modal;
|
||||
module.exports = exports['default'];
|
||||
Reference in New Issue
Block a user