UNPKG

@studiocms/ui

Version:

The UI library for StudioCMS. Includes the layouts & components we use to build StudioCMS.

130 lines (129 loc) 4.23 kB
class ModalHelper { element; cancelButton; confirmButton; isForm = false; modalForm; /** * A helper to manage modals. * @param id The ID of the modal. * @param triggerID The ID of the element that should trigger the modal. */ constructor(id, triggerID) { const element = document.getElementById(id); if (!element) { throw new Error(`No modal with ID ${id} found.`); } this.element = element; this.modalForm = document.getElementById(`${id}-form-element`); const isDismissable = this.element.dataset.dismissable === "true"; const isForm = this.element.dataset.form === "true"; if (isDismissable) { this.addDismissiveClickListener(); } if (isForm) this.isForm = true; this.addButtonListeners(id, isDismissable); if (triggerID) { this.bindTrigger(triggerID); } } /** * A helper function which adds event listeners to the modal buttons to close the modal when clicked. * @param id The ID of the modal. * @param dismissable Whether the modal is dismissable. */ addButtonListeners = (id, dismissable) => { if (dismissable || !this.element.dataset.hasCancelButton && !this.element.dataset.hasActionButton) { const xMarkButton = document.getElementById(`${id}-btn-x`); xMarkButton.addEventListener("click", this.hide); } if (!!this.element.dataset.hasCancelButton && !this.element.dataset.hasActionButton) return; if (this.element.dataset.hasCancelButton) { this.cancelButton = document.getElementById(`${id}-btn-cancel`); this.cancelButton.addEventListener("click", this.hide); } if (this.element.dataset.hasActionButton) { this.confirmButton = document.getElementById(`${id}-btn-confirm`); this.confirmButton.addEventListener("click", this.hide); } }; /** * A helper function to close the modal when the user clicks outside of it. */ addDismissiveClickListener = () => { this.element.addEventListener("click", (e) => { if (!e.target) return; const { left, right, top, bottom } = this.element.getBoundingClientRect(); const clickWithinModalBox = e.clientX < right && e.clientX > left && e.clientY < bottom && e.clientY > top; if (!clickWithinModalBox) { this.element.close(); } }); }; /** * A function to show the modal. */ show = () => { this.element.showModal(); this.element.focus(); }; /** * A function to hide the modal. */ hide = () => { this.element.close(); }; /** * A function to add another trigger to show the modal with. * @param elementID The ID of the element that should trigger the modal when clicked. */ bindTrigger = (elementID) => { const element = document.getElementById(elementID); if (!element) { throw new Error(`No element with ID ${elementID} found.`); } element.addEventListener("click", this.show); }; /** * Registers a callback for the cancel button. * @param func The callback function. */ registerCancelCallback = (func) => { if (!this.cancelButton) { throw new Error("Unable to register cancel callback without a cancel button."); } this.cancelButton.removeEventListener("click", this.hide); this.cancelButton.addEventListener("click", () => { func(); this.hide(); }); }; /** * Registers a callback for the confirm button. * @param func The callback function. If the modal is a form, the function will be called with * the form data as the first argument. */ registerConfirmCallback = (func) => { if (!this.confirmButton) { throw new Error("Unable to register cancel callback without a confirmation button."); } this.confirmButton.removeEventListener("click", this.hide); if (this.isForm) { this.modalForm.addEventListener("submit", (e) => { e.preventDefault(); const formData = new FormData(this.modalForm); func(formData); this.hide(); setTimeout(() => this.modalForm.reset(), 450); }); } else { this.confirmButton.addEventListener("click", () => { func(); this.hide(); }); } }; } export { ModalHelper };