office-ui-fabric-react
Version:
Reusable React components for building experiences for Office 365.
149 lines • 7.57 kB
JavaScript
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