UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,251 lines 52.9 kB
/**
 * DevExtreme (cjs/__internal/ui/overlay/overlay.js)
 * Version: 25.2.3
 * Build date: Fri Dec 12 2025
 *
 * Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.default = exports.OVERLAY_CONTENT_CLASS = void 0;
var _animation = require("../../../common/core/animation");
var _hide_callback = require("../../../common/core/environment/hide_callback");
var _events_engine = _interopRequireDefault(require("../../../common/core/events/core/events_engine"));
var _drag = require("../../../common/core/events/drag");
var _pointer = _interopRequireDefault(require("../../../common/core/events/pointer"));
var _short = require("../../../common/core/events/short");
var _utils = require("../../../common/core/events/utils");
var _visibility_change = require("../../../common/core/events/visibility_change");
var _component_registrator = _interopRequireDefault(require("../../../core/component_registrator"));
var _devices = _interopRequireDefault(require("../../../core/devices"));
var _dom_adapter = _interopRequireDefault(require("../../../core/dom_adapter"));
var _element = require("../../../core/element");
var _errors = _interopRequireDefault(require("../../../core/errors"));
var _renderer = _interopRequireDefault(require("../../../core/renderer"));
var _empty_template = require("../../../core/templates/empty_template");
var _browser = _interopRequireDefault(require("../../../core/utils/browser"));
var _common = require("../../../core/utils/common");
var _deferred = require("../../../core/utils/deferred");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _ready_callbacks = _interopRequireDefault(require("../../../core/utils/ready_callbacks"));
var _size = require("../../../core/utils/size");
var _type = require("../../../core/utils/type");
var _view_port = require("../../../core/utils/view_port");
var _ui = _interopRequireDefault(require("../../../ui/widget/ui.errors"));
var _m_dom = _interopRequireDefault(require("../../core/utils/m_dom"));
var _m_selectors = _interopRequireDefault(require("../../core/utils/m_selectors"));
var _m_window = _interopRequireDefault(require("../../core/utils/m_window"));
var _widget = _interopRequireDefault(require("../../core/widget/widget"));
var _overlay_position_controller = require("../../ui/overlay/overlay_position_controller");
var zIndexPool = _interopRequireWildcard(require("../../ui/overlay/z_index"));

function _getRequireWildcardCache(e) {
    if ("function" != typeof WeakMap) {
        return null
    }
    var r = new WeakMap,
        t = new WeakMap;
    return (_getRequireWildcardCache = function(e) {
        return e ? t : r
    })(e)
}

function _interopRequireWildcard(e, r) {
    if (!r && e && e.__esModule) {
        return e
    }
    if (null === e || "object" != typeof e && "function" != typeof e) {
        return {
            default: e
        }
    }
    var t = _getRequireWildcardCache(r);
    if (t && t.has(e)) {
        return t.get(e)
    }
    var n = {
            __proto__: null
        },
        a = Object.defineProperty && Object.getOwnPropertyDescriptor;
    for (var u in e) {
        if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
            var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
            i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]
        }
    }
    return n.default = e, t && t.set(e, n), n
}

function _interopRequireDefault(e) {
    return e && e.__esModule ? e : {
        default: e
    }
}
const ready = _ready_callbacks.default.add;
const window = _m_window.default.getWindow();
const viewPortChanged = _view_port.changeCallback;
const OVERLAY_STACK = [];
const ANONYMOUS_TEMPLATE_NAME = "content";
const TAB_KEY = "tab";
const OVERLAY_CLASS = "dx-overlay";
const OVERLAY_WRAPPER_CLASS = "dx-overlay-wrapper";
const OVERLAY_CONTENT_CLASS = exports.OVERLAY_CONTENT_CLASS = "dx-overlay-content";
const OVERLAY_SHADER_CLASS = "dx-overlay-shader";
const INNER_OVERLAY_CLASS = "dx-inner-overlay";
const INVISIBLE_STATE_CLASS = "dx-state-invisible";
const RTL_DIRECTION_CLASS = "dx-rtl";
const PREVENT_SAFARI_SCROLLING_CLASS = "dx-prevent-safari-scrolling";
ready((() => {
    _events_engine.default.subscribeGlobal(_dom_adapter.default.getDocument(), _pointer.default.down, (e => {
        for (let i = OVERLAY_STACK.length - 1; i >= 0; i -= 1) {
            var _OVERLAY_STACK$i$_pro, _OVERLAY_STACK$i;
            if (!(null !== (_OVERLAY_STACK$i$_pro = (_OVERLAY_STACK$i = OVERLAY_STACK[i])._proxiedDocumentDownHandler) && void 0 !== _OVERLAY_STACK$i$_pro && _OVERLAY_STACK$i$_pro.call(_OVERLAY_STACK$i, e))) {
                return
            }
        }
    }))
}));
class Overlay extends _widget.default {
    _supportedKeys() {
        return Object.assign({}, super._supportedKeys(), {
            escape() {
                this.hide()
            }
        })
    }
    _getDefaultOptions() {
        return Object.assign({}, super._getDefaultOptions(), {
            activeStateEnabled: false,
            visible: false,
            deferRendering: true,
            shading: true,
            shadingColor: "",
            wrapperAttr: {},
            position: Object.assign({}, _overlay_position_controller.OVERLAY_POSITION_ALIASES.center),
            width: "80vw",
            minWidth: null,
            maxWidth: null,
            height: "80vh",
            minHeight: null,
            maxHeight: null,
            animation: {
                show: {
                    type: "pop",
                    duration: 300,
                    from: {
                        scale: .55
                    }
                },
                hide: {
                    type: "pop",
                    duration: 300,
                    from: {
                        opacity: 1,
                        scale: 1
                    },
                    to: {
                        opacity: 0,
                        scale: .55
                    }
                }
            },
            hideOnOutsideClick: false,
            onShowing: null,
            onShown: null,
            onHiding: null,
            onHidden: null,
            contentTemplate: "content",
            innerOverlay: false,
            restorePosition: true,
            hideOnParentScroll: false,
            preventScrollEvents: true,
            onPositioned: null,
            propagateOutsideClick: false,
            ignoreChildEvents: true,
            _checkParentVisibility: true,
            _fixWrapperPosition: false,
            _loopFocus: false,
            _ignorePreventScrollEventsDeprecation: false,
            hideTopOverlayHandler: () => {
                this.hide()
            }
        })
    }
    _defaultOptionsRules() {
        const rules = [...super._defaultOptionsRules(), {
            device: () => !_m_window.default.hasWindow(),
            options: {
                width: null,
                height: null,
                animation: null,
                _checkParentVisibility: false
            }
        }];
        return rules
    }
    _setOptionsByReference() {
        super._setOptionsByReference();
        this._optionsByReference = Object.assign({}, this._optionsByReference, {
            animation: true
        })
    }
    $wrapper() {
        return this._$wrapper
    }
    _eventBindingTarget() {
        return this._$content
    }
    ctor(element, options) {
        super.ctor(element, options);
        if (options) {
            if ("preventScrollEvents" in options && !options._ignorePreventScrollEventsDeprecation) {
                this._logDeprecatedPreventScrollEventsInfo()
            }
        }
    }
    _logDeprecatedPreventScrollEventsInfo() {
        this._logDeprecatedOptionWarning("preventScrollEvents", {
            since: "23.1",
            message: "If you enable this option, end-users may experience scrolling issues."
        })
    }
    _init() {
        super._init();
        this._initActions();
        this._initHideOnOutsideClickHandler();
        this._initTabTerminatorHandler();
        this._customWrapperClass = null;
        this._$wrapper = (0, _renderer.default)("<div>").addClass("dx-overlay-wrapper");
        this._$content = (0, _renderer.default)("<div>").addClass(OVERLAY_CONTENT_CLASS);
        this._initInnerOverlayClass();
        const $element = this.$element();
        $element.addClass("dx-overlay");
        this._$wrapper.attr("data-bind", "dxControlsDescendantBindings: true");
        this._toggleViewPortSubscription(true);
        const {
            hideTopOverlayHandler: hideTopOverlayHandler
        } = this.option();
        this._initHideTopOverlayHandler(hideTopOverlayHandler);
        this._parentsScrollSubscriptionInfo = {
            handler: e => {
                this._hideOnParentsScrollHandler(e)
            }
        };
        this.warnPositionAsFunction()
    }
    warnPositionAsFunction() {
        const {
            position: position
        } = this.option();
        if ((0, _type.isFunction)(position)) {
            _errors.default.log("W0018")
        }
    }
    _initInnerOverlayClass() {
        var _this$_$content;
        const {
            innerOverlay: innerOverlay
        } = this.option();
        null === (_this$_$content = this._$content) || void 0 === _this$_$content || _this$_$content.toggleClass("dx-inner-overlay", innerOverlay)
    }
    _initHideTopOverlayHandler(handler) {
        if (handler) {
            this._hideTopOverlayHandler = handler
        }
    }
    _getActionsList() {
        return ["onShowing", "onShown", "onHiding", "onHidden", "onPositioned", "onVisualPositionChanged"]
    }
    _initActions() {
        this._actions = {};
        const actions = this._getActionsList();
        (0, _iterator.each)(actions, ((_, action) => {
            if (this._actions) {
                this._actions[action] = this._createActionByOption(action, {
                    excludeValidators: ["disabled", "readOnly"]
                }) || _common.noop
            }
        }))
    }
    _initHideOnOutsideClickHandler() {
        this._proxiedDocumentDownHandler = e => this._documentDownHandler(e)
    }
    _initMarkup() {
        super._initMarkup();
        this._renderWrapperAttributes();
        this._initPositionController()
    }
    _documentDownHandler(e) {
        var _this$_$content2, _this$_$content3;
        if (this._showAnimationProcessing) {
            this._stopAnimation()
        }
        const {
            target: target
        } = e;
        const $target = (0, _renderer.default)(target);
        const isTargetDocument = _m_dom.default.contains(window.document, target);
        const isAttachedTarget = (0, _renderer.default)(window.document).is($target) || isTargetDocument;
        const isInnerOverlay = (0, _renderer.default)($target).closest(".dx-inner-overlay").length;
        const isTargetContent = null === (_this$_$content2 = this._$content) || void 0 === _this$_$content2 ? void 0 : _this$_$content2.is($target);
        const content = null === (_this$_$content3 = this._$content) || void 0 === _this$_$content3 ? void 0 : _this$_$content3.get(0);
        const isTargetInContent = content ? _m_dom.default.contains(content, target) : false;
        const isOutsideClick = isAttachedTarget && !isInnerOverlay && !(isTargetContent || isTargetInContent);
        if (isOutsideClick && this._shouldHideOnOutsideClick(e)) {
            this._outsideClickHandler(e)
        }
        const {
            propagateOutsideClick: propagateOutsideClick
        } = this.option();
        return Boolean(propagateOutsideClick)
    }
    _shouldHideOnOutsideClick(e) {
        const {
            hideOnOutsideClick: hideOnOutsideClick
        } = this.option();
        if ((0, _type.isFunction)(hideOnOutsideClick)) {
            return hideOnOutsideClick(e)
        }
        return Boolean(hideOnOutsideClick)
    }
    _outsideClickHandler(e) {
        const {
            shading: shading
        } = this.option();
        if (shading) {
            e.preventDefault()
        }
        this.hide()
    }
    _getAnonymousTemplateName() {
        return "content"
    }
    _initTemplates() {
        this._templateManager.addDefaultTemplates({
            content: new _empty_template.EmptyTemplate
        });
        super._initTemplates()
    }
    _isTopOverlay() {
        const overlayStack = this._overlayStack();
        for (let i = overlayStack.length - 1; i >= 0; i -= 1) {
            const tabbableElements = overlayStack[i]._findTabbableBounds();
            if (tabbableElements.$first || tabbableElements.$last) {
                return overlayStack[i] === this
            }
        }
        return false
    }
    _overlayStack() {
        return OVERLAY_STACK
    }
    _zIndexInitValue() {
        return Overlay.baseZIndex()
    }
    _toggleViewPortSubscription(toggle) {
        if (this._viewPortChangeHandle) {
            viewPortChanged.remove(this._viewPortChangeHandle)
        }
        if (toggle) {
            this._viewPortChangeHandle = () => {
                this._viewPortChangeHandler()
            };
            viewPortChanged.add(this._viewPortChangeHandle)
        }
    }
    _viewPortChangeHandler() {
        const {
            container: container
        } = this.option();
        this._positionController.updateContainer(container);
        this._refresh()
    }
    _renderWrapperAttributes() {
        const {
            wrapperAttr: wrapperAttr
        } = this.option();
        const attributes = Object.assign({}, wrapperAttr);
        const classNames = attributes.class;
        delete attributes.class;
        const $wrapper = this.$wrapper();
        null === $wrapper || void 0 === $wrapper || $wrapper.attr(attributes);
        if (this._customWrapperClass) {
            null === $wrapper || void 0 === $wrapper || $wrapper.removeClass(this._customWrapperClass)
        }
        null === $wrapper || void 0 === $wrapper || $wrapper.addClass(classNames);
        this._customWrapperClass = classNames
    }
    _renderVisibilityAnimate(visible) {
        this._stopAnimation();
        return visible ? this._show() : this._hide()
    }
    _getAnimationConfig() {
        return this._getOptionValue("animation", this) ?? {}
    }
    _toggleBodyScroll(enabled) {}
    _animateShowing() {
        const animation = this._getAnimationConfig();
        const showAnimation = this._normalizeAnimation(animation.show, "to");
        const startShowAnimation = (null === showAnimation || void 0 === showAnimation ? void 0 : showAnimation.start) ?? _common.noop;
        const completeShowAnimation = (null === showAnimation || void 0 === showAnimation ? void 0 : showAnimation.complete) ?? _common.noop;
        this._animate(showAnimation, ((element, config) => {
            var _this$_actions, _this$_actions$onShow;
            if (this._isAnimationPaused) {
                return
            }
            const {
                focusStateEnabled: focusStateEnabled
            } = this.option();
            if (focusStateEnabled) {
                _events_engine.default.trigger(this._focusTarget(), "focus")
            }
            completeShowAnimation.call(this, element, config);
            this._showAnimationProcessing = false;
            this._isHidden = false;
            null === (_this$_actions = this._actions) || void 0 === _this$_actions || null === (_this$_actions$onShow = _this$_actions.onShown) || void 0 === _this$_actions$onShow || _this$_actions$onShow.call(_this$_actions);
            this._toggleSafariScrolling();
            this._showingDeferred.resolve()
        }), ((element, config) => {
            if (this._isAnimationPaused) {
                return
            }
            startShowAnimation.call(this, element, config);
            this._showAnimationProcessing = true
        }))
    }
    _processShowingHidingCancel(cancelArg, applyFunction, cancelFunction) {
        if ((0, _type.isPromise)(cancelArg)) {
            cancelArg.then((shouldCancel => {
                if (shouldCancel) {
                    cancelFunction()
                } else {
                    applyFunction()
                }
            })).catch((() => applyFunction()))
        } else if (cancelArg) {
            cancelFunction()
        } else {
            applyFunction()
        }
    }
    _show() {
        this._showingDeferred = (0, _deferred.Deferred)();
        this._parentHidden = this._isParentHidden();
        this._showingDeferred.done((() => {
            delete this._parentHidden
        }));
        if (this._parentHidden) {
            this._isHidden = true;
            return this._showingDeferred.resolve()
        }
        if (this._currentVisible) {
            return (0, _deferred.Deferred)().resolve().promise()
        }
        this._currentVisible = true;
        if (this._isHidingActionCanceled) {
            delete this._isHidingActionCanceled;
            this._showingDeferred.reject()
        } else {
            const show = () => {
                var _this$_$content4, _this$_$content5, _this$_actions2, _this$_actions2$onSho;
                this._stopAnimation();
                const {
                    enableBodyScroll: enableBodyScroll
                } = this.option();
                this._toggleBodyScroll(enableBodyScroll);
                this._toggleVisibility(true);
                null === (_this$_$content4 = this._$content) || void 0 === _this$_$content4 || _this$_$content4.css("visibility", "hidden");
                null === (_this$_$content5 = this._$content) || void 0 === _this$_$content5 || _this$_$content5.toggleClass("dx-state-invisible", false);
                this._updateZIndexStackPosition(true);
                this._positionController.openingHandled();
                this._renderContent();
                const showingArgs = {
                    cancel: false
                };
                null === (_this$_actions2 = this._actions) || void 0 === _this$_actions2 || null === (_this$_actions2$onSho = _this$_actions2.onShowing) || void 0 === _this$_actions2$onSho || _this$_actions2$onSho.call(_this$_actions2, showingArgs);
                this._processShowingHidingCancel(showingArgs.cancel, (() => {
                    var _this$_$content8;
                    null === (_this$_$content8 = this._$content) || void 0 === _this$_$content8 || _this$_$content8.css("visibility", "");
                    this._renderVisibility(true);
                    this._animateShowing()
                }), (() => {
                    var _this$_$content6, _this$_$content7;
                    this._toggleVisibility(false);
                    null === (_this$_$content6 = this._$content) || void 0 === _this$_$content6 || _this$_$content6.css("visibility", "");
                    null === (_this$_$content7 = this._$content) || void 0 === _this$_$content7 || _this$_$content7.toggleClass("dx-state-invisible", true);
                    this._isShowingActionCanceled = true;
                    this._moveFromContainer();
                    this._toggleBodyScroll(true);
                    this.option("visible", false);
                    this._showingDeferred.resolve()
                }))
            };
            show()
        }
        return this._showingDeferred.promise()
    }
    _normalizeAnimation(showHideConfig, direction) {
        if (!showHideConfig) {
            return
        }
        const configuration = Object.assign({
            type: "slide",
            skipElementInitialStyles: true
        }, showHideConfig);
        if ((0, _type.isObject)(configuration[direction])) {
            (0, _extend.extend)(configuration[direction], {
                position: this._positionController.position
            })
        }
        return configuration
    }
    _animateHiding() {
        const animation = this._getAnimationConfig();
        const hideAnimation = this._normalizeAnimation(animation.hide, "from");
        const startHideAnimation = (null === hideAnimation || void 0 === hideAnimation ? void 0 : hideAnimation.start) ?? _common.noop;
        const completeHideAnimation = (null === hideAnimation || void 0 === hideAnimation ? void 0 : hideAnimation.complete) ?? _common.noop;
        this._animate(hideAnimation, ((element, config) => {
            var _this$_$content9, _this$_actions3, _this$_actions3$onHid;
            null === (_this$_$content9 = this._$content) || void 0 === _this$_$content9 || _this$_$content9.css("pointerEvents", "");
            this._renderVisibility(false);
            completeHideAnimation.call(this, element, config);
            this._hideAnimationProcessing = false;
            null === (_this$_actions3 = this._actions) || void 0 === _this$_actions3 || null === (_this$_actions3$onHid = _this$_actions3.onHidden) || void 0 === _this$_actions3$onHid || _this$_actions3$onHid.call(_this$_actions3);
            this._hidingDeferred.resolve()
        }), ((element, config) => {
            var _this$_$content10;
            null === (_this$_$content10 = this._$content) || void 0 === _this$_$content10 || _this$_$content10.css("pointerEvents", "none");
            startHideAnimation.call(this, element, config);
            this._hideAnimationProcessing = true
        }))
    }
    _hide() {
        if (!this._currentVisible) {
            return (0, _deferred.Deferred)().resolve().promise()
        }
        this._currentVisible = false;
        this._hidingDeferred = (0, _deferred.Deferred)();
        const hidingArgs = {
            cancel: false
        };
        if (this._isShowingActionCanceled) {
            delete this._isShowingActionCanceled;
            this._hidingDeferred.reject()
        } else {
            var _this$_actions4, _this$_actions4$onHid;
            null === (_this$_actions4 = this._actions) || void 0 === _this$_actions4 || null === (_this$_actions4$onHid = _this$_actions4.onHiding) || void 0 === _this$_actions4$onHid || _this$_actions4$onHid.call(_this$_actions4, hidingArgs);
            this._toggleSafariScrolling();
            this._toggleBodyScroll(true);
            const cancelHide = () => {
                this._isHidingActionCanceled = true;
                const {
                    enableBodyScroll: enableBodyScroll
                } = this.option();
                this._toggleBodyScroll(enableBodyScroll);
                this.option("visible", true);
                this._hidingDeferred.resolve()
            };
            const applyHide = () => {
                this._forceFocusLost();
                this._toggleShading(false);
                this._toggleSubscriptions(false);
                this._animateHiding()
            };
            this._processShowingHidingCancel(hidingArgs.cancel, applyHide, cancelHide)
        }
        return this._hidingDeferred.promise()
    }
    _forceFocusLost() {
        var _this$_$content11;
        const activeElement = _dom_adapter.default.getActiveElement();
        const shouldResetActiveElement = !!(null !== (_this$_$content11 = this._$content) && void 0 !== _this$_$content11 && _this$_$content11.find(activeElement).length);
        if (shouldResetActiveElement) {
            _m_dom.default.resetActiveElement()
        }
    }
    _animate(animation, completeCallback, startCallback) {
        if (animation) {
            const actualStartCallback = startCallback ?? animation.start ?? _common.noop;
            const configuration = Object.assign({}, animation, {
                start: actualStartCallback,
                complete: completeCallback
            });
            if (this._$content) {
                _animation.fx.animate(this._$content.get(0), configuration)
            }
        } else {
            completeCallback()
        }
    }
    _stopAnimation() {
        if (this._$content) {
            _animation.fx.stop(this._$content.get(0), true)
        }
    }
    _renderVisibility(visible) {
        if (visible && this._isParentHidden()) {
            return
        }
        this._currentVisible = visible;
        this._stopAnimation();
        if (!visible) {
            (0, _visibility_change.triggerHidingEvent)(this._$content)
        }
        if (visible) {
            this._checkContainerExists();
            this._moveToContainer();
            this._renderGeometry();
            (0, _visibility_change.triggerShownEvent)(this._$content);
            (0, _visibility_change.triggerResizeEvent)(this._$content)
        } else {
            var _this$_$content12;
            this._toggleVisibility(visible);
            null === (_this$_$content12 = this._$content) || void 0 === _this$_$content12 || _this$_$content12.toggleClass("dx-state-invisible", !visible);
            this._updateZIndexStackPosition(visible);
            this._moveFromContainer()
        }
        this._toggleShading(visible);
        this._toggleSubscriptions(visible)
    }
    _handleZIndexOptionChanged() {
        const {
            zIndex: zIndex
        } = this.option();
        this._zIndex = zIndex ?? zIndexPool.create(this._zIndexInitValue());
        this._updateZIndexStackPosition(this._isVisible())
    }
    _updateZIndexStackPosition(pushToStack) {
        const overlayStack = this._overlayStack();
        const index = overlayStack.indexOf(this);
        const isInStack = -1 !== index;
        const {
            zIndex: zIndex
        } = this.option();
        if (!pushToStack) {
            if (isInStack) {
                overlayStack.splice(index, 1);
                zIndexPool.remove(this._zIndex)
            }
            return
        }
        if (!isInStack) {
            this._zIndex = zIndex ?? zIndexPool.create(this._zIndexInitValue());
            overlayStack.push(this)
        }
        this._updateZIndex()
    }
    _updateZIndex() {
        var _this$_$wrapper, _this$_$content13;
        null === (_this$_$wrapper = this._$wrapper) || void 0 === _this$_$wrapper || _this$_$wrapper.css("zIndex", this._zIndex);
        null === (_this$_$content13 = this._$content) || void 0 === _this$_$content13 || _this$_$content13.css("zIndex", this._zIndex)
    }
    _toggleShading(visible) {
        var _this$_$wrapper2, _this$_$wrapper3;
        const {
            shading: shading,
            shadingColor: shadingColor
        } = this.option();
        null === (_this$_$wrapper2 = this._$wrapper) || void 0 === _this$_$wrapper2 || _this$_$wrapper2.toggleClass("dx-overlay-shader", visible && shading);
        null === (_this$_$wrapper3 = this._$wrapper) || void 0 === _this$_$wrapper3 || _this$_$wrapper3.css("backgroundColor", shading ? shadingColor ?? "" : "");
        this._toggleTabTerminator(Boolean(visible && shading))
    }
    _initTabTerminatorHandler() {
        this._proxiedTabTerminatorHandler = e => {
            this._tabKeyHandler(e)
        }
    }
    _toggleTabTerminator(enabled) {
        const {
            _loopFocus: _loopFocus
        } = this.option();
        const eventName = (0, _utils.addNamespace)("keydown", this.NAME);
        if (_loopFocus || enabled) {
            _events_engine.default.on(_dom_adapter.default.getDocument(), eventName, this._proxiedTabTerminatorHandler)
        } else {
            this._destroyTabTerminator()
        }
    }
    _destroyTabTerminator() {
        const eventName = (0, _utils.addNamespace)("keydown", this.NAME);
        _events_engine.default.off(_dom_adapter.default.getDocument(), eventName, this._proxiedTabTerminatorHandler)
    }
    _findTabbableBounds() {
        var _this$_$wrapper4;
        const $elements = null === (_this$_$wrapper4 = this._$wrapper) || void 0 === _this$_$wrapper4 ? void 0 : _this$_$wrapper4.find("*");
        const elementsCount = ((null === $elements || void 0 === $elements ? void 0 : $elements.length) ?? 0) - 1;
        let $first = null;
        let $last = null;
        for (let i = 0; i <= elementsCount; i += 1) {
            const $currentElement = (null === $elements || void 0 === $elements ? void 0 : $elements.eq(i)) ?? null;
            const $reverseElement = (null === $elements || void 0 === $elements ? void 0 : $elements.eq(elementsCount - i)) ?? null;
            if (!$first && $currentElement.is(_m_selectors.default.tabbable)) {
                $first = $currentElement
            }
            if (!$last && $reverseElement.is(_m_selectors.default.tabbable)) {
                $last = $reverseElement
            }
            if ($first && $last) {
                break
            }
        }
        return {
            $first: $first,
            $last: $last
        }
    }
    _tabKeyHandler(e) {
        var _this$_$wrapper5;
        if ("tab" !== (0, _utils.normalizeKeyName)(e) || !this._isTopOverlay()) {
            return
        }
        const wrapper = null === (_this$_$wrapper5 = this._$wrapper) || void 0 === _this$_$wrapper5 ? void 0 : _this$_$wrapper5.get(0);
        const activeElement = _dom_adapter.default.getActiveElement(wrapper);
        const {
            $first: $firstTabbable,
            $last: $lastTabbable
        } = this._findTabbableBounds();
        const isTabOnLast = !e.shiftKey && activeElement === (null === $lastTabbable || void 0 === $lastTabbable ? void 0 : $lastTabbable.get(0));
        const isShiftTabOnFirst = e.shiftKey && activeElement === (null === $firstTabbable || void 0 === $firstTabbable ? void 0 : $firstTabbable.get(0));
        const isOutsideTarget = !_m_dom.default.contains(wrapper, activeElement);
        const shouldPreventDefault = isTabOnLast || isShiftTabOnFirst || isOutsideTarget;
        if (shouldPreventDefault) {
            e.preventDefault();
            const $focusElement = e.shiftKey ? $lastTabbable : $firstTabbable;
            _events_engine.default.trigger($focusElement, "focusin");
            _events_engine.default.trigger($focusElement, "focus")
        }
    }
    _toggleSubscriptions(enabled) {
        if (_m_window.default.hasWindow()) {
            this._toggleHideTopOverlayCallback(enabled);
            this._toggleHideOnParentsScrollSubscription(enabled)
        }
    }
    _toggleHideTopOverlayCallback(subscribe) {
        if (!this._hideTopOverlayHandler) {
            return
        }
        if (subscribe) {
            _hide_callback.hideCallback.add(this._hideTopOverlayHandler)
        } else {
            _hide_callback.hideCallback.remove(this._hideTopOverlayHandler)
        }
    }
    _toggleHideOnParentsScrollSubscription(needSubscribe) {
        const scrollEvent = (0, _utils.addNamespace)("scroll", this.NAME);
        const info = this._parentsScrollSubscriptionInfo ?? {};
        const {
            prevTargets: prevTargets,
            handler: handler
        } = info;
        _events_engine.default.off(prevTargets, scrollEvent, handler);
        const {
            hideOnParentScroll: hideOnParentScroll
        } = this.option();
        if (needSubscribe && hideOnParentScroll) {
            var _this$_getHideOnParen;
            let $parents = null === (_this$_getHideOnParen = this._getHideOnParentScrollTarget()) || void 0 === _this$_getHideOnParen ? void 0 : _this$_getHideOnParen.parents();
            if ("desktop" === _devices.default.real().deviceType) {
                var _$parents;
                $parents = null === (_$parents = $parents) || void 0 === _$parents ? void 0 : _$parents.add(window)
            }
            _events_engine.default.on($parents, scrollEvent, handler);
            this._parentsScrollSubscriptionInfo = Object.assign({}, info, {
                prevTargets: $parents
            })
        }
    }
    _hideOnParentsScrollHandler(e) {
        let hideHandled = false;
        const {
            hideOnParentScroll: hideOnParentScroll
        } = this.option();
        if ((0, _type.isFunction)(hideOnParentScroll)) {
            hideHandled = hideOnParentScroll(e)
        }
        if (!hideHandled && !this._showAnimationProcessing) {
            this.hide()
        }
    }
    _getHideOnParentScrollTarget() {
        const {
            _hideOnParentScrollTarget: _hideOnParentScrollTarget
        } = this.option();
        const $hideOnParentScrollTarget = (0, _renderer.default)(_hideOnParentScrollTarget);
        if ($hideOnParentScrollTarget.length) {
            return $hideOnParentScrollTarget
        }
        return this._$wrapper
    }
    _render() {
        super._render();
        this._appendContentToElement();
        this._renderVisibilityAnimate(this._isVisible())
    }
    _appendContentToElement() {
        var _this$_$content14;
        if (!(null !== (_this$_$content14 = this._$content) && void 0 !== _this$_$content14 && _this$_$content14.parent().is(this.$element()))) {
            var _this$_$content15;
            null === (_this$_$content15 = this._$content) || void 0 === _this$_$content15 || _this$_$content15.appendTo(this.$element())
        }
    }
    _renderContent() {
        const {
            deferRendering: deferRendering
        } = this.option();
        const shouldDeferRendering = !this._currentVisible && deferRendering;
        const isParentHidden = this._isVisible() && this._isParentHidden();
        if (isParentHidden) {
            this._isHidden = true;
            return
        }
        if (this._contentAlreadyRendered || shouldDeferRendering) {
            return
        }
        this._contentAlreadyRendered = true;
        this._appendContentToElement();
        super._renderContent()
    }
    _isParentHidden() {
        const {
            _checkParentVisibility: _checkParentVisibility
        } = this.option();
        if (!_checkParentVisibility) {
            return false
        }
        if (void 0 !== this._parentHidden) {
            return this._parentHidden
        }
        const $parent = this.$element().parent();
        if ($parent.is(":visible")) {
            return false
        }
        let isHidden = false;
        $parent.add($parent.parents()).each(((index, element) => {
            const $element = (0, _renderer.default)(element);
            if ("none" === $element.css("display")) {
                isHidden = true;
                return false
            }
            return
        }));
        return isHidden || !_dom_adapter.default.getBody().contains($parent.get(0))
    }
    _renderContentImpl() {
        const {
            contentTemplate: contentTemplateOption
        } = this.option();
        const whenContentRendered = (0, _deferred.Deferred)();
        const contentTemplate = this._getTemplate(contentTemplateOption);
        const transclude = this._templateManager.anonymousTemplateName === contentTemplateOption;
        null === contentTemplate || void 0 === contentTemplate || contentTemplate.render({
            container: this.content(),
            noModel: true,
            transclude: transclude,
            onRendered: () => {
                whenContentRendered.resolve();
                const {
                    templatesRenderAsynchronously: templatesRenderAsynchronously
                } = this.option();
                if (templatesRenderAsynchronously) {
                    this._dimensionChanged()
                }
            }
        });
        const {
            preventScrollEvents: preventScrollEvents
        } = this.option();
        this._toggleWrapperScrollEventsSubscription(preventScrollEvents);
        whenContentRendered.done((() => {
            this._processContentRendering()
        }));
        return whenContentRendered.promise()
    }
    _processContentRendering() {
        if (this._isVisible()) {
            this._moveToContainer()
        }
    }
    _getPositionControllerConfig() {
        var _this$_actions5, _this$_actions6;
        const {
            container: container,
            visualContainer: visualContainer,
            restorePosition: restorePosition,
            _fixWrapperPosition: _fixWrapperPosition,
            _skipContentPositioning: _skipContentPositioning
        } = this.option();
        const properties = {
            container: container,
            visualContainer: visualContainer,
            restorePosition: restorePosition,
            _fixWrapperPosition: _fixWrapperPosition,
            _skipContentPositioning: _skipContentPositioning,
            onPositioned: null === (_this$_actions5 = this._actions) || void 0 === _this$_actions5 ? void 0 : _this$_actions5.onPositioned,
            onVisualPositionChanged: null === (_this$_actions6 = this._actions) || void 0 === _this$_actions6 ? void 0 : _this$_actions6.onVisualPositionChanged
        };
        const elements = {
            $root: this.$element(),
            $content: this._$content,
            $wrapper: this._$wrapper
        };
        const positionControllerConfiguration = {
            properties: properties,
            elements: elements
        };
        return positionControllerConfiguration
    }
    _initPositionController() {
        this._positionController = new _overlay_position_controller.OverlayPositionController(this._getPositionControllerConfig())
    }
    _toggleWrapperScrollEventsSubscription(enabled) {
        const eventName = (0, _utils.addNamespace)(_drag.move, this.NAME);
        _events_engine.default.off(this._$wrapper, eventName);
        if (enabled) {
            const callback = e => {
                const {
                    originalEvent: originalEvent
                } = e.originalEvent;
                const {
                    type: type
                } = originalEvent ?? {};
                const isWheel = "wheel" === type;
                const isMouseMove = "mousemove" === type;
                const isScrollByWheel = isWheel && (0, _utils.isCommandKeyPressed)(e);
                e._cancelPreventDefault = true;
                if (originalEvent && false !== e.cancelable && !(isMouseMove || isScrollByWheel)) {
                    e.preventDefault()
                }
            };
            const options = {
                validate: () => true,
                getDirection: () => "both",
                _toggleGestureCover(toggle) {
                    if (!toggle) {
                        this._toggleGestureCoverImpl(toggle)
                    }
                },
                _clearSelection: _common.noop,
                isNative: true
            };
            _events_engine.default.on(this._$wrapper, eventName, options, callback)
        }
    }
    _moveFromContainer() {
        var _this$_$content16, _this$_$wrapper6;
        null === (_this$_$content16 = this._$content) || void 0 === _this$_$content16 || _this$_$content16.appendTo(this.$element());
        null === (_this$_$wrapper6 = this._$wrapper) || void 0 === _this$_$wrapper6 || _this$_$wrapper6.detach()
    }
    _checkContainerExists() {
        const $wrapperContainer = this._positionController.$container;
        if (void 0 === $wrapperContainer) {
            return
        }
        const containerExists = $wrapperContainer.length > 0;
        if (!containerExists) {
            _ui.default.log("W1021", this.NAME)
        }
    }
    _moveToContainer() {
        const $wrapperContainer = this._positionController.$container;
        if (void 0 !== $wrapperContainer) {
            var _this$_$wrapper7;
            null === (_this$_$wrapper7 = this._$wrapper) || void 0 === _this$_$wrapper7 || _this$_$wrapper7.appendTo($wrapperContainer)
        }
        if (this._$wrapper) {
            var _this$_$content17;
            null === (_this$_$content17 = this._$content) || void 0 === _this$_$content17 || _this$_$content17.appendTo(this._$wrapper)
        }
    }
    _renderGeometry() {
        if (this._isVisible() && _m_window.default.hasWindow()) {
            this._stopAnimation();
            this._renderGeometryImpl()
        }
    }
    _renderGeometryImpl() {
        this._positionController.updatePosition(this._getOptionValue("position"));
        this._renderWrapper();
        this._renderDimensions();
        this._renderPosition()
    }
    _renderPosition(state) {
        this._positionController.positionContent()
    }
    _isAllWindowCovered() {
        var _this$_positionContro;
        const {
            shading: shading
        } = this.option();
        const element = null === (_this$_positionContro = this._positionController.$visualContainer) || void 0 === _this$_positionContro ? void 0 : _this$_positionContro.get(0);
        return (0, _type.isWindow)(element) && Boolean(shading)
    }
    _toggleSafariScrolling() {
        const visible = this._isVisible();
        const $body = (0, _renderer.default)(_dom_adapter.default.getBody());
        const isIosSafari = "ios" === _devices.default.real().platform && _browser.default.safari;
        const isAllWindowCovered = this._isAllWindowCovered();
        const isScrollingPrevented = $body.hasClass("dx-prevent-safari-scrolling");
        const shouldPreventScrolling = !isScrollingPrevented && visible && isAllWindowCovered;
        const shouldEnableScrolling = isScrollingPrevented && (!visible || !isAllWindowCovered || this._disposed);
        if (isIosSafari) {
            if (shouldEnableScrolling) {
                $body.removeClass("dx-prevent-safari-scrolling");
                window.scrollTo(0, this._cachedBodyScrollTop);
                this._cachedBodyScrollTop = void 0
            } else if (shouldPreventScrolling) {
                this._cachedBodyScrollTop = window.pageYOffset;
                $body.addClass("dx-prevent-safari-scrolling")
            }
        }
    }
    _renderWrapper() {
        this._positionController.styleWrapperPosition();
        this._renderWrapperDimensions();
        this._positionController.positionWrapper()
    }
    _renderWrapperDimensions() {
        var _this$_$wrapper8;
        const {
            $visualContainer: $visualContainer
        } = this._positionController;
        const documentElement = _dom_adapter.default.getDocumentElement();
        const isVisualContainerWindow = (0, _type.isWindow)(null === $visualContainer || void 0 === $visualContainer ? void 0 : $visualContainer.get(0));
        const wrapperWidth = isVisualContainerWindow ? documentElement.clientWidth : (0, _size.getOuterWidth)($visualContainer);
        const wrapperHeight = isVisualContainerWindow ? window.innerHeight : (0, _size.getOuterHeight)($visualContainer);
        null === (_this$_$wrapper8 = this._$wrapper) || void 0 === _this$_$wrapper8 || _this$_$wrapper8.css({
            width: wrapperWidth,
            height: wrapperHeight
        })
    }
    _renderDimensions() {
        var _this$_$content18, _this$_$content19;
        const content = null === (_this$_$content18 = this._$content) || void 0 === _this$_$content18 ? void 0 : _this$_$content18.get(0);
        null === (_this$_$content19 = this._$content) || void 0 === _this$_$content19 || _this$_$content19.css({
            minWidth: this._getOptionValue("minWidth", content),
            maxWidth: this._getOptionValue("maxWidth", content),
            minHeight: this._getOptionValue("minHeight", content),
            maxHeight: this._getOptionValue("maxHeight", content),
            width: this._getOptionValue("width", content),
            height: this._getOptionValue("height", content)
        })
    }
    _focusTarget() {
        return this._$content
    }
    _attachKeyboardEvents() {
        this._keyboardListenerId = _short.keyboard.on(this._$content, null, (options => this._keyboardHandler(options)))
    }
    _keyboardHandler(options, onlyChildProcessing) {
        const e = options.originalEvent;
        const $target = (0, _renderer.default)(e.target);
        const {
            ignoreChildEvents: ignoreChildEvents
        } = this.option();
        if ($target.is(this._$content ?? "") || !ignoreChildEvents) {
            super._keyboardHandler(options, onlyChildProcessing)
        }
    }
    _isVisible() {
        const visible = this.option("visible");
        return Boolean(visible)
    }
    _visibilityChanged(visible) {
        if (visible) {
            if (this._isVisible()) {
                this._renderVisibilityAnimate(visible)
            }
        } else {
            this._renderVisibilityAnimate(visible)
        }
    }
    _dimensionChanged() {
        this._renderGeometry()
    }
    _clean() {
        if (!this._contentAlreadyRendered) {
            var _this$$content;
            null === (_this$$content = this.$content()) || void 0 === _this$$content || _this$$content.empty()
        }
        this._renderVisibility(false);
        this._cleanFocusState()
    }
    _dispose() {
        var _this$_$wrapper9, _this$_$content20;
        if (this._$content) {
            _animation.fx.stop(this._$content.get(0), false)
        }
        this._toggleViewPortSubscription(false);
        this._toggleSubscriptions(false);
        this._updateZIndexStackPosition(false);
        super._dispose();
        this._toggleSafariScrolling();
        if (this._isVisible()) {
            zIndexPool.remove(this._zIndex)
        }
        this._destroyTabTerminator();
        this._positionController.clean();
        this._actions = {};
        this._parentsScrollSubscriptionInfo = void 0;
        null === (_this$_$wrapper9 = this._$wrapper) || void 0 === _this$_$wrapper9 || _this$_$wrapper9.remove();
        null === (_this$_$content20 = this._$content) || void 0 === _this$_$content20 || _this$_$content20.remove();
        this._$wrapper = null;
        this._$content = null
    }
    _toggleRTLDirection(rtl) {
        var _this$_$content21;
        null === (_this$_$content21 = this._$content) || void 0 === _this$_$content21 || _this$_$content21.toggleClass("dx-rtl", rtl)
    }
    _optionChanged(args) {
        const {
            value: value,
            name: name
        } = args;
        if (this._getActionsList().includes(name)) {
            this._initActions();
            return
        }
        switch (name) {
            case "animation":
            case "hideOnOutsideClick":
            case "propagateOutsideClick":
                break;
            case "_loopFocus":
            case "shading":
                this._toggleShading(this._isVisible());
                this._toggleSafariScrolling();
                break;
            case "shadingColor":
                this._toggleShading(this._isVisible());
                break;
            case "width":
            case "height":
            case "minWidth":
            case "maxWidth":
            case "minHeight":
            case "maxHeight":
                this._renderGeometry();
                break;
            case "position": {
                const {
                    position: position
                } = this.option();
                this._positionController.updatePosition(position);
                this._positionController.restorePositionOnNextRender(true);
                this._renderGeometry();
                this._toggleSafariScrolling();
                break
            }
            case "visible":
                this._renderVisibilityAnimate(Boolean(value)).done((() => {
                    var _this$_animateDeferre;
                    return null === (_this$_animateDeferre = this._animateDeferred) || void 0 === _this$_animateDeferre ? void 0 : _this$_animateDeferre.resolveWith(this)
                })).fail((() => {
                    var _this$_animateDeferre2;
                    return null === (_this$_animateDeferre2 = this._animateDeferred) || void 0 === _this$_animateDeferre2 ? void 0 : _this$_animateDeferre2.reject()
                }));
                break;
            case "container":
                this._positionController.updateContainer(value);
                this._invalidate();
                this._toggleSafariScrolling();
                break;
            case "visualContainer":
                this._positionController.updateVisualContainer(value);
                this._renderWrapper();
                this._toggleSafariScrolling();
                break;
            case "innerOverlay":
                this._initInnerOverlayClass();
                break;
            case "deferRendering":
            case "contentTemplate":
                this._contentAlreadyRendered = false;
                this._clean();
                this._invalidate();
                break;
            case "hideTopOverlayHandler":
                this._toggleHideTopOverlayCallback(false);
                this._initHideTopOverlayHandler(value);
                this._toggleHideTopOverlayCallback(this._isVisible());
                break;
            case "zIndex":
                this._handleZIndexOptionChanged();
                break;
            case "hideOnParentScroll":
            case "_hideOnParentScrollTarget":
                this._toggleHideOnParentsScrollSubscription(this._isVisible());
                break;
            case "rtlEnabled":
                this._contentAlreadyRendered = false;
                super._optionChanged(args);
                break;
            case "_fixWrapperPosition":
                this._positionController.fixWrapperPosition = value;
                break;
            case "wrapperAttr":
                this._renderWrapperAttributes();
                break;
            case "restorePosition":
                this._positionController.restorePosition = value;
                break;
            case "preventScrollEvents":
                this._logDeprecatedPreventScrollEventsInfo();
                this._toggleWrapperScrollEventsSubscription(value);
                break;
            default:
                super._optionChanged(args)
        }
    }
    toggle(showing) {
        const visible = this._isVisible();
        const isShowing = showing ?? !visible;
        const result = (0, _deferred.Deferred)();
        if (isShowing === visible) {
            return result.resolveWith(this, [isShowing]).promise()
        }
        const animateDeferred = (0, _deferred.Deferred)();
        this._animateDeferred = animateDeferred;
        this.option("visible", isShowing);
        animateDeferred.promise().done((() => {
            delete this._animateDeferred;
            result.resolveWith(this, [this._isVisible()])
        })).fail((() => {
            delete this._animateDeferred;
            result.reject()
        }));
        return result.promise()
    }
    $content() {
        return this._$content
    }
    show() {
        return this.toggle(true)
    }
    hide() {
        return this.toggle(false)
    }
    content() {
        return (0, _element.getPublicElement)(this._$content)
    }
    repaint() {
        if (this._contentAlreadyRendered) {
            this._positionController.restorePositionOnNextRender(true);
            this._renderGeometry({
                forceStopAnimation: true
            });
            (0, _visibility_change.triggerResizeEvent)(this._$content)
        } else {
            super.repaint()
        }
    }
    static baseZIndex(zIndex) {
        return zIndexPool.base(zIndex)
    }
}(0, _component_registrator.default)("dxOverlay", Overlay);
var _default = exports.default = Overlay;