@pageblock/utils
Version:
A modern utility library for PageBlock and Webflow, providing reusable components and utilities for web applications and Webflow sites
19 lines (18 loc) • 4.96 kB
JavaScript
/**
* PageBlock Modal - Minified Version
* @version 0.4.0
* @license MIT
*/
(()=>{/**
* PageBlock Modal - Simplified Version for Direct Inclusion
* @version 0.4.0
* @license MIT
*
* Features:
* - Full accessibility support (ARIA attributes, focus trapping)
* - Multiple close options (close button, overlay click, ESC key)
* - Animation options
* - Z-index management for multiple modals
* - Callbacks for open/close events
* - Proper error handling
*/(function(){const i=new WeakMap;let r=1e3,d=[];function u(){document.querySelectorAll("pageblock-modal[data-modal-id]").forEach(t=>{const o=t.getAttribute("data-modal-id");if(!o){console.warn("Modal container found without data-modal-id attribute",t);return}const e=t.querySelector('[data-pb-modal="sheet"]'),n=t.querySelector('[data-pb-modal="overlay"]');if(!e||!n){console.warn(`Modal components missing in container with ID: ${o}`,t);return}e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true"),e.setAttribute("aria-hidden","true");const l=t.getAttribute("data-animation"),s=t.getAttribute("data-variant");i.set(t,{id:o,isOpen:!1,previousFocus:null,animation:l||"fade",variant:s||"default",zIndex:parseInt(e.style.zIndex)||r,modal:e,overlay:n,focusableElements:b(e)})}),document.addEventListener("click",function(t){const o=t.target.closest("[data-pb-modal-trigger]");if(o){t.preventDefault();const l=o.getAttribute("data-pb-modal-trigger");f(l,{trigger:o})}const e=t.target.closest('[data-pb-modal="close"]');if(e){t.preventDefault();const l=e.closest("pageblock-modal"),s=l==null?void 0:l.getAttribute("data-modal-id");c(s)}const n=t.target.closest('[data-pb-modal="overlay"]');if(n&&n===t.target){t.preventDefault();const l=n.closest("pageblock-modal"),s=l==null?void 0:l.getAttribute("data-modal-id");c(s)}}),document.addEventListener("keydown",function(t){if(t.key==="Escape"&&d.length>0){const o=d[d.length-1];c(o)}else if(t.key==="Tab"&&d.length>0){const o=d[d.length-1],e=document.querySelector(`pageblock-modal[data-modal-id="${o}"]`);if(e){const n=i.get(e);n&&n.modal&&v(t,n.modal)}}}),document.addEventListener("pb:modal:open",function(t){const o=t.detail.modalId,e=t.detail.options||{};f(o,e)}),document.addEventListener("pb:modal:close",function(t){const o=t.detail.modalId,e=t.detail.options||{};c(o,e)})}function f(a,t={}){if(!a){console.error("Modal ID is required to open a modal");return}const o=document.querySelector(`pageblock-modal[data-modal-id="${a}"]`);if(!o){console.error(`Modal container not found for ID: ${a}`);return}const e=i.get(o);if(!e){console.error(`Modal state not found for ID: ${a}`);return}const n=e.modal,l=e.overlay;e.isOpen||(e.previousFocus=document.activeElement,r+=2,e.zIndex=r,n.style.zIndex=e.zIndex,l.style.zIndex=e.zIndex-1,n.setAttribute("aria-hidden","false"),n.classList.add("cc-active"),l.classList.add("cc-active"),t.animation&&(o.dataset.animation=t.animation),t.variant&&(o.dataset.variant=t.variant),document.body.style.overflow="hidden",d.push(a),e.isOpen=!0,i.set(o,e),setTimeout(()=>{const s=n.querySelector("[data-pb-modal-autofocus]")||e.focusableElements[0]||n;s&&s.focus()},50),o.dispatchEvent(new CustomEvent("modal:opened",{detail:{modalId:a,options:t}})),typeof t.onOpen=="function"&&t.onOpen(n,l,o))}function c(a,t={}){if(!a){console.error("Modal ID is required to close a modal");return}const o=document.querySelector(`pageblock-modal[data-modal-id="${a}"]`);if(!o){console.error(`Modal container not found for ID: ${a}`);return}const e=i.get(o);if(!e||!e.isOpen)return;const n=e.modal,l=e.overlay;n.setAttribute("aria-hidden","true"),n.classList.remove("cc-active"),l.classList.remove("cc-active");const s=d.indexOf(a);s>-1&&d.splice(s,1),d.length===0&&(document.body.style.overflow=""),e.isOpen=!1,i.set(o,e);const m=()=>{e.previousFocus&&e.previousFocus.focus&&e.previousFocus.focus(),o.dispatchEvent(new CustomEvent("modal:closed",{detail:{modalId:a,options:t}})),typeof t.onClose=="function"&&t.onClose(n,l,o),n.removeEventListener("transitionend",m)};n.addEventListener("transitionend",m)}function p(){[...d].forEach(t=>{c(t)})}function b(a){const t=["a[href]:not([disabled])","button:not([disabled])","textarea:not([disabled])","input:not([disabled])","select:not([disabled])",'[tabindex]:not([tabindex="-1"])'];return Array.from(a.querySelectorAll(t.join(",")))}function v(a,t){const o=t.closest("pageblock-modal"),e=i.get(o);if(!e)return;const n=e.focusableElements;if(n.length===0)return;const l=n[0],s=n[n.length-1];a.shiftKey?document.activeElement===l&&(s.focus(),a.preventDefault()):document.activeElement===s&&(l.focus(),a.preventDefault())}window.PBModal={init:u,open:function(a,t={}){const o=new CustomEvent("pb:modal:open",{detail:{modalId:a,options:t}});document.dispatchEvent(o)},close:function(a,t={}){const o=new CustomEvent("pb:modal:close",{detail:{modalId:a,options:t}});document.dispatchEvent(o)},closeAll:p},document.addEventListener("DOMContentLoaded",function(){u()})})();})();