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;
};
import React from 'react';
import warning from 'warning';
import { isNullable } from '../../lib/utils.js';
import { ThemeFactory } from '../../lib/theming/ThemeFactory.js';
import { Popup } from '../../internal/Popup/index.js';
import { RenderLayer } from '../../internal/RenderLayer/index.js';
import { containsTargetOrRenderContainer } from '../../lib/listenFocusOutside.js';
import { ThemeContext } from '../../lib/theming/ThemeContext.js';
import { isTestEnv } from '../../lib/currentEnvironment.js';
import { CommonWrapper } from '../../internal/CommonWrapper/index.js';
import { rootNode } from '../../lib/rootNode/index.js';
import { createPropsGetter } from '../../lib/createPropsGetter.js';
import { CloseButtonIcon } from '../../internal/CloseButtonIcon/CloseButtonIcon.js';
import { isInstanceOf } from '../../lib/isInstanceOf.js';
import { withSize } from '../../lib/size/SizeDecorator.js';
import { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';
import { getStyles } from './Tooltip.styles.js';
var DEFAULT_DELAY = 100;
export var TooltipDataTids = {
    root: 'Tooltip__root',
    content: 'Tooltip__content',
    crossIcon: 'Tooltip__crossIcon',
};
var DefaultPositions = [
    'right bottom',
    'right middle',
    'right top',
    'top right',
    'top center',
    'top left',
    'left top',
    'left middle',
    'left bottom',
    'bottom left',
    'bottom center',
    'bottom right',
];
/**
 * `Tooltip` — это подсказка, которая объясняет состояние контрола или даёт контекстную справку.
 *
 * Открывается по клику, фокусом на элемент или по наведению. В отличие от `Hint`, `Tooltip` может содержать
 * изображения, кнопки, ссылки и прочие интерактивные элементы.
 */
var Tooltip = /** @class */ (function (_super) {
    __extends(Tooltip, _super);
    function Tooltip() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.getProps = createPropsGetter(Tooltip_1.defaultProps);
        _this.state = { opened: false, focused: false };
        _this.contentElement = null;
        _this.clickedOutside = true;
        _this.popupRef = React.createRef();
        _this.renderContent = function () {
            var content = _this.props.render ? _this.props.render() : null;
            if (isNullable(content)) {
                return null;
            }
            return (React.createElement("div", { ref: _this.refContent, className: _this.cx(_this.styles.tooltipContent(_this.theme), _this.sizeVariables.contentStyle), "data-tid": TooltipDataTids.content },
                content,
                _this.renderCloseButton()));
        };
        _this.getAnchorElement = function () {
            var _a;
            return (_a = _this.popupRef.current) === null || _a === void 0 ? void 0 : _a.anchorElement;
        };
        _this.getPositions = function () {
            return _this.props.allowedPositions
                ? _this.props.allowedPositions.filter(function (item) { return DefaultPositions.includes(item); })
                : DefaultPositions;
        };
        _this.refContent = function (node) {
            _this.contentElement = node;
        };
        _this.open = function () { return _this.setState({ opened: true }); };
        _this.close = function () { return _this.setState({ opened: false }); };
        _this.handleMouseEnter = function (event) {
            var isHoverAnchor = _this.getProps().trigger === 'hoverAnchor';
            if (isHoverAnchor && event.target === _this.contentElement) {
                return;
            }
            _this.clearHoverTimeout();
            _this.hoverTimeout = setTimeout(_this.open, _this.getProps().delayBeforeShow);
        };
        _this.handleMouseLeave = function (event) {
            var trigger = _this.getProps().trigger;
            if ((trigger === 'hover&focus' && _this.state.focused) ||
                (trigger === 'hover' && event.relatedTarget === _this.contentElement)) {
                return;
            }
            _this.clearHoverTimeout();
            if (trigger === 'hoverAnchor') {
                _this.close();
            }
            else {
                _this.hoverTimeout = setTimeout(_this.close, Tooltip_1.delay);
            }
        };
        _this.handleClick = function () {
            _this.open();
        };
        _this.handleClickOutsideAnchor = function (event) {
            _this.clickedOutside = _this.isClickOutsideContent(event);
            if (_this.clickedOutside) {
                if (_this.props.onCloseRequest) {
                    _this.props.onCloseRequest(event);
                }
                _this.close();
            }
        };
        _this.handleFocus = function () {
            _this.setState({ focused: true });
            _this.open();
        };
        _this.handleBlur = function () {
            var trigger = _this.getProps().trigger;
            if (trigger === 'hover&focus' && _this.clickedOutside) {
                _this.close();
            }
            if (trigger === 'focus') {
                _this.close();
            }
            _this.clickedOutside = true;
            _this.setState({ focused: false });
        };
        _this.handleCloseButtonClick = function (event) {
            event.stopPropagation();
            if (_this.props.onCloseClick) {
                _this.props.onCloseClick(event);
            }
            if (event.defaultPrevented) {
                return;
            }
            if (_this.props.onCloseRequest) {
                _this.props.onCloseRequest(event);
            }
            _this.close();
        };
        _this.getSizeVariables = function () {
            switch (_this.size) {
                case 'small':
                    return {
                        closeButtonStyle: _this.styles.closeButtonSmall(_this.theme),
                        contentStyle: _this.styles.tooltipContentSmall(_this.theme),
                        borderRadius: _this.theme.tooltipBorderRadiusSmall,
                        pinSize: _this.theme.tooltipPinSizeSmall,
                        pinOffsetX: _this.theme.tooltipPinOffsetXSmall,
                        pinOffsetY: _this.theme.tooltipPinOffsetYSmall,
                        margin: _this.theme.tooltipMarginSmall,
                    };
                case 'medium':
                    return {
                        closeButtonStyle: _this.styles.closeButtonMedium(_this.theme),
                        contentStyle: _this.styles.tooltipContentMedium(_this.theme),
                        borderRadius: _this.theme.tooltipBorderRadiusMedium,
                        pinSize: _this.theme.tooltipPinSizeMedium,
                        pinOffsetX: _this.theme.tooltipPinOffsetXMedium,
                        pinOffsetY: _this.theme.tooltipPinOffsetYMedium,
                        margin: _this.theme.tooltipMarginMedium,
                    };
                case 'large':
                    return {
                        closeButtonStyle: _this.styles.closeButtonLarge(_this.theme),
                        contentStyle: _this.styles.tooltipContentLarge(_this.theme),
                        borderRadius: _this.theme.tooltipBorderRadiusLarge,
                        pinSize: _this.theme.tooltipPinSizeLarge,
                        pinOffsetX: _this.theme.tooltipPinOffsetXLarge,
                        pinOffsetY: _this.theme.tooltipPinOffsetYLarge,
                        margin: _this.theme.tooltipMarginLarge,
                    };
                default:
                    warning(false, "Can't get size variables: invalid value in size prop '".concat(_this.props.size, "'. Returning default"));
                    return {
                        closeButtonStyle: _this.styles.closeButtonSmall(_this.theme),
                        contentStyle: _this.styles.tooltipContentSmall(_this.theme),
                        borderRadius: _this.theme.tooltipBorderRadiusSmall,
                        pinSize: _this.theme.tooltipPinSizeSmall,
                        pinOffsetX: _this.theme.tooltipPinOffsetXSmall,
                        pinOffsetY: _this.theme.tooltipPinOffsetYSmall,
                        margin: _this.theme.tooltipMarginSmall,
                    };
            }
        };
        return _this;
    }
    Tooltip_1 = Tooltip;
    Tooltip.prototype.validateProps = function (props) {
        warning(props.children || props.anchorElement, "[Tooltip]: you must provide either 'children' or 'anchorElement' prop for Tooltip to work properly");
    };
    Tooltip.prototype.getAllowedPositions = function () {
        return this.props.allowedPositions ? this.props.allowedPositions : DefaultPositions;
    };
    Tooltip.prototype.componentDidMount = function () {
        this.validateProps(this.getProps());
    };
    Tooltip.prototype.componentDidUpdate = function () {
        var trigger = this.getProps().trigger;
        this.validateProps(this.getProps());
        if (trigger === 'closed' && this.state.opened) {
            this.close();
        }
    };
    Tooltip.prototype.componentWillUnmount = function () {
        this.clearHoverTimeout();
    };
    Tooltip.prototype.render = function () {
        var _this = this;
        this.styles = getStyles(this.emotion);
        return (React.createElement(ThemeContext.Consumer, null, function (theme) {
            _this.theme = theme;
            _this.sizeVariables = _this.getSizeVariables();
            return (React.createElement(ThemeContext.Provider, { value: ThemeFactory.create({
                    popupBackground: theme.tooltipBg,
                    popupBorder: theme.tooltipBorder,
                    popupBorderRadius: _this.sizeVariables.borderRadius,
                    popupPinSize: _this.sizeVariables.pinSize,
                    popupPinOffsetX: _this.sizeVariables.pinOffsetX,
                    popupPinOffsetY: _this.sizeVariables.pinOffsetY,
                    popupMargin: _this.sizeVariables.margin,
                }, theme) }, _this.renderMain()));
        }));
    };
    Tooltip.prototype.renderCloseButton = function () {
        var hasCross = this.props.closeButton === undefined
            ? !Tooltip_1.triggersWithoutCloseButton.includes(this.getProps().trigger)
            : this.props.closeButton;
        if (!hasCross) {
            return null;
        }
        var icon = (React.createElement(CloseButtonIcon, { tabbable: false, side: parseInt(this.theme.tooltipCloseBtnSide), color: this.theme.tooltipCloseBtnColor, colorHover: this.theme.tooltipCloseBtnHoverColor }));
        return (React.createElement("div", { className: this.cx(this.styles.closeButton(this.theme), this.sizeVariables.closeButtonStyle), onClick: this.handleCloseButtonClick, "data-tid": TooltipDataTids.crossIcon }, icon));
    };
    /**
     * Программно открывает тултип.
     * <p>Не действует если проп *trigger* `'opened'` или `'closed'`.</p>
     * @public
     */
    Tooltip.prototype.show = function () {
        if (this.state.opened) {
            return;
        }
        var trigger = this.getProps().trigger;
        if (trigger === 'opened' || trigger === 'closed') {
            warning(false, "Function 'show' is not supported with trigger specified '".concat(trigger, "'"));
            return;
        }
        this.open();
    };
    /**
     * Программно закрывает тултип.
     * <p>Не действует если проп *trigger* `'opened'` или `'closed'`.</p>
     * @public
     */
    Tooltip.prototype.hide = function () {
        var trigger = this.getProps().trigger;
        if (trigger === 'opened' || trigger === 'closed') {
            warning(false, "Function 'hide' is not supported with trigger specified '".concat(trigger, "'"));
            return;
        }
        this.close();
    };
    Tooltip.prototype.renderMain = function () {
        var props = this.props;
        var content = this.renderContent();
        var _a = this.getPopupAndLayerProps(), popupProps = _a.popupProps, _b = _a.layerProps, layerProps = _b === void 0 ? { active: false } : _b;
        var anchorElement = props.children || props.anchorElement;
        var popup = this.renderPopup(anchorElement, popupProps, content);
        return (React.createElement(RenderLayer, __assign({}, layerProps, { getAnchorElement: this.getAnchorElement }), popup));
    };
    Tooltip.prototype.renderPopup = function (anchorElement, popupProps, content) {
        var _a = this.getProps(), disableAnimations = _a.disableAnimations, trigger = _a.trigger;
        return (React.createElement(CommonWrapper, __assign({ rootNodeRef: this.setRootNode }, this.props),
            React.createElement(Popup, __assign({ "data-tid": TooltipDataTids.root, anchorElement: anchorElement, hasPin: true, hasShadow: true, maxWidth: "none", opened: this.state.opened, disableAnimations: disableAnimations, positions: this.getPositions(), pos: this.props.pos, ignoreHover: trigger === 'hoverAnchor', onOpen: this.props.onOpen, onClose: this.props.onClose, tryPreserveFirstRenderedPosition: true, ref: this.popupRef, withoutMobile: true }, popupProps), content)));
    };
    Tooltip.prototype.getPopupAndLayerProps = function () {
        var props = this.props;
        var useWrapper = !!props.children && this.getProps().useWrapper;
        var trigger = this.getProps().trigger;
        var defaultPopupAndLayerProps = {
            popupProps: {
                onMouseEnter: this.handleMouseEnter,
                onMouseLeave: this.handleMouseLeave,
                useWrapper: useWrapper,
            },
        };
        switch (trigger) {
            case 'opened':
                return {
                    layerProps: {
                        active: true,
                        onClickOutside: this.handleClickOutsideAnchor,
                    },
                    popupProps: {
                        opened: true,
                        useWrapper: useWrapper,
                    },
                };
            case 'closed':
                return {
                    popupProps: {
                        opened: false,
                        useWrapper: useWrapper,
                    },
                };
            case 'manual':
                return {
                    popupProps: {
                        useWrapper: useWrapper,
                    },
                };
            case 'click':
                return {
                    layerProps: {
                        active: this.state.opened,
                        onClickOutside: this.handleClickOutsideAnchor,
                    },
                    popupProps: {
                        onClick: this.handleClick,
                        useWrapper: useWrapper,
                    },
                };
            case 'focus':
                return {
                    popupProps: {
                        onFocus: this.handleFocus,
                        onBlur: this.handleBlur,
                        useWrapper: useWrapper,
                    },
                };
            case 'hover&focus':
                return {
                    layerProps: {
                        active: this.state.opened,
                        onClickOutside: this.handleClickOutsideAnchor,
                    },
                    popupProps: {
                        onFocus: this.handleFocus,
                        onBlur: this.handleBlur,
                        onMouseEnter: this.handleMouseEnter,
                        onMouseLeave: this.handleMouseLeave,
                        useWrapper: useWrapper,
                    },
                };
            case 'hoverAnchor':
            case 'hover':
                return defaultPopupAndLayerProps;
            default:
                warning(false, "Unknown trigger specified: ".concat(trigger, ". Returning default value."));
                return defaultPopupAndLayerProps;
        }
    };
    Tooltip.prototype.clearHoverTimeout = function () {
        if (this.hoverTimeout) {
            clearTimeout(this.hoverTimeout);
            this.hoverTimeout = null;
        }
    };
    Tooltip.prototype.isClickOutsideContent = function (event) {
        if (this.contentElement && isInstanceOf(event.target, this.globalObject.Element)) {
            return !containsTargetOrRenderContainer(event.target)(this.contentElement);
        }
        return true;
    };
    var Tooltip_1;
    Tooltip.__KONTUR_REACT_UI__ = 'Tooltip';
    Tooltip.displayName = 'Tooltip';
    Tooltip.defaultProps = {
        trigger: 'hover',
        disableAnimations: isTestEnv,
        useWrapper: false,
        delayBeforeShow: DEFAULT_DELAY,
    };
    Tooltip.delay = DEFAULT_DELAY;
    Tooltip.triggersWithoutCloseButton = ['hover', 'hoverAnchor', 'focus', 'hover&focus'];
    Tooltip = Tooltip_1 = __decorate([
        withRenderEnvironment,
        rootNode,
        withSize
    ], Tooltip);
    return Tooltip;
}(React.PureComponent));
export { Tooltip };
//# sourceMappingURL=Tooltip.js.map