import { h, Host } from "@stencil/core";
import { boolToFocusValue, govHost, toBoolAttr } from "../../helpers/Dom/template";
import { canValidateWcagOnRender } from "../../helpers/Dom/win";
import { validateWcagRef } from "../../helpers/Validate/wcag";
import { createID } from "../../utils/string.utils";
import { DialogClass } from "./constants";
import { tick } from "../../utils/stencil.utils";
import { getFocusableElements } from "../../utils/dom.utils";
export class GovDialog {
    constructor() {
        this.hydrated = false;
        /**
         * Attribute for dialog window display
         */
        this.open = false;
        /**
         * Attribute allowing blocking the dialog closing
         */
        this.blockClose = false;
        /**
         * Attribute allowing blocking the backdrop dialog closing
         */
        this.blockBackdropClose = false;
        /**
         * Role of dialog
         */
        this.role = 'dialog';
        /**
         * Used to change the HTML tag in the dialog label for correct semantic structure
         */
        this.labelTag = 'h2';
        /**
         * Adds accessible label for the dialog close button that is only shown for screen readers.
         */
        this.accessibleCloseLabel = 'Zavřít okno';
        this.h = govHost(this.host);
        this.labelId = createID('GovDialogLabel');
        this.contentId = createID('GovDialogContent');
    }
    watchOpen(newValue) {
        var _a;
        this.open = newValue;
        this.setFocus().finally();
        if (!newValue) {
            (_a = this.lastActiveElementRef) === null || _a === void 0 ? void 0 : _a.focus();
        }
        else {
            this.focusTrap();
        }
    }
    showDialog() {
        this.open = true;
        document.body.classList.add(DialogClass.bodyFix);
    }
    hideDialog() {
        this.open = false;
        document.body.classList.remove(DialogClass.bodyFix);
    }
    async componentDidRender() {
        if (canValidateWcagOnRender()) {
            tick(() => this.validateAccessibility());
        }
        if (this.open) {
            this.showDialog();
        }
        else {
            this.hideDialog();
        }
    }
    focusTrap() {
        var _a;
        if (open && this.dialogRef) {
            this.lastActiveElementRef = document.activeElement;
            const focusableEls = getFocusableElements(this.dialogRef);
            if (focusableEls.length) {
                focusableEls[0].focus();
            }
            const handleKeyDown = (e) => {
                if (e.key === "Tab" && this.dialogRef) {
                    const focusableEls = getFocusableElements(this.dialogRef);
                    const firstEl = focusableEls[0];
                    const lastEl = focusableEls[focusableEls.length - 1];
                    if (!e.shiftKey && document.activeElement === lastEl) {
                        e.preventDefault();
                        firstEl.focus();
                    }
                    if (e.shiftKey && document.activeElement === firstEl) {
                        e.preventDefault();
                        lastEl.focus();
                    }
                }
                if (e.key === "Escape") {
                    if (this.blockClose === false) {
                        this.hideDialog();
                        this.govClose.emit();
                    }
                }
            };
            document.addEventListener("keydown", handleKeyDown);
        }
        else {
            (_a = this.lastActiveElementRef) === null || _a === void 0 ? void 0 : _a.focus();
        }
    }
    connectedCallback() {
        this.hydrated = true;
    }
    disconnectedCallback() {
        document.body.classList.remove(DialogClass.bodyFix);
    }
    render() {
        return (h(Host, { key: 'ba9070ed36ce25806a12a88f55d9a36609e17bbb', class: this.h.classes(DialogClass.root), open: this.open, hydrated: this.hydrated }, h("dialog", { key: '79188b6182895a7a7db32e629316a46420d2981c', ref: el => (this.dialogRef = el), class: DialogClass.dialog, hidden: !this.open, tabindex: boolToFocusValue(this.open), open: this.open, "aria-modal": "true", "aria-hidden": toBoolAttr(!this.open), "aria-labelledby": this.accessibleLabelledBy || this.labelId, "aria-describedby": this.accessibleDescribedBy || this.contentId, role: this.role }, h("div", { key: 'a50c41b27b3060292df9b6d2eb657c1e27a384e7', class: DialogClass.inner }, h("div", { key: '487b4639e842aa7257e2ce24a553e8ae67be02be', class: DialogClass.header }, this.h.hasSlot("icon") && (h("span", { key: '75dfd64444588ce6a37607a60eb1c4df7888d3e8' }, h("slot", { key: '80be9198860ffce669b218b6f0f0143f7da83add', name: "icon" }))), this.h.hasSlot('title') && (h("span", { key: '723a628454f0989db5da7a1ae12aef803896b9de', class: DialogClass.title, id: this.labelId }, h("slot", { key: '0aee99ddbdbb0a068b07259d6b2793ddf3dfa629', name: "title" }))), h("gov-button", { key: '6f245f5f2a3a95ff239cd55640c5aac980374cfc', ref: el => (this.closeCtaRef = el), disabled: this.blockClose, class: DialogClass.close, color: "primary", "aria-label": this.accessibleCloseLabel, "aria-labelledby": this.accessibleCloseLabelledBy, type: "base", size: "m", "on-gov-click": this.onCloseHandler.bind(this) }, h("gov-icon", { key: 'f767a25f40e13c322d6871275d996493bbe8730b', slot: "icon-start", name: "x-lg", type: "components" }))), h("div", { key: '4c975dfa826bada579b1ee6edbcece08bf6b7346', class: DialogClass.content, id: this.contentId }, h("slot", { key: 'cdc3d7b173b47237cecf113e344d2ebd05d6daeb' })), this.h.hasSlot('footer') && (h("div", { key: '37e471ea3bb0952c0ccfc290b02af6d69690ae4e', class: DialogClass.footer }, h("slot", { key: '69f6160c0429d82051a6b99d210f132c7ec3ff56', name: "footer" }))))), this.open ? (h("gov-backdrop", { disabled: this.blockBackdropClose, "aria-label": this.accessibleCloseLabel, "aria-labelled-by": this.accessibleCloseLabelledBy, "on-gov-click": this.onCloseHandler.bind(this) })) : null));
    }
    onCloseHandler(e) {
        e.stopPropagation();
        e.preventDefault();
        if (this.blockClose === false) {
            this.hideDialog();
            this.govClose.emit(e);
        }
    }
    /**
     * Sets the close button to focus
     */
    async setFocus() {
        if (this.open && this.closeCtaRef) {
            this.closeCtaRef.setFocus().catch();
        }
    }
    /**
     * Validate the WCAG attributes of the component
     */
    async validateAccessibility() {
        validateWcagRef(this.accessibleLabelledBy, 'accessible-labelled-by', DialogClass.root);
        validateWcagRef(this.accessibleDescribedBy, 'accessible-described-by', DialogClass.root);
    }
    static get is() { return "gov-dialog"; }
    static get properties() {
        return {
            "open": {
                "type": "boolean",
                "attribute": "open",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Attribute for dialog window display"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "blockClose": {
                "type": "boolean",
                "attribute": "block-close",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Attribute allowing blocking the dialog closing"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "blockBackdropClose": {
                "type": "boolean",
                "attribute": "block-backdrop-close",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Attribute allowing blocking the backdrop dialog closing"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "false"
            },
            "role": {
                "type": "string",
                "attribute": "role",
                "mutable": false,
                "complexType": {
                    "original": "Nullable<string>",
                    "resolved": "string",
                    "references": {
                        "Nullable": {
                            "location": "import",
                            "path": "../../types/interfaces",
                            "id": "../../../packages/core/src/types/interfaces.ts::Nullable"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Role of dialog"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'dialog'"
            },
            "labelTag": {
                "type": "string",
                "attribute": "label-tag",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Used to change the HTML tag in the dialog label for correct semantic structure"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'h2'"
            },
            "accessibleLabelledBy": {
                "type": "string",
                "attribute": "accessible-labelled-by",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "String of id's that indicates alternative labels elements"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "accessibleDescribedBy": {
                "type": "string",
                "attribute": "accessible-described-by",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Indicates the id of a component that describes the dialog."
                },
                "getter": false,
                "setter": false,
                "reflect": false
            },
            "accessibleCloseLabel": {
                "type": "string",
                "attribute": "accessible-close-label",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Adds accessible label for the dialog close button that is only shown for screen readers."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'Zav\u0159\u00EDt okno'"
            },
            "accessibleCloseLabelledBy": {
                "type": "string",
                "attribute": "accessible-close-labelled-by",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A string of identifiers that indicate alternative label elements for closing the dialog window"
                },
                "getter": false,
                "setter": false,
                "reflect": false
            }
        };
    }
    static get events() {
        return [{
                "method": "govClose",
                "name": "gov-close",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when a dialog window closes."
                },
                "complexType": {
                    "original": "PointerEvent",
                    "resolved": "PointerEvent",
                    "references": {
                        "PointerEvent": {
                            "location": "global",
                            "id": "global::PointerEvent"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setFocus": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets the close button to focus",
                    "tags": []
                }
            },
            "validateAccessibility": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Validate the WCAG attributes of the component",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "open",
                "methodName": "watchOpen"
            }];
    }
}
//# sourceMappingURL=gov-dialog.js.map
