basecoat-css
Version:
Tailwind CSS for Basecoat components
1 lines • 2.5 kB
JavaScript
(()=>{const e=e=>{const t=e.querySelector(":scope > button"),r=e.querySelector(":scope > [data-popover]"),a=r.querySelector('[role="menu"]');if(!t||!a||!r){const n=[];return t||n.push("trigger"),a||n.push("menu"),r||n.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${n.join(", ")}`,e)}let n=[],i=-1;const s=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),r.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},o=(i=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),r.setAttribute("aria-hidden","false"),n=Array.from(a.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),n.length>0&&i&&("first"===i?d(0):"last"===i&&d(n.length-1))},d=e=>{if(i>-1&&n[i]&&n[i].classList.remove("active"),i=e,i>-1&&n[i]){const e=n[i];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?s():o(!1)})),e.addEventListener("keydown",(e=>{const r="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(r&&s());if(!r)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),o(!1)):"ArrowDown"===e.key?(e.preventDefault(),o("first")):"ArrowUp"===e.key&&(e.preventDefault(),o("last")));if(0===n.length)return;let a=i;switch(e.key){case"ArrowDown":e.preventDefault(),a=-1===i?0:Math.min(i+1,n.length-1);break;case"ArrowUp":e.preventDefault(),a=-1===i?n.length-1:Math.max(i-1,0);break;case"Home":e.preventDefault(),a=0;break;case"End":e.preventDefault(),a=n.length-1;break;case"Enter":case" ":return e.preventDefault(),n[i]?.click(),void s()}a!==i&&d(a)})),a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&n.includes(t)){const e=n.indexOf(t);e!==i&&d(e)}})),a.addEventListener("mouseleave",(()=>{d(-1)})),a.addEventListener("click",(e=>{e.target.closest('[role^="menuitem"]')&&s()})),document.addEventListener("click",(t=>{e.contains(t.target)||s()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&s(!1)})),e.dataset.dropdownMenuInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("dropdown-menu",".dropdown-menu:not([data-dropdown-menu-initialized])",e)})();