"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createOverlayComponent = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importDefault(require("react"));
const react_dom_1 = tslib_1.__importDefault(require("react-dom"));
const utils_1 = require("./utils");
const createOverlayComponent = (tagName, controller, customElement) => {
    utils_1.defineCustomElement(tagName, customElement);
    const displayName = utils_1.dashToPascalCase(tagName);
    const didDismissEventName = `on${displayName}DidDismiss`;
    const didPresentEventName = `on${displayName}DidPresent`;
    const willDismissEventName = `on${displayName}WillDismiss`;
    const willPresentEventName = `on${displayName}WillPresent`;
    let isDismissing = false;
    class Overlay extends react_1.default.Component {
        constructor(props) {
            super(props);
            if (typeof document !== 'undefined') {
                this.el = document.createElement('div');
            }
            this.handleDismiss = this.handleDismiss.bind(this);
        }
        static get displayName() {
            return displayName;
        }
        componentDidMount() {
            if (this.props.isOpen) {
                this.present();
            }
        }
        componentWillUnmount() {
            if (this.overlay) {
                this.overlay.dismiss();
            }
        }
        handleDismiss(event) {
            if (this.props.onDidDismiss) {
                this.props.onDidDismiss(event);
            }
            utils_1.setRef(this.props.forwardedRef, null);
        }
        shouldComponentUpdate(nextProps) {
            // Check if the overlay component is about to dismiss
            if (this.overlay && nextProps.isOpen !== this.props.isOpen && nextProps.isOpen === false) {
                isDismissing = true;
            }
            return true;
        }
        async componentDidUpdate(prevProps) {
            if (this.overlay) {
                utils_1.attachProps(this.overlay, this.props, prevProps);
            }
            if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
                this.present(prevProps);
            }
            if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) {
                await this.overlay.dismiss();
                isDismissing = false;
                /**
                 * Now that the overlay is dismissed
                 * we need to render again so that any
                 * inner components will be unmounted
                 */
                this.forceUpdate();
            }
        }
        async present(prevProps) {
            const _a = this.props, { children, isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent } = _a, cProps = tslib_1.__rest(_a, ["children", "isOpen", "onDidDismiss", "onDidPresent", "onWillDismiss", "onWillPresent"]);
            const elementProps = Object.assign(Object.assign({}, cProps), { ref: this.props.forwardedRef, [didDismissEventName]: this.handleDismiss, [didPresentEventName]: (e) => this.props.onDidPresent && this.props.onDidPresent(e), [willDismissEventName]: (e) => this.props.onWillDismiss && this.props.onWillDismiss(e), [willPresentEventName]: (e) => this.props.onWillPresent && this.props.onWillPresent(e) });
            this.overlay = await controller.create(Object.assign(Object.assign({}, elementProps), { component: this.el, componentProps: {} }));
            utils_1.setRef(this.props.forwardedRef, this.overlay);
            utils_1.attachProps(this.overlay, elementProps, prevProps);
            await this.overlay.present();
        }
        render() {
            /**
             * Continue to render the component even when
             * overlay is dismissing otherwise component
             * will be hidden before animation is done.
             */
            return react_dom_1.default.createPortal(this.props.isOpen || isDismissing ? this.props.children : null, this.el);
        }
    }
    return react_1.default.forwardRef((props, ref) => {
        return react_1.default.createElement(Overlay, Object.assign({}, props, { forwardedRef: ref }));
    });
};
exports.createOverlayComponent = createOverlayComponent;
//# sourceMappingURL=createOverlayComponent.js.map