UNPKG

webcoreui

Version:

UI component and template library for Astro, Svelte, and React apps styled with Sass.

135 lines (103 loc) 3.75 kB
import { bodyFreeze } from './bodyFreeze' export type ModalCallback = { trigger: Element | null modal: HTMLElement } export type Modal = { trigger: string modal: string onOpen?: (args: ModalCallback) => unknown onClose?: (args: ModalCallback) => unknown } export const modal = (config: Modal | string) => { const { trigger, modal, onOpen, onClose } = (typeof config === 'string' ? {} : config) as Modal const modalSelector = typeof config === 'string' ? config : modal const triggerDOM = document.querySelector(trigger) const modalDOM = document.querySelector(modalSelector) as HTMLElement if (modalDOM) { const closeOptions = modalDOM.dataset.close?.split(',') const handleClose = { icon() { const close = modalDOM.querySelector('[data-id="close"]') const listener = () => { modalDOM.dataset.show = '' bodyFreeze(false) onClose?.({ trigger: triggerDOM, modal: modalDOM }) } return { add: () => close?.addEventListener('click', listener), remove: () => close?.removeEventListener('click', listener) } }, esc() { const listener = (event: KeyboardEvent) => { if (modalDOM.dataset.show && event.key === 'Escape') { modalDOM.dataset.show = '' bodyFreeze(false) onClose?.({ trigger: triggerDOM, modal: modalDOM }) } } return { add: () => document.addEventListener('keydown', listener), remove: () => document.removeEventListener('keydown', listener) } }, overlay() { const close = modalDOM.nextElementSibling const listener = () => { modalDOM.dataset.show = '' bodyFreeze(false) onClose?.({ trigger: triggerDOM, modal: modalDOM }) } return { add: () => close?.addEventListener('click', listener), remove: () => close?.removeEventListener('click', listener) } } } const handleOpen = () => { modalDOM.dataset.show = 'true' bodyFreeze() onOpen?.({ trigger: triggerDOM, modal: modalDOM }) } triggerDOM?.addEventListener('click', handleOpen) closeOptions?.forEach(option => { handleClose[option as keyof typeof handleClose]().add() }) return { open() { handleOpen() }, remove() { triggerDOM?.removeEventListener('click', handleOpen) closeOptions?.forEach(option => { handleClose[option as keyof typeof handleClose]().remove() }) } } } } export const closeModal = (modal: string) => { const modalDOM = document.querySelector(modal) as HTMLElement if (modalDOM) { modalDOM.dataset.show = '' bodyFreeze(false) } }