UNPKG

basecoat-css

Version:

Tailwind CSS for Basecoat components

85 lines (71 loc) 2.63 kB
(() => { const initPopover = (popoverComponent) => { const trigger = popoverComponent.querySelector(':scope > button'); const content = popoverComponent.querySelector(':scope > [data-popover]'); if (!trigger || !content) { const missing = []; if (!trigger) missing.push('trigger'); if (!content) missing.push('content'); console.error(`Popover initialisation failed. Missing element(s): ${missing.join(', ')}`, popoverComponent); return; } const closePopover = (focusOnTrigger = true) => { if (trigger.getAttribute('aria-expanded') === 'false') return; trigger.setAttribute('aria-expanded', 'false'); content.setAttribute('aria-hidden', 'true'); if (focusOnTrigger) { trigger.focus(); } }; const openPopover = () => { document.dispatchEvent(new CustomEvent('basecoat:popover', { detail: { source: popoverComponent } })); const elementToFocus = content.querySelector('[autofocus]'); if (elementToFocus) { content.addEventListener('transitionend', () => { elementToFocus.focus(); }, { once: true }); } trigger.setAttribute('aria-expanded', 'true'); content.setAttribute('aria-hidden', 'false'); }; trigger.addEventListener('click', () => { const isExpanded = trigger.getAttribute('aria-expanded') === 'true'; if (isExpanded) { closePopover(); } else { openPopover(); } }); popoverComponent.addEventListener('keydown', (event) => { if (event.key === 'Escape') { closePopover(); } }); document.addEventListener('click', (event) => { if (!popoverComponent.contains(event.target)) { closePopover(); } }); document.addEventListener('basecoat:popover', (event) => { if (event.detail.source !== popoverComponent) { closePopover(false); } }); popoverComponent.dataset.popoverInitialized = true; }; document.querySelectorAll('.popover:not([data-popover-initialized])').forEach(initPopover); const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType !== Node.ELEMENT_NODE) return; if (node.matches('.popover:not([data-popover-initialized])')) { initPopover(node); } node.querySelectorAll('.popover:not([data-popover-initialized])').forEach(initPopover); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })();