# sequra/3.1.1/assets/js/src/core/ModalComponent.js

seQura, version 3.1.1. 140 lines.

- Page: https://pluginprobe.com/plugins/sequra/3.1.1/code/assets/js/src/core/ModalComponent.js
- Raw: https://pluginprobe.com/plugins/sequra/3.1.1/raw/assets/js/src/core/ModalComponent.js
- Modified: 2024-10-29T15:19:22+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/sequra/3.1.1/code/assets/js/src/core/ModalComponent.js#L10-L20`.

```javascript
if (!window.SequraFE) {
    window.SequraFE = {};
}

if (!window.SequraFE.components) {
    window.SequraFE.components = {};
}

(function () {
    /**
     * @typedef ButtonConfig
     * @property {string} label
     * @property {string?} className
     * @property {'primary' | 'secondary'} type
     * @property {() => void} onClick
     */

    /**
     * @typedef ModalConfiguration
     * @property {string?} title
     * @property {string?} className
     * @property {HTMLElement} content The content of the body.
     * @property {ButtonConfig[]} buttons Footer buttons.
     * @property {(modal: HTMLDivElement) => void?} onOpen Will fire after the modal is opened.
     * @property {() => boolean?} onClose Will fire before the modal is closed.
     *      If the return value is false, the modal will not be closed.
     * @property {boolean} [footer=false] Indicates whether to use footer. Defaults to false.
     * @property {boolean} [canClose=true] Indicates whether to use an (X) button or click outside the modal
     * to close it. Defaults to true.
     * @property {boolean} [fullWidthBody=false] Indicates whether to make body full width
     */

    /**
     * @param {ModalConfiguration} config
     * @constructor
     */
    function ModalComponent(config) {
        const { templateService, translationService, utilities, elementGenerator } = SequraFE;

        /**
         * @type {HTMLDivElement}
         */
        let modal;

        /**
         * Closes the modal on Esc key.
         *
         * @param {KeyboardEvent} event
         */
        const closeOnEsc = (event) => {
            if (event.key === 'Escape') {
                this.close();
            }
        };

        /**
         * Closes the modal.
         */
        this.close = () => {
            if (!config.onClose || config.onClose()) {
                window.removeEventListener('keyup', closeOnEsc);
                modal?.remove();
            }
        };

        /**
         * Opens the modal.
         */
        this.open = () => {
            const modalTemplate =
                '<div id="sq-modal" class="sq-modal sqs--hidden">\n' +
                '    <div class="sq-modal-backdrop"></div>' +
                '    <div class="sqp-modal-content">' +
                '        <button class="sqp-close-button"><span></span></button>' +
                '        <div class="sqp-title"></div>' +
                '        <div class="sqp-body"></div>' +
                '        <div class="sqp-footer"></div>' +
                '    </div>' +
                '</div>';

            modal = SequraFE.elementGenerator.createElementFromHTML(modalTemplate);
            const closeBtn = modal.querySelector('.sqp-close-button'),
                closeBtnSpan = modal.querySelector('.sqp-close-button span'),
                title = modal.querySelector('.sqp-title'),
                body = modal.querySelector('.sqp-body'),
                footer = modal.querySelector('.sqp-footer');

            utilities.showElement(modal);
            if (config.canClose === false) {
                utilities.hideElement(closeBtn);
            } else {
                window.addEventListener('keyup', closeOnEsc);
                closeBtn.addEventListener('click', this.close);
                closeBtnSpan.style.display = 'flex';
                modal.addEventListener('click', (event) => {
                    if (event.target.id === 'sq-modal') {
                        event.preventDefault();
                        this.close();

                        return false;
                    }
                });
            }

            if (config.title) {
                title.innerHTML = translationService.translate(config.title);
            } else {
                utilities.hideElement(title);
            }

            if (config.className) {
                modal.classList.add(...config.className.split(' '));
            }

            config.content && body.append(...(Array.isArray(config.content) ? config.content : [config.content]));
            if (config.fullWidthBody) {
                body.classList.add('sqm--full-width');
            }

            if (config.footer === false || !config.buttons) {
                utilities.hideElement(footer);
            } else {
                config.buttons.forEach((button) => {
                    footer.appendChild(elementGenerator.createButton(button));
                });
            }

            templateService.getContentWrapper().appendChild(modal);
            if (config.onOpen) {
                config.onOpen(modal);
            }
        };
    }

    SequraFE.components.Modal = {
        /** @param {ModalConfiguration} config */
        create: (config) => new ModalComponent(config)
    };
})();

```
