import { __decorate } from "tslib";
import { attr, observable } from '@ni/fast-element';
import { applyMixins, ARIAGlobalStatesAndProperties, DesignSystem, FoundationElement } from '@ni/fast-foundation';
import { UserDismissed } from '../patterns/dialog/types';
import { styles } from './styles';
import { template } from './template';
export { UserDismissed };
/**
 * A nimble-styled dialog.
 */
export class Dialog extends FoundationElement {
    constructor() {
        super(...arguments);
        /**
         * @public
         * @description
         * Prevents dismissing the dialog via the Escape key
         */
        this.preventDismiss = false;
        /**
         * @public
         * @description
         * Hides the header of the dialog.
         */
        this.headerHidden = false;
        /**
         * @public
         * @description
         * Hides the footer of the dialog.
         */
        this.footerHidden = false;
        /** @internal */
        this.footerIsEmpty = true;
    }
    /**
     * True if the dialog is open/showing, false otherwise
     */
    get open() {
        return this.resolveShow !== undefined;
    }
    /**
     * Opens the dialog
     * @returns Promise that is resolved when the dialog is closed. The value of the resolved Promise is the reason value passed to the close() method, or UserDismissed if the dialog was closed via the ESC key.
     */
    async show() {
        if (this.open) {
            throw new Error('Dialog is already open');
        }
        this.dialogElement.showModal();
        return await new Promise((resolve, _reject) => {
            this.resolveShow = resolve;
        });
    }
    /**
     * Closes the dialog
     * @param reason An optional value indicating how/why the dialog was closed.
     */
    close(reason) {
        if (!this.open) {
            throw new Error('Dialog is not open');
        }
        this.dialogElement.close();
        this.doResolveShow(reason);
    }
    slottedFooterElementsChanged(_prev, next) {
        this.footerIsEmpty = next === undefined || next.length === 0;
    }
    /**
     * @internal
     */
    cancelHandler(event) {
        if (this.preventDismiss) {
            event.preventDefault();
        }
        else {
            this.doResolveShow(UserDismissed);
        }
        return true;
    }
    /**
     * @internal
     */
    closeHandler(event) {
        if (event.target !== this.dialogElement) {
            return;
        }
        if (this.resolveShow) {
            // If
            // - the browser implements dialogs with the CloseWatcher API, and
            // - the user presses ESC without first interacting with the dialog (e.g. clicking, scrolling),
            // the cancel event is not fired, but the close event still is, and the dialog just closes.
            this.doResolveShow(UserDismissed);
        }
    }
    doResolveShow(reason) {
        if (!this.resolveShow) {
            throw new Error('Do not call doResolveShow unless there is a promise to resolve');
        }
        this.resolveShow(reason);
        this.resolveShow = undefined;
    }
}
// We want the member to match the name of the constant
// eslint-disable-next-line @typescript-eslint/naming-convention
Dialog.UserDismissed = UserDismissed;
__decorate([
    attr({ attribute: 'prevent-dismiss', mode: 'boolean' })
], Dialog.prototype, "preventDismiss", void 0);
__decorate([
    attr({ attribute: 'header-hidden', mode: 'boolean' })
], Dialog.prototype, "headerHidden", void 0);
__decorate([
    attr({ attribute: 'footer-hidden', mode: 'boolean' })
], Dialog.prototype, "footerHidden", void 0);
__decorate([
    observable
], Dialog.prototype, "footerIsEmpty", void 0);
__decorate([
    observable
], Dialog.prototype, "slottedFooterElements", void 0);
applyMixins(Dialog, ARIAGlobalStatesAndProperties);
const nimbleDialog = Dialog.compose({
    baseName: 'dialog',
    template,
    styles,
    baseClass: Dialog
});
DesignSystem.getOrCreate().withPrefix('nimble').register(nimbleDialog());
export const dialogTag = 'nimble-dialog';
//# sourceMappingURL=index.js.map