accessible-menu
Version:
A JavaScript library to help you generate WCAG accessible menus in the DOM.
4 lines (3 loc) • 32.7 kB
JavaScript
"use strict";function g(n,e){n===""||n.length===0||(typeof n=="string"?e.classList.add(n):e.classList.add(...n))}function _(n,e){n===""||n.length===0||(typeof n=="string"?e.classList.remove(n):e.classList.remove(...n))}function M(n,e){try{if(typeof e!="object"){const t=typeof e;throw new TypeError(`Elements given to isValidInstance() must be inside of an object. "${t}" given.`)}for(const t in e)if(!(e[t]instanceof n)){const s=typeof e[t];throw new TypeError(`${t} must be an instance of ${n.name}. "${s}" given.`)}return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function l(n,e){try{if(typeof e!="object"){const t=typeof e;throw new TypeError(`Values given to isValidType() must be inside of an object. "${t}" given.`)}for(const t in e){const s=typeof e[t];if(s!==n)throw new TypeError(`${t} must be a ${n}. "${s}" given.`)}return{status:!0,error:null}}catch(t){return{status:!1,error:t}}}function S(n){try{if(typeof n!="object"){const e=typeof n;throw new TypeError(`Values given to isQuerySelector() must be inside of an object. "${e}" given.`)}for(const e in n)try{if(n[e]===null)throw new Error;document.querySelector(n[e])}catch{throw new TypeError(`${e} must be a valid query selector. "${n[e]}" given.`)}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function y(n){try{if(typeof n!="object"||Array.isArray(n)){const e=typeof n;throw new TypeError(`Values given to isValidClassList() must be inside of an object. "${e}" given.`)}for(const e in n){const t=typeof n[e];if(t!=="string")if(Array.isArray(n[e]))n[e].forEach(s=>{if(typeof s!="string")throw new TypeError(`${e} must be a string or an array of strings. An array containing non-strings given.`)});else throw new TypeError(`${e} must be a string or an array of strings. "${t}" given.`);else{const s={};s[e]=n[e],S(s)}}return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function j(n){try{if(typeof n!="object"){const t=typeof n;throw new TypeError(`Values given to isValidState() must be inside of an object. "${t}" given.`)}const e=["none","self","child"];for(const t in n)if(!e.includes(n[t]))throw new TypeError(`${t} must be one of the following values: ${e.join(", ")}. "${n[t]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function q(n){try{if(typeof n!="object"){const t=typeof n;throw new TypeError(`Values given to isValidEvent() must be inside of an object. "${t}" given.`)}const e=["none","mouse","keyboard","character"];for(const t in n)if(!e.includes(n[t]))throw new TypeError(`${t} must be one of the following values: ${e.join(", ")}. "${n[t]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function O(n){try{if(typeof n!="object"){const t=typeof n;throw new TypeError(`Values given to isValidHoverType() must be inside of an object. "${t}" given.`)}const e=["off","on","dynamic"];for(const t in n)if(!e.includes(n[t]))throw new TypeError(`${t} must be one of the following values: ${e.join(", ")}. "${n[t]}" given.`);return{status:!0,error:null}}catch(e){return{status:!1,error:e}}}function V(n,e){if(l("string",{tagName:n}).status&&M(HTMLElement,e).status){const t=n.toLowerCase();let s=!0;for(const i in e)e[i].tagName.toLowerCase()!==t&&(s=!1);return s}else return!1}class ${_dom={toggle:null,parent:null};_elements={controlledMenu:null,parentMenu:null};_open=!1;_expandEvent=new CustomEvent("accessibleMenuExpand",{bubbles:!0,detail:{toggle:this}});_collapseEvent=new CustomEvent("accessibleMenuCollapse",{bubbles:!0,detail:{toggle:this}});constructor({menuToggleElement:e,parentElement:t,controlledMenu:s,parentMenu:i=null}){this._dom.toggle=e,this._dom.parent=t,this._elements.controlledMenu=s,this._elements.parentMenu=i}initialize(){this._setIds(),this._setAriaAttributes(),this._collapse(!1)}get dom(){return this._dom}get elements(){return this._elements}get isOpen(){return this._open}set isOpen(e){l("boolean",{isOpen:e}),this._open=e}_setIds(){if(this.dom.toggle.id===""||this.elements.controlledMenu.dom.menu.id===""){let e=this.dom.toggle.innerText?.replace(/[^a-zA-Z0-9\s]/g,"")||"",t=this.elements.controlledMenu.key;!e.replace(/\s/g,"").length&&this.dom.toggle.getAttribute("aria-label")&&(e=this.dom.toggle.getAttribute("aria-label").replace(/[^a-zA-Z0-9\s]/g,"")),e.replace(/\s/g,"").length>0&&(e=e.toLowerCase().replace(/\s+/g,"-"),e.startsWith("-")&&(e=e.substring(1)),e.endsWith("-")&&(e=e.slice(0,-1)),t=`${e}-${t}`),this.dom.toggle.id=this.dom.toggle.id||`menu-button-${t}`,this.elements.controlledMenu.dom.menu.id=this.elements.controlledMenu.dom.menu.id||`menu-${t}`}}_setAriaAttributes(){this.dom.toggle.setAttribute("aria-expanded","false"),this.elements.controlledMenu.dom.menu.setAttribute("aria-labelledby",this.dom.toggle.id)}_expand(e=!0){const{closeClass:t,openClass:s,transitionClass:i,openDuration:r}=this.elements.controlledMenu;this.dom.toggle.setAttribute("aria-expanded","true"),this.elements.controlledMenu.elements.rootMenu.hasOpened=!0,i!==""?(g(i,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{_(t,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{g(s,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{setTimeout(()=>{_(i,this.elements.controlledMenu.dom.menu)},r)})})})):(g(s,this.elements.controlledMenu.dom.menu),_(t,this.elements.controlledMenu.dom.menu)),e&&this.dom.toggle.dispatchEvent(this._expandEvent)}_collapse(e=!0){const{closeClass:t,openClass:s,transitionClass:i,closeDuration:r}=this.elements.controlledMenu;this.dom.toggle.setAttribute("aria-expanded","false"),i!==""?(g(i,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{_(s,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{g(t,this.elements.controlledMenu.dom.menu),requestAnimationFrame(()=>{setTimeout(()=>{_(i,this.elements.controlledMenu.dom.menu)},r)})})})):(g(t,this.elements.controlledMenu.dom.menu),_(s,this.elements.controlledMenu.dom.menu)),e&&this.dom.toggle.dispatchEvent(this._collapseEvent)}open(){this.elements.controlledMenu.focusState="self",this.isOpen||(this._expand(),this.isOpen=!0)}preview(){this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this.isOpen||(this._expand(),this.isOpen=!0)}close(){this.isOpen&&(this.elements.controlledMenu.blur(),this.elements.parentMenu&&(this.elements.parentMenu.focusState="self"),this._collapse(),this.isOpen=!1)}toggle(){this.isOpen?this.close():this.open()}closeSiblings(){this.elements.parentMenu&&this.elements.parentMenu.elements.submenuToggles.forEach(e=>{e!==this&&e.close()})}closeChildren(){this.elements.controlledMenu.elements.submenuToggles.forEach(e=>e.close())}}class x{_dom={item:null,link:null};_elements={parentMenu:null,childMenu:null,toggle:null};_submenu=!1;constructor({menuItemElement:e,menuLinkElement:t,parentMenu:s,isSubmenuItem:i=!1,childMenu:r=null,toggle:u=null}){this._dom.item=e,this._dom.link=t,this._elements.parentMenu=s,this._elements.childMenu=r,this._elements.toggle=u,this._submenu=i}initialize(){}get dom(){return this._dom}get elements(){return this._elements}get isSubmenuItem(){return this._submenu}focus(){this.elements.parentMenu.shouldFocus&&requestAnimationFrame(()=>{this.dom.link.focus()})}blur(){this.elements.parentMenu.shouldFocus&&requestAnimationFrame(()=>{this.dom.link.blur()})}}function C(n){try{const e=n.key||n.keyCode,t={Enter:e==="Enter"||e===13,Space:e===" "||e==="Spacebar"||e===32,Escape:e==="Escape"||e==="Esc"||e===27,ArrowUp:e==="ArrowUp"||e==="Up"||e===38,ArrowRight:e==="ArrowRight"||e==="Right"||e===39,ArrowDown:e==="ArrowDown"||e==="Down"||e===40,ArrowLeft:e==="ArrowLeft"||e==="Left"||e===37,Home:e==="Home"||e===36,End:e==="End"||e===35,Character:isNaN(e)&&!!e.match(/^[a-zA-Z]{1}$/),Tab:e==="Tab"||e===9,Asterisk:e==="*"||e===56};return Object.keys(t).find(s=>t[s]===!0)||""}catch{return""}}function o(n){n.preventDefault(),n.stopPropagation()}class E{_MenuType=E;_MenuItemType=x;_MenuToggleType=$;_dom={menu:null,menuItems:[],submenuItems:[],submenuToggles:[],submenus:[],controller:null,container:null};_selectors={menuItems:"",menuLinks:"",submenuItems:"",submenuToggles:"",submenus:""};_elements={menuItems:[],submenuToggles:[],controller:null,parentMenu:null,rootMenu:null};_openClass="show";_closeClass="hide";_transitionClass="transitioning";_transitionDuration=250;_openDuration=-1;_closeDuration=-1;_root=!0;_currentChild=0;_focusState="none";_currentEvent="none";_hoverType="off";_hoverDelay=250;_enterDelay=-1;_leaveDelay=-1;_prefix="am-";_hoverTimeout=null;_hasOpened=!1;_key="";_errors=[];constructor({menuElement:e,menuItemSelector:t="li",menuLinkSelector:s="a",submenuItemSelector:i="li:has(ul)",submenuToggleSelector:r="a",submenuSelector:u="ul",controllerElement:m=null,containerElement:a=null,openClass:c="show",closeClass:d="hide",transitionClass:f="transitioning",transitionDuration:p=250,openDuration:h=-1,closeDuration:T=-1,isTopLevel:b=!0,parentMenu:D=null,hoverType:w="off",hoverDelay:v=250,enterDelay:I=-1,leaveDelay:k=-1,prefix:A="am-",key:F=null}){this._dom.menu=e,this._dom.controller=m,this._dom.container=a,this._selectors.menuItems=t,this._selectors.menuLinks=s,this._selectors.submenuItems=i,this._selectors.submenuToggles=r,this._selectors.submenus=u,this._elements.menuItems=[],this._elements.submenuToggles=[],this._elements.controller=null,this._elements.parentMenu=D,this._elements.rootMenu=b?this:null,this._openClass=c||"",this._closeClass=d||"",this._transitionClass=f||"",this._transitionDuration=p,this._openDuration=h,this._closeDuration=T,this._prefix=A||"",this._key=F||"",this._root=b,this._hoverType=w,this._hoverDelay=v,this._enterDelay=I,this._leaveDelay=k}initialize(){if(!this._validate())throw new Error(`AccessibleMenu: cannot initialize menu. The following errors have been found:
- ${this.errors.join(`
- `)}`);if(this.elements.rootMenu===null&&this._findRootMenu(this),this._generateKey(),this._setDOMElements(),this.isTopLevel){if(this._setIds(),this.dom.controller&&this.dom.container){const e=new this._MenuToggleType({menuToggleElement:this.dom.controller,parentElement:this.dom.container,controlledMenu:this});V("button",{toggle:e.dom.toggle})||e.dom.toggle.setAttribute("role","button"),e.dom.toggle.setAttribute("aria-controls",this.dom.menu.id),this._elements.controller=e}window.AccessibleMenu=window.AccessibleMenu||{menus:{}},typeof window.AccessibleMenu.menus!="object"&&(window.AccessibleMenu.menus={}),window.AccessibleMenu.menus[this.dom.menu.id]=this}this._createChildElements(),this._setTransitionDurations()}get dom(){return this._dom}get selectors(){return this._selectors}get elements(){return this._elements}get isTopLevel(){return this._root}get key(){if(this.isTopLevel)return this._key;const e=this.elements.parentMenu.dom.submenus.indexOf(this.dom.menu)||0;return`${this.elements.parentMenu.key}-${e}`}get errors(){return this._errors}get openClass(){return this.isTopLevel?this._openClass:this.elements.rootMenu.openClass}set openClass(e){y({openClass:e}),this._openClass!==e&&(this._openClass=e)}get closeClass(){return this.isTopLevel?this._closeClass:this.elements.rootMenu.closeClass}set closeClass(e){y({closeClass:e}),this._closeClass!==e&&(this._closeClass=e)}get transitionClass(){return this.isTopLevel?this._transitionClass:this.elements.rootMenu.transitionClass}set transitionClass(e){y({transitionClass:e}),this._transitionClass!==e&&(this._transitionClass=e)}get transitionDuration(){return this.isTopLevel?this._transitionDuration:this.elements.rootMenu.transitionDuration}set transitionDuration(e){l("number",{transitionDuration:e}),this._transitionDuration!==e&&(this._transitionDuration=e,this._setTransitionDurations())}get openDuration(){return this._openDuration===-1?this.transitionDuration:this.isTopLevel?this._openDuration:this.elements.rootMenu.openDuration}set openDuration(e){l("number",{openDuration:e}),this._openDuration!==e&&(this._openDuration=e,this._setTransitionDurations())}get closeDuration(){return this._closeDuration===-1?this.transitionDuration:this.isTopLevel?this._closeDuration:this.elements.rootMenu.closeDuration}set closeDuration(e){l("number",{closeDuration:e}),this._closeDuration!==e&&(this._closeDuration=e,this._setTransitionDurations())}get currentChild(){return this._currentChild}set currentChild(e){l("number",{currentChild:e});function t(s){if(["mouse","character"].includes(s.currentEvent)&&s.elements.parentMenu){let r=0,u=!1;for(;!u&&r<s.elements.parentMenu.elements.menuItems.length;){const m=s.elements.parentMenu.elements.menuItems[r];m.isSubmenuItem&&m.elements.toggle.elements.controlledMenu===s&&(u=!0,s.elements.parentMenu.currentEvent=s.currentEvent,s.elements.parentMenu.currentChild=r),r++}}}e<-1?(this._currentChild=-1,t(this)):e>=this.elements.menuItems.length?(this._currentChild=this.elements.menuItems.length-1,t(this)):this.focusChild!==e&&(this._currentChild=e,t(this))}get focusState(){return this._focusState}set focusState(e){j({focusState:e}),this._focusState!==e&&(this._focusState=e),this.elements.submenuToggles.length>0&&(e==="self"||e==="none")&&this.elements.submenuToggles.forEach(t=>{t.elements.controlledMenu.focusState="none"}),this.elements.parentMenu&&(e==="self"||e==="child")&&(this.elements.parentMenu.focusState="child")}get currentEvent(){return this._currentEvent}set currentEvent(e){q({currentEvent:e}),this._currentEvent!==e&&(this._currentEvent=e,this.elements.submenuToggles.length>0&&this.elements.submenuToggles.forEach(t=>{t.elements.controlledMenu.currentEvent=e}))}get currentMenuItem(){return this.elements.menuItems[this.currentChild]}get hoverType(){return this._root?this._hoverType:this.elements.rootMenu.hoverType}set hoverType(e){O({hoverType:e}),this._hoverType!==e&&(this._hoverType=e)}get hoverDelay(){return this._root?this._hoverDelay:this.elements.rootMenu.hoverDelay}set hoverDelay(e){l("number",{hoverDelay:e}),this._hoverDelay!==e&&(this._hoverDelay=e)}get enterDelay(){return this._enterDelay===-1?this.hoverDelay:this._root?this._enterDelay:this.elements.rootMenu.enterDelay}set enterDelay(e){l("number",{enterDelay:e}),this._enterDelay!==e&&(this._enterDelay=e)}get leaveDelay(){return this._leaveDelay===-1?this.hoverDelay:this._root?this._leaveDelay:this.elements.rootMenu.leaveDelay}set leaveDelay(e){l("number",{leaveDelay:e}),this._leaveDelay!==e&&(this._leaveDelay=e)}get prefix(){return this._root?this._prefix:this.elements.rootMenu.prefix}set prefix(e){l("string",{prefix:e}),this._prefix!==e&&(this._prefix=e)}get shouldFocus(){let e=!1;return(this.currentEvent==="keyboard"||this.currentEvent==="character")&&(e=!0),this.currentEvent==="mouse"&&this.hoverType==="dynamic"&&(e=!0),e}get hasOpened(){return this._root?this._hasOpened:this.elements.rootMenu.hasOpened}set hasOpened(e){l("boolean",{hasOpened:e}),this._hasOpened!==e&&(this._hasOpened=e)}_validate(){let e=!0,t;this._dom.container!==null||this._dom.controller!==null?t=M(HTMLElement,{menuElement:this._dom.menu,controllerElement:this._dom.controller,containerElement:this._dom.container}):t=M(HTMLElement,{menuElement:this._dom.menu}),t.status||(this._errors.push(t.error.message),e=!1);let s;if(this._selectors.submenuItems!==""?s=S({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks,submenuItemSelector:this._selectors.submenuItems,submenuToggleSelector:this._selectors.submenuToggles,submenuSelector:this._selectors.submenus}):s=S({menuItemSelector:this._selectors.menuItems,menuLinkSelector:this._selectors.menuLinks}),s.status||(this._errors.push(s.error.message),e=!1),this._openClass!==""){const h=y({openClass:this._openClass});h.status||(this._errors.push(h.error.message),e=!1)}if(this._closeClass!==""){const h=y({closeClass:this._closeClass});h.status||(this._errors.push(h.error.message),e=!1)}if(this._transitionClass!==""){const h=y({transitionClass:this._transitionClass});h.status||(this._errors.push(h.error.message),e=!1)}const i=l("number",{transitionDuration:this._transitionDuration});i.status||(this._errors.push(i.error.message),e=!1);const r=l("number",{openDuration:this._openDuration});r.status||(this._errors.push(r.error.message),e=!1);const u=l("number",{closeDuration:this._closeDuration});u.status||(this._errors.push(u.error.message),e=!1);const m=l("boolean",{isTopLevel:this._root});if(m.status||(this._errors.push(m.error.message),e=!1),this._elements.parentMenu!==null){const h=M(E,{parentMenu:this._elements.parentMenu});h.status||(this._errors.push(h.error.message),e=!1)}const a=O({hoverType:this._hoverType});a.status||(this._errors.push(a.error.message),e=!1);const c=l("number",{hoverDelay:this._hoverDelay});c.status||(this._errors.push(c.error.message),e=!1);const d=l("number",{enterDelay:this._enterDelay});d.status||(this._errors.push(d.error.message),e=!1);const f=l("number",{leaveDelay:this._leaveDelay});if(f.status||(this._errors.push(f.error.message),e=!1),this._key!==""){const h=l("string",{key:this._key});h.status||(this._errors.push(h.error.message),e=!1)}const p=l("string",{prefix:this._prefix});return p.status||(this._errors.push(p.error.message),e=!1),e}_setDOMElementType(e,t=this.dom.menu,s=!0){if(typeof this.selectors[e]=="string"){if(!Array.isArray(this.dom[e]))throw new Error(`AccessibleMenu: The "${e}" element cannot be set through _setDOMElementType.`);t!==this.dom.menu&&M(HTMLElement,{base:t});const r=Array.from(t.querySelectorAll(this.selectors[e])).filter(u=>u.parentElement===t);s?this._dom[e]=r:this._dom[e]=[...this._dom[e],...r]}else throw new Error(`AccessibleMenu: "${e}" is not a valid element type within the menu.`)}_resetDOMElementType(e){if(typeof this.dom[e]<"u"){if(!Array.isArray(this.dom[e]))throw new Error(`AccessibleMenu: The "${e}" element cannot be reset through _resetDOMElementType.`);this._dom[e]=[]}else throw new Error(`AccessibleMenu: "${e}" is not a valid element type within the menu.`)}_setDOMElements(){this._setDOMElementType("menuItems"),this.selectors.submenuItems!==""&&(this._setDOMElementType("submenuItems"),this._resetDOMElementType("submenuToggles"),this._resetDOMElementType("submenus"),this.dom.submenuItems.forEach(e=>{this._setDOMElementType("submenuToggles",e,!1),this._setDOMElementType("submenus",e,!1)}))}_generateKey(e=!1){(this.key===""||e)&&(this._key=Math.random().toString(36).replace(/[^a-z]+/g,"").substring(0,10))}_setIds(){this.dom.menu.id=this.dom.menu.id||`menu-${this.key}`,this.dom.container&&(this.dom.container.id=this.dom.container.id||`menu-container-${this.key}`),this.dom.controller&&(this.dom.controller.id=this.dom.controller.id||`menu-controller-${this.key}`)}_findRootMenu(e){if(e.isTopLevel)this._elements.rootMenu=e;else if(e.elements.parentMenu!==null)this._findRootMenu(e.elements.parentMenu);else throw new Error("Cannot find root menu.")}_createChildElements(){this.dom.menuItems.forEach(e=>{let t;if(this.dom.submenuItems.includes(e)){const s=e.querySelector(this.selectors.submenuToggles),i=e.querySelector(this.selectors.submenus),r=new this._MenuType({menuElement:i,menuItemSelector:this.selectors.menuItems,menuLinkSelector:this.selectors.menuLinks,submenuItemSelector:this.selectors.submenuItems,submenuToggleSelector:this.selectors.submenuToggles,submenuSelector:this.selectors.submenus,openClass:this.openClass,closeClass:this.closeClass,transitionClass:this.transitionClass,transitionDuration:this.transitionDuration,openDuration:this.openDuration,closeDuration:this.closeDuration,isTopLevel:!1,parentMenu:this,hoverType:this.hoverType,hoverDelay:this.hoverDelay,enterDelay:this.enterDelay,leaveDelay:this.leaveDelay}),u=new this._MenuToggleType({menuToggleElement:s,parentElement:e,controlledMenu:r,parentMenu:this});this._elements.submenuToggles.push(u),t=new this._MenuItemType({menuItemElement:e,menuLinkElement:s,parentMenu:this,isSubmenuItem:!0,childMenu:r,toggle:u})}else{const s=e.querySelector(this.selectors.menuLinks);t=new this._MenuItemType({menuItemElement:e,menuLinkElement:s,parentMenu:this})}this._elements.menuItems.push(t)})}_clearTimeout(){clearTimeout(this._hoverTimeout)}_setTimeout(e,t){l("function",{callback:e}),l("number",{delay:t}),this._hoverTimeout=setTimeout(e,t)}_handleFocus(){this.elements.menuItems.forEach((e,t)=>{e.dom.link.addEventListener("focus",()=>{this.focusState="self",this.currentChild=t})}),this.dom.menu.addEventListener("focusout",e=>{this.currentEvent!=="keyboard"||e.relatedTarget===null||this.dom.menu.contains(e.relatedTarget)||(this.focusState="none",this.closeChildren())})}_handleClick(){function e(t,s,i){o(i),i.button===0&&(s.toggle(),s.isOpen&&(t.focusState="self",s.elements.controlledMenu.focusState="none"))}this.elements.menuItems.forEach((t,s)=>{t.dom.link.addEventListener("click",()=>{this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this._clearTimeout(),this.focusChild(s)},{passive:!0}),t.isSubmenuItem&&t.elements.toggle.dom.toggle.addEventListener("click",i=>{this.currentEvent="mouse",e(this,t.elements.toggle,i)})}),this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("click",t=>{this.currentEvent="mouse",e(this,this.elements.controller,t)}),document.addEventListener("click",t=>{this.focusState!=="none"&&(this.currentEvent="mouse",!this.dom.menu.contains(t.target)&&!this.dom.menu!==t.target&&(this.elements.rootMenu.hasOpened=this.elements.submenuToggles.some(s=>s.isOpen)))})}_handleHover(){this.elements.menuItems.forEach((e,t)=>{e.dom.link.addEventListener("pointerenter",s=>{s.pointerType==="pen"||s.pointerType==="touch"||(this.hoverType==="on"?(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusChild(t),e.isSubmenuItem&&(this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{e.elements.toggle.preview()},this.enterDelay)):e.elements.toggle.preview())):this.hoverType==="dynamic"&&(this.currentChild=t,(!this.isTopLevel||this.focusState!=="none")&&(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusCurrentChild()),(!this.isTopLevel||this.hasOpened)&&(this.currentEvent="mouse",this.elements.rootMenu.blurChildren(),this.focusCurrentChild(),e.isSubmenuItem?this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{e.elements.toggle.preview()},this.enterDelay)):e.elements.toggle.preview():this.enterDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.closeChildren()},this.enterDelay)):this.closeChildren())))}),e.isSubmenuItem&&(e.dom.item.addEventListener("pointerleave",s=>{s.pointerType==="pen"||s.pointerType==="touch"||(this.hoverType==="on"?this.leaveDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.currentEvent="mouse",e.elements.toggle.close()},this.leaveDelay)):(this.currentEvent="mouse",e.elements.toggle.close()):this.hoverType==="dynamic"&&(this.leaveDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.currentEvent="mouse"},this.leaveDelay)):this.currentEvent="mouse"))}),e.dom.item.addEventListener("pointerenter",s=>{s.pointerType==="pen"||s.pointerType==="touch"||e.isSubmenuItem&&(this.hoverType==="on"||this.hoverType==="dynamic")&&this.leaveDelay>0&&this._clearTimeout()}))})}_handleKeydown(){this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keydown",e=>{this.currentEvent="keyboard";const t=C(e);(t==="Space"||t==="Enter")&&o(e)})}_handleKeyup(){this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=C(e);(t==="Space"||t==="Enter")&&(o(e),this.elements.controller.toggle(),this.elements.controller.isOpen&&this.focusFirstChild())})}_setTransitionDurations(){this.dom.menu.style.setProperty(`--${this.prefix}transition-duration`,`${this.transitionDuration}ms`),this.dom.menu.style.setProperty(`--${this.prefix}open-transition-duration`,`${this.openDuration}ms`),this.dom.menu.style.setProperty(`--${this.prefix}close-transition-duration`,`${this.closeDuration}ms`)}focus(){this.focusState="self",this.shouldFocus&&this.dom.menu.focus()}blur(){this.focusState="none",this.shouldFocus&&this.dom.menu.blur()}focusCurrentChild(){this.focusState="self",this.currentChild!==-1&&this.currentMenuItem.focus()}focusChild(e){this.blurCurrentChild(),this.currentChild=e,this.focusCurrentChild()}focusFirstChild(){this.focusChild(0)}focusLastChild(){this.focusChild(this.elements.menuItems.length-1)}focusNextChild(){this.currentChild<this.elements.menuItems.length-1?this.focusChild(this.currentChild+1):this.focusCurrentChild()}focusPreviousChild(){this.currentChild>0?this.focusChild(this.currentChild-1):this.focusCurrentChild()}blurCurrentChild(){this.focusState="none",this.currentChild!==-1&&this.currentMenuItem.blur()}focusController(){this.dom.controller&&(this.shouldFocus&&this.dom.controller.focus(),this.focusState="none")}focusContainer(){this.dom.container&&(this.shouldFocus&&this.dom.container.focus(),this.focusState="none")}closeChildren(){this.elements.submenuToggles.forEach(e=>e.close())}blurChildren(){this.elements.menuItems.forEach(e=>{e.blur(),e.isSubmenuItem&&e.elements.childMenu.blurChildren()})}}class z extends x{constructor({menuItemElement:e,menuLinkElement:t,parentMenu:s,isSubmenuItem:i=!1,childMenu:r=null,toggle:u=null,initialize:m=!0}){super({menuItemElement:e,menuLinkElement:t,parentMenu:s,isSubmenuItem:i,childMenu:r,toggle:u}),m&&this.initialize()}initialize(){super.initialize(),this.dom.item.setAttribute("role","none"),this.dom.link.setAttribute("role","menuitem"),this.dom.link.tabIndex=-1}focus(){super.focus(),this.elements.parentMenu.isTopLevel&&(this.dom.link.tabIndex=0)}blur(){super.blur(),this.elements.parentMenu.isTopLevel&&(this.dom.link.tabIndex=-1)}}class K extends ${constructor({menuToggleElement:e,parentElement:t,controlledMenu:s,parentMenu:i=null,initialize:r=!0}){super({menuToggleElement:e,parentElement:t,controlledMenu:s,parentMenu:i}),r&&this.initialize()}_setAriaAttributes(){super._setAriaAttributes(),this.dom.toggle.setAttribute("aria-haspopup","true")}open(){this.closeSiblings(),super.open()}preview(){this.closeSiblings(),super.preview()}close(){this.isOpen&&(this.closeChildren(),this.elements.parentMenu&&this.elements.parentMenu.focusCurrentChild()),super.close()}}class L extends E{_MenuType=L;_MenuItemType=z;_MenuToggleType=K;constructor({menuElement:e,menuItemSelector:t="li",menuLinkSelector:s="a",submenuItemSelector:i="li:has(ul)",submenuToggleSelector:r="a",submenuSelector:u="ul",controllerElement:m=null,containerElement:a=null,openClass:c="show",closeClass:d="hide",transitionClass:f="transitioning",transitionDuration:p=250,isTopLevel:h=!0,parentMenu:T=null,hoverType:b="off",hoverDelay:D=250,enterDelay:w=-1,leaveDelay:v=-1,prefix:I="am-",key:k=null,initialize:A=!0}){super({menuElement:e,menuItemSelector:t,menuLinkSelector:s,submenuItemSelector:i,submenuToggleSelector:r,submenuSelector:u,controllerElement:m,containerElement:a,openClass:c,closeClass:d,transitionClass:f,transitionDuration:p,isTopLevel:h,parentMenu:T,hoverType:b,hoverDelay:D,enterDelay:w,leaveDelay:v,prefix:I,key:k}),A&&this.initialize()}initialize(){try{super.initialize(),this.isTopLevel?this.dom.menu.setAttribute("role","menubar"):this.dom.menu.setAttribute("role","menu"),this._handleFocus(),this._handleClick(),this._handleHover(),this._handleKeydown(),this._handleKeyup(),this.isTopLevel&&(this.elements.menuItems[0].dom.link.tabIndex=0,this.elements.controller&&this.elements.controller.dom.toggle.removeAttribute("aria-haspopup"))}catch(e){console.error(e)}}_handleClick(){super._handleClick(),document.addEventListener("click",e=>{this.focusState!=="none"&&(this.currentEvent="mouse",!this.dom.menu.contains(e.target)&&!this.dom.menu!==e.target&&(this.closeChildren(),this.blur(),this.elements.controller&&this.elements.controller.close(),this.elements.rootMenu.hasOpened=!1))})}_handleKeydown(){super._handleKeydown(),this.dom.menu.addEventListener("keydown",e=>{this.currentEvent="keyboard";const t=C(e);if(t==="Tab"&&(this.elements.rootMenu.focusState!=="none"?(this.elements.rootMenu.blur(),this.elements.rootMenu.closeChildren()):this.elements.rootMenu.focus()),t==="Character")o(e);else if(this.isTopLevel){if(this.focusState==="self"){const s=["Space","Enter","ArrowRight","ArrowLeft","Home","End"],i=["ArrowDown","ArrowUp"],r=["Escape"];(s.includes(t)||this.currentMenuItem.isSubmenuItem&&i.includes(t)||this.elements.controller&&r.includes(t))&&o(e)}}else["Space","Enter","Escape","ArrowRight","ArrowLeft","ArrowDown","ArrowUp","Home","End"].includes(t)&&o(e)})}_handleKeyup(){super._handleKeyup(),this.dom.menu.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=C(e),{altKey:s,crtlKey:i,metaKey:r}=e;if(t==="Character"&&!(s||i||r))o(e),this.elements.rootMenu.currentEvent="character",this.focusNextChildWithCharacter(e.key);else if(this.isTopLevel){if(this.focusState==="self")if(t==="Space"||t==="Enter")o(e),this.currentMenuItem.isSubmenuItem?(this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.open(),requestAnimationFrame(()=>{this.currentMenuItem.elements.childMenu.focusFirstChild()})):this.currentMenuItem.dom.link.click();else if(t==="ArrowRight"){o(e);const m=this.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.toggle.isOpen;this.focusNextChild(),m&&(this.currentMenuItem.isSubmenuItem?(this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.preview()):this.closeChildren())}else if(t==="ArrowLeft"){o(e);const m=this.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.toggle.isOpen;this.focusPreviousChild(),m&&(this.currentMenuItem.isSubmenuItem?(this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.preview()):this.closeChildren())}else t==="ArrowDown"?this.currentMenuItem.isSubmenuItem&&(o(e),this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.open(),requestAnimationFrame(()=>{this.currentMenuItem.elements.childMenu.focusFirstChild()})):t==="ArrowUp"?this.currentMenuItem.isSubmenuItem&&(o(e),this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.open(),requestAnimationFrame(()=>{this.currentMenuItem.elements.childMenu.focusLastChild()})):t==="Home"?(o(e),this.focusFirstChild()):t==="End"?(o(e),this.focusLastChild()):t==="Escape"&&(this.elements.submenuToggles.some(a=>a.isOpen)?(o(e),this.closeChildren()):this.isTopLevel&&this.elements.controller&&this.elements.controller.isOpen&&(o(e),this.elements.controller.close(),this.focusController()))}else t==="Space"||t==="Enter"?(o(e),this.currentMenuItem.isSubmenuItem?(this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.open(),requestAnimationFrame(()=>{this.currentMenuItem.elements.childMenu.focusFirstChild()})):this.currentMenuItem.dom.link.click()):t==="Escape"?(o(e),this.elements.rootMenu.closeChildren(),this.elements.rootMenu.focusCurrentChild()):t==="ArrowRight"?this.currentMenuItem.isSubmenuItem?(o(e),this.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.currentMenuItem.elements.toggle.open(),requestAnimationFrame(()=>{this.currentMenuItem.elements.childMenu.focusFirstChild()})):(o(e),this.elements.rootMenu.closeChildren(),this.elements.rootMenu.focusNextChild(),this.elements.rootMenu.currentMenuItem.isSubmenuItem&&this.elements.rootMenu.currentMenuItem.elements.toggle.preview()):t==="ArrowLeft"?this.elements.parentMenu.currentMenuItem.isSubmenuItem&&(o(e),this.elements.parentMenu.currentMenuItem.elements.toggle.close(),this.elements.parentMenu.focusCurrentChild(),this.elements.parentMenu===this.elements.rootMenu&&(this.elements.rootMenu.closeChildren(),this.elements.rootMenu.focusPreviousChild(),this.elements.rootMenu.currentMenuItem.isSubmenuItem&&(this.elements.rootMenu.currentMenuItem.elements.childMenu.currentEvent="keyboard",this.elements.rootMenu.currentMenuItem.elements.toggle.preview()))):t==="ArrowDown"?(o(e),this.focusNextChild()):t==="ArrowUp"?(o(e),this.focusPreviousChild()):t==="Home"?(o(e),this.focusFirstChild()):t==="End"&&(o(e),this.focusLastChild())})}focusNextChild(){this.currentChild===this.elements.menuItems.length-1?this.focusFirstChild():this.focusChild(this.currentChild+1)}focusPreviousChild(){this.currentChild===0?this.focusLastChild():this.focusChild(this.currentChild-1)}focusNextChildWithCharacter(e){const t=e.toLowerCase();let s=this.currentChild+1,i=!1;for(;!i&&s<this.elements.menuItems.length;){let r="";this.elements.menuItems[s].dom.item.innerText?r=this.elements.menuItems[s].dom.item.innerText:r=this.elements.menuItems[s].dom.item.textContent,r=r.replace(/[\s]/g,"").toLowerCase().charAt(0),r===t&&(i=!0,this.focusChild(s)),s++}}}module.exports=L;