UNPKG

office-ui-fabric-react

Version:

Reusable React components for building experiences for Office 365.

149 lines 7.57 kB
import * as tslib_1 from "tslib"; import * as React from 'react'; import { BaseComponent, classNamesFunction, getId, allowScrollOnElement } from '../../Utilities'; import { FocusTrapZone } from '../FocusTrapZone/index'; import { animationDuration } from './Modal.styles'; import { Overlay } from '../../Overlay'; import { Layer } from '../../Layer'; import { Popup } from '../Popup/index'; import { withResponsiveMode, ResponsiveMode } from '../../utilities/decorators/withResponsiveMode'; // @TODO - need to change this to a panel whenever the breakpoint is under medium (verify the spec) var DefaultLayerProps = { eventBubblingEnabled: false }; var getClassNames = classNamesFunction(); var ModalBase = /** @class */ (function (_super) { tslib_1.__extends(ModalBase, _super); function ModalBase(props) { var _this = _super.call(this, props) || this; _this._focusTrapZone = React.createRef(); // Allow the user to scroll within the modal but not on the body _this._allowScrollOnModal = function (elt) { if (elt) { allowScrollOnElement(elt, _this._events); } else { _this._events.off(_this._scrollableContent); } _this._scrollableContent = elt; }; _this.state = { id: getId('Modal'), isOpen: props.isOpen, isVisible: props.isOpen, hasBeenOpened: props.isOpen }; _this._warnDeprecations({ onLayerDidMount: 'layerProps.onLayerDidMount' }); return _this; } ModalBase.prototype.componentWillReceiveProps = function (newProps) { clearTimeout(this._onModalCloseTimer); // Opening the dialog if (newProps.isOpen) { if (!this.state.isOpen) { // First Open this.setState({ isOpen: true }); } else { // Modal has been opened // Reopen during closing this.setState({ hasBeenOpened: true, isVisible: true }); if (newProps.topOffsetFixed) { var dialogMain = document.getElementsByClassName('ms-Dialog-main'); var modalRectangle = void 0; if (dialogMain.length > 0) { modalRectangle = dialogMain[0].getBoundingClientRect(); this.setState({ modalRectangleTop: modalRectangle.top }); } } } } // Closing the dialog if (!newProps.isOpen && this.state.isOpen) { this._onModalCloseTimer = this._async.setTimeout(this._onModalClose, parseFloat(animationDuration) * 1000); this.setState({ isVisible: false }); } }; ModalBase.prototype.componentDidUpdate = function (prevProps, prevState) { if (!prevProps.isOpen && !prevState.isVisible) { this.setState({ isVisible: true }); } }; ModalBase.prototype.render = function () { var _a = this.props, className = _a.className, containerClassName = _a.containerClassName, scrollableContentClassName = _a.scrollableContentClassName, elementToFocusOnDismiss = _a.elementToFocusOnDismiss, firstFocusableSelector = _a.firstFocusableSelector, forceFocusInsideTrap = _a.forceFocusInsideTrap, ignoreExternalFocusing = _a.ignoreExternalFocusing, isBlocking = _a.isBlocking, isClickableOutsideFocusTrap = _a.isClickableOutsideFocusTrap, isDarkOverlay = _a.isDarkOverlay, onDismiss = _a.onDismiss, layerProps = _a.layerProps, responsiveMode = _a.responsiveMode, titleAriaId = _a.titleAriaId, styles = _a.styles, subtitleAriaId = _a.subtitleAriaId, theme = _a.theme, topOffsetFixed = _a.topOffsetFixed, onLayerDidMount = _a.onLayerDidMount, isModeless = _a.isModeless; var _b = this.state, isOpen = _b.isOpen, isVisible = _b.isVisible, hasBeenOpened = _b.hasBeenOpened, modalRectangleTop = _b.modalRectangleTop; if (!isOpen) { return null; } var classNames = getClassNames(styles, { theme: theme, className: className, containerClassName: containerClassName, scrollableContentClassName: scrollableContentClassName, isOpen: isOpen, isVisible: isVisible, hasBeenOpened: hasBeenOpened, modalRectangleTop: modalRectangleTop, topOffsetFixed: topOffsetFixed, isModeless: isModeless }); // if the modal is modeless, add the classname to correctly style the layer var layerClassName = isModeless ? this.props.className ? this.props.className + " " + classNames.layer : classNames.layer : this.props.className; var mergedLayerProps = tslib_1.__assign({}, DefaultLayerProps, this.props.layerProps, { onLayerDidMount: layerProps && layerProps.onLayerDidMount ? layerProps.onLayerDidMount : onLayerDidMount, className: layerClassName, insertFirst: isModeless }); // @temp tuatology - Will adjust this to be a panel at certain breakpoints if (responsiveMode >= ResponsiveMode.small) { return (React.createElement(Layer, tslib_1.__assign({}, mergedLayerProps), React.createElement(Popup, { role: isModeless || !isBlocking ? 'dialog' : 'alertdialog', "aria-modal": !isModeless, ariaLabelledBy: titleAriaId, ariaDescribedBy: subtitleAriaId, onDismiss: onDismiss }, React.createElement("div", { className: classNames.root }, !isModeless && React.createElement(Overlay, { isDarkThemed: isDarkOverlay, onClick: isBlocking ? undefined : onDismiss }), React.createElement(FocusTrapZone, { componentRef: this._focusTrapZone, className: classNames.main, elementToFocusOnDismiss: elementToFocusOnDismiss, isClickableOutsideFocusTrap: isModeless || isClickableOutsideFocusTrap || !isBlocking, ignoreExternalFocusing: ignoreExternalFocusing, forceFocusInsideTrap: isModeless ? !isModeless : forceFocusInsideTrap, firstFocusableSelector: firstFocusableSelector }, React.createElement("div", { ref: this._allowScrollOnModal, className: classNames.scrollableContent, "data-is-scrollable": true }, this.props.children)))))); } return null; }; ModalBase.prototype.focus = function () { if (this._focusTrapZone.current) { this._focusTrapZone.current.focus(); } }; // Watch for completed animations and set the state ModalBase.prototype._onModalClose = function () { this.setState({ isOpen: false }); // Call the onDismiss callback if (this.props.onDismissed) { this.props.onDismissed(); } }; ModalBase.defaultProps = { isOpen: false, isDarkOverlay: true, isBlocking: false, className: '', containerClassName: '' }; ModalBase = tslib_1.__decorate([ withResponsiveMode ], ModalBase); return ModalBase; }(BaseComponent)); export { ModalBase }; //# sourceMappingURL=Modal.base.js.map