UNPKG

accessible-menu

Version:

A JavaScript library to help you generate WCAG accessible menus in the DOM.

4 lines (3 loc) 34 kB
"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 b(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 u(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 V(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 z(n,e){if(u("string",{tagName:n}).status&&b(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 x{_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){u("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 ${_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:o=null}){this._dom.item=e,this._dom.link=t,this._elements.parentMenu=s,this._elements.childMenu=r,this._elements.toggle=o,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 M(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 m(n){n.preventDefault(),n.stopPropagation()}class T{_MenuType=T;_MenuItemType=$;_MenuToggleType=x;_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:o="ul",controllerElement:l=null,containerElement:f=null,openClass:a="show",closeClass:c="hide",transitionClass:d="transitioning",transitionDuration:p=250,openDuration:h=-1,closeDuration:E=-1,isTopLevel:C=!0,parentMenu:v=null,hoverType:D="off",hoverDelay:w=250,enterDelay:I=-1,leaveDelay:k=-1,prefix:L="am-",key:F=null}){this._dom.menu=e,this._dom.controller=l,this._dom.container=f,this._selectors.menuItems=t,this._selectors.menuLinks=s,this._selectors.submenuItems=i,this._selectors.submenuToggles=r,this._selectors.submenus=o,this._elements.menuItems=[],this._elements.submenuToggles=[],this._elements.controller=null,this._elements.parentMenu=v,this._elements.rootMenu=C?this:null,this._openClass=a||"",this._closeClass=c||"",this._transitionClass=d||"",this._transitionDuration=p,this._openDuration=h,this._closeDuration=E,this._prefix=L||"",this._key=F||"",this._root=C,this._hoverType=D,this._hoverDelay=w,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});z("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){u("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){u("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){u("number",{closeDuration:e}),this._closeDuration!==e&&(this._closeDuration=e,this._setTransitionDurations())}get currentChild(){return this._currentChild}set currentChild(e){u("number",{currentChild:e});function t(s){if(["mouse","character"].includes(s.currentEvent)&&s.elements.parentMenu){let r=0,o=!1;for(;!o&&r<s.elements.parentMenu.elements.menuItems.length;){const l=s.elements.parentMenu.elements.menuItems[r];l.isSubmenuItem&&l.elements.toggle.elements.controlledMenu===s&&(o=!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){V({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){u("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){u("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){u("number",{leaveDelay:e}),this._leaveDelay!==e&&(this._leaveDelay=e)}get prefix(){return this._root?this._prefix:this.elements.rootMenu.prefix}set prefix(e){u("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){u("boolean",{hasOpened:e}),this._hasOpened!==e&&(this._hasOpened=e)}_validate(){let e=!0,t;this._dom.container!==null||this._dom.controller!==null?t=b(HTMLElement,{menuElement:this._dom.menu,controllerElement:this._dom.controller,containerElement:this._dom.container}):t=b(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=u("number",{transitionDuration:this._transitionDuration});i.status||(this._errors.push(i.error.message),e=!1);const r=u("number",{openDuration:this._openDuration});r.status||(this._errors.push(r.error.message),e=!1);const o=u("number",{closeDuration:this._closeDuration});o.status||(this._errors.push(o.error.message),e=!1);const l=u("boolean",{isTopLevel:this._root});if(l.status||(this._errors.push(l.error.message),e=!1),this._elements.parentMenu!==null){const h=b(T,{parentMenu:this._elements.parentMenu});h.status||(this._errors.push(h.error.message),e=!1)}const f=O({hoverType:this._hoverType});f.status||(this._errors.push(f.error.message),e=!1);const a=u("number",{hoverDelay:this._hoverDelay});a.status||(this._errors.push(a.error.message),e=!1);const c=u("number",{enterDelay:this._enterDelay});c.status||(this._errors.push(c.error.message),e=!1);const d=u("number",{leaveDelay:this._leaveDelay});if(d.status||(this._errors.push(d.error.message),e=!1),this._key!==""){const h=u("string",{key:this._key});h.status||(this._errors.push(h.error.message),e=!1)}const p=u("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&&b(HTMLElement,{base:t});const r=Array.from(t.querySelectorAll(this.selectors[e])).filter(o=>o.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}),o=new this._MenuToggleType({menuToggleElement:s,parentElement:e,controlledMenu:r,parentMenu:this});this._elements.submenuToggles.push(o),t=new this._MenuItemType({menuItemElement:e,menuLinkElement:s,parentMenu:this,isSubmenuItem:!0,childMenu:r,toggle:o})}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){u("function",{callback:e}),u("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){m(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=M(e);(t==="Space"||t==="Enter")&&m(e)})}_handleKeyup(){this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=M(e);(t==="Space"||t==="Enter")&&(m(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 q extends ${constructor({menuItemElement:e,menuLinkElement:t,parentMenu:s,isSubmenuItem:i=!1,childMenu:r=null,toggle:o=null,initialize:l=!0}){super({menuItemElement:e,menuLinkElement:t,parentMenu:s,isSubmenuItem:i,childMenu:r,toggle:o}),l&&this.initialize()}initialize(){super.initialize(),this.dom.item.setAttribute("role","none"),this.dom.link.setAttribute("role","treeitem"),this.dom.link.tabIndex=-1}focus(){super.focus(),this.dom.link.tabIndex=0}blur(){super.blur(),this.dom.link.tabIndex=-1}}class K extends x{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()}initialize(){this._setIds(),this._setAriaAttributes(),this.dom.toggle.getAttribute("aria-expanded")==="true"?this.open():this._collapse(!1)}_setAriaAttributes(){this.dom.toggle.getAttribute("aria-expanded")!=="true"&&this.dom.toggle.setAttribute("aria-expanded","false"),this.elements.controlledMenu.dom.menu.setAttribute("aria-labelledby",this.dom.toggle.id),this.dom.toggle.setAttribute("aria-owns",this.elements.controlledMenu.dom.menu.id)}}class A extends T{_MenuType=A;_MenuItemType=q;_MenuToggleType=K;constructor({menuElement:e,menuItemSelector:t="li",menuLinkSelector:s="a",submenuItemSelector:i="li:has(ul)",submenuToggleSelector:r="a",submenuSelector:o="ul",controllerElement:l=null,containerElement:f=null,openClass:a="show",closeClass:c="hide",transitionClass:d="transitioning",transitionDuration:p=250,isTopLevel:h=!0,parentMenu:E=null,hoverType:C="off",hoverDelay:v=250,enterDelay:D=-1,leaveDelay:w=-1,prefix:I="am-",key:k=null,initialize:L=!0}){super({menuElement:e,menuItemSelector:t,menuLinkSelector:s,submenuItemSelector:i,submenuToggleSelector:r,submenuSelector:o,controllerElement:l,containerElement:f,openClass:a,closeClass:c,transitionClass:d,transitionDuration:p,isTopLevel:h,parentMenu:E,hoverType:C,hoverDelay:v,enterDelay:D,leaveDelay:w,prefix:I,key:k}),L&&this.initialize()}initialize(){try{super.initialize(),this.isTopLevel?(this.dom.menu.setAttribute("role","tree"),this.elements.menuItems[0].dom.link.tabIndex=0):this.dom.menu.setAttribute("role","group"),this._handleFocus(),this._handleClick(),this._handleHover(),this._handleKeydown(),this._handleKeyup(),this.isTopLevel&&this.elements.controller&&this.elements.controller.dom.toggle.removeAttribute("aria-owns")}catch(e){console.error(e)}}_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())))}),e.isSubmenuItem&&(e.dom.item.addEventListener("pointerleave",s=>{s.pointerType==="pen"||s.pointerType==="touch"||(this.hoverType==="on"?this.leaveDelay>0&&this._clearTimeout():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()})),this.isTopLevel&&this.dom.menu.addEventListener("pointerleave",s=>{s.pointerType==="pen"||s.pointerType==="touch"||this.hoverType==="on"&&(this.leaveDelay>0?(this._clearTimeout(),this._setTimeout(()=>{this.closeChildren(),this.blur()},this.leaveDelay)):(this.closeChildren(),this.blur()))})})}_handleKeydown(){super._handleKeydown(),this.dom.menu.addEventListener("keydown",e=>{this.currentEvent="keyboard";const t=M(e);if(t==="Tab"&&(this.elements.rootMenu.focusState!=="none"?this.elements.rootMenu.blur():this.elements.rootMenu.focus()),this.focusState==="self"){const s=["Space","Enter","ArrowUp","ArrowDown","ArrowLeft","Asterisk","Home","End"],i=["ArrowRight"],r=["Escape"];(s.includes(t)||this.currentMenuItem.isSubmenuItem&&i.includes(t)||this.elements.controller&&r.includes(t))&&m(e)}})}_handleKeyup(){super._handleKeyup(),this.dom.menu.addEventListener("keyup",e=>{this.currentEvent="keyboard";const t=M(e),{altKey:s,crtlKey:i,metaKey:r}=e;if(t==="Character"&&!(s||i||r))m(e),this.elements.rootMenu.currentEvent="character",this.focusNextNodeWithCharacter(e.key);else if(this.focusState==="self")if(t==="Enter"||t==="Space")m(e),this.currentMenuItem.isSubmenuItem?this.currentMenuItem.elements.toggle.isOpen?this.currentMenuItem.elements.toggle.close():this.currentMenuItem.elements.toggle.preview():this.currentMenuItem.dom.link.click();else if(t==="Escape")this.isTopLevel&&this.elements.controller&&this.elements.controller.isOpen&&(this.elements.controller.close(),this.focusController());else if(t==="ArrowDown")m(e),this.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.toggle.isOpen?(this.blurCurrentChild(),this.currentMenuItem.elements.childMenu.currentEvent=this.currentEvent,this.currentMenuItem.elements.childMenu.focusFirstChild()):!this.isTopLevel&&this.currentChild===this.elements.menuItems.length-1?this.focusParentsNextChild():this.focusNextChild();else if(t==="ArrowUp"){m(e);const l=this.elements.menuItems[this.currentChild-1];l&&l.isSubmenuItem&&l.elements.toggle.isOpen?(this.blurCurrentChild(),this.currentChild=this.currentChild-1,this.currentMenuItem.elements.childMenu.currentEvent=this.currentEvent,this.focusChildsLastNode()):!this.isTopLevel&&this.currentChild===0?(this.blurCurrentChild(),this.elements.parentMenu.currentEvent=this.currentEvent,this.elements.parentMenu.focusCurrentChild()):this.focusPreviousChild()}else t==="ArrowRight"?this.currentMenuItem.isSubmenuItem&&(m(e),this.currentMenuItem.elements.toggle.isOpen?(this.blurCurrentChild(),this.currentMenuItem.elements.childMenu.currentEvent=this.currentEvent,this.currentMenuItem.elements.childMenu.focusFirstChild()):this.currentMenuItem.elements.toggle.preview()):t==="ArrowLeft"?(m(e),this.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.toggle.isOpen?(this.currentMenuItem.elements.childMenu.blurCurrentChild(),this.currentMenuItem.elements.toggle.close()):this.isTopLevel||(this.blurCurrentChild(),this.elements.parentMenu.currentEvent=this.currentEvent,this.elements.parentMenu.focusCurrentChild())):t==="Home"?(m(e),this.blurCurrentChild(),this.elements.rootMenu.focusFirstChild()):t==="End"?(m(e),this.blurCurrentChild(),this.elements.rootMenu.focusLastNode()):t==="Asterisk"&&(m(e),this.openChildren())})}focusLastNode(){const e=this.elements.menuItems.length-1,t=this.elements.menuItems[e];t.isSubmenuItem&&t.elements.toggle.isOpen?(this.currentChild=e,t.elements.childMenu.currentEvent=this.currentEvent,t.elements.childMenu.focusLastNode()):this.focusLastChild()}openChildren(){this.elements.submenuToggles.forEach(e=>e.preview())}focusNextNodeWithCharacter(e){function t(a){let c=[];return a.elements.menuItems.forEach(d=>{c.push(d),d.isSubmenuItem&&d.elements.toggle.isOpen&&(c=[...c,...t(d.elements.toggle.elements.controlledMenu)])}),c}const s=e.toLowerCase(),i=t(this.elements.rootMenu),r=i.indexOf(this.currentMenuItem)+1,o=[...i.slice(r),...i.slice(0,r)];let l=0,f=!1;for(;!f&&l<o.length;){let a="";if(o[l].dom.item.innerText?a=o[l].dom.item.innerText:a=o[l].dom.item.textContent,a=a.replace(/[\s]/g,"").toLowerCase().charAt(0),a===s){f=!0;const c=o[l].elements.parentMenu,d=c.elements.menuItems.indexOf(o[l]);this.elements.rootMenu.blurChildren(),c.focusChild(d)}l++}}focusParentsNextChild(){this.elements.parentMenu&&(this.elements.parentMenu.currentEvent=this.currentEvent,this.elements.parentMenu.currentChild===this.elements.parentMenu.elements.menuItems.length-1?(this.elements.parentMenu.blurCurrentChild(),this.elements.parentMenu.focusParentsNextChild()):(this.blurChildren(),this.elements.parentMenu.focusNextChild()))}focusChildsLastNode(){this.currentMenuItem.elements.childMenu.currentEvent=this.currentEvent,this.currentMenuItem.elements.childMenu.focusLastChild(),this.currentMenuItem.elements.childMenu.currentMenuItem.isSubmenuItem&&this.currentMenuItem.elements.childMenu.currentMenuItem.elements.toggle.isOpen&&(this.currentMenuItem.elements.childMenu.blurCurrentChild(),this.currentMenuItem.elements.childMenu.focusChildsLastNode())}}module.exports=A;