"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SVGTooltipText = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Tooltip_1 = require("@fluentui/react/lib/Tooltip");
var Utilities_1 = require("../Utilities");
var react_1 = require("@fluentui/react");
var PADDING = 4;
/**
 * Component to render an SVG text element with an optional tooltip.
 * The tooltip appears on hovering and focusing the element when its content overflows.
 */
var SVGTooltipText = /** @class */ (function (_super) {
    tslib_1.__extends(SVGTooltipText, _super);
    function SVGTooltipText(props) {
        var _this = _super.call(this, props) || this;
        /** The element that gets the hover events */
        _this._tooltipHost = React.createRef();
        _this._tooltipHostId = (0, Utilities_1.getId)('tooltip-host');
        _this.show = function () {
            _this._toggleTooltip(true);
        };
        _this.dismiss = function () {
            _this._hideTooltip();
        };
        _this._measureText = function () {
            if (_this._tooltipHost.current && typeof _this._tooltipHost.current.getBBox === 'function') {
                var bbox = _this._tooltipHost.current.getBBox();
                _this.setState({
                    textX: bbox.x,
                    textY: bbox.y,
                    textWidth: bbox.width,
                    textHeight: bbox.height,
                });
            }
        };
        _this._getTargetElement = function () {
            if (!_this._tooltipHost.current) {
                return undefined;
            }
            return _this._tooltipHost.current;
        };
        _this._onTooltipFocus = function (ev) {
            if (_this._ignoreNextFocusEvent) {
                _this._ignoreNextFocusEvent = false;
                return;
            }
            _this._onTooltipMouseEnter(ev);
        };
        _this._onTooltipBlur = function (ev) {
            // The focused element gets a blur event when the document loses focus
            // (e.g. switching tabs in the browser), but we don't want to show the
            // tooltip again when the document gets focus back. Handle this case by
            // checking if the blurred element is still the document's activeElement,
            // and ignoring when it next gets focus back.
            // See https://github.com/microsoft/fluentui/issues/13541
            _this._ignoreNextFocusEvent = (document === null || document === void 0 ? void 0 : document.activeElement) === ev.target;
            _this._dismissTimerId = _this._async.setTimeout(function () {
                _this._hideTooltip();
            }, 0);
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        _this._onTooltipMouseEnter = function (ev) {
            var delay = _this.props.delay;
            if (SVGTooltipText._currentVisibleTooltip && SVGTooltipText._currentVisibleTooltip !== _this) {
                SVGTooltipText._currentVisibleTooltip.dismiss();
            }
            SVGTooltipText._currentVisibleTooltip = _this;
            if (!_this.state.isOverflowing) {
                return;
            }
            if (ev.target && (0, Utilities_1.portalContainsElement)(ev.target, _this._getTargetElement())) {
                // Do not show tooltip when target is inside a portal relative to TooltipHost.
                return;
            }
            _this._clearDismissTimer();
            _this._clearOpenTimer();
            if (delay !== Tooltip_1.TooltipDelay.zero) {
                var delayTime = _this._getDelayTime(delay); // non-null assertion because we set it in `defaultProps`
                _this._openTimerId = _this._async.setTimeout(function () {
                    _this._toggleTooltip(true);
                }, delayTime);
            }
            else {
                _this._toggleTooltip(true);
            }
        };
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        _this._onTooltipMouseLeave = function (ev) {
            var closeDelay = _this.props.closeDelay;
            _this._clearDismissTimer();
            _this._clearOpenTimer();
            if (closeDelay) {
                _this._dismissTimerId = _this._async.setTimeout(function () {
                    _this._toggleTooltip(false);
                }, closeDelay);
            }
            else {
                _this._toggleTooltip(false);
            }
            if (SVGTooltipText._currentVisibleTooltip === _this) {
                SVGTooltipText._currentVisibleTooltip = undefined;
            }
        };
        _this._onTooltipKeyDown = function (ev) {
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            if ((ev.which === Utilities_1.KeyCodes.escape || ev.ctrlKey) && _this.state.isTooltipVisible) {
                _this._hideTooltip();
                ev.stopPropagation();
            }
        };
        _this._clearDismissTimer = function () {
            _this._async.clearTimeout(_this._dismissTimerId);
        };
        _this._clearOpenTimer = function () {
            _this._async.clearTimeout(_this._openTimerId);
        };
        _this._hideTooltip = function () {
            _this._clearOpenTimer();
            _this._clearDismissTimer();
            _this._toggleTooltip(false);
        };
        _this._toggleTooltip = function (isTooltipVisible) {
            if (_this.state.isTooltipVisible !== isTooltipVisible) {
                _this.setState({ isTooltipVisible: isTooltipVisible });
            }
        };
        _this._getDelayTime = function (delay) {
            switch (delay) {
                case Tooltip_1.TooltipDelay.medium:
                    return 300;
                case Tooltip_1.TooltipDelay.long:
                    return 500;
                default:
                    return 0;
            }
        };
        _this._wrapContent = function () {
            var _a = _this.props, content = _a.content, wrapContent = _a.wrapContent, _b = _a.maxWidth, maxWidth = _b === void 0 ? Number.POSITIVE_INFINITY : _b, maxHeight = _a.maxHeight;
            var isOverflowing = false;
            if (content && wrapContent && wrapContent(content, _this._tooltipHostId, maxWidth, maxHeight)) {
                isOverflowing = true;
            }
            if (_this.state.isOverflowing !== isOverflowing) {
                _this.setState({ isOverflowing: isOverflowing });
            }
        };
        _this.state = {
            isTooltipVisible: false,
            isOverflowing: false,
        };
        _this._async = new Utilities_1.Async(_this);
        return _this;
    }
    SVGTooltipText.prototype.render = function () {
        var _a = this.props, content = _a.content, tooltipProps = _a.tooltipProps, textProps = _a.textProps, _b = _a.shouldReceiveFocus, shouldReceiveFocus = _b === void 0 ? true : _b, _c = _a.showBackground, showBackground = _c === void 0 ? false : _c;
        var _d = this.state, isTooltipVisible = _d.isTooltipVisible, textX = _d.textX, textY = _d.textY, textWidth = _d.textWidth, textHeight = _d.textHeight;
        var tooltipRenderProps = tslib_1.__assign({ content: content, targetElement: this._getTargetElement(), calloutProps: {
                onDismiss: this._hideTooltip,
                onMouseEnter: this._onTooltipMouseEnter,
                onMouseLeave: this._onTooltipMouseLeave,
            }, onMouseEnter: this._onTooltipMouseEnter, onMouseLeave: this._onTooltipMouseLeave }, tooltipProps);
        var showTooltip = (!!this.props.isTooltipVisibleProp && this.state.isOverflowing && !!content) || (isTooltipVisible && !!content);
        var backgroundColor = this.props.theme ? this.props.theme.semanticColors.bodyBackground : undefined;
        var isRTL = (0, react_1.getRTL)();
        var rectX = isRTL ? (textX !== null && textX !== void 0 ? textX : 0) + (textWidth !== null && textWidth !== void 0 ? textWidth : 0) - PADDING : (textX !== null && textX !== void 0 ? textX : 0) - PADDING;
        return (React.createElement(React.Fragment, null,
            showBackground && (React.createElement("rect", { x: rectX, y: (textY !== null && textY !== void 0 ? textY : 0) - PADDING, width: (textWidth !== null && textWidth !== void 0 ? textWidth : 0) + 2 * PADDING, height: (textHeight !== null && textHeight !== void 0 ? textHeight : 0) + 2 * PADDING, fill: backgroundColor, transform: textProps === null || textProps === void 0 ? void 0 : textProps.transform })),
            React.createElement("text", tslib_1.__assign({}, textProps, { id: this._tooltipHostId, ref: this._tooltipHost, onFocusCapture: this._onTooltipFocus, onBlurCapture: this._onTooltipBlur, onMouseEnter: this._onTooltipMouseEnter, onMouseLeave: this._onTooltipMouseLeave, onKeyDown: this._onTooltipKeyDown, "data-is-focusable": shouldReceiveFocus && this.state.isOverflowing }), content),
            showTooltip && React.createElement(Tooltip_1.Tooltip, tslib_1.__assign({}, tooltipRenderProps))));
    };
    SVGTooltipText.prototype.componentDidMount = function () {
        this._wrapContent();
        this._measureText();
    };
    SVGTooltipText.prototype.componentDidUpdate = function (prevProps) {
        if (this.props.maxWidth !== prevProps.maxWidth || this.props.maxHeight !== prevProps.maxHeight) {
            this._wrapContent();
            this._measureText();
        }
    };
    SVGTooltipText.prototype.componentWillUnmount = function () {
        if (SVGTooltipText._currentVisibleTooltip && SVGTooltipText._currentVisibleTooltip === this) {
            SVGTooltipText._currentVisibleTooltip = undefined;
        }
        this._async.dispose();
    };
    SVGTooltipText.defaultProps = {
        delay: Tooltip_1.TooltipDelay.medium,
    };
    return SVGTooltipText;
}(React.Component));
exports.SVGTooltipText = SVGTooltipText;
//# sourceMappingURL=SVGTooltipText.js.map