define(["require", "exports", "tslib", "react", "../../Utilities", "../FocusTrapZone/index", "./Modal.styles", "../../Overlay", "../../Layer", "../Popup/index", "../../utilities/decorators/withResponsiveMode", "../Callout/index", "../Icon/index", "../../utilities/DraggableZone/index"], function (require, exports, tslib_1, React, Utilities_1, index_1, Modal_styles_1, Overlay_1, Layer_1, index_2, withResponsiveMode_1, index_3, index_4, index_5) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    // @TODO - need to change this to a panel whenever the breakpoint is under medium (verify the spec)
    var DefaultLayerProps = {
        eventBubblingEnabled: false
    };
    var getClassNames = Utilities_1.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) {
                    Utilities_1.allowScrollOnElement(elt, _this._events);
                }
                else {
                    _this._events.off(_this._scrollableContent);
                }
                _this._scrollableContent = elt;
            };
            _this._onModalContextMenuClose = function () {
                _this.setState({ isModalMenuOpen: false });
            };
            _this._onModalClose = function () {
                _this._lastSetX = 0;
                _this._lastSetY = 0;
                _this.setState({
                    isModalMenuOpen: false,
                    isInKeyboardMoveMode: false,
                    isOpen: false,
                    x: 0,
                    y: 0
                });
                if (_this.props.dragOptions) {
                    _this._events.off(window, 'keyup', _this._onKeyUp, true /* useCapture */);
                }
                // Call the onDismiss callback
                if (_this.props.onDismissed) {
                    _this.props.onDismissed();
                }
            };
            _this._onDragStart = function () {
                _this.setState({ isModalMenuOpen: false, isInKeyboardMoveMode: false });
            };
            _this._onDrag = function (_, ui) {
                var _a = _this.state, x = _a.x, y = _a.y;
                _this.setState({ x: x + ui.delta.x, y: y + ui.delta.y });
            };
            _this._onDragStop = function () {
                _this.focus();
            };
            _this._onKeyUp = function (event) {
                // Need to handle the CTRL + ALT + SPACE key during keyup due to FireFox bug:
                // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143
                // Otherwise it would continue to fire a click even if the event was cancelled
                // during mouseDown.
                if (event.altKey && event.ctrlKey && event.keyCode === Utilities_1.KeyCodes.space) {
                    // Since this is a global handler, we should make sure the target is within the dialog
                    // before opening the dropdown
                    if (Utilities_1.elementContains(_this._scrollableContent, event.target)) {
                        _this.setState({ isModalMenuOpen: !_this.state.isModalMenuOpen });
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }
            };
            // We need a global onKeyDown event when we are in the move mode so that we can
            // handle the key presses and the components inside the modal do not get the events
            _this._onKeyDown = function (event) {
                if (event.altKey && event.ctrlKey && event.keyCode === Utilities_1.KeyCodes.space) {
                    // CTRL + ALT + SPACE is handled during keyUp
                    event.preventDefault();
                    event.stopPropagation();
                    return;
                }
                if (_this.state.isModalMenuOpen && (event.altKey || event.keyCode === Utilities_1.KeyCodes.escape)) {
                    _this.setState({ isModalMenuOpen: false });
                }
                if (_this.state.isInKeyboardMoveMode && (event.keyCode === Utilities_1.KeyCodes.escape || event.keyCode === Utilities_1.KeyCodes.enter)) {
                    _this.setState({ isInKeyboardMoveMode: false });
                    event.preventDefault();
                    event.stopPropagation();
                }
                if (_this.state.isInKeyboardMoveMode) {
                    var handledEvent = true;
                    var delta = _this._getMoveDelta(event);
                    switch (event.keyCode) {
                        case Utilities_1.KeyCodes.escape:
                            _this.setState({ x: _this._lastSetX, y: _this._lastSetY });
                        case Utilities_1.KeyCodes.enter: {
                            _this._lastSetX = 0;
                            _this._lastSetY = 0;
                            _this.setState({ isInKeyboardMoveMode: false });
                            break;
                        }
                        case Utilities_1.KeyCodes.up: {
                            _this.setState({
                                y: _this.state.y - delta
                            });
                            break;
                        }
                        case Utilities_1.KeyCodes.down: {
                            _this.setState({
                                y: _this.state.y + delta
                            });
                            break;
                        }
                        case Utilities_1.KeyCodes.left: {
                            _this.setState({
                                x: _this.state.x - delta
                            });
                            break;
                        }
                        case Utilities_1.KeyCodes.right: {
                            _this.setState({
                                x: _this.state.x + delta
                            });
                            break;
                        }
                        default: {
                            handledEvent = false;
                        }
                    }
                    if (handledEvent) {
                        event.preventDefault();
                        event.stopPropagation();
                    }
                }
            };
            _this._onEnterKeyboardMoveMode = function () {
                _this._lastSetX = _this.state.x;
                _this._lastSetY = _this.state.y;
                _this.setState({ isInKeyboardMoveMode: true, isModalMenuOpen: false });
                _this._events.on(window, 'keydown', _this._onKeyDown, true /* useCapture */);
            };
            _this._onExitKeyboardMoveMode = function () {
                _this._lastSetX = 0;
                _this._lastSetY = 0;
                _this.setState({ isInKeyboardMoveMode: false });
                _this._events.off(window, 'keydown', _this._onKeyDown, true /* useCapture */);
            };
            _this.state = {
                id: Utilities_1.getId('Modal'),
                isOpen: props.isOpen,
                isVisible: props.isOpen,
                hasBeenOpened: props.isOpen,
                x: 0,
                y: 0
            };
            _this._lastSetX = 0;
            _this._lastSetY = 0;
            _this._warnDeprecations({
                onLayerDidMount: 'layerProps.onLayerDidMount'
            });
            return _this;
        }
        // tslint:disable-next-line function-name
        ModalBase.prototype.UNSAFE_componentWillReceiveProps = function (newProps) {
            clearTimeout(this._onModalCloseTimer);
            // Opening the dialog
            if (newProps.isOpen) {
                if (!this.state.isOpen) {
                    // First Open
                    this.setState({
                        isOpen: true
                    });
                    // Add a keyUp handler for all key up events when the dialog is open
                    if (newProps.dragOptions) {
                        this._events.on(window, 'keyup', this._onKeyUp, true /* useCapture */);
                    }
                }
                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(Modal_styles_1.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, overlay = _a.overlay, responsiveMode = _a.responsiveMode, titleAriaId = _a.titleAriaId, styles = _a.styles, subtitleAriaId = _a.subtitleAriaId, theme = _a.theme, topOffsetFixed = _a.topOffsetFixed, onLayerDidMount = _a.onLayerDidMount, isModeless = _a.isModeless, dragOptions = _a.dragOptions;
            var _b = this.state, isOpen = _b.isOpen, isVisible = _b.isVisible, hasBeenOpened = _b.hasBeenOpened, modalRectangleTop = _b.modalRectangleTop, x = _b.x, y = _b.y, isInKeyboardMoveMode = _b.isInKeyboardMoveMode;
            if (!isOpen) {
                return null;
            }
            var layerClassName = layerProps === undefined ? '' : layerProps.className;
            var classNames = getClassNames(styles, {
                theme: theme,
                className: className,
                containerClassName: containerClassName,
                scrollableContentClassName: scrollableContentClassName,
                isOpen: isOpen,
                isVisible: isVisible,
                hasBeenOpened: hasBeenOpened,
                modalRectangleTop: modalRectangleTop,
                topOffsetFixed: topOffsetFixed,
                isModeless: isModeless,
                layerClassName: layerClassName,
                isDefaultDragHandle: dragOptions && !dragOptions.dragHandleSelector
            });
            var mergedLayerProps = tslib_1.__assign({}, DefaultLayerProps, this.props.layerProps, { onLayerDidMount: layerProps && layerProps.onLayerDidMount ? layerProps.onLayerDidMount : onLayerDidMount, insertFirst: isModeless, className: classNames.layer });
            var modalContent = (React.createElement(index_1.FocusTrapZone, { componentRef: this._focusTrapZone, className: classNames.main, elementToFocusOnDismiss: elementToFocusOnDismiss, isClickableOutsideFocusTrap: isModeless || isClickableOutsideFocusTrap || !isBlocking, ignoreExternalFocusing: ignoreExternalFocusing, forceFocusInsideTrap: isModeless ? !isModeless : forceFocusInsideTrap, firstFocusableSelector: firstFocusableSelector, focusPreviouslyFocusedInnerElement: true, onBlur: isInKeyboardMoveMode ? this._onExitKeyboardMoveMode : undefined },
                dragOptions && isInKeyboardMoveMode && (React.createElement("div", { className: classNames.keyboardMoveIconContainer }, dragOptions.keyboardMoveIconProps ? (React.createElement(index_4.Icon, tslib_1.__assign({}, dragOptions.keyboardMoveIconProps))) : (React.createElement(index_4.Icon, { iconName: "move", className: classNames.keyboardMoveIcon })))),
                React.createElement("div", { ref: this._allowScrollOnModal, className: classNames.scrollableContent, "data-is-scrollable": true },
                    dragOptions && this.state.isModalMenuOpen && (React.createElement(dragOptions.menu, { items: [
                            { key: 'move', text: dragOptions.moveMenuItemText, onClick: this._onEnterKeyboardMoveMode },
                            { key: 'close', text: dragOptions.closeMenuItemText, onClick: this._onModalClose }
                        ], onDismiss: this._onModalContextMenuClose, alignTargetEdge: true, coverTarget: true, directionalHint: index_3.DirectionalHint.topLeftEdge, directionalHintFixed: true, shouldFocusOnMount: true, target: this._scrollableContent })),
                    this.props.children)));
            // @temp tuatology - Will adjust this to be a panel at certain breakpoints
            if (responsiveMode >= withResponsiveMode_1.ResponsiveMode.small) {
                return (React.createElement(Layer_1.Layer, tslib_1.__assign({}, mergedLayerProps),
                    React.createElement(index_2.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_1.Overlay, tslib_1.__assign({ isDarkThemed: isDarkOverlay, onClick: isBlocking ? undefined : onDismiss }, overlay)),
                            dragOptions ? (React.createElement(index_5.DraggableZone, { handleSelector: dragOptions.dragHandleSelector || "." + classNames.main.split(' ')[0], preventDragSelector: "button", onStart: this._onDragStart, onDragChange: this._onDrag, onStop: this._onDragStop, position: { x: x, y: y } }, modalContent)) : (modalContent)))));
            }
            return null;
        };
        ModalBase.prototype.focus = function () {
            if (this._focusTrapZone.current) {
                this._focusTrapZone.current.focus();
            }
        };
        ModalBase.prototype._getMoveDelta = function (event) {
            var delta = 10;
            if (event.shiftKey) {
                if (!event.ctrlKey) {
                    delta = 50;
                }
            }
            else if (event.ctrlKey) {
                delta = 1;
            }
            return delta;
        };
        ModalBase.defaultProps = {
            isOpen: false,
            isDarkOverlay: true,
            isBlocking: false,
            className: '',
            containerClassName: ''
        };
        ModalBase = tslib_1.__decorate([
            withResponsiveMode_1.withResponsiveMode
        ], ModalBase);
        return ModalBase;
    }(Utilities_1.BaseComponent));
    exports.ModalBase = ModalBase;
});
//# sourceMappingURL=Modal.base.js.map