Files
op-packages/luci-theme-aurora/htdocs/luci-static/resources/menu-aurora.js
T

1 line
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";"require baseclass";"require ui";return baseclass.extend({__init__(){ui.menu.load().then(e=>this.render(e)),this.initNavigationControls(),this.initUciIndicator()},initUciIndicator(){const e=ui.changes?.setIndicator;e&&(ui.changes.setIndicator=function(t){e.call(this,t),document.querySelector('[data-indicator="uci-changes"]')?.setAttribute("data-count",t||0)})},initNavigationControls(){const e=document.querySelector("#mobile-menu-overlay"),t=document.querySelector("#navigation-toggle");if(!t||!e)return;const a=e.querySelector("#mobile-nav-list"),i=window.matchMedia("(min-width: 768px)"),n="aurora.sidebarCollapsed";let s;const o=()=>i.matches&&"sidebar"===document.body.dataset.navType,l=e=>{const a=o();t.classList.toggle("is-expanded",e&&!i.matches),t.setAttribute("aria-expanded",e?"true":"false"),t.setAttribute("aria-controls",a?"sidebar-panel":"mobile-menu-overlay");const n=e&&!a?_("Close"):_("Navigation");t.setAttribute("title",n),t.setAttribute("aria-label",n)},r=()=>{e.classList.remove("mobile-menu-open"),document.body.classList.remove("mobile-navigation-open"),document.body.style.overflow="",this.resetNavigationGroups(a)},c=t=>{if(o()){r();const e=!t,a=document.body;return a.classList.remove("sidebar-anim-open","sidebar-anim-close"),a.classList.add(e?"sidebar-anim-close":"sidebar-anim-open"),clearTimeout(s),s=setTimeout(()=>{a.classList.remove("sidebar-anim-open","sidebar-anim-close")},300),a.classList.toggle("sidebar-collapsed",e),localStorage.setItem(n,e),void l(t)}if(i.matches)return r(),void l(!1);e.classList.toggle("mobile-menu-open",t),document.body.classList.toggle("mobile-navigation-open",t),document.body.style.overflow=t?"hidden":"",t?this.expandActiveNavigationGroup(a):this.resetNavigationGroups(a),l(t)},d=()=>{if(r(),o()){const e="true"===localStorage.getItem(n);return document.body.classList.toggle("sidebar-collapsed",e),void l(!e)}l(!1)};t.addEventListener("click",t=>{t.stopPropagation(),c(!(o()?!document.body.classList.contains("sidebar-collapsed"):!i.matches&&e.classList.contains("mobile-menu-open")))}),e.addEventListener("click",t=>{t.target===e&&c(!1)}),document.addEventListener("keydown",t=>{"Escape"===t.key&&e.classList.contains("mobile-menu-open")&&c(!1)}),i.addEventListener("change",d),d(),document.addEventListener("click",t=>{const a=t.target?.closest?.(".navigation-direct, .navigation-sublink, .mobile-nav-logout");a&&e.contains(a)&&c(!1)})},renderMobileMenu(e){const t=document.querySelector("#mobile-nav-list"),a=document.querySelector("#mobile-nav-footer-action");t&&(t.innerHTML=""),a&&(a.innerHTML=""),t&&(e.forEach(e=>{e.isLogout?a&&a.appendChild(E("a",{class:"mobile-nav-logout",href:e.href},[e.title])):t.appendChild(this.renderNavigationItem(e,"mobile"))}),this.bindNavigationAccordion(t))},render(e){if(this.renderModeMenu(e),L.env.dispatchpath.length>=3){let t=e,a="";for(let e=0;e<3&&t;e++){const i=L.env.dispatchpath[e];t=t.children?.[i],a+=(a?"/":"")+i}t&&this.renderTabMenu(t,a)}},renderTabMenu(e,t,a=0){const i=document.querySelector("#tabmenu"),n=E("ul",{class:"tabs"}),s=ui.menu.getChildren(e);let o=null;return s.forEach(e=>{const i=L.env.dispatchpath[3+a]===e.name;n.appendChild(E("li",{class:`tabmenu-item-${e.name}${i?" active":""}`},[E("a",{href:L.url(t,e.name)},[_(e.title)])])),i&&(o=e)}),n.children.length?(i.appendChild(n),i.style.display="",o&&this.renderTabMenu(o,`${t}/${o.name}`,a+1),n):E([])},renderMainMenu(e,t,a=0,i=null){const n=a?E("ul",{class:"desktop-nav-list"}):document.querySelector("#topmenu"),s=ui.menu.getChildren(e);if(a>1)return E([]);if(0===a){const e=document.body?.dataset?.navType||"mega-menu";if("sidebar"===e)return this.renderSidebar(i||[]),n||E([]);if(!n||!s.length)return E([]);"mega-menu"===e?this.initMegaMenu(s,t,n):this.initDropdown(s,t,n)}else{if(!s.length)return E([]);s.forEach(a=>{const i=this.isActivePath(e.name,a.name),s={class:i?"is-active-page":"",href:L.url(t,a.name)};i&&(s["aria-current"]="page"),n.appendChild(E("li",{},[E("a",s,[_(a.title)])]))})}return n.style.display="",n},isActivePath:(e,t)=>L.env.dispatchpath[1]===e&&(null==t||L.env.dispatchpath[2]===t),buildNavigationModel(e,t){return e.filter(e=>e?.name).map(e=>{const a=ui.menu.getChildren(e).filter(e=>e?.name).map(a=>({name:a.name,title:_(a.title),href:L.url(t,e.name,a.name),isActivePage:this.isActivePath(e.name,a.name)})),i=a.length>0,n=this.isActivePath(e.name);return{name:e.name,title:_(e.title),href:L.url(t,e.name),hasChildren:i,isLogout:"logout"===e.name,isActiveGroup:i&&n,isActivePage:!i&&n,activePage:a.find(e=>e.isActivePage)||null,pages:a}})},navigationSubmenuId:(e,t)=>`${e}-submenu-${encodeURIComponent(String(t))}`,renderNavigationItem(e,t){const a="mobile"===t,i=a?"mobile-nav-item":"",n=a?"navigation-direct mobile-nav-link":"navigation-direct nav-link";if(!e.hasChildren){const t={class:`${n}${e.isActivePage?" is-active-page":""}`,href:e.href};return e.isActivePage&&(t["aria-current"]="page"),t["data-section"]=e.name,E("li",{class:i},[E("a",t,[E("span",{class:"nav-icon","aria-hidden":"true"}),E("span",{class:"nav-label"},[e.title])])])}const s=this.navigationSubmenuId(t,e.name),o=["navigation-group",a?"mobile-nav-item":"sidebar-group",e.isActiveGroup?"is-active-group":"",e.isActiveGroup?"is-expanded":""].filter(Boolean),l={class:a?"navigation-group-toggle mobile-nav-link mobile-nav-toggle":"navigation-group-toggle nav-category",type:"button","aria-expanded":e.isActiveGroup?"true":"false","aria-controls":s};e.isActiveGroup&&(l["aria-current"]="location"),l["data-section"]=e.name;const r=E("ul",{class:a?"navigation-submenu-list mobile-nav-submenu-list":"navigation-submenu-list sidebar-submenu"});e.pages.forEach(e=>{const t={class:["navigation-sublink",a?"mobile-nav-sublink":"",e.isActivePage?"is-active-page":""].filter(Boolean).join(" "),href:e.href};e.isActivePage&&(t["aria-current"]="page"),r.appendChild(E("li",{class:a?"mobile-nav-subitem":""},[E("a",t,[e.title])]))});const c={class:a?"navigation-group-region mobile-nav-submenu":"navigation-group-region sidebar-section",id:s,"aria-hidden":e.isActiveGroup?"false":"true"};return e.isActiveGroup||(c.inert=""),E("li",{class:o.join(" ")},[E("button",l,[E("span",{class:"nav-icon","aria-hidden":"true"}),E("span",{class:"nav-category-label"},[e.title])]),E("div",c,[r])])},setNavigationGroupExpanded(e,t){const a=e.querySelector(".navigation-group-toggle"),i=e.querySelector(".navigation-group-region");e.classList.toggle("is-expanded",t),a?.setAttribute("aria-expanded",t?"true":"false"),i?.setAttribute("aria-hidden",t?"false":"true"),t?i?.removeAttribute("inert"):i?.setAttribute("inert","")},setExclusiveNavigationGroupExpanded(e,t,a){e&&t&&(a&&e.querySelectorAll(".navigation-group.is-expanded").forEach(e=>{e!==t&&this.setNavigationGroupExpanded(e,!1)}),this.setNavigationGroupExpanded(t,a))},resetNavigationGroups(e){e?.querySelectorAll(".navigation-group.is-expanded").forEach(e=>this.setNavigationGroupExpanded(e,!1))},expandActiveNavigationGroup(e){const t=e?.querySelector(".navigation-group.is-active-group");t&&this.setExclusiveNavigationGroupExpanded(e,t,!0)},bindNavigationAccordion(e){e&&"true"!==e.dataset.accordionBound&&(e.dataset.accordionBound="true",e.addEventListener("click",t=>{const a=t.target?.closest?.(".navigation-group-toggle"),i=a?.closest?.(".navigation-group");i&&e.contains(i)&&(t.preventDefault(),t.stopPropagation(),this.setExclusiveNavigationGroupExpanded(e,i,!i.classList.contains("is-expanded")))}))},renderSidebar(e){const t=document.querySelector("#sidebar-list"),a=document.querySelector("#sidebar-footer"),i=document.querySelector("#header-crumb");if(t&&(t.innerHTML=""),a&&(a.innerHTML=""),i&&(i.innerHTML=""),!t)return;const n=[];e.forEach(e=>{(e.isActiveGroup||e.isActivePage)&&(n.push(e.title),e.activePage&&e.activePage.title!==e.title&&n.push(e.activePage.title)),e.isLogout?(a||t).appendChild(E("a",{class:"nav-link",href:e.href},[e.title])):t.appendChild(this.renderNavigationItem(e,"sidebar"))}),this.bindNavigationAccordion(t),n.forEach((e,t)=>{t&&i?.appendChild(E("li",{class:"crumb-sep"},["/"])),i?.appendChild(E("li",{class:t===n.length-1?"current":""},[e]))})},initPalette(e){const t=document.querySelector("#cmdk-trigger");if(!t||this.paletteIndex)return;this.paletteIndex=[],e.forEach(e=>{e.isLogout||(e.hasChildren?e.pages.forEach(t=>this.paletteIndex.push({title:t.title,name:`${e.name}/${t.name}`,group:e.title,href:t.href})):this.paletteIndex.push({title:e.title,name:e.name,group:null,href:e.href}))}),[["light",_("Light Mode")],["dark",_("Dark Mode")],["device",_("Automatic")]].forEach(([e,t])=>this.paletteIndex.push({title:t,name:`theme ${e}`,group:_("Design"),mode:e}));const a=/Mac|iP(ad|hone|od)/.test(navigator.platform);this.paletteKey=a?"⌘K":"Ctrl+K",t.setAttribute("aria-keyshortcuts",a?"Meta+K":"Control+K"),t.setAttribute("aria-expanded","false"),t.addEventListener("click",()=>this.togglePalette()),this.paletteTrigger=t,document.addEventListener("keydown",e=>{e.isComposing||229===e.keyCode||((a?!e.metaKey||e.ctrlKey:!e.ctrlKey||e.metaKey)||e.altKey||e.shiftKey||"k"!==(e.key||"").toLowerCase()?"Escape"===e.key&&this.palettePanel&&!this.palettePanel.hidden&&this.closePalette():(e.preventDefault(),this.togglePalette()))}),this.onPaletteAway=e=>{this.palettePanel.contains(e.target)||t.contains(e.target)||this.closePalette()}},buildPalette(){const e=E("input",{class:"cmdk-input",type:"text",enterkeyhint:"go",placeholder:_("Type to filter…"),"aria-label":_("Type to filter…"),autocomplete:"off",spellcheck:"false",role:"combobox","aria-expanded":"true","aria-autocomplete":"list","aria-controls":"cmdk-list"}),t=E("div",{class:"cmdk-list",id:"cmdk-list",role:"listbox"}),a=E("button",{class:"cmdk-clear",type:"button","aria-label":_("Clear")});a.addEventListener("click",()=>{e.value="",this.renderPaletteResults(""),e.focus()});const i=E("button",{class:"cmdk-cancel",type:"button"},[_("Cancel")]);i.addEventListener("click",()=>this.closePalette());const n=E("div",{id:"cmdk-panel",class:"cmdk-panel",role:"dialog","aria-modal":"true","aria-label":_("Navigation"),hidden:""},[E("div",{class:"cmdk-inputrow"},[e,a,i]),t,E("div",{class:"cmdk-footer"},[E("kbd",{},["↑↓"]),E("kbd",{},["↵"]),E("kbd",{},[">"]),E("kbd",{},["esc"]),E("span",{class:"cmdk-hint-close"},[E("kbd",{},[this.paletteKey])])])]);e.addEventListener("input",()=>this.renderPaletteResults(e.value)),e.addEventListener("keydown",e=>{e.isComposing||229===e.keyCode||("ArrowDown"===e.key||"ArrowUp"===e.key?(e.preventDefault(),this.movePaletteSelection("ArrowDown"===e.key?1:-1)):"Enter"===e.key&&t.querySelector(".is-selected")?.click())}),t.addEventListener("mousemove",e=>{const t=e.target?.closest?.(".cmdk-row");t&&!t.classList.contains("is-selected")&&this.setPaletteSelection(t)}),t.addEventListener("click",a=>{const i=a.target?.closest?.(".cmdk-row")?.dataset.mode;i&&(a.preventDefault(),setTheme(i),syncSwitchers(),this.renderPaletteResults(e.value),this.setPaletteSelection(t.querySelector(`[data-mode="${i}"]`)),e.focus())}),n.addEventListener("keydown",n=>{if("Tab"!==n.key)return;const s=[e,a,...t.querySelectorAll("a"),i].filter(e=>e.getClientRects().length),o=n.shiftKey?s[0]:s.at(-1);document.activeElement===o&&(n.preventDefault(),(n.shiftKey?s.at(-1):s[0]).focus())}),document.body.appendChild(n),this.paletteTrigger.setAttribute("aria-controls",n.id),this.palettePanel=n,this.paletteInput=e,this.paletteList=t},fuzzyMatch(e,t){const a=String(t).toLowerCase();let i=null;for(let t=a.indexOf(e[0]);t>=0;t=a.indexOf(e[0],t+1)){let n=t,s=0,o=0;const l=[];for(const t of e){if(" "===t){o=0;continue}const e=a.indexOf(t,n);if(e<0){l.length=0;break}o=e===n&&l.length?o+1:1,s+=1+o+(e===n&&l.length?4:0)+(0===e||" "===a[e-1]||"/"===a[e-1]?3:0);const i=e+t.length,r=l[l.length-1];r&&r[1]===e?r[1]=i:l.push([e,i]),n=i}s-=.02*a.length,l.length&&(!i||s>i.score)&&(i={score:s,ranges:l})}return i},matchPaletteEntry(e,t){if(!e)return{score:0,ranges:null};const a=this.fuzzyMatch(e,t.title);if(a)return{score:a.score+12,ranges:a.ranges};const i=this.fuzzyMatch(e,t.name)||(t.group?this.fuzzyMatch(e,t.group):null);return i&&{score:i.score,ranges:null}},renderPaletteResults(e){let t=e.trim().toLowerCase();const a=">"===t[0]||""===t[0];a&&(t=t.slice(1).trim());const i=localStorage.getItem("aurora.theme")||"device",n=[];for(const e of this.paletteIndex){if(a&&!e.mode)continue;const i=this.matchPaletteEntry(t,e);i&&n.push({page:e,score:i.score,ranges:i.ranges})}t&&n.sort((e,t)=>t.score-e.score),this.paletteInput.removeAttribute("aria-activedescendant"),this.paletteList.replaceChildren(),n.length?(n.forEach(({page:e,ranges:t},a)=>{const n=e.mode&&e.mode===i,s={class:"cmdk-row",id:`cmdk-option-${a}`,role:"option","aria-selected":"false",href:e.href||"#"};e.mode&&(s["data-mode"]=e.mode),n&&(s["aria-current"]="true"),this.paletteList.appendChild(E("a",s,[E("span",{class:"cmdk-title"},this.highlightPaletteMatch(e.title,t)),n?E("span",{class:"cmdk-group-name","aria-hidden":"true"},[E("mark",{},["✓"])]):e.group?E("span",{class:"cmdk-group-name"},[e.group]):""]))}),this.setPaletteSelection(this.paletteList.firstChild)):this.paletteList.appendChild(E("div",{class:"cmdk-empty"},[_("No entries available")]))},highlightPaletteMatch(e,t){if(!t||e.toLowerCase().length!==e.length)return[e];const a=[];let i=0;return t.forEach(([t,n])=>{a.push(e.slice(i,t),E("mark",{},[e.slice(t,n)])),i=n}),a.push(e.slice(i)),a},setPaletteSelection(e){const t=this.paletteList.querySelector(".is-selected");t?.classList.remove("is-selected"),t?.setAttribute("aria-selected","false"),e.classList.add("is-selected"),e.setAttribute("aria-selected","true"),this.paletteInput.setAttribute("aria-activedescendant",e.id)},movePaletteSelection(e){const t=[...this.paletteList.querySelectorAll(".cmdk-row")];if(!t.length)return;const a=t.findIndex(e=>e.classList.contains("is-selected")),i=t[(a+e+t.length)%t.length];this.setPaletteSelection(i),i.scrollIntoView({block:"nearest"})},togglePalette(){this.palettePanel||this.buildPalette(),this.palettePanel.hidden?this.openPalette():this.closePalette()},openPalette(){this.paletteReturnFocus=document.activeElement,this.paletteTrigger.setAttribute("aria-expanded","true"),this.palettePanel.hidden=!1,this.paletteInput.value="",this.renderPaletteResults(""),this.paletteInput.focus(),document.addEventListener("pointerdown",this.onPaletteAway)},closePalette(){this.paletteTrigger.setAttribute("aria-expanded","false"),this.palettePanel.hidden=!0,document.removeEventListener("pointerdown",this.onPaletteAway),this.paletteReturnFocus?.isConnected&&this.paletteReturnFocus.focus(),this.paletteReturnFocus=null},buildDropdownItem(e,t,a){const i=ui.menu.getChildren(e),n=i.length>0,s=E("li",{},[E("a",{class:"menu",href:n?"#":L.url(t,e.name)},[_(e.title)])]);a.appendChild(s);const o=s.querySelector("a");let l=null;if(n){const a=this.renderMainMenu(e,`${t}/${e.name}`,1),n=[a];if("mega-menu"===document.body?.dataset?.navType){a.style.setProperty("--menu-rows",Math.max(6,Math.ceil(i.length/4))),n.unshift(E("div",{class:"desktop-nav-anchor"},[E("span",{class:"desktop-nav-title","data-section":e.name},[_(e.title)])]));const t=document.querySelector(".desktop-menu-container > .desktop-menu-board");t&&n.push(t.cloneNode(!0))}l=E("div",{class:"desktop-nav"},n),s.appendChild(l),o.addEventListener("click",e=>e.preventDefault())}return{li:s,nav:l,menuLink:o,hasSubmenu:n}},deactivateDesktopNavExcept(e,t){document.querySelectorAll(".desktop-nav").forEach(t=>{t!==e&&t.classList.remove("active")}),document.querySelectorAll("#topmenu a").forEach(e=>{e!==t&&e.classList.remove("menu-active")})},initMegaMenu(e,t,a){const i=document.querySelector(".desktop-menu-container"),n=i?.querySelector(".desktop-menu-canvas"),s=document.querySelector(".desktop-menu-overlay"),o=document.querySelector("header");if(!o||!s)return;let l=null,r=null,c=0,d=300;const u=()=>{c||(o.querySelectorAll(".desktop-nav").forEach(e=>c=Math.max(c,e.offsetHeight)),d=Math.min(480,Math.max(240,Math.round(c/2)))),o.style.setProperty("--mega-menu-height",`${c}px`),o.style.setProperty("--mega-menu-duration",`${d}ms`)};let m=null;window.addEventListener("resize",()=>{c=0,clearTimeout(m),m=setTimeout(u,150)});let h={x:0,y:0},p=0,v={x:0,y:0};o.addEventListener("mousemove",e=>{e.timeStamp-p>60&&(h=v,p=e.timeStamp),v={x:e.clientX,y:e.clientY}}),e.forEach(e=>{const{li:c,nav:d,menuLink:m,hasSubmenu:p}=this.buildDropdownItem(e,t,a);p&&(n&&n.appendChild(d),c.addEventListener("mouseenter",()=>{r&&(clearTimeout(r),r=null);const e=i?.classList.contains("active"),t=e?(()=>{const e=o.querySelector(".desktop-nav.active");if(!e)return!1;const t=v.x-h.x,a=v.y-h.y;if(a<=2)return!1;const i=e.getBoundingClientRect();if(v.y>=i.top)return!0;const n=v.x+t*(i.top-v.y)/a;return n>=i.left-24&&n<=i.right+24})()?260:0:100;l=setTimeout(()=>{const e=d.classList.contains("active");this.deactivateDesktopNavExcept(d,m),e||(m.classList.add("menu-active"),i&&(u(),i.dataset.closeToken="",i.classList.add("active"),i.classList.remove("closing"),s.classList.add("active")),d.classList.add("active"))},t)}),c.addEventListener("mouseleave",()=>{l&&(clearTimeout(l),l=null)}))});const g=window.requestIdleCallback||(e=>setTimeout(e,1));(document.fonts?.ready||Promise.resolve()).then(()=>g(()=>{c||u()}));const b=()=>{l&&(clearTimeout(l),l=null),r=setTimeout(()=>{this.hideDesktopNav()},150)};o.addEventListener("mouseleave",b),s.addEventListener("mouseenter",b),o.addEventListener("mouseenter",()=>{r&&(clearTimeout(r),r=null)}),s.addEventListener("click",()=>this.hideDesktopNav())},initDropdown(e,t,a){e.forEach(e=>{const{li:i,nav:n,menuLink:s,hasSubmenu:o}=this.buildDropdownItem(e,t,a);if(!o)return;let l=null,r=null;i.addEventListener("mouseenter",()=>{r&&(clearTimeout(r),r=null),l=setTimeout(()=>{this.deactivateDesktopNavExcept(n,s),s.classList.add("menu-active"),n.classList.add("active")},100)}),i.addEventListener("mouseleave",()=>{l&&(clearTimeout(l),l=null),r=setTimeout(()=>{n.classList.remove("active"),s.classList.remove("menu-active")},150)})})},hideDesktopNav(){this.deactivateDesktopNavExcept(null,null);const e=document.querySelector(".desktop-menu-container");if(document.querySelector(".desktop-menu-overlay")?.classList.remove("active"),!e)return;if(!e.classList.contains("active")&&!e.classList.contains("closing"))return;e.classList.add("closing"),e.classList.remove("active");const t=e.querySelector(".desktop-menu-sheet"),a=`${Date.now()}-${Math.random()}`;e.dataset.closeToken=a;let i=null;const n=s=>{if(!s?.target||s.target===t){if(e.dataset.closeToken!==a)return null!==i&&(clearTimeout(i),i=null),void t?.removeEventListener("transitionend",n);null!==i&&(clearTimeout(i),i=null),t?.removeEventListener("transitionend",n),e.classList.contains("active")||(e.classList.remove("closing"),delete e.dataset.closeToken)}};if(!t||window.matchMedia?.("(prefers-reduced-motion: reduce)").matches)return void n();t.addEventListener("transitionend",n);const s=parseInt(document.querySelector("header")?.style.getPropertyValue("--mega-menu-duration"))||300;i=setTimeout(n,s+50)},renderModeMenu(e){const t=document.querySelector("#modemenu"),a=ui.menu.getChildren(e);let i=null;if(a.forEach((e,a)=>{const n=L.env.requestpath.length?e.name===L.env.requestpath[0]:0===a;t&&t.appendChild(E("li",{class:n?"active":""},[E("a",{href:L.url(e.name)},[_(e.title)])])),n&&(i=e)}),i){const e=this.buildNavigationModel(ui.menu.getChildren(i),i.name);this.renderMainMenu(i,i.name,0,e),this.renderMobileMenu(e),this.initPalette(e)}t?.children.length>1&&(t.style.display="")}});