@evermade/menu-toolkit
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -54,2 +54,3 @@ function animate(options) { | ||
hoverTimeout: 750, | ||
hoverOpenDelay: 0, | ||
buttonIcon: '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>', | ||
@@ -417,3 +418,15 @@ shouldWrapAnchorToButton: null, | ||
if (ul) { | ||
openSubMenu(ul, event); | ||
// Delay opening if there is a delay set. | ||
if (settings.hoverOpenDelay === 0) { | ||
openSubMenu(ul, event); | ||
} | ||
else { | ||
setTimeout(() => { | ||
const hoveredEls = document.querySelectorAll(':hover'); | ||
const isHovered = Array.from(hoveredEls).some((el) => el === currentTarget || currentTarget.contains(el)); | ||
if (isHovered) { | ||
openSubMenu(ul, event); | ||
} | ||
}, settings.hoverOpenDelay); | ||
} | ||
} | ||
@@ -420,0 +433,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
/*! @evermade/menu-toolkit 1.0.2 */ | ||
function e(e){const{element:t,animationClass:n,onReady:o,maxExecutionTime:a}=e;t.classList.add(n);let s=!1;function u(){t.removeEventListener("animationend",u,!1),"function"==typeof o&&(s=!0,o(t,n))}t.addEventListener("animationend",u,!1),"function"==typeof o&&a&&setTimeout((()=>{s||(s=!0,o(t,n),t.removeEventListener("animationend",u,!1))}),a)}function t(t,n){const o=t;let a=[];if(!(t instanceof HTMLElement))throw new Error("Menu element must be an valid HTMLElement");const s=Object.assign(Object.assign({},{action:"click",subMenuAnchorSelector:".menu-item-has-children > a",subMenuListItemSelector:".menu-item-has-children",openSubMenuClass:"is-open",buttonClass:"",visuallyHiddenClass:"screen-reader-text",expandChildMenuText:"Sub menu",hoverTimeout:750,buttonIcon:'<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>',shouldWrapAnchorToButton:null,activeListItemSelector:".current-menu-item",openActiveSubMenuOnCreate:!1,closeSubMenuOnOutsideClick:!0,animateOpen:!1,animateClose:!1,animateOpenClass:"animate-open",animateCloseClass:"animate-close",animateOpenMaxExecutionTime:250,animateCloseMaxExecutionTime:250,onBeforeCreate:null,onAfterCreate:null,onBeforeOpenSubMenu:null,onAfterOpenSubMenu:null,onBeforeCloseSubMenu:null,onAfterCloseSubMenu:null}),n),u=Array.from(o.querySelectorAll(s.subMenuAnchorSelector)),l=Array.from(o.querySelectorAll(s.subMenuListItemSelector)),r=e=>{const t=e.target.closest('[data-menu="sub-toggle"]');if(!t)return;const n=o.querySelector(`#${t.getAttribute("aria-controls")}`);if(n)if(p(n))d(n,e);else{const t=h().filter((e=>e!==n&&!e.contains(n)));t.length&&t.forEach((e=>{d(e)})),m(n,e)}},i=e=>{e.target.closest('[data-menu="root"]')||g()},c=e=>{var t,n,o;const a=e.target,s=null===(n=null===(t=a.closest('[data-menu="sub-menu"]'))||void 0===t?void 0:t.parentElement)||void 0===n?void 0:n.querySelector('[data-menu="sub-toggle"]'),u=a.closest('[data-menu="sub-toggle"]');let l;l="sub-toggle"===a.getAttribute("data-menu")?a:s||u;const r=l?l.closest("li"):a.closest("li");if(!r)return;const i=C(r),c=i[i.length-1];if("Tab"===e.key&&!e.shiftKey&&e.target===c){const t=h().filter((t=>{const n=C(t);return!(n[n.length-1]!==e.target)||!t.contains(r)}));t.length&&t.forEach((e=>{d(e)}))}if(l&&"Tab"===e.key&&e.shiftKey&&e.target===l){const e=h().filter((e=>!e.contains(r)));e.length&&e.forEach((e=>{d(e)}))}if("Escape"===e.key){const e=null===(o=a.closest('[data-menu="sub-menu"]'))||void 0===o?void 0:o.closest("li");if(e){const t=C(e);t.length&&t[0].focus();const n=e.querySelector('[data-menu="sub-menu"]');n&&p(n)&&d(n)}}},m=(t,n)=>{if(p(t))return;"function"==typeof s.onBeforeOpenSubMenu&&s.onBeforeOpenSubMenu(t,n);const a=o.querySelector(`[aria-controls="${t.id}"]`);a&&a.setAttribute("aria-expanded","true"),s.animateCloseClass&&t.classList.remove(s.animateCloseClass),t.classList.add(s.openSubMenuClass);const u=()=>{s.animateOpenClass&&t.classList.remove(s.animateOpenClass),"function"==typeof s.onAfterOpenSubMenu&&s.onAfterOpenSubMenu(t,n)};s.animateOpen?e({element:t,animationClass:s.animateOpenClass,onReady:()=>{u()},maxExecutionTime:s.animateOpenMaxExecutionTime}):u()},d=(t,n)=>{if(!p(t))return;const a=o.querySelector(`[aria-controls="${t.id}"]`);a&&a.setAttribute("aria-expanded","false");const u=()=>{t.classList.remove(s.openSubMenuClass),s.animateCloseClass&&t.classList.remove(s.animateCloseClass),"function"==typeof s.onAfterCloseSubMenu&&s.onAfterCloseSubMenu(t,n)};s.animateClose?e({element:t,animationClass:s.animateCloseClass,onReady:()=>{u()},maxExecutionTime:s.animateCloseMaxExecutionTime}):u()},f=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');a=a.filter((e=>e.ul!==t&&!e.ul.contains(t)||(clearTimeout(e.id),!1)));h().filter((e=>e!==t&&!e.contains(t)&&!t.contains(e))).forEach((t=>{d(t,e)})),t&&m(t,e)},b=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');t&&(a=a.filter((e=>e.ul!==t||(clearTimeout(e.id),!1))),a.push({id:setTimeout((e=>{d(e)}),s.hoverTimeout,t),ul:t}))},p=e=>e.classList.contains(s.openSubMenuClass),h=()=>Array.from(o.querySelectorAll(`.${s.openSubMenuClass}[data-menu="sub-menu"]`)),C=e=>Array.from(e.querySelectorAll("\na[href]:not([hidden]),\narea[href],\ninput:not([disabled]),\nselect:not([disabled]),\ntextarea:not([disabled]),\nbutton:not([disabled])\n")).filter((e=>{const t=e.closest('[data-menu="sub-menu"]');return!t||p(t)})),g=()=>{const e=h();e.length&&e.forEach((e=>{d(e)}))},y=()=>{const e=o.querySelector(s.activeListItemSelector);if(e){let t=e.closest('[data-menu="sub-menu"]');if(t||(t=e.querySelector('[data-menu="sub-menu"]')),t){const e=[];let n=t.parentElement;for(;n&&n!==o;)"UL"===n.tagName&&e.push(n),n=n.parentElement;[...e,t].forEach((e=>{m(e)}))}}},S=(e,t)=>{const n=e.getAttribute("href");let o=!0;return n&&"#"!==n&&(o=!1),"boolean"==typeof s.shouldWrapAnchorToButton?o=s.shouldWrapAnchorToButton:"function"==typeof s.shouldWrapAnchorToButton&&(o=s.shouldWrapAnchorToButton(o,e,t)),o},A=(e,t)=>"function"==typeof s.buttonClass?s.buttonClass(o,e,t):s.buttonClass,v=(e,t)=>"function"==typeof s.buttonIcon?s.buttonIcon(o,e,t):s.buttonIcon;return(()=>{if("root"===o.getAttribute("data-menu"))return void console.log("menuFromHTML: Menu already initialized.",o);"function"==typeof s.onBeforeCreate&&s.onBeforeCreate(),o.setAttribute("data-menu","root");let e=1;u.forEach(((t,n)=>{var a;const u=document.createElement("button");u.setAttribute("data-menu","sub-toggle"),u.setAttribute("aria-expanded","false");let l=1,r=t.parentElement;for(;r&&r!==o;)"UL"===r.tagName&&l++,r=r.parentElement;for(u.setAttribute("data-menu-level",`${l}`);document.getElementById(`sub-menu-${e}-${n}`);)e++;u.setAttribute("aria-controls",`sub-menu-${e}-${n}`);const i=null===(a=t.closest("li"))||void 0===a?void 0:a.querySelector("ul");i&&(i.id=`sub-menu-${e}-${n}`,i.setAttribute("data-menu","sub-menu")),u.className=A(i,l),u.type="button";const c=v(i,l);if(S(t,l)){const e=document.createElement("span");for(;t.childNodes.length>0;)e.appendChild(t.childNodes[0]);u.appendChild(e),u.insertAdjacentHTML("beforeend",c),u.setAttribute("data-toggle-type","cover"),t.after(u),t.setAttribute("hidden","")}else u.innerHTML=`<span class="${s.visuallyHiddenClass}">${s.expandChildMenuText}</span>${c}`,u.setAttribute("data-toggle-type","icon"),t.after(u)})),s.openActiveSubMenuOnCreate&&y(),o.addEventListener("click",r,!1),o.addEventListener("keydown",c,!1),s.closeSubMenuOnOutsideClick&&document.addEventListener("click",i,!1),"hover"===s.action&&l.forEach((e=>{e.addEventListener("mouseenter",f,!1),e.addEventListener("mouseleave",b,!1)})),"function"==typeof s.onAfterCreate&&s.onAfterCreate(),o.classList.add("is-ready")})(),{openSubMenu:m,closeSubMenu:d,closeAllSubMenus:g,openActiveSubMenu:y,getOpenSubMenus:h,getButtonClass:A,getButtonIcon:v}}export{t as menuFromHTML}; | ||
/*! @evermade/menu-toolkit 1.0.3 */ | ||
function e(e){const{element:t,animationClass:n,onReady:o,maxExecutionTime:a}=e;t.classList.add(n);let s=!1;function u(){t.removeEventListener("animationend",u,!1),"function"==typeof o&&(s=!0,o(t,n))}t.addEventListener("animationend",u,!1),"function"==typeof o&&a&&setTimeout((()=>{s||(s=!0,o(t,n),t.removeEventListener("animationend",u,!1))}),a)}function t(t,n){const o=t;let a=[];if(!(t instanceof HTMLElement))throw new Error("Menu element must be an valid HTMLElement");const s=Object.assign(Object.assign({},{action:"click",subMenuAnchorSelector:".menu-item-has-children > a",subMenuListItemSelector:".menu-item-has-children",openSubMenuClass:"is-open",buttonClass:"",visuallyHiddenClass:"screen-reader-text",expandChildMenuText:"Sub menu",hoverTimeout:750,hoverOpenDelay:0,buttonIcon:'<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>',shouldWrapAnchorToButton:null,activeListItemSelector:".current-menu-item",openActiveSubMenuOnCreate:!1,closeSubMenuOnOutsideClick:!0,animateOpen:!1,animateClose:!1,animateOpenClass:"animate-open",animateCloseClass:"animate-close",animateOpenMaxExecutionTime:250,animateCloseMaxExecutionTime:250,onBeforeCreate:null,onAfterCreate:null,onBeforeOpenSubMenu:null,onAfterOpenSubMenu:null,onBeforeCloseSubMenu:null,onAfterCloseSubMenu:null}),n),u=Array.from(o.querySelectorAll(s.subMenuAnchorSelector)),r=Array.from(o.querySelectorAll(s.subMenuListItemSelector)),l=e=>{const t=e.target.closest('[data-menu="sub-toggle"]');if(!t)return;const n=o.querySelector(`#${t.getAttribute("aria-controls")}`);if(n)if(p(n))d(n,e);else{const t=h().filter((e=>e!==n&&!e.contains(n)));t.length&&t.forEach((e=>{d(e)})),m(n,e)}},i=e=>{e.target.closest('[data-menu="root"]')||y()},c=e=>{var t,n,o;const a=e.target,s=null===(n=null===(t=a.closest('[data-menu="sub-menu"]'))||void 0===t?void 0:t.parentElement)||void 0===n?void 0:n.querySelector('[data-menu="sub-toggle"]'),u=a.closest('[data-menu="sub-toggle"]');let r;r="sub-toggle"===a.getAttribute("data-menu")?a:s||u;const l=r?r.closest("li"):a.closest("li");if(!l)return;const i=C(l),c=i[i.length-1];if("Tab"===e.key&&!e.shiftKey&&e.target===c){const t=h().filter((t=>{const n=C(t);return!(n[n.length-1]!==e.target)||!t.contains(l)}));t.length&&t.forEach((e=>{d(e)}))}if(r&&"Tab"===e.key&&e.shiftKey&&e.target===r){const e=h().filter((e=>!e.contains(l)));e.length&&e.forEach((e=>{d(e)}))}if("Escape"===e.key){const e=null===(o=a.closest('[data-menu="sub-menu"]'))||void 0===o?void 0:o.closest("li");if(e){const t=C(e);t.length&&t[0].focus();const n=e.querySelector('[data-menu="sub-menu"]');n&&p(n)&&d(n)}}},m=(t,n)=>{if(p(t))return;"function"==typeof s.onBeforeOpenSubMenu&&s.onBeforeOpenSubMenu(t,n);const a=o.querySelector(`[aria-controls="${t.id}"]`);a&&a.setAttribute("aria-expanded","true"),s.animateCloseClass&&t.classList.remove(s.animateCloseClass),t.classList.add(s.openSubMenuClass);const u=()=>{s.animateOpenClass&&t.classList.remove(s.animateOpenClass),"function"==typeof s.onAfterOpenSubMenu&&s.onAfterOpenSubMenu(t,n)};s.animateOpen?e({element:t,animationClass:s.animateOpenClass,onReady:()=>{u()},maxExecutionTime:s.animateOpenMaxExecutionTime}):u()},d=(t,n)=>{if(!p(t))return;const a=o.querySelector(`[aria-controls="${t.id}"]`);a&&a.setAttribute("aria-expanded","false");const u=()=>{t.classList.remove(s.openSubMenuClass),s.animateCloseClass&&t.classList.remove(s.animateCloseClass),"function"==typeof s.onAfterCloseSubMenu&&s.onAfterCloseSubMenu(t,n)};s.animateClose?e({element:t,animationClass:s.animateCloseClass,onReady:()=>{u()},maxExecutionTime:s.animateCloseMaxExecutionTime}):u()},f=e=>{const t=e.currentTarget,n=t.querySelector('[data-menu="sub-menu"]');a=a.filter((e=>e.ul!==n&&!e.ul.contains(n)||(clearTimeout(e.id),!1)));h().filter((e=>e!==n&&!e.contains(n)&&!n.contains(e))).forEach((t=>{d(t,e)})),n&&(0===s.hoverOpenDelay?m(n,e):setTimeout((()=>{const o=document.querySelectorAll(":hover");Array.from(o).some((e=>e===t||t.contains(e)))&&m(n,e)}),s.hoverOpenDelay))},b=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');t&&(a=a.filter((e=>e.ul!==t||(clearTimeout(e.id),!1))),a.push({id:setTimeout((e=>{d(e)}),s.hoverTimeout,t),ul:t}))},p=e=>e.classList.contains(s.openSubMenuClass),h=()=>Array.from(o.querySelectorAll(`.${s.openSubMenuClass}[data-menu="sub-menu"]`)),C=e=>Array.from(e.querySelectorAll("\na[href]:not([hidden]),\narea[href],\ninput:not([disabled]),\nselect:not([disabled]),\ntextarea:not([disabled]),\nbutton:not([disabled])\n")).filter((e=>{const t=e.closest('[data-menu="sub-menu"]');return!t||p(t)})),y=()=>{const e=h();e.length&&e.forEach((e=>{d(e)}))},g=()=>{const e=o.querySelector(s.activeListItemSelector);if(e){let t=e.closest('[data-menu="sub-menu"]');if(t||(t=e.querySelector('[data-menu="sub-menu"]')),t){const e=[];let n=t.parentElement;for(;n&&n!==o;)"UL"===n.tagName&&e.push(n),n=n.parentElement;[...e,t].forEach((e=>{m(e)}))}}},v=(e,t)=>{const n=e.getAttribute("href");let o=!0;return n&&"#"!==n&&(o=!1),"boolean"==typeof s.shouldWrapAnchorToButton?o=s.shouldWrapAnchorToButton:"function"==typeof s.shouldWrapAnchorToButton&&(o=s.shouldWrapAnchorToButton(o,e,t)),o},A=(e,t)=>"function"==typeof s.buttonClass?s.buttonClass(o,e,t):s.buttonClass,S=(e,t)=>"function"==typeof s.buttonIcon?s.buttonIcon(o,e,t):s.buttonIcon;return(()=>{if("root"===o.getAttribute("data-menu"))return void console.log("menuFromHTML: Menu already initialized.",o);"function"==typeof s.onBeforeCreate&&s.onBeforeCreate(),o.setAttribute("data-menu","root");let e=1;u.forEach(((t,n)=>{var a;const u=document.createElement("button");u.setAttribute("data-menu","sub-toggle"),u.setAttribute("aria-expanded","false");let r=1,l=t.parentElement;for(;l&&l!==o;)"UL"===l.tagName&&r++,l=l.parentElement;for(u.setAttribute("data-menu-level",`${r}`);document.getElementById(`sub-menu-${e}-${n}`);)e++;u.setAttribute("aria-controls",`sub-menu-${e}-${n}`);const i=null===(a=t.closest("li"))||void 0===a?void 0:a.querySelector("ul");i&&(i.id=`sub-menu-${e}-${n}`,i.setAttribute("data-menu","sub-menu")),u.className=A(i,r),u.type="button";const c=S(i,r);if(v(t,r)){const e=document.createElement("span");for(;t.childNodes.length>0;)e.appendChild(t.childNodes[0]);u.appendChild(e),u.insertAdjacentHTML("beforeend",c),u.setAttribute("data-toggle-type","cover"),t.after(u),t.setAttribute("hidden","")}else u.innerHTML=`<span class="${s.visuallyHiddenClass}">${s.expandChildMenuText}</span>${c}`,u.setAttribute("data-toggle-type","icon"),t.after(u)})),s.openActiveSubMenuOnCreate&&g(),o.addEventListener("click",l,!1),o.addEventListener("keydown",c,!1),s.closeSubMenuOnOutsideClick&&document.addEventListener("click",i,!1),"hover"===s.action&&r.forEach((e=>{e.addEventListener("mouseenter",f,!1),e.addEventListener("mouseleave",b,!1)})),"function"==typeof s.onAfterCreate&&s.onAfterCreate(),o.classList.add("is-ready")})(),{openSubMenu:m,closeSubMenu:d,closeAllSubMenus:y,openActiveSubMenu:g,getOpenSubMenus:h,getButtonClass:A,getButtonIcon:S}}export{t as menuFromHTML}; |
@@ -60,2 +60,3 @@ (function (global, factory) { | ||
hoverTimeout: 750, | ||
hoverOpenDelay: 0, | ||
buttonIcon: '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>', | ||
@@ -423,3 +424,15 @@ shouldWrapAnchorToButton: null, | ||
if (ul) { | ||
openSubMenu(ul, event); | ||
// Delay opening if there is a delay set. | ||
if (settings.hoverOpenDelay === 0) { | ||
openSubMenu(ul, event); | ||
} | ||
else { | ||
setTimeout(() => { | ||
const hoveredEls = document.querySelectorAll(':hover'); | ||
const isHovered = Array.from(hoveredEls).some((el) => el === currentTarget || currentTarget.contains(el)); | ||
if (isHovered) { | ||
openSubMenu(ul, event); | ||
} | ||
}, settings.hoverOpenDelay); | ||
} | ||
} | ||
@@ -426,0 +439,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
/*! @evermade/menu-toolkit 1.0.2 */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Menu={})}(this,(function(e){"use strict";function t(e){const{element:t,animationClass:n,onReady:o,maxExecutionTime:a}=e;t.classList.add(n);let s=!1;function u(){t.removeEventListener("animationend",u,!1),"function"==typeof o&&(s=!0,o(t,n))}t.addEventListener("animationend",u,!1),"function"==typeof o&&a&&setTimeout((()=>{s||(s=!0,o(t,n),t.removeEventListener("animationend",u,!1))}),a)}e.menuFromHTML=function(e,n){const o=e;let a=[];if(!(e instanceof HTMLElement))throw new Error("Menu element must be an valid HTMLElement");const s=Object.assign(Object.assign({},{action:"click",subMenuAnchorSelector:".menu-item-has-children > a",subMenuListItemSelector:".menu-item-has-children",openSubMenuClass:"is-open",buttonClass:"",visuallyHiddenClass:"screen-reader-text",expandChildMenuText:"Sub menu",hoverTimeout:750,buttonIcon:'<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>',shouldWrapAnchorToButton:null,activeListItemSelector:".current-menu-item",openActiveSubMenuOnCreate:!1,closeSubMenuOnOutsideClick:!0,animateOpen:!1,animateClose:!1,animateOpenClass:"animate-open",animateCloseClass:"animate-close",animateOpenMaxExecutionTime:250,animateCloseMaxExecutionTime:250,onBeforeCreate:null,onAfterCreate:null,onBeforeOpenSubMenu:null,onAfterOpenSubMenu:null,onBeforeCloseSubMenu:null,onAfterCloseSubMenu:null}),n),u=Array.from(o.querySelectorAll(s.subMenuAnchorSelector)),l=Array.from(o.querySelectorAll(s.subMenuListItemSelector)),r=e=>{const t=e.target.closest('[data-menu="sub-toggle"]');if(!t)return;const n=o.querySelector(`#${t.getAttribute("aria-controls")}`);if(n)if(p(n))m(n,e);else{const t=h().filter((e=>e!==n&&!e.contains(n)));t.length&&t.forEach((e=>{m(e)})),d(n,e)}},i=e=>{e.target.closest('[data-menu="root"]')||y()},c=e=>{var t,n,o;const a=e.target,s=null===(n=null===(t=a.closest('[data-menu="sub-menu"]'))||void 0===t?void 0:t.parentElement)||void 0===n?void 0:n.querySelector('[data-menu="sub-toggle"]'),u=a.closest('[data-menu="sub-toggle"]');let l;l="sub-toggle"===a.getAttribute("data-menu")?a:s||u;const r=l?l.closest("li"):a.closest("li");if(!r)return;const i=C(r),c=i[i.length-1];if("Tab"===e.key&&!e.shiftKey&&e.target===c){const t=h().filter((t=>{const n=C(t);return!(n[n.length-1]!==e.target)||!t.contains(r)}));t.length&&t.forEach((e=>{m(e)}))}if(l&&"Tab"===e.key&&e.shiftKey&&e.target===l){const e=h().filter((e=>!e.contains(r)));e.length&&e.forEach((e=>{m(e)}))}if("Escape"===e.key){const e=null===(o=a.closest('[data-menu="sub-menu"]'))||void 0===o?void 0:o.closest("li");if(e){const t=C(e);t.length&&t[0].focus();const n=e.querySelector('[data-menu="sub-menu"]');n&&p(n)&&m(n)}}},d=(e,n)=>{if(p(e))return;"function"==typeof s.onBeforeOpenSubMenu&&s.onBeforeOpenSubMenu(e,n);const a=o.querySelector(`[aria-controls="${e.id}"]`);a&&a.setAttribute("aria-expanded","true"),s.animateCloseClass&&e.classList.remove(s.animateCloseClass),e.classList.add(s.openSubMenuClass);const u=()=>{s.animateOpenClass&&e.classList.remove(s.animateOpenClass),"function"==typeof s.onAfterOpenSubMenu&&s.onAfterOpenSubMenu(e,n)};s.animateOpen?t({element:e,animationClass:s.animateOpenClass,onReady:()=>{u()},maxExecutionTime:s.animateOpenMaxExecutionTime}):u()},m=(e,n)=>{if(!p(e))return;const a=o.querySelector(`[aria-controls="${e.id}"]`);a&&a.setAttribute("aria-expanded","false");const u=()=>{e.classList.remove(s.openSubMenuClass),s.animateCloseClass&&e.classList.remove(s.animateCloseClass),"function"==typeof s.onAfterCloseSubMenu&&s.onAfterCloseSubMenu(e,n)};s.animateClose?t({element:e,animationClass:s.animateCloseClass,onReady:()=>{u()},maxExecutionTime:s.animateCloseMaxExecutionTime}):u()},f=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');a=a.filter((e=>e.ul!==t&&!e.ul.contains(t)||(clearTimeout(e.id),!1)));h().filter((e=>e!==t&&!e.contains(t)&&!t.contains(e))).forEach((t=>{m(t,e)})),t&&d(t,e)},b=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');t&&(a=a.filter((e=>e.ul!==t||(clearTimeout(e.id),!1))),a.push({id:setTimeout((e=>{m(e)}),s.hoverTimeout,t),ul:t}))},p=e=>e.classList.contains(s.openSubMenuClass),h=()=>Array.from(o.querySelectorAll(`.${s.openSubMenuClass}[data-menu="sub-menu"]`)),C=e=>Array.from(e.querySelectorAll("\na[href]:not([hidden]),\narea[href],\ninput:not([disabled]),\nselect:not([disabled]),\ntextarea:not([disabled]),\nbutton:not([disabled])\n")).filter((e=>{const t=e.closest('[data-menu="sub-menu"]');return!t||p(t)})),y=()=>{const e=h();e.length&&e.forEach((e=>{m(e)}))},g=()=>{const e=o.querySelector(s.activeListItemSelector);if(e){let t=e.closest('[data-menu="sub-menu"]');if(t||(t=e.querySelector('[data-menu="sub-menu"]')),t){const e=[];let n=t.parentElement;for(;n&&n!==o;)"UL"===n.tagName&&e.push(n),n=n.parentElement;[...e,t].forEach((e=>{d(e)}))}}},M=(e,t)=>{const n=e.getAttribute("href");let o=!0;return n&&"#"!==n&&(o=!1),"boolean"==typeof s.shouldWrapAnchorToButton?o=s.shouldWrapAnchorToButton:"function"==typeof s.shouldWrapAnchorToButton&&(o=s.shouldWrapAnchorToButton(o,e,t)),o},S=(e,t)=>"function"==typeof s.buttonClass?s.buttonClass(o,e,t):s.buttonClass,v=(e,t)=>"function"==typeof s.buttonIcon?s.buttonIcon(o,e,t):s.buttonIcon;return(()=>{if("root"===o.getAttribute("data-menu"))return void console.log("menuFromHTML: Menu already initialized.",o);"function"==typeof s.onBeforeCreate&&s.onBeforeCreate(),o.setAttribute("data-menu","root");let e=1;u.forEach(((t,n)=>{var a;const u=document.createElement("button");u.setAttribute("data-menu","sub-toggle"),u.setAttribute("aria-expanded","false");let l=1,r=t.parentElement;for(;r&&r!==o;)"UL"===r.tagName&&l++,r=r.parentElement;for(u.setAttribute("data-menu-level",`${l}`);document.getElementById(`sub-menu-${e}-${n}`);)e++;u.setAttribute("aria-controls",`sub-menu-${e}-${n}`);const i=null===(a=t.closest("li"))||void 0===a?void 0:a.querySelector("ul");i&&(i.id=`sub-menu-${e}-${n}`,i.setAttribute("data-menu","sub-menu")),u.className=S(i,l),u.type="button";const c=v(i,l);if(M(t,l)){const e=document.createElement("span");for(;t.childNodes.length>0;)e.appendChild(t.childNodes[0]);u.appendChild(e),u.insertAdjacentHTML("beforeend",c),u.setAttribute("data-toggle-type","cover"),t.after(u),t.setAttribute("hidden","")}else u.innerHTML=`<span class="${s.visuallyHiddenClass}">${s.expandChildMenuText}</span>${c}`,u.setAttribute("data-toggle-type","icon"),t.after(u)})),s.openActiveSubMenuOnCreate&&g(),o.addEventListener("click",r,!1),o.addEventListener("keydown",c,!1),s.closeSubMenuOnOutsideClick&&document.addEventListener("click",i,!1),"hover"===s.action&&l.forEach((e=>{e.addEventListener("mouseenter",f,!1),e.addEventListener("mouseleave",b,!1)})),"function"==typeof s.onAfterCreate&&s.onAfterCreate(),o.classList.add("is-ready")})(),{openSubMenu:d,closeSubMenu:m,closeAllSubMenus:y,openActiveSubMenu:g,getOpenSubMenus:h,getButtonClass:S,getButtonIcon:v}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
/*! @evermade/menu-toolkit 1.0.3 */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Menu={})}(this,(function(e){"use strict";function t(e){const{element:t,animationClass:n,onReady:o,maxExecutionTime:a}=e;t.classList.add(n);let s=!1;function u(){t.removeEventListener("animationend",u,!1),"function"==typeof o&&(s=!0,o(t,n))}t.addEventListener("animationend",u,!1),"function"==typeof o&&a&&setTimeout((()=>{s||(s=!0,o(t,n),t.removeEventListener("animationend",u,!1))}),a)}e.menuFromHTML=function(e,n){const o=e;let a=[];if(!(e instanceof HTMLElement))throw new Error("Menu element must be an valid HTMLElement");const s=Object.assign(Object.assign({},{action:"click",subMenuAnchorSelector:".menu-item-has-children > a",subMenuListItemSelector:".menu-item-has-children",openSubMenuClass:"is-open",buttonClass:"",visuallyHiddenClass:"screen-reader-text",expandChildMenuText:"Sub menu",hoverTimeout:750,hoverOpenDelay:0,buttonIcon:'<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>',shouldWrapAnchorToButton:null,activeListItemSelector:".current-menu-item",openActiveSubMenuOnCreate:!1,closeSubMenuOnOutsideClick:!0,animateOpen:!1,animateClose:!1,animateOpenClass:"animate-open",animateCloseClass:"animate-close",animateOpenMaxExecutionTime:250,animateCloseMaxExecutionTime:250,onBeforeCreate:null,onAfterCreate:null,onBeforeOpenSubMenu:null,onAfterOpenSubMenu:null,onBeforeCloseSubMenu:null,onAfterCloseSubMenu:null}),n),u=Array.from(o.querySelectorAll(s.subMenuAnchorSelector)),l=Array.from(o.querySelectorAll(s.subMenuListItemSelector)),r=e=>{const t=e.target.closest('[data-menu="sub-toggle"]');if(!t)return;const n=o.querySelector(`#${t.getAttribute("aria-controls")}`);if(n)if(p(n))m(n,e);else{const t=h().filter((e=>e!==n&&!e.contains(n)));t.length&&t.forEach((e=>{m(e)})),d(n,e)}},i=e=>{e.target.closest('[data-menu="root"]')||C()},c=e=>{var t,n,o;const a=e.target,s=null===(n=null===(t=a.closest('[data-menu="sub-menu"]'))||void 0===t?void 0:t.parentElement)||void 0===n?void 0:n.querySelector('[data-menu="sub-toggle"]'),u=a.closest('[data-menu="sub-toggle"]');let l;l="sub-toggle"===a.getAttribute("data-menu")?a:s||u;const r=l?l.closest("li"):a.closest("li");if(!r)return;const i=y(r),c=i[i.length-1];if("Tab"===e.key&&!e.shiftKey&&e.target===c){const t=h().filter((t=>{const n=y(t);return!(n[n.length-1]!==e.target)||!t.contains(r)}));t.length&&t.forEach((e=>{m(e)}))}if(l&&"Tab"===e.key&&e.shiftKey&&e.target===l){const e=h().filter((e=>!e.contains(r)));e.length&&e.forEach((e=>{m(e)}))}if("Escape"===e.key){const e=null===(o=a.closest('[data-menu="sub-menu"]'))||void 0===o?void 0:o.closest("li");if(e){const t=y(e);t.length&&t[0].focus();const n=e.querySelector('[data-menu="sub-menu"]');n&&p(n)&&m(n)}}},d=(e,n)=>{if(p(e))return;"function"==typeof s.onBeforeOpenSubMenu&&s.onBeforeOpenSubMenu(e,n);const a=o.querySelector(`[aria-controls="${e.id}"]`);a&&a.setAttribute("aria-expanded","true"),s.animateCloseClass&&e.classList.remove(s.animateCloseClass),e.classList.add(s.openSubMenuClass);const u=()=>{s.animateOpenClass&&e.classList.remove(s.animateOpenClass),"function"==typeof s.onAfterOpenSubMenu&&s.onAfterOpenSubMenu(e,n)};s.animateOpen?t({element:e,animationClass:s.animateOpenClass,onReady:()=>{u()},maxExecutionTime:s.animateOpenMaxExecutionTime}):u()},m=(e,n)=>{if(!p(e))return;const a=o.querySelector(`[aria-controls="${e.id}"]`);a&&a.setAttribute("aria-expanded","false");const u=()=>{e.classList.remove(s.openSubMenuClass),s.animateCloseClass&&e.classList.remove(s.animateCloseClass),"function"==typeof s.onAfterCloseSubMenu&&s.onAfterCloseSubMenu(e,n)};s.animateClose?t({element:e,animationClass:s.animateCloseClass,onReady:()=>{u()},maxExecutionTime:s.animateCloseMaxExecutionTime}):u()},f=e=>{const t=e.currentTarget,n=t.querySelector('[data-menu="sub-menu"]');a=a.filter((e=>e.ul!==n&&!e.ul.contains(n)||(clearTimeout(e.id),!1)));h().filter((e=>e!==n&&!e.contains(n)&&!n.contains(e))).forEach((t=>{m(t,e)})),n&&(0===s.hoverOpenDelay?d(n,e):setTimeout((()=>{const o=document.querySelectorAll(":hover");Array.from(o).some((e=>e===t||t.contains(e)))&&d(n,e)}),s.hoverOpenDelay))},b=e=>{const t=e.currentTarget.querySelector('[data-menu="sub-menu"]');t&&(a=a.filter((e=>e.ul!==t||(clearTimeout(e.id),!1))),a.push({id:setTimeout((e=>{m(e)}),s.hoverTimeout,t),ul:t}))},p=e=>e.classList.contains(s.openSubMenuClass),h=()=>Array.from(o.querySelectorAll(`.${s.openSubMenuClass}[data-menu="sub-menu"]`)),y=e=>Array.from(e.querySelectorAll("\na[href]:not([hidden]),\narea[href],\ninput:not([disabled]),\nselect:not([disabled]),\ntextarea:not([disabled]),\nbutton:not([disabled])\n")).filter((e=>{const t=e.closest('[data-menu="sub-menu"]');return!t||p(t)})),C=()=>{const e=h();e.length&&e.forEach((e=>{m(e)}))},g=()=>{const e=o.querySelector(s.activeListItemSelector);if(e){let t=e.closest('[data-menu="sub-menu"]');if(t||(t=e.querySelector('[data-menu="sub-menu"]')),t){const e=[];let n=t.parentElement;for(;n&&n!==o;)"UL"===n.tagName&&e.push(n),n=n.parentElement;[...e,t].forEach((e=>{d(e)}))}}},v=(e,t)=>{const n=e.getAttribute("href");let o=!0;return n&&"#"!==n&&(o=!1),"boolean"==typeof s.shouldWrapAnchorToButton?o=s.shouldWrapAnchorToButton:"function"==typeof s.shouldWrapAnchorToButton&&(o=s.shouldWrapAnchorToButton(o,e,t)),o},A=(e,t)=>"function"==typeof s.buttonClass?s.buttonClass(o,e,t):s.buttonClass,S=(e,t)=>"function"==typeof s.buttonIcon?s.buttonIcon(o,e,t):s.buttonIcon;return(()=>{if("root"===o.getAttribute("data-menu"))return void console.log("menuFromHTML: Menu already initialized.",o);"function"==typeof s.onBeforeCreate&&s.onBeforeCreate(),o.setAttribute("data-menu","root");let e=1;u.forEach(((t,n)=>{var a;const u=document.createElement("button");u.setAttribute("data-menu","sub-toggle"),u.setAttribute("aria-expanded","false");let l=1,r=t.parentElement;for(;r&&r!==o;)"UL"===r.tagName&&l++,r=r.parentElement;for(u.setAttribute("data-menu-level",`${l}`);document.getElementById(`sub-menu-${e}-${n}`);)e++;u.setAttribute("aria-controls",`sub-menu-${e}-${n}`);const i=null===(a=t.closest("li"))||void 0===a?void 0:a.querySelector("ul");i&&(i.id=`sub-menu-${e}-${n}`,i.setAttribute("data-menu","sub-menu")),u.className=A(i,l),u.type="button";const c=S(i,l);if(v(t,l)){const e=document.createElement("span");for(;t.childNodes.length>0;)e.appendChild(t.childNodes[0]);u.appendChild(e),u.insertAdjacentHTML("beforeend",c),u.setAttribute("data-toggle-type","cover"),t.after(u),t.setAttribute("hidden","")}else u.innerHTML=`<span class="${s.visuallyHiddenClass}">${s.expandChildMenuText}</span>${c}`,u.setAttribute("data-toggle-type","icon"),t.after(u)})),s.openActiveSubMenuOnCreate&&g(),o.addEventListener("click",r,!1),o.addEventListener("keydown",c,!1),s.closeSubMenuOnOutsideClick&&document.addEventListener("click",i,!1),"hover"===s.action&&l.forEach((e=>{e.addEventListener("mouseenter",f,!1),e.addEventListener("mouseleave",b,!1)})),"function"==typeof s.onAfterCreate&&s.onAfterCreate(),o.classList.add("is-ready")})(),{openSubMenu:d,closeSubMenu:m,closeAllSubMenus:C,openActiveSubMenu:g,getOpenSubMenus:h,getButtonClass:A,getButtonIcon:S}},Object.defineProperty(e,"__esModule",{value:!0})})); |
@@ -54,2 +54,3 @@ function animate(options) { | ||
hoverTimeout: 750, | ||
hoverOpenDelay: 0, | ||
buttonIcon: '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>', | ||
@@ -417,3 +418,15 @@ shouldWrapAnchorToButton: null, | ||
if (ul) { | ||
openSubMenu(ul, event); | ||
// Delay opening if there is a delay set. | ||
if (settings.hoverOpenDelay === 0) { | ||
openSubMenu(ul, event); | ||
} | ||
else { | ||
setTimeout(() => { | ||
const hoveredEls = document.querySelectorAll(':hover'); | ||
const isHovered = Array.from(hoveredEls).some((el) => el === currentTarget || currentTarget.contains(el)); | ||
if (isHovered) { | ||
openSubMenu(ul, event); | ||
} | ||
}, settings.hoverOpenDelay); | ||
} | ||
} | ||
@@ -420,0 +433,0 @@ }; |
{ | ||
"name": "@evermade/menu-toolkit", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "Toolkit for developing accessible menus.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -162,2 +162,3 @@ # Menu Toolkit | ||
hoverTimeout: 750, | ||
hoverOpenDelay: 0, | ||
buttonIcon: | ||
@@ -192,2 +193,4 @@ '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>', | ||
If you are working with mega menu where only 1st level opens anything you can set this for example: `:scope > .menu-item-has-children > a`. | ||
Defaults to `.menu-item-has-children > a`. | ||
@@ -199,2 +202,4 @@ | ||
If you are working with mega menu where only 1st level opens anything you can set this for example: `:scope > .menu-item-has-children`. | ||
Defaults to `.menu-item-has-children`. | ||
@@ -232,2 +237,8 @@ | ||
#### hoverOpenDelay (number) | ||
Time in milliseconds to wait before opening sub menu after hover. This is used to prevent accidental opening of sub menus and let cursor quickly move over the menu without opening it. | ||
Defaults to `0`. | ||
#### buttonIcon (string) | ||
@@ -407,2 +418,6 @@ | ||
### 1.0.3 | ||
Add support for hover open delay. This allows cursors to quickly move over the menu without opening it. This is good for huge mega menus. | ||
### 1.0.2 | ||
@@ -409,0 +424,0 @@ |
@@ -16,2 +16,3 @@ import animate from './utils/animate'; | ||
hoverTimeout: number; | ||
hoverOpenDelay: number; | ||
buttonIcon: ((el: El, subMenu: El, level: number) => string) | string; | ||
@@ -76,2 +77,3 @@ shouldWrapAnchorToButton: | ||
hoverTimeout: 750, | ||
hoverOpenDelay: 0, | ||
buttonIcon: | ||
@@ -511,3 +513,15 @@ '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>', | ||
if (ul) { | ||
openSubMenu(ul, event); | ||
// Delay opening if there is a delay set. | ||
if (settings.hoverOpenDelay === 0) { | ||
openSubMenu(ul, event); | ||
} else { | ||
setTimeout(() => { | ||
const hoveredEls = document.querySelectorAll(':hover'); | ||
const isHovered = Array.from(hoveredEls).some((el) => el === currentTarget || currentTarget.contains(el)); | ||
if (isHovered) { | ||
openSubMenu(ul, event); | ||
} | ||
}, settings.hoverOpenDelay); | ||
} | ||
} | ||
@@ -514,0 +528,0 @@ }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
159067
3480
437