From d48a56752bb22e3eccfac8ba53eff2630e6396a8 Mon Sep 17 00:00:00 2001 From: Troy Chaplin Date: Mon, 22 Dec 2025 23:14:03 -0500 Subject: [PATCH] refactor: frontend assets --- build/priority-editor.asset.php | 2 +- build/priority-editor.js | 2 +- build/priority-plus-nav.asset.php | 2 +- build/priority-plus-nav.js | 2 +- src/core/PriorityNav.js | 636 ++++++++++++++++ src/dom/dom-builder.js | 178 +++++ src/dom/dom-extractor.js | 85 +++ src/events/accordion-handler.js | 77 ++ src/events/event-handlers.js | 78 ++ src/layout/width-calculator.js | 100 +++ src/priority-plus-nav.js | 1117 +---------------------------- src/utils/constants.js | 8 + src/utils/dom-utils.js | 70 ++ src/utils/html-utils.js | 88 +++ src/variation/block.js | 2 +- 15 files changed, 1326 insertions(+), 1121 deletions(-) create mode 100644 src/core/PriorityNav.js create mode 100644 src/dom/dom-builder.js create mode 100644 src/dom/dom-extractor.js create mode 100644 src/events/accordion-handler.js create mode 100644 src/events/event-handlers.js create mode 100644 src/layout/width-calculator.js create mode 100644 src/utils/constants.js create mode 100644 src/utils/dom-utils.js create mode 100644 src/utils/html-utils.js diff --git a/build/priority-editor.asset.php b/build/priority-editor.asset.php index 99a410e..2d5aeeb 100644 --- a/build/priority-editor.asset.php +++ b/build/priority-editor.asset.php @@ -1 +1 @@ - array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => '8329a80772c4c16c8436'); + array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => '3c18caf20bb2d937b841'); diff --git a/build/priority-editor.js b/build/priority-editor.js index 9320099..eb7a3d2 100644 --- a/build/priority-editor.js +++ b/build/priority-editor.js @@ -1 +1 @@ -(()=>{"use strict";const o=window.wp.i18n,e=window.wp.blocks,r=window.wp.primitives,i=window.ReactJSXRuntime;var t=(0,i.jsx)(r.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(r.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M7.404 16.596a6.5 6.5 0 1 0 9.192-9.192 6.5 6.5 0 0 0-9.192 9.192ZM6.344 6.343a8 8 0 1 0 11.313 11.314A8 8 0 0 0 6.343 6.343Zm4.906 9.407v-3h-3v-1.5h3v-3h1.5v3h3v1.5h-3v3h-1.5Z"})});const n=window.wp.hooks;(0,e.registerBlockVariation)("core/navigation",{name:"priority-nav",title:(0,o.__)("Priority+ Nav","priority-nav"),description:(0,o.__)('A responsive navigation that automatically moves overflow items to a "More" dropdown.',"priority-nav"),icon:t,scope:["inserter","transform"],attributes:{className:"is-style-priority-nav",overlayMenu:"never",priorityNavEnabled:!0,priorityNavMoreLabel:"Browse",priorityNavMoreIcon:"none"},isActive:(o,e)=>o.className?.includes(e.className)}),(0,n.addFilter)("blocks.registerBlockType","priority-nav/extend-core-navigation",(o,e)=>"core/navigation"!==e?o:{...o,attributes:{...o.attributes,priorityNavEnabled:{type:"boolean",default:!1},priorityNavMoreLabel:{type:"string",default:"Browse"},priorityNavMoreIcon:{type:"string",default:"none"}}});const a=window.wp.blockEditor,l=window.wp.components,s=(0,window.wp.compose.createHigherOrderComponent)(e=>r=>{const{name:t,attributes:n,setAttributes:s}=r;if("core/navigation"!==t)return(0,i.jsx)(e,{...r});const{priorityNavEnabled:v,priorityNavMoreLabel:p,priorityNavMoreIcon:c}=n;return(0,i.jsxs)(i.Fragment,{children:[v&&(0,i.jsx)("div",{className:"priority-nav-editor-wrapper",children:(0,i.jsx)(e,{...r})}),!v&&(0,i.jsx)(e,{...r}),(0,i.jsx)(a.InspectorControls,{children:(0,i.jsxs)(l.PanelBody,{title:(0,o.__)("Priority+ Settings","priority-nav"),children:[(0,i.jsx)(l.TextControl,{label:(0,o.__)("More Button Label","priority-nav"),value:p,onChange:o=>s({priorityNavMoreLabel:o}),help:(0,o.__)('Text displayed on the "More" button',"priority-nav")}),(0,i.jsx)(l.SelectControl,{label:(0,o.__)("More Button Icon","priority-nav"),value:c,options:[{label:(0,o.__)("None","priority-nav"),value:"none"},{label:(0,o.__)("Chevron Down (▼)","priority-nav"),value:"chevron"},{label:(0,o.__)("Plus (+)","priority-nav"),value:"plus"},{label:(0,o.__)("Menu (≡)","priority-nav"),value:"menu"}],onChange:o=>s({priorityNavMoreIcon:o})})]})})]})},"withPriorityNavControls");(0,n.addFilter)("editor.BlockEdit","priority-nav/add-priority-nav-controls",s)})(); \ No newline at end of file +(()=>{"use strict";const o=window.wp.i18n,e=window.wp.blocks,r=window.wp.primitives,i=window.ReactJSXRuntime;var t=(0,i.jsx)(r.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(r.Path,{fillRule:"evenodd",clipRule:"evenodd",d:"M7.404 16.596a6.5 6.5 0 1 0 9.192-9.192 6.5 6.5 0 0 0-9.192 9.192ZM6.344 6.343a8 8 0 1 0 11.313 11.314A8 8 0 0 0 6.343 6.343Zm4.906 9.407v-3h-3v-1.5h3v-3h1.5v3h3v1.5h-3v3h-1.5Z"})});const n=window.wp.hooks;(0,e.registerBlockVariation)("core/navigation",{name:"priority-nav",title:(0,o.__)("Priority Plus Nav","priority-nav"),description:(0,o.__)('A responsive navigation that automatically moves overflow items to a "More" dropdown.',"priority-nav"),icon:t,scope:["inserter","transform"],attributes:{className:"is-style-priority-nav",overlayMenu:"never",priorityNavEnabled:!0,priorityNavMoreLabel:"Browse",priorityNavMoreIcon:"none"},isActive:(o,e)=>o.className?.includes(e.className)}),(0,n.addFilter)("blocks.registerBlockType","priority-nav/extend-core-navigation",(o,e)=>"core/navigation"!==e?o:{...o,attributes:{...o.attributes,priorityNavEnabled:{type:"boolean",default:!1},priorityNavMoreLabel:{type:"string",default:"Browse"},priorityNavMoreIcon:{type:"string",default:"none"}}});const a=window.wp.blockEditor,l=window.wp.components,s=(0,window.wp.compose.createHigherOrderComponent)(e=>r=>{const{name:t,attributes:n,setAttributes:s}=r;if("core/navigation"!==t)return(0,i.jsx)(e,{...r});const{priorityNavEnabled:v,priorityNavMoreLabel:p,priorityNavMoreIcon:c}=n;return(0,i.jsxs)(i.Fragment,{children:[v&&(0,i.jsx)("div",{className:"priority-nav-editor-wrapper",children:(0,i.jsx)(e,{...r})}),!v&&(0,i.jsx)(e,{...r}),(0,i.jsx)(a.InspectorControls,{children:(0,i.jsxs)(l.PanelBody,{title:(0,o.__)("Priority+ Settings","priority-nav"),children:[(0,i.jsx)(l.TextControl,{label:(0,o.__)("More Button Label","priority-nav"),value:p,onChange:o=>s({priorityNavMoreLabel:o}),help:(0,o.__)('Text displayed on the "More" button',"priority-nav")}),(0,i.jsx)(l.SelectControl,{label:(0,o.__)("More Button Icon","priority-nav"),value:c,options:[{label:(0,o.__)("None","priority-nav"),value:"none"},{label:(0,o.__)("Chevron Down (▼)","priority-nav"),value:"chevron"},{label:(0,o.__)("Plus (+)","priority-nav"),value:"plus"},{label:(0,o.__)("Menu (≡)","priority-nav"),value:"menu"}],onChange:o=>s({priorityNavMoreIcon:o})})]})})]})},"withPriorityNavControls");(0,n.addFilter)("editor.BlockEdit","priority-nav/add-priority-nav-controls",s)})(); \ No newline at end of file diff --git a/build/priority-plus-nav.asset.php b/build/priority-plus-nav.asset.php index 8d819ce..a72523f 100644 --- a/build/priority-plus-nav.asset.php +++ b/build/priority-plus-nav.asset.php @@ -1 +1 @@ - array(), 'version' => '51fcd302839f0a1322ce'); + array(), 'version' => 'ccab84b63ca39dba3b2d'); diff --git a/build/priority-plus-nav.js b/build/priority-plus-nav.js index a34549d..4a5cf8a 100644 --- a/build/priority-plus-nav.js +++ b/build/priority-plus-nav.js @@ -1 +1 @@ -(()=>{"use strict";var t,e={103(){class t{static instanceCounter=0;static DEFAULT_MORE_LABEL="Browse";static DEFAULT_MORE_ICON="none";static DEFAULT_GAP=8;static RETRY_INTERVAL=100;static MAX_RETRY_ATTEMPTS=20;constructor(e){"true"!==e.dataset.priorityNavInitialized&&(this.instanceId="priority-nav-"+t.instanceCounter++,e.classList.contains("wp-block-navigation")&&e.classList.contains("is-style-priority-nav")&&(e.dataset.priorityNavInitialized="true",this.nav=e,this.wrapper=e,this.nav&&(this.list=this.nav.querySelector(".wp-block-navigation__container"),this.moreLabel=this.nav.getAttribute("data-more-label")||t.DEFAULT_MORE_LABEL,this.moreIcon=this.nav.getAttribute("data-more-icon")||t.DEFAULT_MORE_ICON,this.openSubmenusOnClick=this.detectOpenSubmenusOnClick(),this.list&&(this.createMoreButton(),this.items=Array.from(this.list.children),this.itemWidths=[],this.isOpen=!1,this.isCalculating=!1,this.openAccordions=[],this.submenuCounter=0,this.responsiveContainer=this.nav.querySelector(".wp-block-navigation__responsive-container"),this.mutationObserver=null,this.retryTimeout=null,this.isEnabled=!0,this.moreButtonWidth=null,this.init()))))}detectOpenSubmenusOnClick(){let t=null;if(this.nav.attributes)for(let e=0;e0&&i.height>0}getElementWidth(t){return this.isElementVisible(t)?t.getBoundingClientRect().width:0}createMoreButton(){this.moreContainer=document.createElement("div"),this.moreContainer.className="priority-nav-more",this.moreButton=document.createElement("button"),this.moreButton.type="button",this.moreButton.className="priority-nav-more-button wp-block-navigation-item",this.moreButton.setAttribute("aria-expanded","false"),this.moreButton.setAttribute("aria-haspopup","true"),this.moreButton.setAttribute("aria-label",this.moreLabel);const t={chevron:"▼",plus:"+",menu:"≡"},e=t[this.moreIcon]?`${t[this.moreIcon]}`:"";this.moreButton.innerHTML=`\n\t\t\t${this.moreLabel}\n\t\t\t${e}\n\t\t`,this.dropdown=document.createElement("ul"),this.dropdown.className="priority-nav-dropdown wp-block-navigation__submenu-container",this.dropdown.setAttribute("role","menu"),this.moreContainer.appendChild(this.moreButton),this.moreContainer.appendChild(this.dropdown),this.list.parentNode.appendChild(this.moreContainer),this.moreContainer.style.display="none"}init(){this.wrapper&&document.body.contains(this.wrapper)&&(this.setupEventListeners(),this.setupResponsiveObserver(),this.isInHamburgerMode()?this.disablePriorityNav():this.enablePriorityNav(),"undefined"!=typeof ResizeObserver&&(this.resizeObserver=new ResizeObserver(()=>{if(document.body.contains(this.wrapper)&&!this.isCalculating){const t=this.isEnabled,e=this.isInHamburgerMode();e&&t?this.disablePriorityNav():e||t?!e&&t&&requestAnimationFrame(()=>this.checkOverflow()):this.enablePriorityNav()}}),this.resizeObserver.observe(this.wrapper)))}isInHamburgerMode(){return!(!this.responsiveContainer||this.isElementVisible(this.responsiveContainer)&&"true"!==this.responsiveContainer.getAttribute("aria-hidden"))||!(!this.list||this.isElementVisible(this.list))}isMeasurable(){return this.isElementVisible(this.list)}disablePriorityNav(){this.items&&Array.isArray(this.items)&&(this.isEnabled=!1,this.items.forEach(t=>{t&&t.style&&(t.style.display="")}),this.moreContainer&&this.moreContainer.style&&(this.moreContainer.style.display="none"),this.closeDropdown())}enablePriorityNav(){this.isEnabled=!0,this.isMeasurable()?((0===this.itemWidths.length||this.itemWidths.some(t=>0===t))&&this.cacheItemWidths(),requestAnimationFrame(()=>{this.checkOverflow()})):this.scheduleRetry()}scheduleRetry(e=t.MAX_RETRY_ATTEMPTS){this.retryTimeout&&clearTimeout(this.retryTimeout);let i=0;const s=()=>{i++,this.isMeasurable()&&!this.isInHamburgerMode()?(this.enablePriorityNav(),this.retryTimeout=null):this.retryTimeout=i{if(!document.body.contains(this.nav))return;let e=!1;if(t.forEach(t=>{"attributes"!==t.type||"aria-hidden"!==t.attributeName&&"class"!==t.attributeName||(e=!0)}),e){const t=this.isInHamburgerMode();t&&this.isEnabled?this.disablePriorityNav():t||this.isEnabled||this.enablePriorityNav()}}),this.mutationObserver.observe(this.responsiveContainer,{attributes:!0,attributeFilter:["aria-hidden","class"]}),this.list&&document.body.contains(this.list)&&this.mutationObserver.observe(this.list,{attributes:!0,attributeFilter:["style","class"],attributeOldValue:!1}))}hasValidWidthCache(){return this.itemWidths.length===this.items.length&&!this.itemWidths.some(t=>0===t)}cacheItemWidths(){this.isMeasurable()&&(this.items.forEach(t=>{t.style.display=""}),this.list.offsetHeight,this.itemWidths=this.items.map(t=>{const e=this.getElementWidth(t);return e>0?e:0}),this.itemWidths.some(t=>0===t)&&this.scheduleRetry())}cacheMoreButtonWidth(){if(null!==this.moreButtonWidth)return this.moreButtonWidth;const t="none"===this.moreContainer.style.display;return t&&(this.moreContainer.style.display=""),this.moreButton.offsetHeight,this.moreButtonWidth=this.getElementWidth(this.moreButton),t&&(this.moreContainer.style.display="none"),this.moreButtonWidth}setupEventListeners(){this.moreButtonClickHandler=t=>{t.preventDefault(),t.stopPropagation(),this.toggleDropdown()},this.moreButton.addEventListener("click",this.moreButtonClickHandler),this.documentClickHandler=t=>{this.moreContainer&&!this.moreContainer.contains(t.target)&&this.isOpen&&this.closeDropdown()},document.addEventListener("click",this.documentClickHandler,!0),this.documentKeydownHandler=t=>{"Escape"===t.key&&this.isOpen&&(this.openAccordions.length>0?(this.closeAllAccordions(),t.preventDefault()):this.closeDropdown())},document.addEventListener("keydown",this.documentKeydownHandler),this.dropdownClickHandler=t=>{const e=t.target.closest(".priority-nav-accordion-toggle");if(e){t.preventDefault(),t.stopPropagation();const i=e.getAttribute("aria-controls"),s=this.dropdown.querySelector(`#${i}`);s&&this.toggleAccordionItem(e,s)}},this.dropdown.addEventListener("click",this.dropdownClickHandler)}calculateAvailableWidth(){const t=this.nav.getBoundingClientRect(),e=window.getComputedStyle(this.nav),i=parseFloat(e.paddingLeft)+parseFloat(e.paddingRight),s=t.width>0?t.width:this.getElementWidth(this.wrapper);return s>0?s-i:0}getGap(){const e=window.getComputedStyle(this.list),i=window.getComputedStyle(this.nav);return parseFloat(e.gap)||parseFloat(i.gap)||t.DEFAULT_GAP}calculateVisibleItems(t,e,i){let s=0;for(let t=0;t0?i:0)+this.itemWidths[t];if(s<=t)return this.items.length;let n=0,r=0;for(let s=0;s0?i:0)+this.itemWidths[s];if(!(n+o+i+e<=t)&&0!==s)break;n+=o,r++}return r}buildDropdownFromOverflow(t){this.dropdown.innerHTML="",this.submenuCounter=0;for(let e=t;e=t)return this.items.forEach(t=>t.style.display="none"),this.moreContainer.style.display="",void(this.isCalculating=!1);const i=this.getGap(),s=this.calculateVisibleItems(t,e,i);if(s===this.items.length)this.items.forEach(t=>t.style.display=""),this.moreContainer.style.display="none",this.closeDropdown();else{this.moreContainer.style.display="none";for(let t=s;tt.remove());let s=i.textContent.trim();if(!s){const e=Array.from(t.childNodes).filter(t=>t.nodeType===Node.TEXT_NODE);e.length>0&&(s=e.map(t=>t.textContent.trim()).filter(t=>t).join(" "))}return s}removeChildTextFromParent(t,e){if(!t||!e)return t;const i=[];if(e.querySelectorAll("li a").forEach(e=>{const s=e.textContent.trim();s&&t.includes(s)&&i.push(s)}),i.length>0){let e=t;return i.forEach(t=>{e=e.replace(t,"").trim()}),e}return t}extractNavItemData(t){const e={text:"",url:"#",hasSubmenu:!1,children:[]},i=t.querySelector(":scope > .wp-block-navigation__submenu-container");let s=t.querySelector(":scope > a");if(s||(s=t.querySelector(":scope > .wp-block-navigation-item__content a")),!s){if(i){const i=t.cloneNode(!0),s=i.querySelector(".wp-block-navigation__submenu-container");s&&s.remove(),e.text=i.textContent.trim()}else e.text=t.textContent.trim();return i&&(e.hasSubmenu=!0,i.querySelectorAll(":scope > li").forEach(t=>{e.children.push(this.extractNavItemData(t))})),e}return e.text=this.extractLinkText(s),i&&e.text&&(e.text=this.removeChildTextFromParent(e.text,i)),e.url=s.getAttribute("href")||"#",i&&(e.hasSubmenu=!0,i.querySelectorAll(":scope > li").forEach(t=>{e.children.push(this.extractNavItemData(t))})),e}buildAccordionHTML(t,e){const i=`${this.instanceId}-submenu-${this.submenuCounter++}`;let s="";return t.hasSubmenu?(s=this.openSubmenusOnClick?`\n\t\t\t\t\t\n\t\t\t\t\t