import * as React from 'react';
import { Tooltip as BootstrapTooltip } from 'reactstrap';
/**
 * A global tooltip displayed for elements containing a `data-tooltip` attribute.
 */
export class Tooltip extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = { subjectSeq: 0 };
        this.toggleHint = (event) => {
            const subject = this.getSubject(event);
            this.setState(prevState => ({
                subject,
                subjectSeq: prevState.subject === subject ? prevState.subjectSeq : prevState.subjectSeq + 1,
                content: subject ? this.getContent(subject) : undefined,
            }));
        };
        this.updateContent = () => {
            this.setState(prevState => ({ content: prevState.subject ? this.getContent(prevState.subject) : undefined }));
        };
        /**
         * Find the nearest ancestor element to e that contains a tooltip.
         */
        this.getSubject = (event) => {
            // As a special case, don't show the tooltip for click events on submit buttons that are probably triggered
            // by the user pressing the enter button. It is not desirable for the tooltip to be shown in that case.
            if (event.type === 'click' &&
                event.target.tagName === 'BUTTON' &&
                event.target.type === 'submit' &&
                event.pageX === 0 &&
                event.pageY === 0) {
                return undefined;
            }
            let e = event.target;
            while (e) {
                if (e === document.body) {
                    break;
                }
                if (e.hasAttribute(Tooltip.SUBJECT_ATTRIBUTE)) {
                    // If e is not actually attached to the DOM, then abort.
                    if (!document.body.contains(e)) {
                        return undefined;
                    }
                    return e;
                }
                e = e.parentElement;
            }
            return undefined;
        };
        this.getContent = (subject) => {
            if (!document.body.contains(subject)) {
                return undefined;
            }
            return subject.getAttribute(Tooltip.SUBJECT_ATTRIBUTE) || undefined;
        };
    }
    /**
     * Forces an update of the tooltip content. Other components must call this if they modify their tooltip
     * content while the tooltip is still visible.
     */
    static forceUpdate() {
        if (Tooltip.INSTANCE) {
            Tooltip.INSTANCE.updateContent();
        }
    }
    componentDidMount() {
        Tooltip.INSTANCE = this;
        document.addEventListener('focusin', this.toggleHint);
        document.addEventListener('mouseover', this.toggleHint);
        document.addEventListener('touchend', this.toggleHint);
        document.addEventListener('click', this.toggleHint);
    }
    componentWillUnmount() {
        Tooltip.INSTANCE = undefined;
        document.removeEventListener('focusin', this.toggleHint);
        document.removeEventListener('mouseover', this.toggleHint);
        document.removeEventListener('touchend', this.toggleHint);
        document.removeEventListener('click', this.toggleHint);
    }
    render() {
        return this.state.subject ? (React.createElement(BootstrapTooltip
        // Set key prop to work around a bug where quickly mousing between 2 elements with tooltips
        // displays the 2nd element's tooltip as still pointing to the first.
        , { 
            // Set key prop to work around a bug where quickly mousing between 2 elements with tooltips
            // displays the 2nd element's tooltip as still pointing to the first.
            key: this.state.subjectSeq, className: "tooltip", isOpen: true, target: this.state.subject, placement: "auto" }, this.state.content)) : null;
    }
}
Tooltip.SUBJECT_ATTRIBUTE = 'data-tooltip';
//# sourceMappingURL=Tooltip.js.map