var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
import React from 'react';
import { Transition } from 'react-transition-group';
import warning from 'warning';
import { getDOMRect } from '../../lib/dom/getDOMRect.js';
import * as LayoutEvents from '../../lib/LayoutEvents.js';
import { ZIndex } from '../ZIndex/index.js';
import { RenderContainer } from '../RenderContainer/index.js';
import { getRandomID, isFunction, isNonNullable, isNullable, isRefableElement } from '../../lib/utils.js';
import { ThemeContext } from '../../lib/theming/ThemeContext.js';
import { isTestEnv } from '../../lib/currentEnvironment.js';
import { CommonWrapper } from '../CommonWrapper/index.js';
import { responsiveLayout } from '../../components/ResponsiveLayout/decorator.js';
import { MobilePopup } from '../MobilePopup/index.js';
import { getRootNode, rootNode } from '../../lib/rootNode/index.js';
import { isInstanceWithAnchorElement } from '../../lib/InstanceWithAnchorElement.js';
import { createPropsGetter } from '../../lib/createPropsGetter.js';
import { isInstanceOf } from '../../lib/isInstanceOf.js';
import { mergeRefs } from '../../lib/mergeRefs.js';
import { getVisualStateDataAttributes } from '../CommonWrapper/utils/getVisualStateDataAttributes.js';
import { getElementRef } from '../../lib/getElementRef.js';
import { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';
import { PopupPin } from './PopupPin.js';
import { PopupHelper } from './PopupHelper.js';
import { getStyles } from './Popup.styles.js';
var TRANSITION_TIMEOUT = { enter: 0, exit: 200 };
export var PopupNonPinnablePositions = ['middle center', 'middle left', 'middle right'];
export var PopupPinnablePositions = [
    'top center',
    'top left',
    'top right',
    'bottom center',
    'bottom left',
    'bottom right',
    'left middle',
    'left top',
    'left bottom',
    'right middle',
    'right top',
    'right bottom',
];
export var PopupPositions = __spreadArray(__spreadArray([], PopupPinnablePositions, true), PopupNonPinnablePositions, true);
export var DefaultPosition = PopupPositions[0];
export var DUMMY_LOCATION = {
    position: DefaultPosition,
    coordinates: {
        top: -9999,
        left: -9999,
    },
    isFullyVisible: false,
};
export var PopupDataTids = {
    root: 'Popup__root',
    content: 'PopupContent',
    contentInner: 'PopupContentInner',
    popupPin: 'PopupPin__root',
};
export var PopupIds = {
    root: PopupDataTids.root,
};
var Popup = /** @class */ (function (_super) {
    __extends(Popup, _super);
    function Popup() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.getProps = createPropsGetter(Popup_1.defaultProps);
        _this.state = { location: _this.props.opened ? DUMMY_LOCATION : null };
        _this.locationUpdateId = null;
        _this.refForTransition = React.createRef();
        _this.hasAnchorElementListeners = false;
        _this.rootId = PopupIds.root + getRandomID();
        _this.anchorElement = null;
        _this.absoluteParent = null;
        _this.renderInPortal = function (anchor, ref) {
            var location = _this.state.location;
            return (React.createElement(RenderContainer, { anchor: anchor, ref: ref }, _this.isMobileLayout && !_this.props.withoutMobile
                ? _this.renderMobile()
                : location && _this.renderContent(location)));
        };
        _this.renderWithoutPortal = function (anchor, ref) {
            var location = _this.state.location;
            return (React.createElement(EmptyWrapper, { ref: ref },
                anchor,
                location && (React.createElement("div", { ref: _this.updateAbsoluteElement, className: _this.styles.absoluteParent() }, _this.renderContent(location)))));
        };
        _this.updateAnchorElement = function (instance) {
            var childDomNode = isInstanceWithAnchorElement(instance) ? instance.getAnchorElement() : getRootNode(instance);
            var anchorElement = _this.anchorElement;
            if (childDomNode !== anchorElement) {
                _this.removeEventListeners(anchorElement);
                _this.anchorElement = childDomNode;
                _this.addEventListeners(childDomNode);
            }
        };
        _this.updateAbsoluteElement = function (instance) {
            _this.absoluteParent = instance;
        };
        _this.handleMouseEnter = function (event) {
            if (_this.props.onMouseEnter) {
                _this.props.onMouseEnter(event);
            }
        };
        _this.handleMouseLeave = function (event) {
            if (_this.props.onMouseLeave) {
                _this.props.onMouseLeave(event);
            }
        };
        _this.handleClick = function (event) {
            if (_this.props.onClick) {
                _this.props.onClick(event);
            }
        };
        _this.handleFocus = function (event) {
            if (_this.props.onFocus) {
                _this.props.onFocus(event);
            }
        };
        _this.handleBlur = function (event) {
            if (_this.props.onBlur) {
                _this.props.onBlur(event);
            }
        };
        _this.calculateWidth = function (width) {
            if (typeof width === 'string' && width.includes('%')) {
                var anchorWidth_1 = getDOMRect(_this.anchorElement).width;
                return width.replace(/(\d)+%/g, function (percent) { return "".concat((anchorWidth_1 * parseFloat(percent)) / 100, "px"); });
            }
            return width;
        };
        _this.content = function (children) {
            var backgroundColor = _this.props.backgroundColor;
            var _a = _this.getProps(), width = _a.width, minWidth = _a.minWidth;
            return (React.createElement("div", { className: _this.styles.content(_this.theme), "data-tid": PopupDataTids.content, ref: mergeRefs(_this.refForTransition, _this.refPopupContentElement) },
                React.createElement("div", { className: _this.styles.contentInner(_this.theme), style: { backgroundColor: backgroundColor, width: _this.calculateWidth(width), minWidth: _this.calculateWidth(minWidth) }, "data-tid": PopupDataTids.contentInner }, children)));
        };
        _this.prepareDataVisualState = function () {
            var _a;
            var _b;
            var position = (_b = _this.state.location) === null || _b === void 0 ? void 0 : _b.position;
            if (position) {
                var attrName = "position-" + position.replace(' ', '-');
                return getVisualStateDataAttributes((_a = {}, _a[attrName] = true, _a));
            }
            return {};
        };
        _this.resetLocation = function () {
            _this.cancelDelayedUpdateLocation();
            _this.state.location !== null && _this.setState({ location: null });
        };
        _this.refPopupContentElement = function (element) {
            _this.lastPopupContentElement = element;
        };
        _this.handleLayoutEvent = function () {
            if (!_this.state.location) {
                return;
            }
            _this.updateLocation();
        };
        _this.updateLocation = function () {
            var _a, _b;
            var popupContentElement = _this.lastPopupContentElement;
            if (!popupContentElement) {
                return;
            }
            var location = _this.getLocation(popupContentElement, _this.state.location);
            if (location) {
                (_b = (_a = _this.props).onPositionChange) === null || _b === void 0 ? void 0 : _b.call(_a, location.position, location.isFullyVisible);
            }
            if (!_this.locationEquals(_this.state.location, location)) {
                _this.setState({ location: location });
            }
        };
        _this.getRelativeShift = function () {
            var absoluteParent = _this.absoluteParent;
            if (!_this.props.disablePortal || !absoluteParent) {
                return {
                    top: 0,
                    left: 0,
                };
            }
            var rect = PopupHelper.getElementAbsoluteRect(absoluteParent);
            return {
                top: -rect.top,
                left: -rect.left,
            };
        };
        return _this;
    }
    Popup_1 = Popup;
    Popup.prototype.componentDidMount = function () {
        this.updateLocation();
        this.layoutEventsToken = LayoutEvents.addListener(this.handleLayoutEvent, this.globalObject);
        if (!this.hasAnchorElementListeners) {
            this.addEventListeners(this.anchorElement);
        }
    };
    Popup.getDerivedStateFromProps = function (props, state) {
        /**
         * Delaying updateLocation to ensure it happens after props update
         */
        if (props.opened) {
            if (!state.location) {
                return { location: DUMMY_LOCATION };
            }
        }
        else if (state.location) {
            return { location: DUMMY_LOCATION };
        }
        return state;
    };
    Popup.prototype.componentDidUpdate = function (prevProps, prevState) {
        var hadNoLocation = prevState.location === DUMMY_LOCATION;
        var hasLocation = this.state.location !== DUMMY_LOCATION;
        var wasClosed = prevProps.opened && !this.props.opened;
        if (this.isMobileLayout && prevState.location === null && this.state.location === null) {
            this.setState({ location: DUMMY_LOCATION });
        }
        if (this.props.opened && hadNoLocation && hasLocation && this.props.onOpen) {
            this.props.onOpen();
        }
        if (wasClosed && !hasLocation && this.props.onClose) {
            this.props.onClose();
        }
        if (this.props.opened) {
            this.delayUpdateLocation();
        }
    };
    Popup.prototype.componentWillUnmount = function () {
        this.cancelDelayedUpdateLocation();
        if (this.hasAnchorElementListeners) {
            this.removeEventListeners(this.anchorElement);
        }
        if (this.layoutEventsToken) {
            this.layoutEventsToken.remove();
            this.layoutEventsToken = null;
        }
        if (this.state.location && this.props.onClose) {
            this.props.onClose();
        }
    };
    Popup.prototype.render = function () {
        var _this = this;
        this.styles = getStyles(this.emotion);
        return (React.createElement(ThemeContext.Consumer, null, function (theme) {
            _this.theme = theme;
            return _this.renderMain();
        }));
    };
    Popup.prototype.renderMobile = function () {
        var opened = this.props.opened;
        var children = this.renderChildren();
        return children ? (React.createElement(CommonWrapper, { rootNodeRef: this.setRootNode },
            React.createElement(MobilePopup, { opened: opened, withoutRenderContainer: true, onCloseRequest: this.props.mobileOnCloseRequest }, this.content(children)))) : null;
    };
    Popup.prototype.renderMain = function () {
        var anchorElement = this.props.anchorElement;
        var useWrapper = this.getProps().useWrapper;
        var anchor = null;
        if (isInstanceOf(anchorElement, this.globalObject.Element)) {
            this.updateAnchorElement(anchorElement);
        }
        else if (React.isValidElement(anchorElement)) {
            anchor = useWrapper ? React.createElement("span", null, anchorElement) : anchorElement;
        }
        else {
            anchor = React.createElement("span", null, anchorElement);
        }
        var anchorWithRef = anchor && React.isValidElement(anchor) && isRefableElement(anchor)
            ? React.cloneElement(anchor, {
                ref: mergeRefs(getElementRef(anchor), this.updateAnchorElement),
            })
            : null;
        // we need to get anchor's DOM node
        // so we either set our own ref on it via cloning
        // or relay on findDOMNode (inside getRootNode)
        // which should be called within updateAnchorElement
        // in the case when the anchor is not refable
        var canGetAnchorNode = !!anchorWithRef || isInstanceOf(anchorElement, this.globalObject.Element);
        var renderRef = canGetAnchorNode ? null : this.updateAnchorElement;
        var renderAnchor = anchorWithRef || anchor;
        return this.props.disablePortal
            ? this.renderWithoutPortal(renderAnchor, renderRef)
            : this.renderInPortal(renderAnchor, renderRef);
    };
    Popup.prototype.addEventListeners = function (element) {
        if (element && isInstanceOf(element, this.globalObject.Element)) {
            // @ts-expect-error: Type ElementEventMap is missing events: https://github.com/skbkontur/retail-ui/pull/2946#discussion_r931072657
            element.addEventListener('mouseenter', this.handleMouseEnter);
            // @ts-expect-error: See the comment above
            element.addEventListener('mouseleave', this.handleMouseLeave);
            // @ts-expect-error: See the comment above
            element.addEventListener('click', this.handleClick);
            element.addEventListener('focusin', this.handleFocus);
            element.addEventListener('focusout', this.handleBlur);
            this.hasAnchorElementListeners = true;
        }
    };
    Popup.prototype.removeEventListeners = function (element) {
        if (element && isInstanceOf(element, this.globalObject.Element)) {
            // @ts-expect-error: Type ElementEventMap is missing events: https://github.com/skbkontur/retail-ui/pull/2946#discussion_r931072657
            element.removeEventListener('mouseenter', this.handleMouseEnter);
            // @ts-expect-error: See the comment above
            element.removeEventListener('mouseleave', this.handleMouseLeave);
            // @ts-expect-error: See the comment above
            element.removeEventListener('click', this.handleClick);
            element.removeEventListener('focusin', this.handleFocus);
            element.removeEventListener('focusout', this.handleBlur);
            this.hasAnchorElementListeners = false;
        }
    };
    Popup.prototype.renderContent = function (location) {
        var _this = this;
        var _a = this.props, maxWidth = _a.maxWidth, opened = _a.opened;
        var _b = this.getProps(), hasShadow = _b.hasShadow, disableAnimations = _b.disableAnimations, ignoreHover = _b.ignoreHover;
        var children = this.renderChildren();
        var relativeShift = this.getRelativeShift();
        var direction = PopupHelper.getPositionObject(location.position).direction;
        var rootStyle = {
            maxWidth: maxWidth,
            top: location.coordinates.top + relativeShift.top,
            left: location.coordinates.left + relativeShift.left,
        };
        return (React.createElement(Transition, { timeout: TRANSITION_TIMEOUT, appear: !disableAnimations, in: Boolean(opened && children), mountOnEnter: true, unmountOnExit: true, enter: !disableAnimations, exit: !disableAnimations, onExited: this.resetLocation, nodeRef: this.refForTransition }, function (state) {
            var _a, _b;
            var _c;
            return (React.createElement(CommonWrapper, __assign({}, _this.props, { rootNodeRef: _this.setRootNode }, _this.prepareDataVisualState()),
                React.createElement(ZIndex, { id: (_c = _this.props.id) !== null && _c !== void 0 ? _c : _this.rootId, "data-tid": PopupDataTids.root, priority: _this.props.priority, className: _this.cx(__assign((_a = {}, _a[_this.styles.popup(_this.theme)] = true, _a[_this.styles.shadow(_this.theme)] = hasShadow, _a[_this.styles.popupIgnoreHover()] = ignoreHover, _a), (disableAnimations
                        ? {}
                        : (_b = {},
                            _b[_this.styles["transition-enter-".concat(direction)](_this.theme)] = true,
                            _b[_this.styles.transitionEnter()] = state === 'entering',
                            _b[_this.styles.transitionEnterActive()] = state === 'entered',
                            _b[_this.styles.transitionExit()] = state === 'exiting',
                            _b)))), style: rootStyle, onMouseEnter: _this.handleMouseEnter, onMouseLeave: _this.handleMouseLeave },
                    _this.content(children),
                    (!_this.isMobileLayout || _this.props.withoutMobile) && _this.renderPin(location.position))));
        }));
    };
    Popup.prototype.renderChildren = function () {
        return isFunction(this.props.children) ? this.props.children() : this.props.children;
    };
    Popup.prototype.renderPin = function (positionName) {
        var _a = this.props, pinSize = _a.pinSize, backgroundColor = _a.backgroundColor;
        var hasPin = this.getProps().hasPin;
        var position = PopupHelper.getPositionObject(positionName);
        return (hasPin &&
            !PopupNonPinnablePositions.includes(positionName) && (React.createElement(PopupPin, { popupElement: this.lastPopupContentElement, popupPosition: positionName, size: pinSize || parseInt(this.theme.popupPinSize), offset: this.getPinOffset(position.align), backgroundColor: backgroundColor || this.theme.popupBackground })));
    };
    Popup.prototype.delayUpdateLocation = function () {
        var _a, _b;
        this.cancelDelayedUpdateLocation();
        this.locationUpdateId = (_b = (_a = this.globalObject).requestAnimationFrame) === null || _b === void 0 ? void 0 : _b.call(_a, this.updateLocation);
    };
    Popup.prototype.cancelDelayedUpdateLocation = function () {
        var _a, _b;
        if (this.locationUpdateId) {
            (_b = (_a = this.globalObject).cancelAnimationFrame) === null || _b === void 0 ? void 0 : _b.call(_a, this.locationUpdateId);
            this.locationUpdateId = null;
        }
    };
    Popup.prototype.locationEquals = function (x, y) {
        if (x === y) {
            return true;
        }
        if (isNullable(x) || isNullable(y)) {
            return false;
        }
        return (x.coordinates.left === y.coordinates.left && x.coordinates.top === y.coordinates.top && x.position === y.position);
    };
    Popup.prototype.getOrderedPositions = function () {
        var positions = this.props.positions ? this.props.positions : PopupPinnablePositions;
        var pos_ = '';
        if (this.props.pos) {
            pos_ = this.props.pos;
        }
        else {
            pos_ = positions[0];
        }
        var index = positions.findIndex(function (position) { return position.startsWith(pos_); });
        if (index === -1) {
            warning(false, 'Unexpected position ' + pos_ + ' passed to Popup. Expected one of: ' + positions.join(', '));
            return positions;
        }
        return __spreadArray(__spreadArray([], positions.slice(index), true), positions.slice(0, index), true);
    };
    Popup.prototype.getLocation = function (popupElement, location) {
        var tryBestFallbackPosition = this.getProps().tryBestFallbackPosition;
        var positions = this.getOrderedPositions();
        var anchorElement = this.anchorElement;
        warning(anchorElement && isInstanceOf(anchorElement, this.globalObject.Element), 'Anchor element is not defined or not instance of Element');
        if (!(anchorElement && isInstanceOf(anchorElement, this.globalObject.Element))) {
            return location;
        }
        var anchorRect = PopupHelper.getElementAbsoluteRect(anchorElement);
        var popupRect = PopupHelper.getElementAbsoluteRect(popupElement);
        var reusedLocation = this.tryReuseCurrentLocation(location, positions, anchorRect, popupRect);
        if (reusedLocation) {
            return reusedLocation;
        }
        var fullyVisibleLocation = this.tryGetFirstFullyVisibleLocation(positions, anchorRect, popupRect);
        if (fullyVisibleLocation) {
            return fullyVisibleLocation;
        }
        return this.getFallbackLocation(positions, anchorRect, popupRect, Boolean(tryBestFallbackPosition));
    };
    Popup.prototype.tryReuseCurrentLocation = function (location, positions, anchorRect, popupRect) {
        var tryPreserveFirstRenderedPosition = this.getProps().tryPreserveFirstRenderedPosition;
        if (!(location && location !== DUMMY_LOCATION && location.position)) {
            return null;
        }
        var position = location.position;
        var coordinates = this.getCoordinates(anchorRect, popupRect, position);
        var isFullyVisible = PopupHelper.isFullyVisible(coordinates, popupRect, this.globalObject);
        var canBecomeVisible = !isFullyVisible && PopupHelper.canBecomeFullyVisible(position, coordinates, this.globalObject);
        var shouldReuseCurrentLocation = 
        // если нужно сохранить первоначальную позицию и Попап целиком
        // находится в пределах вьюпорта (или может быть проскроллен в него)
        (tryPreserveFirstRenderedPosition && (isFullyVisible || canBecomeVisible)) ||
            // если Попап целиком во вьюпорте и в самой приоритетной позиции
            // (иначе нужно попытаться позицию сменить)
            (isFullyVisible && position === positions[0]);
        if (!shouldReuseCurrentLocation) {
            return null;
        }
        return { coordinates: coordinates, position: position, isFullyVisible: true };
    };
    Popup.prototype.tryGetFirstFullyVisibleLocation = function (positions, anchorRect, popupRect) {
        for (var _i = 0, positions_1 = positions; _i < positions_1.length; _i++) {
            var position = positions_1[_i];
            var coordinates = this.getCoordinates(anchorRect, popupRect, position);
            if (PopupHelper.isFullyVisible(coordinates, popupRect, this.globalObject)) {
                return { coordinates: coordinates, position: position, isFullyVisible: true };
            }
        }
        return null;
    };
    Popup.prototype.getFallbackLocation = function (positions, anchorRect, popupRect, tryBestFallbackPosition) {
        var position = tryBestFallbackPosition
            ? this.pickBestFallbackPosition(positions, anchorRect, popupRect)
            : positions[0];
        var coordinates = this.getCoordinates(anchorRect, popupRect, position);
        return {
            coordinates: coordinates,
            position: position,
            isFullyVisible: PopupHelper.isFullyVisible(coordinates, popupRect, this.globalObject),
        };
    };
    Popup.prototype.pickBestFallbackPosition = function (positions, anchorRect, popupRect) {
        var _this = this;
        var defaultPosition = positions[0];
        var coords = this.getCoordinates(anchorRect, popupRect, defaultPosition);
        var overflow = PopupHelper.getOverflowEdges(coords, popupRect, this.globalObject);
        var preferredDirection = PopupHelper.getPreferredDirection(overflow, defaultPosition);
        var preferredAlignOrder = overflow.left || overflow.right ? ['right', 'center', 'left'] : ['center', 'left', 'right'];
        var candidates = PopupHelper.getOrderedFallbackCandidates(positions, overflow, preferredDirection, preferredAlignOrder, PopupPinnablePositions);
        var positionsSet = new Set(positions);
        var viewport = PopupHelper.getViewportAbsoluteRect(this.globalObject);
        var evaluatedCandidates = candidates.map(function (position) {
            return _this.evaluateFallbackCandidate(position, anchorRect, popupRect, viewport);
        });
        var bestAreaCandidate = this.pickBestAreaCandidate(evaluatedCandidates, positionsSet);
        var bestOverflowCandidate = this.pickBestOverflowCandidate(evaluatedCandidates, positionsSet);
        // Если есть хотя бы одна позиция с ненулевой видимой площадью,
        // выбираем её (с приоритетом полностью видимых вариантов).
        // Иначе — используем старую эвристику по количеству переполненных сторон.
        return bestAreaCandidate && bestAreaCandidate.visibleArea > 0
            ? bestAreaCandidate.position
            : bestOverflowCandidate.position;
    };
    Popup.prototype.evaluateFallbackCandidate = function (position, anchorRect, popupRect, viewport) {
        var coordinates = this.getCoordinates(anchorRect, popupRect, position);
        var popupAbsolute = {
            top: coordinates.top,
            left: coordinates.left,
            width: popupRect.width,
            height: popupRect.height,
        };
        var overlapWidth = Math.min(popupAbsolute.left + popupAbsolute.width, viewport.left + viewport.width) -
            Math.max(popupAbsolute.left, viewport.left);
        var overlapHeight = Math.min(popupAbsolute.top + popupAbsolute.height, viewport.top + viewport.height) -
            Math.max(popupAbsolute.top, viewport.top);
        var visibleWidth = Math.max(0, overlapWidth);
        var visibleHeight = Math.max(0, overlapHeight);
        var overflow = PopupHelper.getOverflowEdges(coordinates, popupRect, this.globalObject);
        var isFullyVisible = visibleWidth === popupAbsolute.width && visibleHeight === popupAbsolute.height;
        var isAreaEligible = PopupHelper.getPositionObject(position).direction !== 'left' || isFullyVisible;
        return {
            position: position,
            coordinates: coordinates,
            overflowCount: PopupHelper.getOverflowCount(overflow),
            visibleArea: visibleWidth * visibleHeight,
            isFullyVisible: isFullyVisible,
            isAreaEligible: isAreaEligible,
        };
    };
    Popup.prototype.pickBestAreaCandidate = function (candidates, positionsSet) {
        var bestCandidate = null;
        for (var _i = 0, candidates_1 = candidates; _i < candidates_1.length; _i++) {
            var candidate = candidates_1[_i];
            if (!candidate.isAreaEligible || candidate.visibleArea <= 0) {
                continue;
            }
            var isBetterArea = !bestCandidate ||
                // предпочитаем любые полностью видимые позиции
                (candidate.isFullyVisible && !bestCandidate.isFullyVisible) ||
                // среди одинаковых по полноте — большую видимую площадь
                (candidate.isFullyVisible === bestCandidate.isFullyVisible &&
                    candidate.visibleArea > bestCandidate.visibleArea) ||
                // при равной площади — ту, что указана в props.positions
                (candidate.visibleArea === bestCandidate.visibleArea &&
                    positionsSet.has(candidate.position) &&
                    !positionsSet.has(bestCandidate.position));
            if (isBetterArea) {
                bestCandidate = candidate;
            }
        }
        return bestCandidate;
    };
    Popup.prototype.pickBestOverflowCandidate = function (candidates, positionsSet) {
        var bestCandidate = candidates[0];
        for (var _i = 0, candidates_2 = candidates; _i < candidates_2.length; _i++) {
            var candidate = candidates_2[_i];
            var isBetterOverflow = candidate.overflowCount < bestCandidate.overflowCount ||
                (candidate.overflowCount === bestCandidate.overflowCount &&
                    positionsSet.has(candidate.position) &&
                    !positionsSet.has(bestCandidate.position));
            if (isBetterOverflow) {
                bestCandidate = candidate;
            }
        }
        return bestCandidate;
    };
    Popup.prototype.getPinnedPopupOffset = function (anchorRect, position) {
        if (!this.getProps().hasPin || /center|middle/.test(position.align)) {
            return 0;
        }
        var anchorSize = /top|bottom/.test(position.direction) ? anchorRect.width : anchorRect.height;
        var pinSize = this.props.pinSize;
        return Math.max(0, this.getPinOffset(position.align) + (pinSize || parseInt(this.theme.popupPinSize)) - anchorSize / 2);
    };
    Popup.prototype.getCoordinates = function (anchorRect, popupRect, positionName) {
        var marginFromProps = this.props.margin;
        var margin = isNonNullable(marginFromProps) && !isNaN(marginFromProps)
            ? marginFromProps
            : parseInt(this.theme.popupMargin) || 0;
        var position = PopupHelper.getPositionObject(positionName);
        var popupOffset = this.getProps().popupOffset + this.getPinnedPopupOffset(anchorRect, position);
        var defaultCoordinates = {
            top: anchorRect.top - popupRect.height - margin,
            left: this.getHorizontalPosition(anchorRect, popupRect, position.align, popupOffset),
        };
        switch (position.direction) {
            case 'top':
                return defaultCoordinates;
            case 'middle':
                return {
                    top: anchorRect.top + anchorRect.height / 2 - popupRect.height / 2,
                    left: this.getHorizontalPosition(anchorRect, popupRect, position.align, popupOffset),
                };
            case 'bottom':
                return {
                    top: anchorRect.top + anchorRect.height + margin,
                    left: this.getHorizontalPosition(anchorRect, popupRect, position.align, popupOffset),
                };
            case 'left':
                return {
                    top: this.getVerticalPosition(anchorRect, popupRect, position.align, popupOffset),
                    left: anchorRect.left - popupRect.width - margin,
                };
            case 'right':
                return {
                    top: this.getVerticalPosition(anchorRect, popupRect, position.align, popupOffset),
                    left: anchorRect.left + anchorRect.width + margin,
                };
            default:
                warning(false, "Unexpected align '".concat(position.direction, "'. Must be one of - 'top', 'bottom', 'left', 'right', 'center', 'middle'. Returning default value."));
                return defaultCoordinates;
        }
    };
    Popup.prototype.getPinOffset = function (align) {
        var pinOffset = this.props.pinOffset;
        var defaultPinOffset = pinOffset || parseInt(this.theme.popupPinOffsetY);
        switch (align) {
            case 'top':
            case 'bottom':
                return defaultPinOffset;
            case 'left':
            case 'right':
                return pinOffset || parseInt(this.theme.popupPinOffsetX);
            case 'center':
            case 'middle':
                return 0;
            default:
                warning(false, "Unexpected align '".concat(align, "'. Must be one of - 'top', 'bottom', 'left', 'right', 'center', 'middle'. Returning default value."));
                return defaultPinOffset;
        }
    };
    Popup.prototype.getHorizontalPosition = function (anchorRect, popupRect, align, popupOffset) {
        var defaultHorizontalPosition = anchorRect.left - (popupRect.width - anchorRect.width) / 2;
        switch (align) {
            case 'left':
                return anchorRect.left - popupOffset;
            case 'center':
                return defaultHorizontalPosition;
            case 'right':
                return anchorRect.left - (popupRect.width - anchorRect.width) + popupOffset;
            default:
                warning(false, "Unexpected align '".concat(align, "'. Must be one of - 'left', 'center', 'right'. Returning default value."));
                return defaultHorizontalPosition;
        }
    };
    Popup.prototype.getVerticalPosition = function (anchorRect, popupRect, align, popupOffset) {
        var defaultVerticalPosition = anchorRect.top - popupOffset;
        switch (align) {
            case 'top':
                return defaultVerticalPosition;
            case 'middle':
                return anchorRect.top - (popupRect.height - anchorRect.height) / 2;
            case 'bottom':
                return anchorRect.top - (popupRect.height - anchorRect.height) + popupOffset;
            default:
                warning(false, "Unexpected align '".concat(align, "'. Must be one of - 'top', 'middle', 'bottom'. Returning default value."));
                return defaultVerticalPosition;
        }
    };
    var Popup_1;
    Popup.__KONTUR_REACT_UI__ = 'Popup';
    Popup.displayName = 'Popup';
    Popup.defaultProps = {
        popupOffset: 0,
        hasPin: false,
        hasShadow: false,
        disableAnimations: isTestEnv,
        useWrapper: false,
        ignoreHover: false,
        disablePortal: false,
        width: 'auto',
        priority: ZIndex.priorities.Popup,
    };
    // see #2873 and #2895
    Popup.defaultRootNode = null;
    Popup = Popup_1 = __decorate([
        withRenderEnvironment,
        responsiveLayout,
        rootNode
    ], Popup);
    return Popup;
}(React.Component));
export { Popup };
var EmptyWrapper = /** @class */ (function (_super) {
    __extends(EmptyWrapper, _super);
    function EmptyWrapper() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    EmptyWrapper.prototype.render = function () {
        return this.props.children;
    };
    return EmptyWrapper;
}(React.Component));
//# sourceMappingURL=Popup.js.map