@wordpress/components
Version:
UI components for WordPress.
196 lines (157 loc) • 4.91 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _compose = require("@wordpress/compose");
var _deprecated = _interopRequireDefault(require("@wordpress/deprecated"));
var _frame = _interopRequireDefault(require("./frame"));
var _header = _interopRequireDefault(require("./header"));
var ariaHelper = _interopRequireWildcard(require("./aria-helper"));
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
// Used to count the number of open modals.
let parentElement,
openModalCount = 0;
class Modal extends _element.Component {
constructor(props) {
super(props);
this.prepareDOM();
}
/**
* Appends the modal's node to the DOM, so the portal can render the
* modal in it. Also calls the openFirstModal when this is the first modal to be
* opened.
*/
componentDidMount() {
openModalCount++;
if (openModalCount === 1) {
this.openFirstModal();
}
}
/**
* Removes the modal's node from the DOM. Also calls closeLastModal when this is
* the last modal to be closed.
*/
componentWillUnmount() {
openModalCount--;
if (openModalCount === 0) {
this.closeLastModal();
}
this.cleanDOM();
}
/**
* Prepares the DOM for the modals to be rendered.
*
* Every modal is mounted in a separate div appended to a parent div
* that is appended to the document body.
*
* The parent div will be created if it does not yet exist, and the
* separate div for this specific modal will be appended to that.
*/
prepareDOM() {
if (!parentElement) {
parentElement = document.createElement('div');
document.body.appendChild(parentElement);
}
this.node = document.createElement('div');
parentElement.appendChild(this.node);
}
/**
* Removes the specific mounting point for this modal from the DOM.
*/
cleanDOM() {
parentElement.removeChild(this.node);
}
/**
* Prepares the DOM for this modal and any additional modal to be mounted.
*
* It appends an additional div to the body for the modals to be rendered in,
* it hides any other elements from screen-readers and adds an additional class
* to the body to prevent scrolling while the modal is open.
*/
openFirstModal() {
ariaHelper.hideApp(parentElement);
document.body.classList.add(this.props.bodyOpenClassName);
}
/**
* Cleans up the DOM after the last modal is closed and makes the app available
* for screen-readers again.
*/
closeLastModal() {
document.body.classList.remove(this.props.bodyOpenClassName);
ariaHelper.showApp();
}
/**
* Renders the modal.
*
* @return {WPElement} The modal element.
*/
render() {
const {
onRequestClose,
title,
icon,
closeButtonLabel,
children,
aria,
instanceId,
isDismissible,
isDismissable,
//Deprecated
// Many of the documented props for Modal are passed straight through
// to the ModalFrame component and handled there.
...otherProps
} = this.props;
const headingId = title ? `components-modal-header-${instanceId}` : aria.labelledby;
if (isDismissable) {
(0, _deprecated.default)('isDismissable prop of the Modal component', {
since: '5.4',
alternative: 'isDismissible prop (renamed) of the Modal component'
});
} // Disable reason: this stops mouse events from triggering tooltips and
// other elements underneath the modal overlay.
return (0, _element.createPortal)((0, _element.createElement)(_frame.default, (0, _extends2.default)({
onRequestClose: onRequestClose,
aria: {
labelledby: headingId,
describedby: aria.describedby
}
}, otherProps), (0, _element.createElement)("div", {
className: 'components-modal__content',
role: "document"
}, (0, _element.createElement)(_header.default, {
closeLabel: closeButtonLabel,
headingId: title && headingId,
icon: icon,
isDismissible: isDismissible || isDismissable,
onClose: onRequestClose,
title: title
}), children)), this.node);
}
}
Modal.defaultProps = {
bodyOpenClassName: 'modal-open',
role: 'dialog',
title: null,
focusOnMount: true,
shouldCloseOnEsc: true,
shouldCloseOnClickOutside: true,
isDismissible: true,
/* accessibility */
aria: {
labelledby: null,
describedby: null
}
};
var _default = (0, _compose.withInstanceId)(Modal);
exports.default = _default;
//# sourceMappingURL=index.js.map