GoScrobble/web/node_modules/reactstrap/lib/Modal.js

496 lines
18 KiB
JavaScript

"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _Portal = _interopRequireDefault(require("./Portal"));
var _Fade = _interopRequireDefault(require("./Fade"));
var _utils = require("./utils");
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function noop() {}
var FadePropTypes = _propTypes.default.shape(_Fade.default.propTypes);
var propTypes = {
isOpen: _propTypes.default.bool,
autoFocus: _propTypes.default.bool,
centered: _propTypes.default.bool,
scrollable: _propTypes.default.bool,
size: _propTypes.default.string,
toggle: _propTypes.default.func,
keyboard: _propTypes.default.bool,
role: _propTypes.default.string,
labelledBy: _propTypes.default.string,
backdrop: _propTypes.default.oneOfType([_propTypes.default.bool, _propTypes.default.oneOf(['static'])]),
onEnter: _propTypes.default.func,
onExit: _propTypes.default.func,
onOpened: _propTypes.default.func,
onClosed: _propTypes.default.func,
children: _propTypes.default.node,
className: _propTypes.default.string,
wrapClassName: _propTypes.default.string,
modalClassName: _propTypes.default.string,
backdropClassName: _propTypes.default.string,
contentClassName: _propTypes.default.string,
external: _propTypes.default.node,
fade: _propTypes.default.bool,
cssModule: _propTypes.default.object,
zIndex: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
backdropTransition: FadePropTypes,
modalTransition: FadePropTypes,
innerRef: _propTypes.default.oneOfType([_propTypes.default.object, _propTypes.default.string, _propTypes.default.func]),
unmountOnClose: _propTypes.default.bool,
returnFocusAfterClose: _propTypes.default.bool,
container: _utils.targetPropType,
trapFocus: _propTypes.default.bool
};
var propsToOmit = Object.keys(propTypes);
var defaultProps = {
isOpen: false,
autoFocus: true,
centered: false,
scrollable: false,
role: 'dialog',
backdrop: true,
keyboard: true,
zIndex: 1050,
fade: true,
onOpened: noop,
onClosed: noop,
modalTransition: {
timeout: _utils.TransitionTimeouts.Modal
},
backdropTransition: {
mountOnEnter: true,
timeout: _utils.TransitionTimeouts.Fade // uses standard fade transition
},
unmountOnClose: true,
returnFocusAfterClose: true,
container: 'body',
trapFocus: false
};
var Modal = /*#__PURE__*/function (_React$Component) {
(0, _inheritsLoose2.default)(Modal, _React$Component);
function Modal(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_this._element = null;
_this._originalBodyPadding = null;
_this.getFocusableChildren = _this.getFocusableChildren.bind((0, _assertThisInitialized2.default)(_this));
_this.handleBackdropClick = _this.handleBackdropClick.bind((0, _assertThisInitialized2.default)(_this));
_this.handleBackdropMouseDown = _this.handleBackdropMouseDown.bind((0, _assertThisInitialized2.default)(_this));
_this.handleEscape = _this.handleEscape.bind((0, _assertThisInitialized2.default)(_this));
_this.handleStaticBackdropAnimation = _this.handleStaticBackdropAnimation.bind((0, _assertThisInitialized2.default)(_this));
_this.handleTab = _this.handleTab.bind((0, _assertThisInitialized2.default)(_this));
_this.onOpened = _this.onOpened.bind((0, _assertThisInitialized2.default)(_this));
_this.onClosed = _this.onClosed.bind((0, _assertThisInitialized2.default)(_this));
_this.manageFocusAfterClose = _this.manageFocusAfterClose.bind((0, _assertThisInitialized2.default)(_this));
_this.clearBackdropAnimationTimeout = _this.clearBackdropAnimationTimeout.bind((0, _assertThisInitialized2.default)(_this));
_this.trapFocus = _this.trapFocus.bind((0, _assertThisInitialized2.default)(_this));
_this.state = {
isOpen: false,
showStaticBackdropAnimation: false
};
return _this;
}
var _proto = Modal.prototype;
_proto.componentDidMount = function componentDidMount() {
var _this$props = this.props,
isOpen = _this$props.isOpen,
autoFocus = _this$props.autoFocus,
onEnter = _this$props.onEnter;
if (isOpen) {
this.init();
this.setState({
isOpen: true
});
if (autoFocus) {
this.setFocus();
}
}
if (onEnter) {
onEnter();
} // traps focus inside the Modal, even if the browser address bar is focused
document.addEventListener('focus', this.trapFocus, true);
this._isMounted = true;
};
_proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
if (this.props.isOpen && !prevProps.isOpen) {
this.init();
this.setState({
isOpen: true
}); // let render() renders Modal Dialog first
return;
} // now Modal Dialog is rendered and we can refer this._element and this._dialog
if (this.props.autoFocus && this.state.isOpen && !prevState.isOpen) {
this.setFocus();
}
if (this._element && prevProps.zIndex !== this.props.zIndex) {
this._element.style.zIndex = this.props.zIndex;
}
};
_proto.componentWillUnmount = function componentWillUnmount() {
this.clearBackdropAnimationTimeout();
if (this.props.onExit) {
this.props.onExit();
}
if (this._element) {
this.destroy();
if (this.props.isOpen || this.state.isOpen) {
this.close();
}
}
document.removeEventListener('focus', this.trapFocus, true);
this._isMounted = false;
};
_proto.trapFocus = function trapFocus(ev) {
if (!this.props.trapFocus) {
return;
}
if (!this._element) //element is not attached
return;
if (this._dialog && this._dialog.parentNode === ev.target) // initial focus when the Modal is opened
return;
if (this.modalIndex < Modal.openCount - 1) // last opened modal
return;
var children = this.getFocusableChildren();
for (var i = 0; i < children.length; i++) {
// focus is already inside the Modal
if (children[i] === ev.target) return;
}
if (children.length > 0) {
// otherwise focus the first focusable element in the Modal
ev.preventDefault();
ev.stopPropagation();
children[0].focus();
}
};
_proto.onOpened = function onOpened(node, isAppearing) {
this.props.onOpened();
(this.props.modalTransition.onEntered || noop)(node, isAppearing);
};
_proto.onClosed = function onClosed(node) {
var unmountOnClose = this.props.unmountOnClose; // so all methods get called before it is unmounted
this.props.onClosed();
(this.props.modalTransition.onExited || noop)(node);
if (unmountOnClose) {
this.destroy();
}
this.close();
if (this._isMounted) {
this.setState({
isOpen: false
});
}
};
_proto.setFocus = function setFocus() {
if (this._dialog && this._dialog.parentNode && typeof this._dialog.parentNode.focus === 'function') {
this._dialog.parentNode.focus();
}
};
_proto.getFocusableChildren = function getFocusableChildren() {
return this._element.querySelectorAll(_utils.focusableElements.join(', '));
};
_proto.getFocusedChild = function getFocusedChild() {
var currentFocus;
var focusableChildren = this.getFocusableChildren();
try {
currentFocus = document.activeElement;
} catch (err) {
currentFocus = focusableChildren[0];
}
return currentFocus;
} // not mouseUp because scrollbar fires it, shouldn't close when user scrolls
;
_proto.handleBackdropClick = function handleBackdropClick(e) {
if (e.target === this._mouseDownElement) {
e.stopPropagation();
var backdrop = this._dialog ? this._dialog.parentNode : null;
if (backdrop && e.target === backdrop && this.props.backdrop === 'static') {
this.handleStaticBackdropAnimation();
}
if (!this.props.isOpen || this.props.backdrop !== true) return;
if (backdrop && e.target === backdrop && this.props.toggle) {
this.props.toggle(e);
}
}
};
_proto.handleTab = function handleTab(e) {
if (e.which !== 9) return;
if (this.modalIndex < Modal.openCount - 1) return; // last opened modal
var focusableChildren = this.getFocusableChildren();
var totalFocusable = focusableChildren.length;
if (totalFocusable === 0) return;
var currentFocus = this.getFocusedChild();
var focusedIndex = 0;
for (var i = 0; i < totalFocusable; i += 1) {
if (focusableChildren[i] === currentFocus) {
focusedIndex = i;
break;
}
}
if (e.shiftKey && focusedIndex === 0) {
e.preventDefault();
focusableChildren[totalFocusable - 1].focus();
} else if (!e.shiftKey && focusedIndex === totalFocusable - 1) {
e.preventDefault();
focusableChildren[0].focus();
}
};
_proto.handleBackdropMouseDown = function handleBackdropMouseDown(e) {
this._mouseDownElement = e.target;
};
_proto.handleEscape = function handleEscape(e) {
if (this.props.isOpen && e.keyCode === _utils.keyCodes.esc && this.props.toggle) {
if (this.props.keyboard) {
e.preventDefault();
e.stopPropagation();
this.props.toggle(e);
} else if (this.props.backdrop === 'static') {
e.preventDefault();
e.stopPropagation();
this.handleStaticBackdropAnimation();
}
}
};
_proto.handleStaticBackdropAnimation = function handleStaticBackdropAnimation() {
var _this2 = this;
this.clearBackdropAnimationTimeout();
this.setState({
showStaticBackdropAnimation: true
});
this._backdropAnimationTimeout = setTimeout(function () {
_this2.setState({
showStaticBackdropAnimation: false
});
}, 100);
};
_proto.init = function init() {
try {
this._triggeringElement = document.activeElement;
} catch (err) {
this._triggeringElement = null;
}
if (!this._element) {
this._element = document.createElement('div');
this._element.setAttribute('tabindex', '-1');
this._element.style.position = 'relative';
this._element.style.zIndex = this.props.zIndex;
this._mountContainer = (0, _utils.getTarget)(this.props.container);
this._mountContainer.appendChild(this._element);
}
this._originalBodyPadding = (0, _utils.getOriginalBodyPadding)();
(0, _utils.conditionallyUpdateScrollbar)();
if (Modal.openCount === 0) {
document.body.className = (0, _classnames.default)(document.body.className, (0, _utils.mapToCssModules)('modal-open', this.props.cssModule));
}
this.modalIndex = Modal.openCount;
Modal.openCount += 1;
};
_proto.destroy = function destroy() {
if (this._element) {
this._mountContainer.removeChild(this._element);
this._element = null;
}
this.manageFocusAfterClose();
};
_proto.manageFocusAfterClose = function manageFocusAfterClose() {
if (this._triggeringElement) {
var returnFocusAfterClose = this.props.returnFocusAfterClose;
if (this._triggeringElement.focus && returnFocusAfterClose) this._triggeringElement.focus();
this._triggeringElement = null;
}
};
_proto.close = function close() {
if (Modal.openCount <= 1) {
var modalOpenClassName = (0, _utils.mapToCssModules)('modal-open', this.props.cssModule); // Use regex to prevent matching `modal-open` as part of a different class, e.g. `my-modal-opened`
var modalOpenClassNameRegex = new RegExp("(^| )" + modalOpenClassName + "( |$)");
document.body.className = document.body.className.replace(modalOpenClassNameRegex, ' ').trim();
}
this.manageFocusAfterClose();
Modal.openCount = Math.max(0, Modal.openCount - 1);
(0, _utils.setScrollbarWidth)(this._originalBodyPadding);
};
_proto.renderModalDialog = function renderModalDialog() {
var _classNames,
_this3 = this;
var attributes = (0, _utils.omit)(this.props, propsToOmit);
var dialogBaseClass = 'modal-dialog';
return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, attributes, {
className: (0, _utils.mapToCssModules)((0, _classnames.default)(dialogBaseClass, this.props.className, (_classNames = {}, _classNames["modal-" + this.props.size] = this.props.size, _classNames[dialogBaseClass + "-centered"] = this.props.centered, _classNames[dialogBaseClass + "-scrollable"] = this.props.scrollable, _classNames)), this.props.cssModule),
role: "document",
ref: function ref(c) {
_this3._dialog = c;
}
}), /*#__PURE__*/_react.default.createElement("div", {
className: (0, _utils.mapToCssModules)((0, _classnames.default)('modal-content', this.props.contentClassName), this.props.cssModule)
}, this.props.children));
};
_proto.render = function render() {
var unmountOnClose = this.props.unmountOnClose;
if (!!this._element && (this.state.isOpen || !unmountOnClose)) {
var isModalHidden = !!this._element && !this.state.isOpen && !unmountOnClose;
this._element.style.display = isModalHidden ? 'none' : 'block';
var _this$props2 = this.props,
wrapClassName = _this$props2.wrapClassName,
modalClassName = _this$props2.modalClassName,
backdropClassName = _this$props2.backdropClassName,
cssModule = _this$props2.cssModule,
isOpen = _this$props2.isOpen,
backdrop = _this$props2.backdrop,
role = _this$props2.role,
labelledBy = _this$props2.labelledBy,
external = _this$props2.external,
innerRef = _this$props2.innerRef;
var modalAttributes = {
onClick: this.handleBackdropClick,
onMouseDown: this.handleBackdropMouseDown,
onKeyUp: this.handleEscape,
onKeyDown: this.handleTab,
style: {
display: 'block'
},
'aria-labelledby': labelledBy,
role: role,
tabIndex: '-1'
};
var hasTransition = this.props.fade;
var modalTransition = _objectSpread(_objectSpread(_objectSpread({}, _Fade.default.defaultProps), this.props.modalTransition), {}, {
baseClass: hasTransition ? this.props.modalTransition.baseClass : '',
timeout: hasTransition ? this.props.modalTransition.timeout : 0
});
var backdropTransition = _objectSpread(_objectSpread(_objectSpread({}, _Fade.default.defaultProps), this.props.backdropTransition), {}, {
baseClass: hasTransition ? this.props.backdropTransition.baseClass : '',
timeout: hasTransition ? this.props.backdropTransition.timeout : 0
});
var Backdrop = backdrop && (hasTransition ? /*#__PURE__*/_react.default.createElement(_Fade.default, (0, _extends2.default)({}, backdropTransition, {
in: isOpen && !!backdrop,
cssModule: cssModule,
className: (0, _utils.mapToCssModules)((0, _classnames.default)('modal-backdrop', backdropClassName), cssModule)
})) : /*#__PURE__*/_react.default.createElement("div", {
className: (0, _utils.mapToCssModules)((0, _classnames.default)('modal-backdrop', 'show', backdropClassName), cssModule)
}));
return /*#__PURE__*/_react.default.createElement(_Portal.default, {
node: this._element
}, /*#__PURE__*/_react.default.createElement("div", {
className: (0, _utils.mapToCssModules)(wrapClassName)
}, /*#__PURE__*/_react.default.createElement(_Fade.default, (0, _extends2.default)({}, modalAttributes, modalTransition, {
in: isOpen,
onEntered: this.onOpened,
onExited: this.onClosed,
cssModule: cssModule,
className: (0, _utils.mapToCssModules)((0, _classnames.default)('modal', modalClassName, this.state.showStaticBackdropAnimation && 'modal-static'), cssModule),
innerRef: innerRef
}), external, this.renderModalDialog()), Backdrop));
}
return null;
};
_proto.clearBackdropAnimationTimeout = function clearBackdropAnimationTimeout() {
if (this._backdropAnimationTimeout) {
clearTimeout(this._backdropAnimationTimeout);
this._backdropAnimationTimeout = undefined;
}
};
return Modal;
}(_react.default.Component);
Modal.propTypes = propTypes;
Modal.defaultProps = defaultProps;
Modal.openCount = 0;
var _default = Modal;
exports.default = _default;