UNPKG

@stormid/modal

Version:

Accessible modal dialog

3 lines (2 loc) 4.3 kB
function e(){return e=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var n in a)({}).hasOwnProperty.call(a,n)&&(e[n]=a[n])}return e},e.apply(null,arguments)}var t={onClassName:"is--active",toggleSelectorAttribute:"data-modal-toggle",callback:!1,startOpen:!1,delay:0};const a=["button","a"],n=["a[href]","area[href]","input:not([disabled]):not([type=hidden])","select:not([disabled])","textarea:not([disabled])","button:not([disabled])","iframe","object","embed","[contenteditable]",'[tabindex]:not([tabindex="-1"])'],o=(e,t)=>()=>{const a=new CustomEvent(e,{bubbles:!0,detail:{getState:t.getState}});window.document.dispatchEvent(a)},l=e=>e.querySelector("[role=dialog]")||e.querySelector("[role=alertdialog]")||console.warn("No dialog or alertdialog found in modal node"),i=(e,t)=>{const n=e.getAttribute(t.toggleSelectorAttribute),o=n&&[].slice.call(document.querySelectorAll((l=n,a.map(e=>`${e}.${l}`).join(", "))));var l;if(o)return o;console.warn(`Modal cannot be initialised, no modal toggle elements found. Does the modal have a ${t.toggleSelectorAttribute} attribute that identifies toggle buttons or links?`)},s=e=>[].slice.call(e.querySelectorAll(n.join(","))),r=t=>a=>{const n=t.getState(),{isOpen:o}=n;o&&27===a.keyCode&&(a.preventDefault(),t.update(e({},t.getState(),{isOpen:!o}),[u(t)])),o&&9===a.keyCode&&d(n)(a)},d=e=>t=>{const a=e.focusableChildren.indexOf(document.activeElement);t.shiftKey&&0===a?(t.preventDefault(),e.focusableChildren[e.focusableChildren.length-1].focus()):t.shiftKey||a!==e.focusableChildren.length-1||(t.preventDefault(),e.focusableChildren[0].focus())},c=e=>{e.node[e.isOpen?"removeAttribute":"setAttribute"]("hidden","hidden"),[].slice.call(document.querySelectorAll("body > *")).forEach(t=>t!==e.node&&t[e.isOpen?"setAttribute":"removeAttribute"]("aria-hidden","true")),e.node.classList.toggle(e.settings.onClassName),document.documentElement.classList.toggle("is--modal")},u=e=>t=>{t.isOpen?(e=>()=>{const t=e.getState();t.dialog.hasAttribute("aria-hidden")&&t.dialog.removeAttribute("aria-hidden");const a=document.body.firstElementChild||null;a!==t.node&&document.body.insertBefore(t.node,a),document.addEventListener("keydown",t.keyListener),c(t);const n=()=>t.focusableChildren.length>0&&t.focusableChildren[0].focus();t.settings.delay?window.setTimeout(n,t.settings.delay):n(),o("modal.open",e)()})(e)():(e=>()=>{const t=e.getState();document.removeEventListener("keydown",t.keyListener),c(t),t.lastFocused.focus(),o("modal.close",e)()})(e)(t),"function"==typeof t.settings.callback&&t.settings.callback.call(t)},b=e=>({node:t,dialog:a,toggles:n})=>{a&&n&&(t.setAttribute("hidden","hidden"),a.getAttribute("aria-label")||a.getAttribute("aria-labelledby")&&document.querySelector(`#${a.getAttribute("aria-labelledby")}`)||console.warn("The modal dialog should have an aria-labelledby attribute that matches the id of an element that contains text, or an aria-label attribute."),"alertdialog"!==a.getAttribute("role")||a.getAttribute("aria-describedby")&&document.querySelector(`#${a.getAttribute("aria-describedby")}`)||console.warn("The alertdialog should have an aria-describedby attribute that matches the id of an element that contains text"),n.forEach(t=>{t.addEventListener("click",t=>{t.preventDefault(),g(e)})}))},g=t=>t.update(e({},t.getState(),{isOpen:!t.getState().isOpen,lastFocused:t.getState().isOpen?t.getState().lastFocused:document.activeElement}),[u(t)]);var h=(a,n)=>{let o=(e=>"string"==typeof e?[].slice.call(document.querySelectorAll(e)):e instanceof Array?e:Object.prototype.isPrototypeOf.call(NodeList.prototype,e)?[].slice.call(e):e instanceof HTMLElement?[e]:[])(a);return 0===o.length?console.warn(`Modal not initialised, no elements found for selector '${a}'`):o.map(a=>Object.create((({node:e,settings:t})=>{const a=(()=>{let e={};return{update:(t,a)=>{e=null!=t?t:e,a&&a.forEach(t=>t(e))},getState:()=>e}})();return a.update({settings:t,node:e,dialog:l(e),toggles:i(e,t),focusableChildren:s(e),keyListener:r(a),lastFocused:!1,isOpen:!1},[b(a),()=>t.startOpen&&g(a)]),{getState:a.getState,open(){a.getState().isOpen||g(a)},close(){a.getState().isOpen&&g(a)}}})({settings:e({},t,a.dataset,n),node:a})))};export{h as default}; //# sourceMappingURL=index.modern.mjs.map