import { __decorate } from "tslib";
import { html, nothing } from "lit";
import { property, query, queryAssignedElements, queryAssignedNodes, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { UiElement } from "../UiElement.js";
import { isDisabled, setDisabled } from "../lib/disabled.js";
import '../../define/ui/ui-button.js';
/**
 * Styled dialog using a native `<dialog>` element under the hood.
 * Note, since native dialog renders in the top layer it is not necessary
 * to place the dialog in the `<body>`.
 *
 * ## Using buttons
 *
 * The dialog automatically recognizes buttons with values `confirm` and `dismiss`
 * to close the dialog and dispatch the `close` event. The event has additional
 * closing reason detail.
 *
 * ```javascript
 * <ui-button value="dismiss">Cancel</ui-button>
 * <ui-button value="confirm">Take action</ui-button>
 * ```
 *
 * ```javascript
 * <button value="dismiss">Cancel</button>
 * <button value="confirm">Take action</button>
 * ```
 *
 * The detail object of the `close` event has the following properties:
 * - cancelled - Whether the dialog was cancelled by either activating the `dismiss` button or by pressing escape.
 *
 * The `close` event is only dispatched when the user interact with the dialog. Imperative control of the
 * dialog won't trigger the close button.
 *
 * ## Full example
 *
 * ```javascript
 * <ui-dialog modal>
 *  <ui-icon slot="icon" icon="delete"></ui-icon>
 *
 *  <span slot="title">Delete photos?</span>
 *  <p>This action will permanently remove the selected pictures from your account.</p>
 *
 *  <ui-button slot="button" value="dismiss" type="text">Cancel</ui-button>
 *  <ui-button slot="button" value="confirm" type="text">Confirm</ui-button>
 * </ui-dialog>
 * ```
 *
 * @slot - The slot for the content of the dialog.
 * @slot icon - The slot to place the dialog icon
 * @slot title - The slot to place the dialog title. Do not put elements here, just the text.
 * @slot button - The slot to place the dialog buttons. Use the `confirm` or `dismiss` buttons to automatically close the dialog.
 * @fires close - A non-bubbling, non-cancellable event with the `UiDialogClosingReason` as the detail.
 */
export default class UiDialog extends UiElement {
    get disabled() {
        return isDisabled(this);
    }
    /**
     * When set, the button is a disabled state.
     * @attribute
     */
    set disabled(value) {
        const old = isDisabled(this);
        setDisabled(this, value);
        this.requestUpdate('disabled', old);
    }
    constructor() {
        super();
        /**
         * Opens the dialog as modal when toggling dialog's open state.
         *
         * Setting this value after the dialog was opened has no effect.
         *
         * @attribute
         */
        this.modal = false;
        /**
         * Toggles visibility of the dialog.
         * Note, the dialog is opened asynchronously after the update is performed.
         * @attribute
         */
        this.open = false;
        this.hasIcon = false;
        this.hasTitle = false;
        this.hasButton = false;
        this.addEventListener('click', this.handleClick);
        this.addEventListener('keydown', this.handleKeyDown);
    }
    handleClick(e) {
        super.handleClick(e);
        const path = e.composedPath();
        const { buttons } = this;
        const button = path.find(i => buttons.includes(i));
        if (!button) {
            return;
        }
        const { value = '' } = button;
        this.handleInteraction(value);
    }
    handleKeyDown(e) {
        super.handleKeyDown(e);
        if (e.key === 'Escape') {
            this.handleInteraction('dismiss');
        }
    }
    updated(changedProperties) {
        if (changedProperties.has('open')) {
            this.controlVisibility();
        }
        super.updated(changedProperties);
    }
    controlVisibility() {
        const { dialog, modal, open } = this;
        if (!dialog) {
            return;
        }
        if (open) {
            if (modal) {
                dialog.showModal();
            }
            else {
                dialog.show();
            }
        }
        else {
            dialog.close();
        }
    }
    handleSlotChange() {
        const { icons, titles, buttons } = this;
        this.hasIcon = !!icons && !!icons.length;
        this.hasTitle = !!titles && !!titles.length;
        this.hasButton = !!buttons && !!buttons.length;
    }
    handleInteraction(value) {
        if (!['dismiss', 'confirm'].includes(value)) {
            return;
        }
        this.open = false;
        const detail = {
            cancelled: value === 'dismiss',
        };
        if (this.dialogValue !== undefined) {
            detail.value = this.dialogValue;
        }
        this.dispatchEvent(new CustomEvent('close', {
            composed: true,
            detail,
        }));
    }
    handleDialogClose() {
        if (!this.open) {
            return;
        }
        this.open = false;
        this.handleInteraction('dismiss');
    }
    handleDismiss() {
        this.handleInteraction('dismiss');
    }
    handleConfirm() {
        this.handleInteraction('confirm');
    }
    render() {
        return html `
    <dialog @close="${this.handleDialogClose}">
      ${this.renderIcon()}
      ${this.renderTitle()}
      ${this.renderBody()}
      ${this.renderButtons()}
    </dialog>
    `;
    }
    renderIcon() {
        const classes = {
            icon: true,
            'with-icon': this.hasIcon,
        };
        return html `
    <div class="${classMap(classes)}" part="icon"><slot name="icon" @slotchange="${this.handleSlotChange}"></slot></div>
    `;
    }
    renderTitle() {
        const classes = {
            title: true,
            'with-title': this.hasTitle,
        };
        return html `
    <div class="${classMap(classes)}" part="title"><slot name="title" @slotchange="${this.handleSlotChange}"></slot></div>
    `;
    }
    renderBody() {
        return html `
    <div class="content"><slot></slot></div>
    `;
    }
    renderButtons() {
        const classes = {
            buttons: true,
            'with-buttons': this.hasButton || !!this.confirmLabel || !!this.dismissLabel,
        };
        return html `
    <div class="${classMap(classes)}" part="button">
      <slot name="button" @slotchange="${this.handleSlotChange}"></slot>
      ${this.renderDismissButton()}
      ${this.renderConfirmButton()}
    </div>
    `;
    }
    renderDismissButton() {
        const { dismissLabel } = this;
        if (!dismissLabel) {
            return nothing;
        }
        return html `
     <ui-button value="dismiss" type="text" class="internal-button" @click="${this.handleDismiss}">${dismissLabel}</ui-button>
    `;
    }
    renderConfirmButton() {
        const { confirmLabel } = this;
        if (!confirmLabel) {
            return nothing;
        }
        return html `
     <ui-button value="confirm" type="text" class="internal-button" @click="${this.handleConfirm}">${confirmLabel}</ui-button>
    `;
    }
}
__decorate([
    property({ reflect: true, type: Boolean })
], UiDialog.prototype, "disabled", null);
__decorate([
    property({ type: Boolean })
], UiDialog.prototype, "modal", void 0);
__decorate([
    property({ type: Boolean })
], UiDialog.prototype, "open", void 0);
__decorate([
    property({ type: String })
], UiDialog.prototype, "dismissLabel", void 0);
__decorate([
    property({ type: String })
], UiDialog.prototype, "confirmLabel", void 0);
__decorate([
    query('dialog')
], UiDialog.prototype, "dialog", void 0);
__decorate([
    state()
], UiDialog.prototype, "hasIcon", void 0);
__decorate([
    state()
], UiDialog.prototype, "hasTitle", void 0);
__decorate([
    state()
], UiDialog.prototype, "hasButton", void 0);
__decorate([
    queryAssignedElements({ flatten: true, slot: 'icon' })
], UiDialog.prototype, "icons", void 0);
__decorate([
    queryAssignedNodes({ flatten: true, slot: 'title' })
], UiDialog.prototype, "titles", void 0);
__decorate([
    queryAssignedElements({ flatten: true, slot: 'button' })
], UiDialog.prototype, "buttons", void 0);
//# sourceMappingURL=UiDialog.js.map