import * as React from 'react';
/**
 * Click outside behavior
 */
export class ClickOutside extends React.PureComponent {
    constructor(props) {
        super(props);
        /**
         * Check whether the click is inside the element or excluded
         * @param event - Click event
         */
        /**
         * Check whether the click is inside the element or excluded
         * @param event - Click event
         */
        // @ts-ignore
        this._isInsideClick = (event) => {
            const { rootRef, excludeClass } = this.props;
            let target = event.target;
            while (target) {
                // Same node
                if (rootRef.current === target) {
                    return true;
                }
                // Contains an excluded class
                if (target.classList) {
                    if (typeof excludeClass === 'string' &&
                        target.classList.contains(excludeClass)) {
                        return true;
                    }
                    if (typeof excludeClass === 'object' &&
                        target.classList
                            .toString()
                            .split(' ')
                            .some(c => excludeClass.includes(c))) {
                        return true;
                    }
                }
                // @ts-expect-error
                target = target.parentElement;
            }
            return;
        };
        /**
         * Triggers onClickOutside callback when clicked outside child
         * @param event - Click event
         */
        this._onClickOutside = (event) => {
            const { onClickOutside } = this.props;
            if (typeof onClickOutside === 'function' && !this._isInsideClick(event)) {
                onClickOutside(event);
            }
        };
        this._boundEvents = [];
    }
    /**
     * Register ClickOutside events
     */
    _registerEvents() {
        const { options } = this.props;
        ['mouseup', 'touchend'].forEach(eventName => {
            document.addEventListener(eventName, this._onClickOutside, options);
            this._boundEvents.push(eventName);
        });
    }
    /**
     * Unregister ClickOutside events
     */
    _unregisterEvents() {
        const { options } = this.props;
        while (this._boundEvents.length > 0) {
            const eventName = this._boundEvents.pop();
            if (eventName) {
                document.removeEventListener(eventName, this._onClickOutside, options);
            }
        }
    }
    componentDidMount() {
        if (this.props.onClickOutside) {
            this._registerEvents();
        }
    }
    componentDidUpdate(prevProps) {
        if (this.props.onClickOutside !== prevProps.onClickOutside) {
            if (this.props.onClickOutside) {
                this._registerEvents();
            }
            else {
                this._unregisterEvents();
            }
        }
    }
    componentWillUnmount() {
        this._unregisterEvents();
    }
    render() {
        return this.props.children;
    }
}
//# sourceMappingURL=ClickOutside.js.map