import { Host, h } from "@stencil/core"; import { queryShadowRoot, isHidden, isFocusable } from "../../global/utils/focus-trap"; import { animationTo, KEYFRAMES } from "../../global/utils/animation"; export class IfxModal { constructor() { this.focusableElements = []; this.handleTopFocus = () => { this.attemptFocus(this.getLastFocusableElement()); }; this.handleBottomFocus = () => { this.attemptFocus(this.getFirstFocusableElement()); }; this.handleKeypress = (event) => { if (!this.showModal) { return; } if (event.key === 'Escape') { this.doBeforeClose('ESCAPE_KEY'); } }; this.opened = false; this.showModal = this.opened || false; this.caption = 'Modal Title'; this.closeOnOverlayClick = true; this.variant = 'default'; this.alertIcon = ''; this.okButtonLabel = 'OK'; this.cancelButtonLabel = 'Cancel'; this.slotButtonsPresent = false; } componentDidLoad() { // Query all focusable elements and store them in `focusableElements`. // Needed for the "focus trap" functionality. this.focusableElements = queryShadowRoot(this.hostElement.shadowRoot, (el) => isHidden(el) || el.matches('[data-focus-trap-edge]'), isFocusable); } getFirstFocusableElement() { return this.focusableElements[0]; } getLastFocusableElement() { return this.focusableElements[this.focusableElements.length - 1]; } attemptFocus(element) { if (element == null) { setTimeout(() => { this.closeButton.focus(); }); return; } setTimeout(() => { element.focus(); }, 0); } open() { this.showModal = true; try { const anim = animationTo(this.modalContainer, KEYFRAMES.fadeIn, { duration: 200, }); anim.addEventListener('finish', () => { this.attemptFocus(this.getFirstFocusableElement()); this.ifxModalOpen.emit(); }); // this.attemptFocus(this.getFirstFocusableElement()); // this.ifxModalOpen.emit(); this.hostElement.addEventListener('keydown', this.handleKeypress); } catch (err) { this.ifxModalOpen.emit(); } } close() { try { const anim = animationTo(this.modalContainer, KEYFRAMES.fadeOut, { duration: 200, }); anim.addEventListener('finish', () => { this.showModal = false; this.ifxModalClose.emit(); }); this.hostElement.removeEventListener('keydown', this.handleKeypress); } catch (err) { this.showModal = false; this.ifxModalClose.emit(); } } doBeforeClose(trigger) { const triggers = []; triggers.push(trigger); const prevented = triggers.some((event) => event.defaultPrevented); if (!prevented) { this.opened = false; } } openedChanged(newValue) { if (newValue === true) { this.open(); } else { this.close(); } } handleOverlayClick() { if (this.closeOnOverlayClick) { this.doBeforeClose('BACKDROP'); } } handleButtonsSlotChange(e) { var _a; if (((_a = e.currentTarget.assignedElements()[0]) === null || _a === void 0 ? void 0 : _a.childElementCount) > 0) { this.slotButtonsPresent = true; } else { this.slotButtonsPresent = false; } } render() { const isAlertVariant = this.variant !== 'default'; return (h(Host, null, h("div", { ref: (el) => (this.modalContainer = el), class: `modal-container ${this.showModal ? 'open' : ''}` }, h("div", { class: "modal-overlay", onClick: () => this.handleOverlayClick() }), h("div", { "data-focus-trap-edge": true, onFocus: this.handleTopFocus, tabindex: "0" }), h("div", { class: `modal-content-container`, role: "dialog", "aria-modal": "true", "aria-label": this.caption }, isAlertVariant ? (h("div", { class: `modal-icon-container ${this.variant === 'alert-brand' ? '' : 'danger'}` }, this.alertIcon ? h("ifx-icon", { icon: this.alertIcon }) : null)) : null, h("div", { class: "modal-content" }, h("div", { class: "modal-header" }, h("h2", null, this.caption), h("ifx-icon-button", { ref: (el) => (this.closeButton = el), icon: "cross-24", variant: "tertiary", onClick: () => this.doBeforeClose('CLOSE_BUTTON') })), h("div", { class: "modal-body" }, h("slot", { name: "content" /*onSlotchange={() => console.log('slots children modified')}*/ })), h("div", { class: `modal-footer ${this.slotButtonsPresent ? 'buttons-present' : ''}` }, h("slot", { name: "buttons", onSlotchange: (e) => this.handleButtonsSlotChange(e) })))), h("div", { "data-focus-trap-edge": true, onFocus: this.handleBottomFocus, tabindex: "0" })))); } static get is() { return "ifx-modal"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["modal.scss"] }; } static get styleUrls() { return { "$": ["modal.css"] }; } static get properties() { return { "opened": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "" }, "attribute": "opened", "reflect": true, "defaultValue": "false" }, "caption": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "caption", "reflect": false, "defaultValue": "'Modal Title'" }, "closeOnOverlayClick": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "close-on-overlay-click", "reflect": false, "defaultValue": "true" }, "variant": { "type": "string", "mutable": false, "complexType": { "original": "'default' | 'alert-brand' | 'alert-danger'", "resolved": "\"alert-brand\" | \"alert-danger\" | \"default\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "variant", "reflect": false, "defaultValue": "'default'" }, "alertIcon": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "alert-icon", "reflect": false, "defaultValue": "''" }, "okButtonLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "ok-button-label", "reflect": false, "defaultValue": "'OK'" }, "cancelButtonLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "" }, "attribute": "cancel-button-label", "reflect": false, "defaultValue": "'Cancel'" } }; } static get states() { return { "showModal": {}, "slotButtonsPresent": {} }; } static get events() { return [{ "method": "ifxModalOpen", "name": "ifxModalOpen", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }, { "method": "ifxModalClose", "name": "ifxModalClose", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "opened", "methodName": "openedChanged" }]; } } //# sourceMappingURL=modal.js.map