Plugin Directory

Changeset 3725635


Ignore:
Timestamp:
10/02/2026 11:39:13 PM (3 weeks ago)
Author:
wooscroll
Message:

Release version 1.0.6

Location:
loops-block/trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • loops-block/trunk/build/loop.js

    r3622994 r3725635  
    270270    var el = el
    271271    , options = options || {}
    272     , trigger = el.getElementsByClassName('scroller')[0]
     272    , trigger = el.querySelector('.scroller') ?? el.nextElementSibling?.closest('.scroller')
    273273    , autoTrigger = options.autoTrigger == false ? false : true
    274274    , autoTriggerUntil = options.autoTriggerUntil || 1000
    … …  
    305305            trigger.className = '';
    306306            trigger.removeEventListener('click', _load);
    307             el.removeChild(trigger);
     307            trigger.remove();
    308308            var dom = document.createElement('div'), i;
    309309            dom.innerHTML = r.response.content;
    … …  
    311311            while(i=dom.firstChild) el.appendChild(i);
    312312
    313             trigger = el.getElementsByClassName('scroller')[0];
     313            trigger = el.querySelector('.scroller') ?? el.nextElementSibling?.closest('.scroller');
    314314            trigger && trigger.addEventListener('click', _load, false);
    315315
  • loops-block/trunk/build/loop.min.js

    r3671635 r3725635  
    1 !function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).BezierEasing=e()}((function(){return function e(t,n,i){function o(a,l){if(!n[a]){if(!t[a]){var s="function"==typeof require&&require;if(!l&&s)return s(a,!0);if(r)return r(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[a]={exports:{}};t[a][0].call(d.exports,(function(e){return o(t[a][1][e]||e)}),d,d.exports,e,t,n,i)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a<i.length;a++)o(i[a]);return o}({1:[function(e,t,n){var i="function"==typeof Float32Array;function o(e,t){return 1-3*t+3*e}function r(e,t){return 3*t-6*e}function a(e){return 3*e}function l(e,t,n){return((o(t,n)*e+r(t,n))*e+a(t))*e}function s(e,t,n){return 3*o(t,n)*e*e+2*r(t,n)*e+a(t)}function u(e){return e}t.exports=function(e,t,n,o){if(!(0<=e&&e<=1&&0<=n&&n<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&n===o)return u;for(var r=i?new Float32Array(11):new Array(11),a=0;a<11;++a)r[a]=l(.1*a,e,n);return function(i){return 0===i?0:1===i?1:l(function(t){for(var i=0,o=1;10!==o&&r[o]<=t;++o)i+=.1;var a=i+(t-r[--o])/(r[o+1]-r[o])*.1,u=s(a,e,n);return.001<=u?function(e,t,n,i){for(var o=0;o<4;++o){var r=s(t,n,i);if(0===r)return t;t-=(l(t,n,i)-e)/r}return t}(t,a,e,n):0===u?a:function(e,t,n,i,o){for(var r,a,s=0;0<(r=l(a=t+(n-t)/2,i,o)-e)?n=a:t=a,Math.abs(r)>1e-7&&++s<10;);return a}(t,i,i+.1,e,n)}(i),t,o)}}},{}]},{},[1])(1)})),function(){"use strict";function plugin(){for(var el,str_plugin="data-plugin",str_option="data-option",els=document.querySelectorAll('[data-plugin],[class^="plugin-"],[class*=" plugin-"]'),options,plugin,i=0;i<els.length;i++){if(el=els[i],el.className.indexOf("plug-initialized")>-1)return;plugin=el.getAttribute(str_plugin)||el.className.match(/(?:^|\s)plugin-(.*?)(?:$|\s)/)[1],options=el.getAttribute(str_option)||"{}",options=eval("("+options+")");for(var klass=el.className,reg=/data-([^-]+)-([^\s]+)/g,result;null!==(result=reg.exec(klass));)options[result[1]]=result[2];for(var d in el.dataset)if(d.indexOf(plugin)>-1){var attr=d.replace(plugin,"").toLowerCase();""!==attr&&(options[attr]=el.dataset[d])}options.child&&(el=el.children[0]),(el[plugin]||window[plugin])&&(el.removeAttribute(str_plugin),el.removeAttribute(str_option),el.className+=" plug-initialized",el[plugin]?el[plugin].apply(el,options):new window[plugin](el,options))}}function on(e,t,n){document.addEventListener(e,(function(e){let i=e.target;for(;i&&i!==document;){if(i.matches&&i.matches(t))return void n.call(i,e);i=i.parentElement}}))}function init(){location.href.indexOf("dir=rtl")>-1&&document.body.classList.add("rtl"),plugin()}window.slider=function(e,t){var n,i,o,r,a,l,s="rtl"==getComputedStyle(e).direction,u=0!=t.arrows,d=!!t.dots,c=(t.slides,!!t.autoplay),f=t.autoplaySpeed||4e3,p=!!t.loop,v=parseInt(getComputedStyle(e).gridColumnGap,10),g=e.parentElement.className.indexOf("block-loop-center")>-1,m=parseFloat(getComputedStyle(e).getPropertyValue("--loop-max-width"))/100,h=(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent),t.l_c||"slider-left-btn"),y=t.r_c||"slider-right-btn",w=t.l_svg||'<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>',L=t.r_svg||'<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>',E=8,b=!1,N="block-slider-scrolling";function x(){var e=A(),t="";if(r&&!(e<2)){for(var n=0;n<e;n++)t+='<button data-index="'+n+'"></button>';r.innerHTML=t,r.addEventListener("click",k)}}function k(t){H();var n=1,i=e.scrollLeft;t.target.parentElement.className.indexOf("block-loop-dot")>-1?(n=t.target.dataset.index,i=0):n=t.currentTarget.className.indexOf(h)>-1?-1:1,_(i+=n*O())}function T(){!0===t.autoplay&&0!=c&&(c=!0,setTimeout(C,f))}function H(){c=!1}function C(){if(!b){var t=e.scrollLeft+(g?O():O(1));e.scrollLeft+e.offsetWidth==e.scrollWidth&&(p?(t=0,g&&(t=O())):H()),c&&_(t),P()}}function O(t){var n=e.offsetWidth,i=e.children[0].offsetWidth,o=t?t*(i+v):n+v;return g&&m<1&&(o=parseInt(m*(o+v/2)),0!=e.scrollLeft&&e.scrollLeft+e.offsetWidth!=e.scrollWidth||(o-=n*(1-m)/2)),o*(s?-1:1)}function A(){return Math.round(e.scrollWidth/e.offsetWidth)}function i(){i||(requestAnimationFrame((function(){x(),P(),i=!1})),i=!0)}function P(){for(var t=A(),n=e.children,i=e.scrollLeft,c=i+e.offsetWidth,f=e.scrollWidth,p=Math.round((f-i)/e.offsetWidth),v=0;v<n.length;v++){var g=n[v],m=g.offsetLeft,h=m+g.offsetWidth,y=n[v].getElementsByTagName("video")[0];if(c-4<m||i+4>h){var w=new RegExp("(\\s|^)slider-active(\\s|$)");n[v].className=n[v].className.replace(w,""),y&&y.pause()}else-1==n[v].className.indexOf("slider-active")&&(n[v].className+=" slider-active",y&&y.play())}if(u&&(a.style.display=a&&i*(s?-1:1)<E?"none":"",l&&f-i*(s?-1:1)<e.offsetWidth+E?l.style.display="none":l.style.display="",o)){var L=e.getElementsByClassName("post-thumbnail"),b=getComputedStyle(e);L[0]&&(o.style.setProperty("--height",L[0].offsetHeight+"px"),o.style.setProperty("--top",e.offsetTop+L[0].offsetTop+parseInt(L[0].offsetHeight/2)+"px")),b.getPropertyValue("--loop-rows")>1&&L[0]&&o.style.setProperty("--top","calc(50% + "+parseInt(e.offsetTop/2)+"px)")}if(d){var N=r.querySelector('[data-index="'+(t-p)*(s?-1:1)+'"]'),x=r.getElementsByTagName("button");for(v=0;v<x.length;v++)x[v].className="";N&&(N.className="active")}}function _(t){if(!e.classList.contains(N)){var n=e.scrollLeft;!function(e,t,n,i,o,r,a){var l=[.425,.005,0,1];l=BezierEasing(l[0],l[1],l[2],l[3]);const s=o=>{e[t]=n+(i-n)*o},u=Date.now(),d=()=>{var e=(Date.now()-u)/o;e>1?(s(1),a&&a()):(requestAnimationFrame(d),s(l(e)))};r&&r();d()}(e,"scrollLeft",n,t,1500,(function(){b=!0,e.classList.add(N)}),(function(){b=!1,e.classList.remove(N),T()}))}}e.className+=" block-loop-slider",u&&((o=document.createElement("div")).className="block-loop-nav",e.parentNode.appendChild(o),function(){A();var e="";e='<div class="'+h+'"><button>'+w+'</button></div><span></span><div class="'+y+'"><button>'+L+"</button></div>",o.innerHTML=e,a=o.getElementsByClassName(h)[0],l=o.getElementsByClassName(y)[0],a.addEventListener("click",k),l.addEventListener("click",k)}()),d&&((r=document.createElement("div")).className="block-loop-dot",e.parentNode.appendChild(r),x()),g&&_(O()),c&&T(),P(),e.addEventListener("ontouchstart"in window?"touchstart":"mouseenter",(function(){c=!1})),e.addEventListener("ontouchstart"in window?"touchend":"mouseleave",(function(){c=!0})),e.addEventListener("scroll",(function(){n||(requestAnimationFrame((function(){P(),n=!1})),n=!0)})),window.addEventListener("resize",i)},window.scroller=function(e,t){t=t||{};var n=(e=e).getElementsByClassName("scroller")[0],i=0!=t.autoTrigger,o=t.autoTriggerUntil||1e3,r=0,a=t.loadingHtml||'<span class="spinner"></span><span class="screen-reader-text"></span>';if(n){var l=window,s=getComputedStyle(n.parentElement).getPropertyValue("overflow-y");"scroll"!=s&&"auto"!=s||(l=n.parentElement),l.addEventListener("scroll",(function(){n&&function(e,t,n){var i=e.offsetTop,o=i+e.clientHeight,r=t.pageYOffset?t.pageYOffset:t.scrollTop,a=r+(t.pageYOffset?t.innerHeight:t.clientHeight),l=n&&(i<r&&o>r||o>a&&i<a);return i>=r&&o<=a||l}(n,l)&&i&&r<o&&u()}),!1),n.addEventListener("click",u,!1)}function u(t){if(t&&t.preventDefault(),t&&t.stopPropagation(),!(n.className.indexOf("is-loading")>-1)){n.innerHTML=a,n.className+=" is-loading";var i=n.href,o=new XMLHttpRequest;o.responseType="json",o.onreadystatechange=function(){if(4==o.readyState&&200==o.status){n.className="",n.removeEventListener("click",u),e.removeChild(n);var t,i=document.createElement("div");for(i.innerHTML=o.response.content;t=i.firstChild;)e.appendChild(t);(n=e.getElementsByClassName("scroller")[0])&&n.addEventListener("click",u,!1),document.dispatchEvent(new Event("refresh")),r++}},o.open("GET",i,!0),"undefined"!=typeof play&&void 0!==play.nonce&&o.setRequestHeader("X-WP-Nonce",play.nonce),o.send()}}},window.range=function(e){var t=e.getAttribute("value"),n=null===t?[]:t.split(","),i=+(e.min||0),o=+(e.max||100),r=document.createElement("span"),a=document.createElement("span"),l=e.cloneNode();e.classList.add("multirange"),e.classList.add("original"),l.classList.add("multirange"),l.classList.add("ghost"),r.classList.add("range-min"),a.classList.add("range-max"),e.value=n[0]||i+(o-i)/2,l.value=n[1]||i+(o-i)/2,e.parentNode.insertBefore(l,e.nextSibling),e.parentNode.insertBefore(r,e.previousSibling),e.parentNode.insertBefore(a,e.previousSibling);var s=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value");function u(t){var n=(e.valueLow-i)/(o-i)*100,s=(e.valueHigh-i)/(o-i)*100;l.style.setProperty("--low",n+"%"),l.style.setProperty("--high",s+"%"),r&&(r.innerHTML=e.valueLow,r.style.setProperty("--left",n)),a&&(a.innerHTML=e.valueHigh,a.style.setProperty("--left",s)),1!==t&&(clearTimeout(d),d=setTimeout((function(){var t=e.getAttribute("data-url"),n=e.getAttribute("name"),i=(e.getAttribute("type"),new RegExp(n+"__(\\d+)-(\\d+)[%2C]*[(\\d+)\\-(\\d+)]*"));t=t.replace(i,n+"__"+e.valueLow+"-"+e.valueHigh),"undefined"==typeof Pjax?location.href=t:document.dispatchEvent(new CustomEvent("reload",{detail:{url:t}}))}),1e3))}Object.defineProperty(e,"originalValue",s.get?s:{get:function(){return this.value},set:function(e){this.value=e}}),Object.defineProperties(e,{valueLow:{get:function(){return Math.min(this.originalValue,l.value)},set:function(e){this.originalValue=e,u()},enumerable:!0},valueHigh:{get:function(){return Math.max(this.originalValue,l.value)},set:function(e){l.value=e,u()},enumerable:!0}}),s.get&&Object.defineProperty(e,"value",{get:function(){return this.valueLow+","+this.valueHigh},set:function(e){var t=e.split(",");this.valueLow=t[0],this.valueHigh=t[1],u()},enumerable:!0}),"function"==typeof e.oninput&&(l.oninput=e.oninput.bind(e)),l.addEventListener("mousedown",(function(t){var n=i+(o-i)*t.offsetX/this.offsetWidth,r=(e.valueHigh+e.valueLow)/2;e.valueLow==l.value==n>r&&(e.value=l.value)})),e.addEventListener("input",u),l.addEventListener("input",u);var d=null;u(1)},on("click",".dropdown-toggle-filter",(function(e){e.preventDefault();var t=this.nextElementSibling;t&&(t.classList.toggle("show"),t.parentNode.querySelector(".dropdown-backdrop")||t.parentNode.insertAdjacentHTML("beforeend",'<div class="dropdown-backdrop"></div>'),on("click",".dropdown-backdrop",(function(e){t.classList.remove("show")})))})),window.addEventListener("call:plugin",(function(){plugin()})),window.addEventListener("pjax:complete",(function(){init()})),init()}();
     1!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).BezierEasing=e()}((function(){return function e(t,n,i){function o(l,a){if(!n[l]){if(!t[l]){var s="function"==typeof require&&require;if(!a&&s)return s(l,!0);if(r)return r(l,!0);var u=new Error("Cannot find module '"+l+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[l]={exports:{}};t[l][0].call(d.exports,(function(e){return o(t[l][1][e]||e)}),d,d.exports,e,t,n,i)}return n[l].exports}for(var r="function"==typeof require&&require,l=0;l<i.length;l++)o(i[l]);return o}({1:[function(e,t,n){var i="function"==typeof Float32Array;function o(e,t){return 1-3*t+3*e}function r(e,t){return 3*t-6*e}function l(e){return 3*e}function a(e,t,n){return((o(t,n)*e+r(t,n))*e+l(t))*e}function s(e,t,n){return 3*o(t,n)*e*e+2*r(t,n)*e+l(t)}function u(e){return e}t.exports=function(e,t,n,o){if(!(0<=e&&e<=1&&0<=n&&n<=1))throw new Error("bezier x values must be in [0, 1] range");if(e===t&&n===o)return u;for(var r=i?new Float32Array(11):new Array(11),l=0;l<11;++l)r[l]=a(.1*l,e,n);return function(i){return 0===i?0:1===i?1:a(function(t){for(var i=0,o=1;10!==o&&r[o]<=t;++o)i+=.1;var l=i+(t-r[--o])/(r[o+1]-r[o])*.1,u=s(l,e,n);return.001<=u?function(e,t,n,i){for(var o=0;o<4;++o){var r=s(t,n,i);if(0===r)return t;t-=(a(t,n,i)-e)/r}return t}(t,l,e,n):0===u?l:function(e,t,n,i,o){for(var r,l,s=0;0<(r=a(l=t+(n-t)/2,i,o)-e)?n=l:t=l,Math.abs(r)>1e-7&&++s<10;);return l}(t,i,i+.1,e,n)}(i),t,o)}}},{}]},{},[1])(1)})),function(){"use strict";function plugin(){for(var el,str_plugin="data-plugin",str_option="data-option",els=document.querySelectorAll('[data-plugin],[class^="plugin-"],[class*=" plugin-"]'),options,plugin,i=0;i<els.length;i++){if(el=els[i],el.className.indexOf("plug-initialized")>-1)return;plugin=el.getAttribute(str_plugin)||el.className.match(/(?:^|\s)plugin-(.*?)(?:$|\s)/)[1],options=el.getAttribute(str_option)||"{}",options=eval("("+options+")");for(var klass=el.className,reg=/data-([^-]+)-([^\s]+)/g,result;null!==(result=reg.exec(klass));)options[result[1]]=result[2];for(var d in el.dataset)if(d.indexOf(plugin)>-1){var attr=d.replace(plugin,"").toLowerCase();""!==attr&&(options[attr]=el.dataset[d])}options.child&&(el=el.children[0]),(el[plugin]||window[plugin])&&(el.removeAttribute(str_plugin),el.removeAttribute(str_option),el.className+=" plug-initialized",el[plugin]?el[plugin].apply(el,options):new window[plugin](el,options))}}function on(e,t,n){document.addEventListener(e,(function(e){let i=e.target;for(;i&&i!==document;){if(i.matches&&i.matches(t))return void n.call(i,e);i=i.parentElement}}))}function init(){location.href.indexOf("dir=rtl")>-1&&document.body.classList.add("rtl"),plugin()}window.slider=function(e,t){var n,i,o,r,l,a,s="rtl"==getComputedStyle(e).direction,u=0!=t.arrows,d=!!t.dots,c=(t.slides,!!t.autoplay),f=t.autoplaySpeed||4e3,p=!!t.loop,v=parseInt(getComputedStyle(e).gridColumnGap,10),g=e.parentElement.className.indexOf("block-loop-center")>-1,m=parseFloat(getComputedStyle(e).getPropertyValue("--loop-max-width"))/100,h=(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent),t.l_c||"slider-left-btn"),y=t.r_c||"slider-right-btn",w=t.l_svg||'<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>',L=t.r_svg||'<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>',b=8,E=!1,x="block-slider-scrolling";function N(){var e=A(),t="";if(r&&!(e<2)){for(var n=0;n<e;n++)t+='<button data-index="'+n+'"></button>';r.innerHTML=t,r.addEventListener("click",k)}}function k(t){H();var n=1,i=e.scrollLeft;t.target.parentElement.className.indexOf("block-loop-dot")>-1?(n=t.target.dataset.index,i=0):n=t.currentTarget.className.indexOf(h)>-1?-1:1,P(i+=n*O())}function T(){!0===t.autoplay&&0!=c&&(c=!0,setTimeout(C,f))}function H(){c=!1}function C(){if(!E){var t=e.scrollLeft+(g?O():O(1));e.scrollLeft+e.offsetWidth==e.scrollWidth&&(p?(t=0,g&&(t=O())):H()),c&&P(t),S()}}function O(t){var n=e.offsetWidth,i=e.children[0].offsetWidth,o=t?t*(i+v):n+v;return g&&m<1&&(o=parseInt(m*(o+v/2)),0!=e.scrollLeft&&e.scrollLeft+e.offsetWidth!=e.scrollWidth||(o-=n*(1-m)/2)),o*(s?-1:1)}function A(){return Math.round(e.scrollWidth/e.offsetWidth)}function i(){i||(requestAnimationFrame((function(){N(),S(),i=!1})),i=!0)}function S(){for(var t=A(),n=e.children,i=e.scrollLeft,c=i+e.offsetWidth,f=e.scrollWidth,p=Math.round((f-i)/e.offsetWidth),v=0;v<n.length;v++){var g=n[v],m=g.offsetLeft,h=m+g.offsetWidth,y=n[v].getElementsByTagName("video")[0];if(c-4<m||i+4>h){var w=new RegExp("(\\s|^)slider-active(\\s|$)");n[v].className=n[v].className.replace(w,""),y&&y.pause()}else-1==n[v].className.indexOf("slider-active")&&(n[v].className+=" slider-active",y&&y.play())}if(u&&(l.style.display=l&&i*(s?-1:1)<b?"none":"",a&&f-i*(s?-1:1)<e.offsetWidth+b?a.style.display="none":a.style.display="",o)){var L=e.getElementsByClassName("post-thumbnail"),E=getComputedStyle(e);L[0]&&(o.style.setProperty("--height",L[0].offsetHeight+"px"),o.style.setProperty("--top",e.offsetTop+L[0].offsetTop+parseInt(L[0].offsetHeight/2)+"px")),E.getPropertyValue("--loop-rows")>1&&L[0]&&o.style.setProperty("--top","calc(50% + "+parseInt(e.offsetTop/2)+"px)")}if(d){var x=r.querySelector('[data-index="'+(t-p)*(s?-1:1)+'"]'),N=r.getElementsByTagName("button");for(v=0;v<N.length;v++)N[v].className="";x&&(x.className="active")}}function P(t){if(!e.classList.contains(x)){var n=e.scrollLeft;!function(e,t,n,i,o,r,l){var a=[.425,.005,0,1];a=BezierEasing(a[0],a[1],a[2],a[3]);const s=o=>{e[t]=n+(i-n)*o},u=Date.now(),d=()=>{var e=(Date.now()-u)/o;e>1?(s(1),l&&l()):(requestAnimationFrame(d),s(a(e)))};r&&r();d()}(e,"scrollLeft",n,t,1500,(function(){E=!0,e.classList.add(x)}),(function(){E=!1,e.classList.remove(x),T()}))}}e.className+=" block-loop-slider",u&&((o=document.createElement("div")).className="block-loop-nav",e.parentNode.appendChild(o),function(){A();var e="";e='<div class="'+h+'"><button>'+w+'</button></div><span></span><div class="'+y+'"><button>'+L+"</button></div>",o.innerHTML=e,l=o.getElementsByClassName(h)[0],a=o.getElementsByClassName(y)[0],l.addEventListener("click",k),a.addEventListener("click",k)}()),d&&((r=document.createElement("div")).className="block-loop-dot",e.parentNode.appendChild(r),N()),g&&P(O()),c&&T(),S(),e.addEventListener("ontouchstart"in window?"touchstart":"mouseenter",(function(){c=!1})),e.addEventListener("ontouchstart"in window?"touchend":"mouseleave",(function(){c=!0})),e.addEventListener("scroll",(function(){n||(requestAnimationFrame((function(){S(),n=!1})),n=!0)})),window.addEventListener("resize",i)},window.scroller=function(e,t){t=t||{};var n=(e=e).querySelector(".scroller")??e.nextElementSibling?.closest(".scroller"),i=0!=t.autoTrigger,o=t.autoTriggerUntil||1e3,r=0,l=t.loadingHtml||'<span class="spinner"></span><span class="screen-reader-text"></span>';if(n){var a=window,s=getComputedStyle(n.parentElement).getPropertyValue("overflow-y");"scroll"!=s&&"auto"!=s||(a=n.parentElement),a.addEventListener("scroll",(function(){n&&function(e,t,n){var i=e.offsetTop,o=i+e.clientHeight,r=t.pageYOffset?t.pageYOffset:t.scrollTop,l=r+(t.pageYOffset?t.innerHeight:t.clientHeight),a=n&&(i<r&&o>r||o>l&&i<l);return i>=r&&o<=l||a}(n,a)&&i&&r<o&&u()}),!1),n.addEventListener("click",u,!1)}function u(t){if(t&&t.preventDefault(),t&&t.stopPropagation(),!(n.className.indexOf("is-loading")>-1)){n.innerHTML=l,n.className+=" is-loading";var i=n.href,o=new XMLHttpRequest;o.responseType="json",o.onreadystatechange=function(){if(4==o.readyState&&200==o.status){n.className="",n.removeEventListener("click",u),n.remove();var t,i=document.createElement("div");for(i.innerHTML=o.response.content;t=i.firstChild;)e.appendChild(t);(n=e.querySelector(".scroller")??e.nextElementSibling?.closest(".scroller"))&&n.addEventListener("click",u,!1),document.dispatchEvent(new Event("refresh")),r++}},o.open("GET",i,!0),"undefined"!=typeof play&&void 0!==play.nonce&&o.setRequestHeader("X-WP-Nonce",play.nonce),o.send()}}},window.range=function(e){var t=e.getAttribute("value"),n=null===t?[]:t.split(","),i=+(e.min||0),o=+(e.max||100),r=document.createElement("span"),l=document.createElement("span"),a=e.cloneNode();e.classList.add("multirange"),e.classList.add("original"),a.classList.add("multirange"),a.classList.add("ghost"),r.classList.add("range-min"),l.classList.add("range-max"),e.value=n[0]||i+(o-i)/2,a.value=n[1]||i+(o-i)/2,e.parentNode.insertBefore(a,e.nextSibling),e.parentNode.insertBefore(r,e.previousSibling),e.parentNode.insertBefore(l,e.previousSibling);var s=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value");function u(t){var n=(e.valueLow-i)/(o-i)*100,s=(e.valueHigh-i)/(o-i)*100;a.style.setProperty("--low",n+"%"),a.style.setProperty("--high",s+"%"),r&&(r.innerHTML=e.valueLow,r.style.setProperty("--left",n)),l&&(l.innerHTML=e.valueHigh,l.style.setProperty("--left",s)),1!==t&&(clearTimeout(d),d=setTimeout((function(){var t=e.getAttribute("data-url"),n=e.getAttribute("name"),i=(e.getAttribute("type"),new RegExp(n+"__(\\d+)-(\\d+)[%2C]*[(\\d+)\\-(\\d+)]*"));t=t.replace(i,n+"__"+e.valueLow+"-"+e.valueHigh),"undefined"==typeof Pjax?location.href=t:document.dispatchEvent(new CustomEvent("reload",{detail:{url:t}}))}),1e3))}Object.defineProperty(e,"originalValue",s.get?s:{get:function(){return this.value},set:function(e){this.value=e}}),Object.defineProperties(e,{valueLow:{get:function(){return Math.min(this.originalValue,a.value)},set:function(e){this.originalValue=e,u()},enumerable:!0},valueHigh:{get:function(){return Math.max(this.originalValue,a.value)},set:function(e){a.value=e,u()},enumerable:!0}}),s.get&&Object.defineProperty(e,"value",{get:function(){return this.valueLow+","+this.valueHigh},set:function(e){var t=e.split(",");this.valueLow=t[0],this.valueHigh=t[1],u()},enumerable:!0}),"function"==typeof e.oninput&&(a.oninput=e.oninput.bind(e)),a.addEventListener("mousedown",(function(t){var n=i+(o-i)*t.offsetX/this.offsetWidth,r=(e.valueHigh+e.valueLow)/2;e.valueLow==a.value==n>r&&(e.value=a.value)})),e.addEventListener("input",u),a.addEventListener("input",u);var d=null;u(1)},on("click",".dropdown-toggle-filter",(function(e){e.preventDefault();var t=this.nextElementSibling;t&&(t.classList.toggle("show"),t.parentNode.querySelector(".dropdown-backdrop")||t.parentNode.insertAdjacentHTML("beforeend",'<div class="dropdown-backdrop"></div>'),on("click",".dropdown-backdrop",(function(e){t.classList.remove("show")})))})),window.addEventListener("call:plugin",(function(){plugin()})),window.addEventListener("pjax:complete",(function(){init()})),init()}();
  • loops-block/trunk/build/loop/block.json

    r3622994 r3725635  
    178178            "default": false
    179179        },
     180        "transient_cache":{
     181            "type"   : "boolean",
     182            "default": false
     183        },
    180184        "className"   : {
    181185            "type"   : "string",
  • loops-block/trunk/build/loop/index.js

    r3622994 r3725635  
    1 !function(e,o){const{createElement:t,useState:l}=e.element,{RichText:a,BlockControls:n,InnerBlocks:s,AlignmentToolbar:i,MediaUpload:r,InspectorControls:u,useBlockProps:b}=e.blockEditor,{TextControl:p,Button:c,SelectControl:d,RangeControl:m,ToggleControl:v,RadioControl:g,CheckboxControl:k,TextareaControl:f,FormTokenField:h,DatePicker:y,Autocomplete:C,Dropdown:A,Placeholder:x,PanelBody:T}=e.components,D=e.apiFetch,_=e.serverSideRender,N=e.blocks.registerBlockType,w=e.i18n.__;var L=t("svg",{width:16,height:20,viewBox:"0 0 16 16"},t("path",{d:"M5.68 5.792 7.345 7.75 5.681 9.708a2.75 2.75 0 1 1 0-3.916ZM8 6.978 6.416 5.113l-.014-.015a3.75 3.75 0 1 0 0 5.304l.014-.015L8 8.522l1.584 1.865.014.015a3.75 3.75 0 1 0 0-5.304l-.014.015zm.656.772 1.663-1.958a2.75 2.75 0 1 1 0 3.916z"}));N("block/loop",{title:w("Loops","loops-block"),description:w("An advanced block that allows displaying posts, taxonomies and users based on different query parameters and visual configurations.","loops-block"),icon:L,category:"common",edit:function(a){var n=a.attributes,s=b(),i=e.hooks.applyFilters("hook_orderby",[{label:"No order",value:"none"},{label:"ID",value:"ID"},{label:"Title",value:"title"},{label:"Author",value:"author"},{label:"Published date",value:"date"},{label:"Modified date",value:"modified"},{label:"By parent",value:"parent"},{label:"Random order",value:"rand"},{label:"Comment count",value:"comment_count"},{label:"Menu order",value:"menu_order"},{label:"Meta value",value:"meta_value"},{label:"Numeric meta value",value:"meta_value_num"},{label:"By include order",value:"post__in"}]);const[k,C]=l([]),[N,I]=l([]),[S,M]=l([]);return[t(u,{key:"inspector"},t(T,{title:w("General","loops-block"),className:"block-display",initialOpen:!0},t(p,{label:w("ID","loops-block"),value:n.id,onChange:function(e){a.setAttributes({id:e})}}),t(d,{label:w("Type","loops-block"),options:loopsblock.types,value:n.type,onChange:function(e){a.setAttributes({type:e})}}),"taxonomy"==n.type&&t(d,{label:w("Taxonomies","loops-block"),options:loopsblock.taxonomies,value:n.taxonomy,onChange:function(e){a.setAttributes({taxonomy:e})}}),t(d,{label:w("Template","loops-block"),options:loopsblock.templates,value:n.template,onChange:function(e){a.setAttributes({template:e})}}),"user"!==n.type&&"taxonomy"!==n.type&&t(d,{label:w("Order by","loops-block"),options:i,value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),"user"==n.type&&t(d,{label:w("Order by","loops-block"),options:[{label:"No order",value:"none"},{label:"ID",value:"ID"},{label:"Display Name",value:"display_name"},{label:"Name",value:"user_name"},{label:"Login",value:"user_login"},{label:"Nicename",value:"user_nicename"},{label:"Email",value:"user_email"},{label:"URL",value:"user_url"},{label:"Registered",value:"user_registered"},{label:"Post count",value:"post_count"},{label:"Include",value:"include"},{label:"Meta value",value:"meta_value"},{label:"Numeric meta value",value:"meta_value_num"}],value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),"taxonomy"==n.type&&t(d,{label:w("Order by","loops-block"),options:[{label:"No order",value:"none"},{label:"ID",value:"term_id"},{label:"Name",value:"name"},{label:"Count",value:"count"}],value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),t(d,{label:w("Order","loops-block"),options:[{label:"Descending",value:"DESC"},{label:"Ascending",value:"ASC"}],value:n.order,onChange:function(e){a.setAttributes({order:e})}}),t(v,{label:w("Debug","loops-block"),checked:n.debug,onChange:function(e){a.setAttributes({debug:e})}})),t(T,{title:w("Query","loops-block"),initialOpen:!1},t("div",{},t(h,{label:w("IDs in","loops-block"),value:n.ids,suggestions:k,onChange:function(e){a.setAttributes({ids:e})},saveTransform:function(e){return e.split(":")[0]},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;D({path:"/loop/ids"+o}).then((function(e){C(e)}))}}})),"user"!==n.type&&"taxonomy"!==n.type&&t("div",{},t(h,{label:w("Taxonomies (taxonomy:term:operator)","loops-block"),value:n.taxQuery,suggestions:N,onChange:function(e){a.setAttributes({taxQuery:e})},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;D({path:"/loop/terms"+o}).then((function(e){I(e)}))}}})),"taxonomy"!==n.type&&t("div",{},t(h,{label:w("Meta (key:value:compare:type)","loops-block"),value:n.metaQuery,onChange:function(e){a.setAttributes({metaQuery:e})}})),"taxonomy"!==n.type&&t(g,{label:w("Date","loops-block"),options:[{label:w("Anytime","loops-block"),value:"0"},{label:w("Specific","loops-block"),value:"1"},{label:w("Relative","loops-block"),value:"2"}],selected:n.date.type,onChange:function(e){var o=lodash.cloneDeep(n.date);o.type=e,a.setAttributes({date:o})}}),"1"==n.date.type&&t("div",{className:"components-panel__row components-loop-date"},t(A,{position:"bottom right",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("From","loops-block")),t(c,{isLink:!0},n.date.after))},renderContent:function(e){return t(y,{currentDate:n.date.after,onChange:function(e){var o=lodash.cloneDeep(n.date);o.after=moment(e).format("YYYY-MM-DD"),a.setAttributes({date:o})}})}}),t(A,{position:"bottom right",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("To","loops-block")),t(c,{isLink:!0},n.date.before))},renderContent:function(e){return t(y,{currentDate:n.date.before,onChange:function(e){var o=lodash.cloneDeep(n.date);o.before=moment(e).format("YYYY-MM-DD"),a.setAttributes({date:o})}})}})),"2"==n.date.type&&t("div",{className:"components-panel__row components-loop-date"},t(A,{position:"bottom right",contentClassName:"components-loop-date-popup",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("From","loops-block")),t(c,{isLink:!0},n.date.afterNum+" "+n.date.afterUnit))},renderContent:function(e){return t("div",{className:"components-loop-date-dialog"},t(p,{type:"number",value:n.date.afterNum,onChange:function(e){var o=lodash.cloneDeep(n.date);o.afterNum=e,a.setAttributes({date:o})}}),t(d,{options:[{label:"Days",value:"days ago"},{label:"Weeks",value:"weeks ago"},{label:"Months",value:"months ago"},{label:"Years",value:"years ago"}],value:n.date.afterUnit,onChange:function(e){var o=lodash.cloneDeep(n.date);o.afterUnit=e,a.setAttributes({date:o})}}),t("span",{},w("ago","loops-block")))}}),t(A,{position:"bottom right",contentClassName:"components-loop-date-popup",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("To","loops-block")),t(c,{isLink:!0},n.date.beforeNum+" "+n.date.beforeUnit))},renderContent:function(e){return t("div",{className:"components-loop-date-dialog"},t(p,{type:"number",value:n.date.beforeNum,onChange:function(e){var o=lodash.cloneDeep(n.date);o.beforeNum=e,a.setAttributes({date:o})}}),t(d,{options:[{label:"Days",value:"days ago"},{label:"Weeks",value:"weeks ago"},{label:"Months",value:"months ago"},{label:"Years",value:"years ago"}],value:n.date.beforeUnit,onChange:function(e){var o=lodash.cloneDeep(n.date);o.beforeUnit=e,a.setAttributes({date:o})}}),t("span",{},w("ago","loops-block")))}})),t(p,{label:w("Query arguments","loops-block"),value:n.query,rows:1,help:w("eg: post_type=any. See WP_Query, WP_User_Query and WP_Term_Query","loops-block"),onChange:function(e){a.setAttributes({query:e})}})),t(T,{title:w("Title & Link","loops-block"),className:"block-display",initialOpen:!1},t(p,{label:w("Title","loops-block"),value:n.title,onChange:function(e){a.setAttributes({title:e})}}),t(p,{label:w("Subtitle","loops-block"),value:n.subtitle,onChange:function(e){a.setAttributes({subtitle:e})}}),t(p,{label:w("Link Text","loops-block"),value:n.linkText,onChange:function(e){a.setAttributes({linkText:e})}}),t(p,{label:w("Link URL","loops-block"),value:n.link,placeholder:"http://",onChange:function(e){a.setAttributes({link:e})}})),t(T,{title:w("Display","loops-block"),className:"block-display",initialOpen:!1},t(d,{label:w("Display","loops-block"),options:[{label:"Grid",value:"grid"},{label:"List",value:"row"},{label:"Mixed",value:"mixed"}],value:n.display,onChange:function(e){a.setAttributes({display:e})}}),t(v,{label:w("Index style","loops-block"),checked:n.index,onChange:function(e){a.setAttributes({index:e})}}),"mixed"!==n.display&&t(m,{label:w("Columns","loops-block"),value:n.cols,min:-1,max:12,onChange:function(e){a.setAttributes({cols:e})}}),t(m,{label:w("Rows","loops-block"),value:n.rows,min:-1,max:12,onChange:function(e){a.setAttributes({rows:e})}}),t(m,{label:w("Gap","loops-block"),value:n.gap,min:-1,max:100,onChange:function(e){a.setAttributes({gap:e})}}),t(m,{label:w("Thumbnail ratio","loops-block"),value:n.ratio,min:0,max:3,step:.01,onChange:function(e){a.setAttributes({ratio:e})}}),t(d,{label:w("Thumbnail size","loops-block"),options:loopsblock.image_sizes,value:n.image,onChange:function(e){a.setAttributes({image:e})}}),t(m,{label:w("Post per page","loops-block"),value:n.pages,onChange:function(e){a.setAttributes({pages:e})}}),t(d,{label:w("Pager","loops-block"),options:[{label:"None",value:""},{label:"Pagination",value:"pagination"},{label:"Load More",value:"more"},{label:"Scroll",value:"scroll"}],value:n.pager,onChange:function(e){a.setAttributes({pager:e})}}),t(v,{label:w("Enable slider","loops-block"),checked:n.slider,onChange:function(e){a.setAttributes({slider:e})}}),n.slider&&t("div",{className:""},t(v,{label:w("Prev/Next arrows","loops-block"),checked:n.sliderArrows,onChange:function(e){a.setAttributes({sliderArrows:e})}}),t(v,{label:w("Show dot indicators","loops-block"),checked:n.sliderDots,onChange:function(e){a.setAttributes({sliderDots:e})}}),t(v,{label:w("Enable autoplay","loops-block"),checked:n.sliderAutoplay,onChange:function(e){a.setAttributes({sliderAutoplay:e})}}),t(v,{label:w("Loop slider","loops-block"),checked:n.sliderLoop,onChange:function(e){a.setAttributes({sliderLoop:e})}}),t("p")),t(v,{label:w("Show empty","loops-block"),checked:n.empty,onChange:function(e){a.setAttributes({empty:e})}}),n.empty&&t(f,{label:w("Empty content","loops-block"),value:n.emptyContent,onChange:function(e){a.setAttributes({emptyContent:e})}})),t(T,{title:w("Filter","loops-block"),className:"block-display",initialOpen:!1},t(d,{label:w("Style","loops-block"),options:[{label:"Dropdown",value:"dropdown"},{label:"List",value:"list"}],value:n.filterStyle,onChange:function(e){a.setAttributes({filterStyle:e})}}),t(v,{label:w("Show filter keys","loops-block"),checked:n.filterKeys,onChange:function(e){a.setAttributes({filterKeys:e})}}),n.filterKeys&&t(f,{label:w("Clear filters text","loops-block"),value:n.filterClearText,onChange:function(e){a.setAttributes({filterClearText:e})}}),t(h,{label:w("filter::value[name]","loops-block"),value:n.filter,suggestions:S,className:"components-form-token-filter",onChange:function(e){a.setAttributes({filter:e})},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;D({path:"/loop/filter"+o}).then((function(e){M(e)}))}},onFocus:function(e){var t=o(".components-form-token-filter .components-flex");t.sortable({items:"> div",update:function(e,l){var n=t.find("> div").map((function(){return o.trim(o(this).find("> span > span > span:last").text())})).get();a.setAttributes({filter:n})}})}}),t("p",{className:"components-base-control__help"},w("Enter 3 or more characters","loops-block"))),t(T,{title:w("AD","loops-block"),className:"block-display",initialOpen:!1},t(p,{label:w("Image","loops-block"),placeholder:w("Enter, upload, choose from Media Library","loops-block"),value:n.adImage,onChange:function(e){a.setAttributes({adImage:e})}}),t(r,{allowedTypes:"image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime",onSelect:function(e){return a.setAttributes({adImage:e.url})},render:function(e){return t("div",{style:{display:"inline-flex",margin:"-1.5rem 0 1rem 0"}},t(c,{icon:"upload",label:w("Upload","loops-block"),onClick:e.open}),t(c,{icon:"no-alt",label:w("Clear","loops-block"),onClick:function(){a.setAttributes({adImage:""})}}))}}),t(p,{label:w("Title","loops-block"),value:n.adTitle,onChange:function(e){a.setAttributes({adTitle:e})}}),t(p,{label:w("Subtitle","loops-block"),value:n.adSubtitle,onChange:function(e){a.setAttributes({adSubtitle:e})}}),t(p,{label:w("Sponsor","loops-block"),value:n.adSponsor,onChange:function(e){a.setAttributes({adSponsor:e})}}),t(p,{label:w("Link URL","loops-block"),value:n.adLink,placeholder:"http://",onChange:function(e){a.setAttributes({adLink:e})}}),t(p,{label:w("Order","loops-block"),value:n.adOrder,type:"number",onChange:function(e){a.setAttributes({adOrder:e})}}))),t("div",s,""===n.type?t(x,{icon:L,label:w("Loops","loops-block"),instructions:w("Display post taxonomy & user items in loop.","loops-block")},t(d,{label:w("Choose loop type","loops-block"),options:loopsblock.types,value:n.type,onChange:function(e){a.setAttributes({type:e})}})):t(_,{block:"block/loop",attributes:n}))]},save:function(){return null}})}(window.wp,jQuery);
     1!function(e,o){const{createElement:t,useState:l}=e.element,{RichText:a,BlockControls:n,InnerBlocks:s,AlignmentToolbar:i,MediaUpload:r,InspectorControls:u,useBlockProps:c}=e.blockEditor,{TextControl:b,Button:p,SelectControl:d,RangeControl:m,ToggleControl:v,RadioControl:g,CheckboxControl:k,TextareaControl:f,FormTokenField:h,DatePicker:y,Autocomplete:C,Dropdown:A,Placeholder:x,PanelBody:T}=e.components,_=e.apiFetch,D=e.serverSideRender,N=e.blocks.registerBlockType,w=e.i18n.__;var L=t("svg",{width:16,height:20,viewBox:"0 0 16 16"},t("path",{d:"M5.68 5.792 7.345 7.75 5.681 9.708a2.75 2.75 0 1 1 0-3.916ZM8 6.978 6.416 5.113l-.014-.015a3.75 3.75 0 1 0 0 5.304l.014-.015L8 8.522l1.584 1.865.014.015a3.75 3.75 0 1 0 0-5.304l-.014.015zm.656.772 1.663-1.958a2.75 2.75 0 1 1 0 3.916z"}));N("block/loop",{title:w("Loops","loops-block"),description:w("An advanced block that allows displaying posts, taxonomies and users based on different query parameters and visual configurations.","loops-block"),icon:L,category:"common",edit:function(a){var n=a.attributes,s=c(),i=e.hooks.applyFilters("hook_orderby",[{label:"No order",value:"none"},{label:"ID",value:"ID"},{label:"Title",value:"title"},{label:"Author",value:"author"},{label:"Published date",value:"date"},{label:"Modified date",value:"modified"},{label:"By parent",value:"parent"},{label:"Random order",value:"rand"},{label:"Comment count",value:"comment_count"},{label:"Menu order",value:"menu_order"},{label:"Meta value",value:"meta_value"},{label:"Numeric meta value",value:"meta_value_num"},{label:"By include order",value:"post__in"}]);const[k,C]=l([]),[N,I]=l([]),[S,M]=l([]);return[t(u,{key:"inspector"},t(T,{title:w("General","loops-block"),className:"block-display",initialOpen:!0},t(b,{label:w("ID","loops-block"),value:n.id,onChange:function(e){a.setAttributes({id:e})}}),t(d,{label:w("Type","loops-block"),options:loopsblock.types,value:n.type,onChange:function(e){a.setAttributes({type:e})}}),"taxonomy"==n.type&&t(d,{label:w("Taxonomies","loops-block"),options:loopsblock.taxonomies,value:n.taxonomy,onChange:function(e){a.setAttributes({taxonomy:e})}}),t(d,{label:w("Template","loops-block"),options:loopsblock.templates,value:n.template,onChange:function(e){a.setAttributes({template:e})}}),"user"!==n.type&&"taxonomy"!==n.type&&t(d,{label:w("Order by","loops-block"),options:i,value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),"user"==n.type&&t(d,{label:w("Order by","loops-block"),options:[{label:"No order",value:"none"},{label:"ID",value:"ID"},{label:"Display Name",value:"display_name"},{label:"Name",value:"user_name"},{label:"Login",value:"user_login"},{label:"Nicename",value:"user_nicename"},{label:"Email",value:"user_email"},{label:"URL",value:"user_url"},{label:"Registered",value:"user_registered"},{label:"Post count",value:"post_count"},{label:"Include",value:"include"},{label:"Meta value",value:"meta_value"},{label:"Numeric meta value",value:"meta_value_num"}],value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),"taxonomy"==n.type&&t(d,{label:w("Order by","loops-block"),options:[{label:"No order",value:"none"},{label:"ID",value:"term_id"},{label:"Name",value:"name"},{label:"Count",value:"count"}],value:n.orderby,onChange:function(e){a.setAttributes({orderby:e})}}),t(d,{label:w("Order","loops-block"),options:[{label:"Descending",value:"DESC"},{label:"Ascending",value:"ASC"}],value:n.order,onChange:function(e){a.setAttributes({order:e})}}),t(v,{label:w("Debug","loops-block"),checked:n.debug,onChange:function(e){a.setAttributes({debug:e})}}),t(v,{label:w("Enable transient cache","loops-block"),checked:n.transient_cache,onChange:function(e){a.setAttributes({transient_cache:e})}})),t(T,{title:w("Query","loops-block"),initialOpen:!1},t("div",{},t(h,{label:w("IDs in","loops-block"),value:n.ids,suggestions:k,onChange:function(e){a.setAttributes({ids:e})},saveTransform:function(e){return e.split(":")[0]},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;_({path:"/loop/ids"+o}).then((function(e){C(e)}))}}})),"user"!==n.type&&"taxonomy"!==n.type&&t("div",{},t(h,{label:w("Taxonomies (taxonomy:term:operator)","loops-block"),value:n.taxQuery,suggestions:N,onChange:function(e){a.setAttributes({taxQuery:e})},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;_({path:"/loop/terms"+o}).then((function(e){I(e)}))}}})),"taxonomy"!==n.type&&t("div",{},t(h,{label:w("Meta (key:value:compare:type)","loops-block"),value:n.metaQuery,onChange:function(e){a.setAttributes({metaQuery:e})}})),"taxonomy"!==n.type&&t(g,{label:w("Date","loops-block"),options:[{label:w("Anytime","loops-block"),value:"0"},{label:w("Specific","loops-block"),value:"1"},{label:w("Relative","loops-block"),value:"2"}],selected:n.date.type,onChange:function(e){var o=lodash.cloneDeep(n.date);o.type=e,a.setAttributes({date:o})}}),"1"==n.date.type&&t("div",{className:"components-panel__row components-loop-date"},t(A,{position:"bottom right",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("From","loops-block")),t(p,{isLink:!0},n.date.after))},renderContent:function(e){return t(y,{currentDate:n.date.after,onChange:function(e){var o=lodash.cloneDeep(n.date);o.after=moment(e).format("YYYY-MM-DD"),a.setAttributes({date:o})}})}}),t(A,{position:"bottom right",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("To","loops-block")),t(p,{isLink:!0},n.date.before))},renderContent:function(e){return t(y,{currentDate:n.date.before,onChange:function(e){var o=lodash.cloneDeep(n.date);o.before=moment(e).format("YYYY-MM-DD"),a.setAttributes({date:o})}})}})),"2"==n.date.type&&t("div",{className:"components-panel__row components-loop-date"},t(A,{position:"bottom right",contentClassName:"components-loop-date-popup",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("From","loops-block")),t(p,{isLink:!0},n.date.afterNum+" "+n.date.afterUnit))},renderContent:function(e){return t("div",{className:"components-loop-date-dialog"},t(b,{type:"number",value:n.date.afterNum,onChange:function(e){var o=lodash.cloneDeep(n.date);o.afterNum=e,a.setAttributes({date:o})}}),t(d,{options:[{label:"Days",value:"days ago"},{label:"Weeks",value:"weeks ago"},{label:"Months",value:"months ago"},{label:"Years",value:"years ago"}],value:n.date.afterUnit,onChange:function(e){var o=lodash.cloneDeep(n.date);o.afterUnit=e,a.setAttributes({date:o})}}),t("span",{},w("ago","loops-block")))}}),t(A,{position:"bottom right",contentClassName:"components-loop-date-popup",renderToggle:function(e){e.isOpen;var o=e.onToggle;return t("div",{onClick:o},t("label",{},w("To","loops-block")),t(p,{isLink:!0},n.date.beforeNum+" "+n.date.beforeUnit))},renderContent:function(e){return t("div",{className:"components-loop-date-dialog"},t(b,{type:"number",value:n.date.beforeNum,onChange:function(e){var o=lodash.cloneDeep(n.date);o.beforeNum=e,a.setAttributes({date:o})}}),t(d,{options:[{label:"Days",value:"days ago"},{label:"Weeks",value:"weeks ago"},{label:"Months",value:"months ago"},{label:"Years",value:"years ago"}],value:n.date.beforeUnit,onChange:function(e){var o=lodash.cloneDeep(n.date);o.beforeUnit=e,a.setAttributes({date:o})}}),t("span",{},w("ago","loops-block")))}})),t(b,{label:w("Query arguments","loops-block"),value:n.query,rows:1,help:w("eg: post_type=any. See WP_Query, WP_User_Query and WP_Term_Query","loops-block"),onChange:function(e){a.setAttributes({query:e})}})),t(T,{title:w("Title & Link","loops-block"),className:"block-display",initialOpen:!1},t(b,{label:w("Title","loops-block"),value:n.title,onChange:function(e){a.setAttributes({title:e})}}),t(b,{label:w("Subtitle","loops-block"),value:n.subtitle,onChange:function(e){a.setAttributes({subtitle:e})}}),t(b,{label:w("Link Text","loops-block"),value:n.linkText,onChange:function(e){a.setAttributes({linkText:e})}}),t(b,{label:w("Link URL","loops-block"),value:n.link,placeholder:"http://",onChange:function(e){a.setAttributes({link:e})}})),t(T,{title:w("Display","loops-block"),className:"block-display",initialOpen:!1},t(d,{label:w("Display","loops-block"),options:[{label:"Grid",value:"grid"},{label:"List",value:"row"},{label:"Mixed",value:"mixed"}],value:n.display,onChange:function(e){a.setAttributes({display:e})}}),t(v,{label:w("Index style","loops-block"),checked:n.index,onChange:function(e){a.setAttributes({index:e})}}),"mixed"!==n.display&&t(m,{label:w("Columns","loops-block"),value:n.cols,min:-1,max:12,onChange:function(e){a.setAttributes({cols:e})}}),t(m,{label:w("Rows","loops-block"),value:n.rows,min:-1,max:12,onChange:function(e){a.setAttributes({rows:e})}}),t(m,{label:w("Gap","loops-block"),value:n.gap,min:-1,max:100,onChange:function(e){a.setAttributes({gap:e})}}),t(m,{label:w("Thumbnail ratio","loops-block"),value:n.ratio,min:0,max:3,step:.01,onChange:function(e){a.setAttributes({ratio:e})}}),t(d,{label:w("Thumbnail size","loops-block"),options:loopsblock.image_sizes,value:n.image,onChange:function(e){a.setAttributes({image:e})}}),t(m,{label:w("Post per page","loops-block"),value:n.pages,onChange:function(e){a.setAttributes({pages:e})}}),t(d,{label:w("Pager","loops-block"),options:[{label:"None",value:""},{label:"Pagination",value:"pagination"},{label:"Load More",value:"more"},{label:"Scroll",value:"scroll"}],value:n.pager,onChange:function(e){a.setAttributes({pager:e})}}),t(v,{label:w("Enable slider","loops-block"),checked:n.slider,onChange:function(e){a.setAttributes({slider:e})}}),n.slider&&t("div",{className:""},t(v,{label:w("Prev/Next arrows","loops-block"),checked:n.sliderArrows,onChange:function(e){a.setAttributes({sliderArrows:e})}}),t(v,{label:w("Show dot indicators","loops-block"),checked:n.sliderDots,onChange:function(e){a.setAttributes({sliderDots:e})}}),t(v,{label:w("Enable autoplay","loops-block"),checked:n.sliderAutoplay,onChange:function(e){a.setAttributes({sliderAutoplay:e})}}),t(v,{label:w("Loop slider","loops-block"),checked:n.sliderLoop,onChange:function(e){a.setAttributes({sliderLoop:e})}}),t("p")),t(v,{label:w("Show empty","loops-block"),checked:n.empty,onChange:function(e){a.setAttributes({empty:e})}}),n.empty&&t(f,{label:w("Empty content","loops-block"),value:n.emptyContent,onChange:function(e){a.setAttributes({emptyContent:e})}})),t(T,{title:w("Filter","loops-block"),className:"block-display",initialOpen:!1},t(d,{label:w("Style","loops-block"),options:[{label:"Dropdown",value:"dropdown"},{label:"List",value:"list"}],value:n.filterStyle,onChange:function(e){a.setAttributes({filterStyle:e})}}),t(v,{label:w("Show filter keys","loops-block"),checked:n.filterKeys,onChange:function(e){a.setAttributes({filterKeys:e})}}),n.filterKeys&&t(f,{label:w("Clear filters text","loops-block"),value:n.filterClearText,onChange:function(e){a.setAttributes({filterClearText:e})}}),t(h,{label:w("filter::value[name]","loops-block"),value:n.filter,suggestions:S,className:"components-form-token-filter",onChange:function(e){a.setAttributes({filter:e})},onInputChange:function(e){if(!(e.length<2||/^https?:/.test(e))){var o="?search="+encodeURIComponent(e)+"&type="+n.type;_({path:"/loop/filter"+o}).then((function(e){M(e)}))}},onFocus:function(e){var t=o(".components-form-token-filter .components-flex");t.sortable({items:"> div",update:function(e,l){var n=t.find("> div").map((function(){return o.trim(o(this).find("> span > span > span:last").text())})).get();a.setAttributes({filter:n})}})}}),t("p",{className:"components-base-control__help"},w("Enter 3 or more characters","loops-block"))),t(T,{title:w("AD","loops-block"),className:"block-display",initialOpen:!1},t(b,{label:w("Image","loops-block"),placeholder:w("Enter, upload, choose from Media Library","loops-block"),value:n.adImage,onChange:function(e){a.setAttributes({adImage:e})}}),t(r,{allowedTypes:"image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime",onSelect:function(e){return a.setAttributes({adImage:e.url})},render:function(e){return t("div",{style:{display:"inline-flex",margin:"-1.5rem 0 1rem 0"}},t(p,{icon:"upload",label:w("Upload","loops-block"),onClick:e.open}),t(p,{icon:"no-alt",label:w("Clear","loops-block"),onClick:function(){a.setAttributes({adImage:""})}}))}}),t(b,{label:w("Title","loops-block"),value:n.adTitle,onChange:function(e){a.setAttributes({adTitle:e})}}),t(b,{label:w("Subtitle","loops-block"),value:n.adSubtitle,onChange:function(e){a.setAttributes({adSubtitle:e})}}),t(b,{label:w("Sponsor","loops-block"),value:n.adSponsor,onChange:function(e){a.setAttributes({adSponsor:e})}}),t(b,{label:w("Link URL","loops-block"),value:n.adLink,placeholder:"http://",onChange:function(e){a.setAttributes({adLink:e})}}),t(b,{label:w("Order","loops-block"),value:n.adOrder,type:"number",onChange:function(e){a.setAttributes({adOrder:e})}}))),t("div",s,""===n.type?t(x,{icon:L,label:w("Loops","loops-block"),instructions:w("Display post taxonomy & user items in loop.","loops-block")},t(d,{label:w("Choose loop type","loops-block"),options:loopsblock.types,value:n.type,onChange:function(e){a.setAttributes({type:e})}})):t(D,{block:"block/loop",attributes:n}))]},save:function(){return null}})}(window.wp,jQuery);
  • loops-block/trunk/build/style.css

    r3622994 r3725635  
    828828.block-loop-row .entry-description,
    829829.block-loop-row .entry-info,
    830 .is-series .entry-description,
    831 .is-series .entry-info{
     830.is-series .block-loop-item .entry-description,
     831.is-series .block-loop-item .entry-info{
    832832  margin-bottom: 0;
    833833}
    834834.block-loop-row .entry-info .play-duration,
    835 .is-series .entry-info .play-duration{
     835.is-series .block-loop-item .entry-info .play-duration{
    836836  padding: 0;
    837837}
  • loops-block/trunk/build/style.min.css

    r3622994 r3725635  
    1 :root{--loop-cols:5;--loop-xs-cols:2;--loop-rows:1;--loop-columns:max( var(--loop-cols) - 4, var(--loop-xs-cols) );--loop-grid-gap:1.5rem;--loop-row-gap:1rem;--loop-max-width:100%;--loop-min-width:0;--loop-line:2;--loop-line-height:1.3;--loop-ratio:1;--loop-radius:6px;--loop-center-width:70%;--loop-font-size:0.9375rem}.is-loop-icon{display:inline-flex;align-items:center;grid-gap:.25em}.is-loop-icon:after,.is-loop-icon:before{content:'';display:block;width:1em;height:1em;border:.125em solid currentColor;transform:rotate(45deg);border-radius:100%;order:-1}.is-loop-icon:before{border-top-right-radius:0}.is-loop-icon:after{border-bottom-left-radius:0}.wp-block-loop{position:relative}.block-loop-items{margin-bottom:1.5rem;list-style:none;display:grid;grid-gap:var(--loop-grid-gap);--loop--cols:calc((var(--loop-max-width) - (var(--loop-columns) - 1) * var(--loop-grid-gap)) / var(--loop-columns));grid-template-columns:repeat(auto-fill,minmax(var(--loop--cols),1fr))}.block-loop-slider,[data-plugin=slider]{display:grid;overflow-x:auto;border-radius:var(--loop-radius);scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;overscroll-behavior-x:none;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;grid-auto-flow:column;--loop--cols:calc((var(--loop-max-width) - (var(--loop-columns) - 1) * var(--loop-grid-gap)) / var(--loop-columns));grid-auto-columns:var(--loop--cols);grid-template-rows:repeat(var(--loop-rows),max-content);grid-template-columns:inherit!important;box-sizing:border-box}.block-loop-slider::-webkit-scrollbar,.block-loop-snaps .block-loop-items::-webkit-scrollbar{display:none}.block-loop-snaps .block-loop-items{position:fixed;z-index:2;left:0;right:0;top:var(--navbar-height);bottom:var(--mobile-menu-height);display:flex;flex-direction:column;align-items:center;overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;overscroll-behavior-y:none;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;border-radius:var(--loop-radius);margin-bottom:0}.block-slider-scrolling{-ms-scroll-snap-type:none;scroll-snap-type:none;scroll-behavior:inherit}.block-slider-scrolling video{display:none!important}.block-loop-slider .entry-content>*,[data-plugin=slider] .entry-content>*{width:100%!important;max-width:100%!important}.block-loop-slider>*,.block-loop-snaps>*{scroll-snap-align:start}.column-sm-gap{--column-gap:var(--loop-grid-gap, 1rem)}@media (max-width:1000px){.is-stacked-tablet{flex-wrap:wrap!important}.is-stacked-tablet>.wp-block-column{flex-basis:100%!important}}@media (min-width:420px){.wp-block-loop{--loop-columns:max( min(var(--loop-cols), 5) - 3, 2 )}}@media (min-width:640px){.wp-block-loop{--loop-columns:max( var(--loop-cols) - 2, 2 )}}@media (min-width:960px){.wp-block-loop{--loop-columns:max( var(--loop-cols) - 1, 3 )}}@media (min-width:1260px){.wp-block-loop{--loop-columns:var(--loop-cols)}}.grid-1{--loop-columns:1!important}.grid-2{--loop-columns:2!important}.grid-3{--loop-columns:3!important}@media (max-width:419px){.grid-xs-1{--loop-columns:1!important}.grid-xs-2{--loop-columns:2!important}.grid-xs-3{--loop-columns:3!important}}@media (max-width:781px){.grid-sm-1{--loop-columns:1!important}.grid-sm-2{--loop-columns:2!important}.grid-sm-3{--loop-columns:3!important}}@media (max-width:991px){.grid-md-1{--loop-columns:1!important}.grid-md-2{--loop-columns:2!important}.grid-md-3{--loop-columns:3!important}}@media (min-width:1400px){.grid-xl-1{--loop-columns:1!important}.grid-xl-2{--loop-columns:2!important}.grid-xl-3{--loop-columns:3!important}}.block-loop-title{display:flex;flex-wrap:wrap;align-items:center}.block-loop-heading{width:1%;flex:1}.block-loop-more{font-size:14px;font-weight:400}.block-loop-subtitle{color:var(--text-secondary-color,#888);line-height:1.1;text-transform:none;display:block;width:100%}.block-loop-nav{opacity:0;transition:opacity .2s;position:absolute;display:flex;align-items:center;z-index:5;height:0;width:calc(100% + 2.5rem);left:-1.25rem;top:var(--top,50%)}.alignfull>.block-loop-nav{width:calc(100% - 2.5rem);left:1.25rem}.block-loop-nav span{flex:1}.wp-block-loop:hover .block-loop-nav{opacity:1}.block-loop-nav button{width:2.5rem;height:2.5rem;padding:0;border-radius:100%;display:inline-flex;justify-content:center;align-items:center;border:none;box-shadow:0 2px 4px rgba(0,0,0,.1)}.block-loop-nav button svg{pointer-events:none;transform:rotate(var(--transform-rotate,0))}.block-loop-dot-overlay .block-loop-dot{position:absolute;z-index:5;left:50%;bottom:1rem;transform:translate(-50%,0);color:#fff}.block-loop-dot-left .block-loop-dot{margin:-4rem auto 0 auto;text-align:left;max-width:var(--content-width);width:calc(100% - var(--x-gap) * 2)}.block-loop-dot{text-align:center}.block-loop-dot button{width:1.5rem;height:1.5rem;padding:0;border-radius:2rem;border:none;background-color:transparent;color:inherit}.block-loop-dot button:after{content:"";display:inline-block;width:6px;height:6px;border-radius:6px;margin:0 auto;background-color:currentColor;opacity:.5}.block-loop-dot button.active:after{opacity:1}.block-loop-center{--loop-columns:1;--loop-max-width:var(--loop-center-width)!important}.block-loop-center .block-loop-item{scroll-snap-align:center}.block-loop-center .block-loop-nav>div{height:var(--height);width:calc(50% - var(--loop-center-width)/ 2);display:flex;align-items:center}.block-loop-center .block-loop-nav .slider-right-btn{justify-content:flex-end}.scroller{width:15rem;font-size:12px!important;display:inline-flex;justify-content:center;margin:0 auto;text-decoration:none}.scroller.is-loading{cursor:wait;pointer-events:none}.block-loop-empty,.wp-block-loop .pagination,.wp-block-loop .scroller{grid-column:1/-1;order:10000}.pagination .nav-links{display:flex;align-items:center;justify-content:center}.pagination .page-numbers{padding:.25em;text-decoration:none}.wp-block-loop .navigation .next,.wp-block-loop .navigation .prev{line-height:0}.wp-block-loop .navigation .nav-next-text,.wp-block-loop .navigation .nav-prev-text,.wp-block-loop .navigation .next:before,.wp-block-loop .navigation .prev:before{display:none}.block-loop-item{position:relative;padding:0;max-width:100%;border-radius:var(--loop-radius);display:flex;flex-direction:column;flex-wrap:wrap;scroll-snap-align:start;order:10;font-size:var(--loop-font-size)}.block-loop-item:nth-child(1){order:0}.block-loop-item:nth-child(2){order:1}.block-loop-item:nth-child(3){order:2}.block-loop-item:nth-child(4){order:3}.block-loop-item:nth-child(5){order:4}.block-loop-item:nth-child(6){order:5}.block-loop-item:nth-child(7){order:6}.block-loop-item:nth-child(8){order:7}.block-loop-item:nth-child(9){order:8}.block-loop-item .entry-content,.block-loop-item .entry-footer,.block-loop-item .entry-header,.block-loop-item .post-thumbnail{width:100%;box-sizing:border-box;padding-left:0;padding-right:0}.block-loop-item .entry-header{margin-bottom:1rem}.block-loop-item .entry-footer{margin-bottom:1rem}.block-loop-item .entry-header{padding:var(--loop-header-gap,.5rem) 0;margin:0;flex:1;display:flex;align-items:flex-start;grid-gap:var(--loop-header-gap,.5rem)}.block-loop-item .entry-title{margin:0;font-weight:500;letter-spacing:0}.block-loop-item .entry-subtitle{color:var(--text-secondary-color,#888)}.block-loop-item a{text-decoration:none}.block-loop-item .entry-meta{display:flex;flex-wrap:wrap;grid-gap:0;margin:0;color:var(--text-secondary-color,#888)}.block-loop-item .byline .author,.block-loop-item .entry-artist,.block-loop-item .entry-excerpt,.block-loop-item .entry-title,.wp-block-loop-user .entry-title a{display:block;display:-webkit-box;-webkit-box-orient:vertical;text-overflow:ellipsis;white-space:normal;-webkit-line-clamp:var(--loop-line);line-height:var(--loop-line-height);font-size:inherit;overflow:hidden;padding-bottom:.1em;word-break:break-word;word-wrap:break-word}.block-loop-item .entry-excerpt{--loop-line:2}.wp-block-loop-user .entry-title{display:flex;overflow:visible}.block-loop-item .byline .author,.wp-block-loop-user .entry-title a{--loop-line:1}.block-loop-item .entry-meta>span{margin:0}.block-loop-item .wp-video,.block-loop-item .wp-video video{width:100%!important;height:auto;border-radius:inherit}.block-loop-item .attachment,.block-loop-item.attachment{float:none;width:100%}.block-loop-item.attachment audio~p{display:none}.block-loop-item .post-thumbnail br,.block-loop-item .post-thumbnail p{display:none}.block-loop-item .post-thumbnail{width:100%;position:relative;margin:0;padding:0;border-radius:inherit;background-color:rgba(110,120,130,.2)}.block-loop-item .btn-follow{padding:.25em .75em;font-size:12px;vertical-align:text-bottom;margin:.25rem 0}.block-loop-item .post-thumbnail a{border-radius:inherit}.block-loop-item .post-thumbnail .avatar,.block-loop-item .post-thumbnail img,.block-loop-item .post-thumbnail video{border-radius:inherit;position:absolute;width:100%;height:100%;object-fit:cover;display:inline-flex;justify-content:center;align-items:center}.block-loop-item .post-thumbnail:after{padding-top:calc(100% / var(--loop-ratio));min-height:auto;content:"";width:100%;display:block}.block-loop-item .entry-action{opacity:0;pointer-events:none;color:#fff;background-color:rgba(0,0,0,.2);position:absolute;z-index:3;left:50%;top:50%;width:100%;height:100%;padding:0 5%;border-radius:inherit;transform:translate(-50%,-50%);transition:opacity .3s;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;justify-content:space-around;box-sizing:border-box}.block-loop-item .entry-action .count{display:none}.block-loop-item .entry-action.show{z-index:10}.block-loop-item .entry-action button,.block-loop-item .entry-action button:hover{flex-shrink:0}.entry-action-link{position:absolute;width:100%;height:100%}.block-loop-item-link{padding:.75rem 1rem;background-color:var(--btn-background,rgba(150,155,160,.2));border-radius:var(--btn-radius,.5rem)}.block-loop-item-link.active,.block-loop-item-link:hover{background-color:var(--btn-background-hover,rgba(150,155,160,.3))}.block-loop-item.active .entry-action,.block-loop-item:active .entry-action,.block-loop-item:hover .entry-action,.block-loop-item:hover .entry-header-inner~.btn-more{opacity:1;pointer-events:initial}.block-loop-item .count,.comment-toolbar .count,.entry-meta .count{color:var(--text-secondary-color,#888);padding-inline-start:.25rem;-webkit-padding-start:.25rem;font-size:.85rem;font-weight:400}.block-loop-row .play-count{padding:0 .5rem}.block-loop-item .entry-avatar{width:36px;flex-shrink:0}.block-loop-item .entry-footer{display:none;margin:0}.block-loop-item .entry-description{font-size:.875rem}.block-loop-item .entry-description p{margin-bottom:0}.block-loop-item .waveform{width:100%}.block-loop-index.block-loop-row .waveform:before{content:"";display:inline-block;min-width:1rem}.wp-block-loop .btn-play{font-size:1.125rem}.block-loop-row .btn-play{font-size:.875rem}.wp-block-loop-user .post-thumbnail{width:80%;margin:10% 10% 0 10%;border-radius:50%}.wp-block-loop-user .entry-header{text-align:center;flex-direction:column;align-items:center;grid-gap:0}.wp-block-loop-user .post-thumbnail{--loop-ratio:1;border-radius:50%!important}.wp-block-loop-user.block-loop-row{--loop-grid-gap:0.75rem}.wp-block-loop-user.block-loop-row .block-loop-item{align-items:center}.wp-block-loop-user.block-loop-row .post-thumbnail{margin:0;min-width:0;width:3rem}.wp-block-loop-user.block-loop-row .entry-header{align-items:center;text-align:inherit;display:flex;flex-direction:row;gap:.5rem}.wp-block-loop-user .entry-title{font-size:.8125rem;font-weight:600;align-items:center;justify-content:center;flex:1}.wp-block-loop-user.block-loop-row .entry-title{justify-content:flex-start}.wp-block-loop-user .user-followers{font-weight:400;font-size:.85em;color:var(--text-secondary-color);width:100%}.block-loop-row{--loop-columns:1}.hide-more-actions .entry-footer>:not(.btn-more){display:none}.block-loop-row .block-loop-item{display:flex;grid-gap:var(--loop-row-gap);flex-direction:row;align-items:flex-start}.block-loop-row .entry-header{flex:1;display:flex;flex-wrap:wrap;padding:0;align-items:center;align-self:stretch;grid-gap:0}.block-loop-row .entry-avatar{display:none}.block-loop-row .post-thumbnail{width:6rem;min-width:var(--loop-min-width)}.block-loop-mixed .block-loop-item{display:flex;grid-gap:var(--loop-row-gap);flex-direction:row;--loop-header-gap:0;align-items:center}.block-loop-mixed .block-loop-item:first-child{grid-column:span calc(var(--loop-columns)/2);grid-row:span var(--loop-rows,4);align-items:stretch}.block-loop-mixed .block-loop-item:not(:first-child){grid-column:span calc(var(--loop-columns)/2)}.block-loop-mixed .block-loop-item:not(:first-child) .post-thumbnail{width:33%}@media (max-width:576px){.block-loop-mixed .block-loop-items{--loop-columns:1}}.block-loop-xs{--loop-line:1}.block-loop-xs .btn-play{font-size:.75rem}.block-loop-xs .post-thumbnail{width:3rem;border-radius:5px;min-width:auto}.block-loop-sm .post-thumbnail{width:4rem;border-radius:7px;min-width:auto}.block-loop-lg .post-thumbnail{width:10rem;min-width:auto}.block-loop-autotype .block-loop-items{--loop-columns:1}.has-loop-posts .block-loop-items{grid-gap:0;--loop-columns:1}.has-loop-posts .block-loop-item{padding:.5rem .5rem}.has-loop-posts .entry-header{flex-wrap:nowrap;padding:0}.has-loop-posts .post-thumbnail{border-radius:2px;width:3rem;flex-shrink:0}.has-loop-posts.block-loop-index .icon-play{display:none;padding:.5rem;position:absolute;top:50%;transform:translateY(-50%);line-height:0}.has-loop-posts.block-loop-index .block-loop-item.active:before,.has-loop-posts.block-loop-index .block-loop-item:hover:before{color:transparent}.has-loop-posts.block-loop-index .block-loop-item.active .icon-play,.has-loop-posts.block-loop-index .block-loop-item:hover .icon-play{display:block}.has-loop-posts .block-loop-item:hover{background-color:var(--tracks-item-odd-color,rgba(150,155,160,.1))}.has-loop-posts .block-loop-item.active{background-color:var(--tracks-item-hover-color,rgba(150,155,160,.2))}.has-loop-posts .icon-plus{display:none}.is-album .has-loop-posts .entry-meta a,.is-album .has-loop-posts .entry-title a{pointer-events:none}.has-loop-posts .entry-meta{justify-content:flex-start!important}.is-album .has-loop-posts .post-thumbnail{display:none}.is-series .has-loop-posts .block-loop-items{margin:0 -1rem}.is-series .has-loop-posts .block-loop-item{padding:.75rem 1rem;border:none!important}.is-series .has-loop-posts .block-loop-item .entry-header{padding-bottom:1rem;border-bottom:1px solid var(--color-border)}.is-series .has-loop-posts .block-loop-item.active .entry-header,.is-series .has-loop-posts .block-loop-item:hover .entry-header{border-color:transparent}.is-series .has-loop-posts .btn-play{border:1px solid var(--color-border);background-clip:padding-box}.is-series .has-loop-posts .block-loop-item>.btn-play{align-self:flex-start}.block-loop-row .entry-description,.block-loop-row .entry-info,.is-series .entry-description,.is-series .entry-info{margin-bottom:0}.block-loop-row .entry-info .play-duration,.is-series .entry-info .play-duration{padding:0}.block-loop-inline .entry-header{grid-gap:1.5rem}.block-loop-inline>button.btn-play{transform:scale(1)}.block-loop-inline .btn-play-waveform{display:none}.block-loop-inline .waveform{flex:1}.entry-header-inner{flex:1;max-width:100%}.entry-header-inner~.btn-more{margin:-.375rem -.5rem;opacity:0}.entry-header-inner .byline,.entry-header-inner .entry-artist{width:100%;justify-content:inherit}.entry-header-inner .byline{display:flex;align-items:center}.entry-meta-date{font-size:.75rem}.entry-header-inner .play-count+.entry-meta-date:before{display:inline-block;text-align:center;content:'\00B7';color:var(--text-secondary-color);width:1rem;font-weight:700}.block-loop-item .add_to_cart_inline,.block-loop-item .entry-header-inner .btn-purchase{margin:4px 0}.block-loop-item .add_to_cart_inline .btn-purchase,.block-loop-item form{margin:0!important}.block-loop-xs .add_to_cart_inline,.block-loop-xs .btn-purchase,.has-loop-posts .add_to_cart_inline,.has-loop-posts .btn-purchase{display:none}.block-loop-item .added_to_cart,.block-loop-item .btn-purchase,.plyr-playlist .btn-purchase{font-size:12px}.block-loop-item .entry-action .btn-more{position:absolute;padding:.75em;bottom:0;right:0}.block-loop-row .entry-action{justify-content:center}.block-loop-row .post-thumbnail .entry-action .btn-like,.block-loop-row .post-thumbnail .entry-action .btn-more{display:none}.block-loop-row .entry-footer{display:flex;align-items:center;padding-left:0;padding-right:0;width:auto}.block-loop-row .count,.block-loop-row .play-duration{font-size:.875em}.block-loop-row .play-duration{padding:0 .5rem}.play-count{white-space:nowrap;display:inline-flex;align-items:center;white-space:nowrap}.play-count:before{display:inline-block;width:0;height:0;content:"";border-left:.5em solid;border-top:.3em solid transparent;border-bottom:.3em solid transparent;opacity:.5}.btn-play+.play-count:before{display:none}.entry-badge .play-duration{background-color:#000;color:#fff;font-size:11px;font-weight:500;border-radius:4px;padding:1px 4px;position:absolute;right:.5rem;bottom:.5rem}.block-loop-index{counter-reset:li}.block-loop-index:not(.block-loop-row) .block-loop-item .entry-header:before{content:counter(li);counter-increment:li;font-weight:400;-ms-flex-negative:0;flex-shrink:0;opacity:.75;min-width:1rem}.block-loop-index.block-loop-row .block-loop-item:before{content:counter(li);counter-increment:li;min-width:1.5rem;font-weight:400;-ms-flex-negative:0;flex-shrink:0;opacity:.5;text-align:center;font-size:.9em;white-space:nowrap;align-self:center}.block-loop-overlay .entry-header{position:absolute;bottom:0;left:0;width:100%!important;padding:.75rem 1rem!important;box-sizing:border-box;color:#fff;background:linear-gradient(180deg,transparent,rgba(0,0,0,.85));border-radius:inherit;border-top-right-radius:0;border-top-left-radius:0;opacity:0;pointer-events:none}.block-loop-overlay .entry-header .entry-title{color:inherit;font-weight:700}.block-loop-overlay .entry-header .entry-meta,.block-loop-overlay .entry-header .entry-subtitle{color:rgba(255,255,255,.75)}.block-loop-overlay .entry-header a:hover{color:inherit}.block-loop-overlay .block-loop-item:hover .entry-header,.block-loop-overlay.block-loop-show-header .entry-header{opacity:1;pointer-events:initial;z-index:2}.block-loop-overlay-center .entry-header{top:0;opacity:1;font-weight:700;font-size:1rem;text-align:center;display:flex!important;align-items:center;justify-content:center}.block-loop-overlay-center .entry-meta{justify-content:center}.block-loop-ad .entry-meta{font-size:.75rem}.block-loop-ad.block-loop-item .post-thumbnail{background-color:var(--color-primary)}.block-loop-overlay .block-loop-ad .entry-header{background:0 0;bottom:auto}.block-loop-hero{--text-secondary-color:rgba(255,255,255,0.95);--button-radius:3rem;--loop-hero-min-height:15rem}.block-loop-hero.wp-block-loop.alignfull{margin-left:0;margin-right:0;--loop-radius:0;--loop-max-width:100%;--loop-hero-min-height:clamp(20rem, 50vh, 30rem)}.entry-content>.block-loop-hero.wp-block-loop.alignfull .block-loop-items{padding:0}.block-loop-hero .block-loop-nav{top:auto;right:2rem;bottom:5rem;width:auto;justify-content:flex-end;gap:.5rem}.block-loop-hero .block-loop-nav span,.block-loop-hero .count{display:none}.block-loop-hero .entry-header{position:absolute;top:0;left:0;bottom:0;width:100%;padding:var(--x-gap,1.5rem);color:#fff;background:linear-gradient(-135deg,transparent 0,transparent 25%,rgba(0,0,0,.6) 70%,rgba(0,0,0,1) 100%);border-radius:inherit;border-top-right-radius:0;border-bottom-right-radius:0;flex-direction:column}.block-loop-hero .entry-header-inner{flex:none;margin-top:auto}.block-loop-hero video{position:absolute;left:0;top:0;width:100%;height:100%;object-fit:cover;display:none}.block-loop-hero .slider-active video{display:block}.block-loop-hero .entry-meta{grid-gap:1rem}.block-loop-hero .entry-header .entry-title{font-size:clamp(1.75rem,2.5vw,3rem);font-weight:600;line-height:1;max-width:40rem;margin-bottom:1rem}.block-loop-hero .byline{width:auto}.block-loop-hero .btn-purchase{border-color:#fff;padding:.5rem 1rem}.block-loop-hero .post-thumbnail{min-height:var(--loop-hero-min-height)}.block-loop-hero .btn-play{font-size:inherit}.block-loop-hero.alignfull .entry-header .entry-title{font-size:clamp(1.75rem,5vw,5rem);max-width:30rem}.block-loop-hero .entry-header{z-index:2;background:linear-gradient(180deg,transparent 0,transparent 25%,rgba(0,0,0,.7) 75%,var(--color-grey-800))}.block-loop-hero .post-thumbnail:before{content:'';display:block;position:absolute;z-index:1;top:0;left:0;right:0;bottom:0;background:linear-gradient(-80deg,transparent 50%,rgba(0,0,0,1) 100%)}.block-loop-hero .block-loop-dot{position:absolute;z-index:3;right:2rem;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;color:#fff}.block-loop-hero .byline,.block-loop-hero .byline+:before{display:none}.block-loop-hide-byline .byline{display:none}.block-loop-hide-footer .entry-footer{display:none}.block-loop-hide-avatar .entry-avatar{display:none}.block-loop-hide-meta .entry-footer>:not(.btn-more){display:none}.block-loop-short-item{--loop-ratio:calc(9/16);--loop-radius:1rem;--loop-line:3;--height:calc( 100vh - var(--navbar-height) - var(--mobile-menu-height) - var(--loop-short-bottom-padding, 2rem) );height:var(--height);width:calc(var(--height) * .5625)}.block-loop-short-item .entry-header{position:absolute;z-index:99;bottom:0;width:100%;color:#fff;background:linear-gradient(180deg,transparent,rgba(0,0,0,.4));padding:3rem 1rem 1rem;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.block-loop-short-item .entry-meta{grid-gap:.5rem;margin-top:1rem}.block-loop-short-item .btn-follow{padding:1rem;border:none}.block-loop-short-item .btn-follow:not(.active){color:#000;background-color:#fff}.block-loop-short-item .byline{color:#fff;width:auto;flex:1}.block-loop-short-item.active .entry-action{opacity:0}.block-loop-short-item.active:hover .entry-action{opacity:1}.block-loop-short-item .post-thumbnail{border-radius:inherit!important;z-index:2}.block-loop-short-item.active .post-thumbnail .post-thumbnail-inner,.block-loop-short-item.is-current .post-thumbnail .post-thumbnail-inner{display:none}.block-loop-short-item .post-thumbnail .entry-action{background:linear-gradient(0deg,transparent,transparent 90%,rgba(0,0,0,.2));align-items:flex-start;justify-content:space-between;width:100%;height:auto;transform:none;left:0;top:0;padding:0}.block-loop-short-item .btn-play{position:relative!important;box-shadow:none!important;background-color:transparent!important;border:none;color:#fff}.block-loop-short-item .btn-play:after{display:none}.block-loop-short-item .entry-actions{position:absolute;left:100%;bottom:0;padding:0 1rem;grid-gap:.75rem;display:flex;flex-direction:column}.block-loop-short-item .entry-action-link{pointer-events:none}.block-loop-short-item .entry-actions .btn-comment,.block-loop-short-item .entry-actions button{display:inline-flex!important;flex-direction:column;padding:0;margin:0!important;position:relative!important}.block-loop-short-item .entry-actions .count{padding:.25rem 0 0 0;font-size:12px;font-weight:600}.block-loop-short-item .entry-actions .btn-svg-icon{padding:1rem;background-color:rgba(150,150,150,.15);border-radius:2rem}.block-loop-short-item .entry-actions .btn-svg-icon svg{width:20px;height:20px;fill:currentColor}.block-loop-snaps .scroller{margin-top:-1.25rem;margin-bottom:.25rem;border:none;background:0 0}@media (max-width:419px){.block-loop-slider{--loop-columns:1}.block-loop-snaps{--x-gap:0;--loop-radius:0;--loop-grid-gap:0;z-index:2}.block-loop-short-item{--loop-ratio:auto;--loop-radius:0;--text-secondary-color:#fff;width:100vw;height:inherit;flex-shrink:0}.plyr-short{--loop-radius:0}.block-loop-short-item .post-thumbnail{height:100%}.block-loop-short-item .entry-actions{left:auto;right:0;top:4rem;bottom:auto;z-index:999;color:#fff}}.block-loop-hover .entry-header{padding:.5rem .5rem 1rem .5rem!important}.block-loop-hover .entry-header-inner{display:flex;align-items:center;flex-direction:column;text-align:center}.block-loop-hover .block-loop-item.active,.block-loop-hover .block-loop-item:focus,.block-loop-hover .block-loop-item:hover{--text-secondary-color:#fff;background-color:#222;color:#fff}.block-loop-hover .block-loop-item.active .post-thumbnail:after,.block-loop-hover .block-loop-item:focus .post-thumbnail:after,.block-loop-hover .block-loop-item:hover .post-thumbnail:after{position:relative;z-index:1;background-color:#222;background:linear-gradient(180deg,rgba(22,22,22,.2),#222);border-radius:inherit;border-bottom-left-radius:0;border-bottom-right-radius:0}.block-loop-hover .entry-action{background-color:transparent}.block-loop-reverse .block-loop-item{flex-direction:column-reverse}.block-loop-reverse .block-loop-item .entry-header{padding-top:0}.block-loop-divider .block-loop-title{padding-top:1.5rem;border-top:.5px solid var(--color-border,rgba(150,160,170,.1))}.wp-block-loop.alignfull{margin-left:2rem;margin-right:2rem}.entry-title-lg .block-loop-item .entry-header-inner{font-size:clamp(1rem,3vw,1.25rem)}.wp-admin .display{font-weight:900;line-height:1;margin-top:0;margin-bottom:1rem}.wp-admin .circle{border-radius:50%}.wp-admin .rounded{border-radius:6px}.wp-admin .h-auto{min-height:auto}.white{color:#222;background-color:#fff}.text-white{color:#fff}.m-auto{margin-left:auto;margin-right:auto}.h-auto{min-height:auto}.border{border:1px solid var(--color-border,#eee)}.rounded,.rounded.wp-block-cover>span,.rounded:before{border-radius:var(--border-radius,8px)}.circle{border-radius:100%}.wp-block-cover{--y-gap:0}.wp-block-cover mark{padding:3px 4px;line-height:1;display:inline-flex;align-items:center;border-radius:3px}.is-position-top-bottom .wp-block-cover__inner-container{display:flex;flex-direction:column;justify-content:space-between;align-self:stretch;width:100%!important;position:static}.is-position-top-bottom .wp-block-video,.is-position-top-bottom .wp-block-video div,.is-position-top-bottom .wp-block-video video{position:absolute;top:0;bottom:0;left:0;right:0;margin:0;z-index:-1}.is-position-top-bottom .wp-block-video video{object-fit:cover;width:100%;height:100%}.is-align-self-start{align-self:flex-start}.is-align-self-end{align-self:flex-end;margin-bottom:0}.no-border{border:none}.no-padding{padding:0!important}.no-margin{margin:0!important}.no-gap{gap:0!important}.has-padding{padding:clamp(1rem,3vw,3rem)}.has-small-padding{padding:clamp(.5rem,2vw,1.5rem)}.has-large-padding{padding:clamp(2rem,4vw,5rem)}.has-container{--content-width:640px}#ffl-settings .postbox-header{border-bottom:none}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:var(--dropdown-menu-width,10rem);padding:.25rem;margin:.125rem 0 0;font-size:.875rem;color:#212529;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.05);box-shadow:0 3px 5px rgba(0,0,0,.05);border-radius:var(--dropdown-menu-radius,.5rem);text-shadow:none;text-align:initial}.dropdown-toggle{cursor:pointer;display:inline-block;text-align:center;min-width:1.5rem;text-decoration:none;outline:0}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-inline-start:.3em;-webkit-margin-start:.3em;vertical-align:middle;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent;opacity:.5}.dropdown-menu.show{display:block}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-menu[x-out-of-boundaries]{display:none}.dropdown-menu ul{display:block!important;list-style:none;padding:0;margin-bottom:0}.dropdown-item,.dropdown-menu li a{display:block;width:100%;padding:.5rem 1rem;box-sizing:border-box;clear:both;font-weight:400;border-radius:6px;cursor:pointer;text-decoration:none;outline:0}.dropdown-item:hover,.dropdown-menu .cat-item a:hover,.dropdown-menu .play-notification-item:hover{color:inherit;background-color:var(--dropdown-menu-item-background,rgba(150,150,150,.1))}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid var(--dropdown-menu-item-background)}.dropdown-menu .play-notification-item{border:none}.dropdown-term-filter,.loop-filter-item .dropdown-menu{max-height:15rem;overflow-y:scroll;-webkit-overflow-scrolling:touch;overflow:-moz-scrollbars-none;-ms-overflow-style:none;outline:0}.dropdown-term-filter::-webkit-scrollbar{display:none}.dropdown-term-filter ul ul a{padding-inline-start:2rem;-webkit-padding-start:2rem}.loop-filter{display:flex;flex-wrap:wrap;margin-bottom:1.5rem;grid-gap:1rem}.loop-filter-list{flex-direction:column}.loop-filter-item{position:relative}.loop-filter-list .loop-filter-item{display:flex;grid-gap:1rem}.loop-filter .list-menu{display:flex;flex-wrap:wrap;grid-gap:.5rem;grid-row-gap:.5rem}.loop-filter .list-item{white-space:nowrap;display:inline-flex;align-items:center;padding:1px 5px;border-radius:4px;text-decoration:none}.loop-filter .list-menu .selected{background-color:rgba(150,150,150,.2)}.loop-filter .loop-filter-item-heading{font-weight:600}.loop-filter .dropdown-menu .selected{position:relative}.loop-filter .loop-filter-item-search input{margin:0}.loop-toggle-hide{display:none!important}.loop-filter-more-less{cursor:pointer;font-weight:500}.loop-filter .dropdown-menu .selected:after{content:'';display:inline-block;width:.65em;height:.35em;border-left:.1em solid currentColor;border-bottom:.1em solid currentColor;transform:translate(-50%,-50%) rotate(-45deg);position:absolute;right:.5rem;top:45%;opacity:.6}.loop-filter-count{display:inline-block;background-color:rgba(150,160,170,.2);padding:0 .45em;margin-inline-start:.125rem;-webkit-margin-start:.125rem;font-size:11px;border-radius:1rem}.loop-filter-count:empty{display:none}.dropdown-menu .multi-range{margin:1rem}input[type=range].multirange{-webkit-appearance:none;height:2px;padding:0;margin:1rem 0 0;width:calc(100% - 0px);display:inline-block;vertical-align:top;background-color:rgba(150,150,150,.5);color:currentColor;outline:0;border:0;border-radius:6px}input[type=range].multirange.original{position:absolute}input[type=range].multirange::-webkit-slider-thumb{-webkit-appearance:none;position:relative;z-index:2;border:none;width:12px;height:12px;border-radius:100%;background-color:currentColor}input[type=range].multirange::-moz-range-thumb{border:none;width:12px;height:12px;border-radius:100%;background-color:currentColor}input[type=range].multirange.original::-moz-range-thumb{z-index:2}input[type=range].multirange.ghost{position:relative;background:var(--track-background);--track-background:linear-gradient(to right, transparent var(--low), var(--range-color) 0, var(--range-color) var(--high), transparent 0) no-repeat 0 100%/100% 100%;--range-color:currentColor}input[type=range].multirange.ghost::-webkit-slider-thumb{position:relative;z-index:2}input[type=range].multirange.ghost::-moz-range-thumb{z-index:2}.multi-range{position:relative}.range-max,.range-min{position:absolute;top:-6px;font-size:10px;width:10px;display:flex;justify-content:center;text-align:center;left:calc(var(--left) * 1%);margin-left:calc(0px - var(--left)/ 100 * 10px)}.spinner{display:inline-block;width:1rem;height:1rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner .75s linear infinite;animation:spinner .75s linear infinite}.loop-filter-keys{width:100%;display:flex;grid-gap:.5rem;flex-wrap:wrap}.loop-filter-keys a{font-weight:600;font-size:.9em;display:inline-flex;text-decoration:none}.loop-filter-keys a:after{content:'\00d7';font-family:arial;font-weight:400;display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;line-height:0;border-radius:100%;background-color:#666;color:#fff;opacity:0;margin:-4px -7px 0 -7px;transition:opacity .2s}.loop-filter-keys a:hover:after{opacity:1}.loop-filter-total{width:100%}a.loop-filter-clear{font-weight:400;align-items:center;opacity:.7}a.loop-filter-clear:hover{opacity:1}a.loop-filter-clear:after{order:-1;margin:2px;opacity:1}@keyframes spinner{0%{transform:scale(0)}50%{opacity:1}}@media (max-width:576px){:root{--loop-grid-gap:1rem}.block-loop-row .block-loop-items{--loop-columns:1}.block-loop-row:not(.has-loop-posts):not(.block-loop-xs):not(.block-loop-inline) .block-loop-item:not(.block-loop-inline) .entry-footer{flex:auto;width:100%}.block-loop-row:not(.has-loop-posts):not(.block-loop-xs):not(.block-loop-inline) .block-loop-item:not(.block-loop-inline) .post-thumbnail{width:4.5rem}.block-loop-row .entry-footer>:first-child:not(.btn-add){padding-inline-start:0}.block-loop-row .add_to_cart_inline,.block-loop-row .btn-purchase,.block-loop-row .entry-description,.block-loop-row .entry-info{display:none}.block-loop-inline .waveform,.block-loop-nav,.has-loop-posts .btn-download,.has-loop-posts .btn-like,.has-loop-posts .play-count{display:none}.modal-open .wp-block-loop-product .block-loop-slider{overflow:visible}.entry-content>.wp-block-loop-slider:not(.block-loop-center) .block-loop-items{padding:0 var(--x-gap,var(--wp--style--root--padding-left,1rem));margin:0 calc(var(--x-gap,var(--wp--style--root--padding-left,1rem)) * -1);scroll-snap-type:none;--loop-max-width:85%}}@media (min-width:577px){.block-loop-with-filter{display:flex;align-items:flex-start;height:100%}.block-loop-with-filter .block-loop-items{flex:1}.block-loop-with-filter .loop-filter{flex-direction:column;min-width:15rem;margin:0;height:100%}.is-series .has-loop-posts .post-thumbnail{border-radius:5px;width:5rem;height:5rem}}
     1:root{--loop-cols:5;--loop-xs-cols:2;--loop-rows:1;--loop-columns:max( var(--loop-cols) - 4, var(--loop-xs-cols) );--loop-grid-gap:1.5rem;--loop-row-gap:1rem;--loop-max-width:100%;--loop-min-width:0;--loop-line:2;--loop-line-height:1.3;--loop-ratio:1;--loop-radius:6px;--loop-center-width:70%;--loop-font-size:0.9375rem}.is-loop-icon{display:inline-flex;align-items:center;grid-gap:.25em}.is-loop-icon:after,.is-loop-icon:before{content:'';display:block;width:1em;height:1em;border:.125em solid currentColor;transform:rotate(45deg);border-radius:100%;order:-1}.is-loop-icon:before{border-top-right-radius:0}.is-loop-icon:after{border-bottom-left-radius:0}.wp-block-loop{position:relative}.block-loop-items{margin-bottom:1.5rem;list-style:none;display:grid;grid-gap:var(--loop-grid-gap);--loop--cols:calc((var(--loop-max-width) - (var(--loop-columns) - 1) * var(--loop-grid-gap)) / var(--loop-columns));grid-template-columns:repeat(auto-fill,minmax(var(--loop--cols),1fr))}.block-loop-slider,[data-plugin=slider]{display:grid;overflow-x:auto;border-radius:var(--loop-radius);scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;overscroll-behavior-x:none;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;grid-auto-flow:column;--loop--cols:calc((var(--loop-max-width) - (var(--loop-columns) - 1) * var(--loop-grid-gap)) / var(--loop-columns));grid-auto-columns:var(--loop--cols);grid-template-rows:repeat(var(--loop-rows),max-content);grid-template-columns:inherit!important;box-sizing:border-box}.block-loop-slider::-webkit-scrollbar,.block-loop-snaps .block-loop-items::-webkit-scrollbar{display:none}.block-loop-snaps .block-loop-items{position:fixed;z-index:2;left:0;right:0;top:var(--navbar-height);bottom:var(--mobile-menu-height);display:flex;flex-direction:column;align-items:center;overflow-y:auto;scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;overscroll-behavior-y:none;-ms-scroll-snap-type:y mandatory;scroll-snap-type:y mandatory;border-radius:var(--loop-radius);margin-bottom:0}.block-slider-scrolling{-ms-scroll-snap-type:none;scroll-snap-type:none;scroll-behavior:inherit}.block-slider-scrolling video{display:none!important}.block-loop-slider .entry-content>*,[data-plugin=slider] .entry-content>*{width:100%!important;max-width:100%!important}.block-loop-slider>*,.block-loop-snaps>*{scroll-snap-align:start}.column-sm-gap{--column-gap:var(--loop-grid-gap, 1rem)}@media (max-width:1000px){.is-stacked-tablet{flex-wrap:wrap!important}.is-stacked-tablet>.wp-block-column{flex-basis:100%!important}}@media (min-width:420px){.wp-block-loop{--loop-columns:max( min(var(--loop-cols), 5) - 3, 2 )}}@media (min-width:640px){.wp-block-loop{--loop-columns:max( var(--loop-cols) - 2, 2 )}}@media (min-width:960px){.wp-block-loop{--loop-columns:max( var(--loop-cols) - 1, 3 )}}@media (min-width:1260px){.wp-block-loop{--loop-columns:var(--loop-cols)}}.grid-1{--loop-columns:1!important}.grid-2{--loop-columns:2!important}.grid-3{--loop-columns:3!important}@media (max-width:419px){.grid-xs-1{--loop-columns:1!important}.grid-xs-2{--loop-columns:2!important}.grid-xs-3{--loop-columns:3!important}}@media (max-width:781px){.grid-sm-1{--loop-columns:1!important}.grid-sm-2{--loop-columns:2!important}.grid-sm-3{--loop-columns:3!important}}@media (max-width:991px){.grid-md-1{--loop-columns:1!important}.grid-md-2{--loop-columns:2!important}.grid-md-3{--loop-columns:3!important}}@media (min-width:1400px){.grid-xl-1{--loop-columns:1!important}.grid-xl-2{--loop-columns:2!important}.grid-xl-3{--loop-columns:3!important}}.block-loop-title{display:flex;flex-wrap:wrap;align-items:center}.block-loop-heading{width:1%;flex:1}.block-loop-more{font-size:14px;font-weight:400}.block-loop-subtitle{color:var(--text-secondary-color,#888);line-height:1.1;text-transform:none;display:block;width:100%}.block-loop-nav{opacity:0;transition:opacity .2s;position:absolute;display:flex;align-items:center;z-index:5;height:0;width:calc(100% + 2.5rem);left:-1.25rem;top:var(--top,50%)}.alignfull>.block-loop-nav{width:calc(100% - 2.5rem);left:1.25rem}.block-loop-nav span{flex:1}.wp-block-loop:hover .block-loop-nav{opacity:1}.block-loop-nav button{width:2.5rem;height:2.5rem;padding:0;border-radius:100%;display:inline-flex;justify-content:center;align-items:center;border:none;box-shadow:0 2px 4px rgba(0,0,0,.1)}.block-loop-nav button svg{pointer-events:none;transform:rotate(var(--transform-rotate,0))}.block-loop-dot-overlay .block-loop-dot{position:absolute;z-index:5;left:50%;bottom:1rem;transform:translate(-50%,0);color:#fff}.block-loop-dot-left .block-loop-dot{margin:-4rem auto 0 auto;text-align:left;max-width:var(--content-width);width:calc(100% - var(--x-gap) * 2)}.block-loop-dot{text-align:center}.block-loop-dot button{width:1.5rem;height:1.5rem;padding:0;border-radius:2rem;border:none;background-color:transparent;color:inherit}.block-loop-dot button:after{content:"";display:inline-block;width:6px;height:6px;border-radius:6px;margin:0 auto;background-color:currentColor;opacity:.5}.block-loop-dot button.active:after{opacity:1}.block-loop-center{--loop-columns:1;--loop-max-width:var(--loop-center-width)!important}.block-loop-center .block-loop-item{scroll-snap-align:center}.block-loop-center .block-loop-nav>div{height:var(--height);width:calc(50% - var(--loop-center-width)/ 2);display:flex;align-items:center}.block-loop-center .block-loop-nav .slider-right-btn{justify-content:flex-end}.scroller{width:15rem;font-size:12px!important;display:inline-flex;justify-content:center;margin:0 auto;text-decoration:none}.scroller.is-loading{cursor:wait;pointer-events:none}.block-loop-empty,.wp-block-loop .pagination,.wp-block-loop .scroller{grid-column:1/-1;order:10000}.pagination .nav-links{display:flex;align-items:center;justify-content:center}.pagination .page-numbers{padding:.25em;text-decoration:none}.wp-block-loop .navigation .next,.wp-block-loop .navigation .prev{line-height:0}.wp-block-loop .navigation .nav-next-text,.wp-block-loop .navigation .nav-prev-text,.wp-block-loop .navigation .next:before,.wp-block-loop .navigation .prev:before{display:none}.block-loop-item{position:relative;padding:0;max-width:100%;border-radius:var(--loop-radius);display:flex;flex-direction:column;flex-wrap:wrap;scroll-snap-align:start;order:10;font-size:var(--loop-font-size)}.block-loop-item:nth-child(1){order:0}.block-loop-item:nth-child(2){order:1}.block-loop-item:nth-child(3){order:2}.block-loop-item:nth-child(4){order:3}.block-loop-item:nth-child(5){order:4}.block-loop-item:nth-child(6){order:5}.block-loop-item:nth-child(7){order:6}.block-loop-item:nth-child(8){order:7}.block-loop-item:nth-child(9){order:8}.block-loop-item .entry-content,.block-loop-item .entry-footer,.block-loop-item .entry-header,.block-loop-item .post-thumbnail{width:100%;box-sizing:border-box;padding-left:0;padding-right:0}.block-loop-item .entry-header{margin-bottom:1rem}.block-loop-item .entry-footer{margin-bottom:1rem}.block-loop-item .entry-header{padding:var(--loop-header-gap,.5rem) 0;margin:0;flex:1;display:flex;align-items:flex-start;grid-gap:var(--loop-header-gap,.5rem)}.block-loop-item .entry-title{margin:0;font-weight:500;letter-spacing:0}.block-loop-item .entry-subtitle{color:var(--text-secondary-color,#888)}.block-loop-item a{text-decoration:none}.block-loop-item .entry-meta{display:flex;flex-wrap:wrap;grid-gap:0;margin:0;color:var(--text-secondary-color,#888)}.block-loop-item .byline .author,.block-loop-item .entry-artist,.block-loop-item .entry-excerpt,.block-loop-item .entry-title,.wp-block-loop-user .entry-title a{display:block;display:-webkit-box;-webkit-box-orient:vertical;text-overflow:ellipsis;white-space:normal;-webkit-line-clamp:var(--loop-line);line-height:var(--loop-line-height);font-size:inherit;overflow:hidden;padding-bottom:.1em;word-break:break-word;word-wrap:break-word}.block-loop-item .entry-excerpt{--loop-line:2}.wp-block-loop-user .entry-title{display:flex;overflow:visible}.block-loop-item .byline .author,.wp-block-loop-user .entry-title a{--loop-line:1}.block-loop-item .entry-meta>span{margin:0}.block-loop-item .wp-video,.block-loop-item .wp-video video{width:100%!important;height:auto;border-radius:inherit}.block-loop-item .attachment,.block-loop-item.attachment{float:none;width:100%}.block-loop-item.attachment audio~p{display:none}.block-loop-item .post-thumbnail br,.block-loop-item .post-thumbnail p{display:none}.block-loop-item .post-thumbnail{width:100%;position:relative;margin:0;padding:0;border-radius:inherit;background-color:rgba(110,120,130,.2)}.block-loop-item .btn-follow{padding:.25em .75em;font-size:12px;vertical-align:text-bottom;margin:.25rem 0}.block-loop-item .post-thumbnail a{border-radius:inherit}.block-loop-item .post-thumbnail .avatar,.block-loop-item .post-thumbnail img,.block-loop-item .post-thumbnail video{border-radius:inherit;position:absolute;width:100%;height:100%;object-fit:cover;display:inline-flex;justify-content:center;align-items:center}.block-loop-item .post-thumbnail:after{padding-top:calc(100% / var(--loop-ratio));min-height:auto;content:"";width:100%;display:block}.block-loop-item .entry-action{opacity:0;pointer-events:none;color:#fff;background-color:rgba(0,0,0,.2);position:absolute;z-index:3;left:50%;top:50%;width:100%;height:100%;padding:0 5%;border-radius:inherit;transform:translate(-50%,-50%);transition:opacity .3s;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;justify-content:space-around;box-sizing:border-box}.block-loop-item .entry-action .count{display:none}.block-loop-item .entry-action.show{z-index:10}.block-loop-item .entry-action button,.block-loop-item .entry-action button:hover{flex-shrink:0}.entry-action-link{position:absolute;width:100%;height:100%}.block-loop-item-link{padding:.75rem 1rem;background-color:var(--btn-background,rgba(150,155,160,.2));border-radius:var(--btn-radius,.5rem)}.block-loop-item-link.active,.block-loop-item-link:hover{background-color:var(--btn-background-hover,rgba(150,155,160,.3))}.block-loop-item.active .entry-action,.block-loop-item:active .entry-action,.block-loop-item:hover .entry-action,.block-loop-item:hover .entry-header-inner~.btn-more{opacity:1;pointer-events:initial}.block-loop-item .count,.comment-toolbar .count,.entry-meta .count{color:var(--text-secondary-color,#888);padding-inline-start:.25rem;-webkit-padding-start:.25rem;font-size:.85rem;font-weight:400}.block-loop-row .play-count{padding:0 .5rem}.block-loop-item .entry-avatar{width:36px;flex-shrink:0}.block-loop-item .entry-footer{display:none;margin:0}.block-loop-item .entry-description{font-size:.875rem}.block-loop-item .entry-description p{margin-bottom:0}.block-loop-item .waveform{width:100%}.block-loop-index.block-loop-row .waveform:before{content:"";display:inline-block;min-width:1rem}.wp-block-loop .btn-play{font-size:1.125rem}.block-loop-row .btn-play{font-size:.875rem}.wp-block-loop-user .post-thumbnail{width:80%;margin:10% 10% 0 10%;border-radius:50%}.wp-block-loop-user .entry-header{text-align:center;flex-direction:column;align-items:center;grid-gap:0}.wp-block-loop-user .post-thumbnail{--loop-ratio:1;border-radius:50%!important}.wp-block-loop-user.block-loop-row{--loop-grid-gap:0.75rem}.wp-block-loop-user.block-loop-row .block-loop-item{align-items:center}.wp-block-loop-user.block-loop-row .post-thumbnail{margin:0;min-width:0;width:3rem}.wp-block-loop-user.block-loop-row .entry-header{align-items:center;text-align:inherit;display:flex;flex-direction:row;gap:.5rem}.wp-block-loop-user .entry-title{font-size:.8125rem;font-weight:600;align-items:center;justify-content:center;flex:1}.wp-block-loop-user.block-loop-row .entry-title{justify-content:flex-start}.wp-block-loop-user .user-followers{font-weight:400;font-size:.85em;color:var(--text-secondary-color);width:100%}.block-loop-row{--loop-columns:1}.hide-more-actions .entry-footer>:not(.btn-more){display:none}.block-loop-row .block-loop-item{display:flex;grid-gap:var(--loop-row-gap);flex-direction:row;align-items:flex-start}.block-loop-row .entry-header{flex:1;display:flex;flex-wrap:wrap;padding:0;align-items:center;align-self:stretch;grid-gap:0}.block-loop-row .entry-avatar{display:none}.block-loop-row .post-thumbnail{width:6rem;min-width:var(--loop-min-width)}.block-loop-mixed .block-loop-item{display:flex;grid-gap:var(--loop-row-gap);flex-direction:row;--loop-header-gap:0;align-items:center}.block-loop-mixed .block-loop-item:first-child{grid-column:span calc(var(--loop-columns)/2);grid-row:span var(--loop-rows,4);align-items:stretch}.block-loop-mixed .block-loop-item:not(:first-child){grid-column:span calc(var(--loop-columns)/2)}.block-loop-mixed .block-loop-item:not(:first-child) .post-thumbnail{width:33%}@media (max-width:576px){.block-loop-mixed .block-loop-items{--loop-columns:1}}.block-loop-xs{--loop-line:1}.block-loop-xs .btn-play{font-size:.75rem}.block-loop-xs .post-thumbnail{width:3rem;border-radius:5px;min-width:auto}.block-loop-sm .post-thumbnail{width:4rem;border-radius:7px;min-width:auto}.block-loop-lg .post-thumbnail{width:10rem;min-width:auto}.block-loop-autotype .block-loop-items{--loop-columns:1}.has-loop-posts .block-loop-items{grid-gap:0;--loop-columns:1}.has-loop-posts .block-loop-item{padding:.5rem .5rem}.has-loop-posts .entry-header{flex-wrap:nowrap;padding:0}.has-loop-posts .post-thumbnail{border-radius:2px;width:3rem;flex-shrink:0}.has-loop-posts.block-loop-index .icon-play{display:none;padding:.5rem;position:absolute;top:50%;transform:translateY(-50%);line-height:0}.has-loop-posts.block-loop-index .block-loop-item.active:before,.has-loop-posts.block-loop-index .block-loop-item:hover:before{color:transparent}.has-loop-posts.block-loop-index .block-loop-item.active .icon-play,.has-loop-posts.block-loop-index .block-loop-item:hover .icon-play{display:block}.has-loop-posts .block-loop-item:hover{background-color:var(--tracks-item-odd-color,rgba(150,155,160,.1))}.has-loop-posts .block-loop-item.active{background-color:var(--tracks-item-hover-color,rgba(150,155,160,.2))}.has-loop-posts .icon-plus{display:none}.is-album .has-loop-posts .entry-meta a,.is-album .has-loop-posts .entry-title a{pointer-events:none}.has-loop-posts .entry-meta{justify-content:flex-start!important}.is-album .has-loop-posts .post-thumbnail{display:none}.is-series .has-loop-posts .block-loop-items{margin:0 -1rem}.is-series .has-loop-posts .block-loop-item{padding:.75rem 1rem;border:none!important}.is-series .has-loop-posts .block-loop-item .entry-header{padding-bottom:1rem;border-bottom:1px solid var(--color-border)}.is-series .has-loop-posts .block-loop-item.active .entry-header,.is-series .has-loop-posts .block-loop-item:hover .entry-header{border-color:transparent}.is-series .has-loop-posts .btn-play{border:1px solid var(--color-border);background-clip:padding-box}.is-series .has-loop-posts .block-loop-item>.btn-play{align-self:flex-start}.block-loop-row .entry-description,.block-loop-row .entry-info,.is-series .block-loop-item .entry-description,.is-series .block-loop-item .entry-info{margin-bottom:0}.block-loop-row .entry-info .play-duration,.is-series .block-loop-item .entry-info .play-duration{padding:0}.block-loop-inline .entry-header{grid-gap:1.5rem}.block-loop-inline>button.btn-play{transform:scale(1)}.block-loop-inline .btn-play-waveform{display:none}.block-loop-inline .waveform{flex:1}.entry-header-inner{flex:1;max-width:100%}.entry-header-inner~.btn-more{margin:-.375rem -.5rem;opacity:0}.entry-header-inner .byline,.entry-header-inner .entry-artist{width:100%;justify-content:inherit}.entry-header-inner .byline{display:flex;align-items:center}.entry-meta-date{font-size:.75rem}.entry-header-inner .play-count+.entry-meta-date:before{display:inline-block;text-align:center;content:'\00B7';color:var(--text-secondary-color);width:1rem;font-weight:700}.block-loop-item .add_to_cart_inline,.block-loop-item .entry-header-inner .btn-purchase{margin:4px 0}.block-loop-item .add_to_cart_inline .btn-purchase,.block-loop-item form{margin:0!important}.block-loop-xs .add_to_cart_inline,.block-loop-xs .btn-purchase,.has-loop-posts .add_to_cart_inline,.has-loop-posts .btn-purchase{display:none}.block-loop-item .added_to_cart,.block-loop-item .btn-purchase,.plyr-playlist .btn-purchase{font-size:12px}.block-loop-item .entry-action .btn-more{position:absolute;padding:.75em;bottom:0;right:0}.block-loop-row .entry-action{justify-content:center}.block-loop-row .post-thumbnail .entry-action .btn-like,.block-loop-row .post-thumbnail .entry-action .btn-more{display:none}.block-loop-row .entry-footer{display:flex;align-items:center;padding-left:0;padding-right:0;width:auto}.block-loop-row .count,.block-loop-row .play-duration{font-size:.875em}.block-loop-row .play-duration{padding:0 .5rem}.play-count{white-space:nowrap;display:inline-flex;align-items:center;white-space:nowrap}.play-count:before{display:inline-block;width:0;height:0;content:"";border-left:.5em solid;border-top:.3em solid transparent;border-bottom:.3em solid transparent;opacity:.5}.btn-play+.play-count:before{display:none}.entry-badge .play-duration{background-color:#000;color:#fff;font-size:11px;font-weight:500;border-radius:4px;padding:1px 4px;position:absolute;right:.5rem;bottom:.5rem}.block-loop-index{counter-reset:li}.block-loop-index:not(.block-loop-row) .block-loop-item .entry-header:before{content:counter(li);counter-increment:li;font-weight:400;-ms-flex-negative:0;flex-shrink:0;opacity:.75;min-width:1rem}.block-loop-index.block-loop-row .block-loop-item:before{content:counter(li);counter-increment:li;min-width:1.5rem;font-weight:400;-ms-flex-negative:0;flex-shrink:0;opacity:.5;text-align:center;font-size:.9em;white-space:nowrap;align-self:center}.block-loop-overlay .entry-header{position:absolute;bottom:0;left:0;width:100%!important;padding:.75rem 1rem!important;box-sizing:border-box;color:#fff;background:linear-gradient(180deg,transparent,rgba(0,0,0,.85));border-radius:inherit;border-top-right-radius:0;border-top-left-radius:0;opacity:0;pointer-events:none}.block-loop-overlay .entry-header .entry-title{color:inherit;font-weight:700}.block-loop-overlay .entry-header .entry-meta,.block-loop-overlay .entry-header .entry-subtitle{color:rgba(255,255,255,.75)}.block-loop-overlay .entry-header a:hover{color:inherit}.block-loop-overlay .block-loop-item:hover .entry-header,.block-loop-overlay.block-loop-show-header .entry-header{opacity:1;pointer-events:initial;z-index:2}.block-loop-overlay-center .entry-header{top:0;opacity:1;font-weight:700;font-size:1rem;text-align:center;display:flex!important;align-items:center;justify-content:center}.block-loop-overlay-center .entry-meta{justify-content:center}.block-loop-ad .entry-meta{font-size:.75rem}.block-loop-ad.block-loop-item .post-thumbnail{background-color:var(--color-primary)}.block-loop-overlay .block-loop-ad .entry-header{background:0 0;bottom:auto}.block-loop-hero{--text-secondary-color:rgba(255,255,255,0.95);--button-radius:3rem;--loop-hero-min-height:15rem}.block-loop-hero.wp-block-loop.alignfull{margin-left:0;margin-right:0;--loop-radius:0;--loop-max-width:100%;--loop-hero-min-height:clamp(20rem, 50vh, 30rem)}.entry-content>.block-loop-hero.wp-block-loop.alignfull .block-loop-items{padding:0}.block-loop-hero .block-loop-nav{top:auto;right:2rem;bottom:5rem;width:auto;justify-content:flex-end;gap:.5rem}.block-loop-hero .block-loop-nav span,.block-loop-hero .count{display:none}.block-loop-hero .entry-header{position:absolute;top:0;left:0;bottom:0;width:100%;padding:var(--x-gap,1.5rem);color:#fff;background:linear-gradient(-135deg,transparent 0,transparent 25%,rgba(0,0,0,.6) 70%,rgba(0,0,0,1) 100%);border-radius:inherit;border-top-right-radius:0;border-bottom-right-radius:0;flex-direction:column}.block-loop-hero .entry-header-inner{flex:none;margin-top:auto}.block-loop-hero video{position:absolute;left:0;top:0;width:100%;height:100%;object-fit:cover;display:none}.block-loop-hero .slider-active video{display:block}.block-loop-hero .entry-meta{grid-gap:1rem}.block-loop-hero .entry-header .entry-title{font-size:clamp(1.75rem,2.5vw,3rem);font-weight:600;line-height:1;max-width:40rem;margin-bottom:1rem}.block-loop-hero .byline{width:auto}.block-loop-hero .btn-purchase{border-color:#fff;padding:.5rem 1rem}.block-loop-hero .post-thumbnail{min-height:var(--loop-hero-min-height)}.block-loop-hero .btn-play{font-size:inherit}.block-loop-hero.alignfull .entry-header .entry-title{font-size:clamp(1.75rem,5vw,5rem);max-width:30rem}.block-loop-hero .entry-header{z-index:2;background:linear-gradient(180deg,transparent 0,transparent 25%,rgba(0,0,0,.7) 75%,var(--color-grey-800))}.block-loop-hero .post-thumbnail:before{content:'';display:block;position:absolute;z-index:1;top:0;left:0;right:0;bottom:0;background:linear-gradient(-80deg,transparent 50%,rgba(0,0,0,1) 100%)}.block-loop-hero .block-loop-dot{position:absolute;z-index:3;right:2rem;top:50%;transform:translateY(-50%);display:flex;flex-direction:column;color:#fff}.block-loop-hero .byline,.block-loop-hero .byline+:before{display:none}.block-loop-hide-byline .byline{display:none}.block-loop-hide-footer .entry-footer{display:none}.block-loop-hide-avatar .entry-avatar{display:none}.block-loop-hide-meta .entry-footer>:not(.btn-more){display:none}.block-loop-short-item{--loop-ratio:calc(9/16);--loop-radius:1rem;--loop-line:3;--height:calc( 100vh - var(--navbar-height) - var(--mobile-menu-height) - var(--loop-short-bottom-padding, 2rem) );height:var(--height);width:calc(var(--height) * .5625)}.block-loop-short-item .entry-header{position:absolute;z-index:99;bottom:0;width:100%;color:#fff;background:linear-gradient(180deg,transparent,rgba(0,0,0,.4));padding:3rem 1rem 1rem;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}.block-loop-short-item .entry-meta{grid-gap:.5rem;margin-top:1rem}.block-loop-short-item .btn-follow{padding:1rem;border:none}.block-loop-short-item .btn-follow:not(.active){color:#000;background-color:#fff}.block-loop-short-item .byline{color:#fff;width:auto;flex:1}.block-loop-short-item.active .entry-action{opacity:0}.block-loop-short-item.active:hover .entry-action{opacity:1}.block-loop-short-item .post-thumbnail{border-radius:inherit!important;z-index:2}.block-loop-short-item.active .post-thumbnail .post-thumbnail-inner,.block-loop-short-item.is-current .post-thumbnail .post-thumbnail-inner{display:none}.block-loop-short-item .post-thumbnail .entry-action{background:linear-gradient(0deg,transparent,transparent 90%,rgba(0,0,0,.2));align-items:flex-start;justify-content:space-between;width:100%;height:auto;transform:none;left:0;top:0;padding:0}.block-loop-short-item .btn-play{position:relative!important;box-shadow:none!important;background-color:transparent!important;border:none;color:#fff}.block-loop-short-item .btn-play:after{display:none}.block-loop-short-item .entry-actions{position:absolute;left:100%;bottom:0;padding:0 1rem;grid-gap:.75rem;display:flex;flex-direction:column}.block-loop-short-item .entry-action-link{pointer-events:none}.block-loop-short-item .entry-actions .btn-comment,.block-loop-short-item .entry-actions button{display:inline-flex!important;flex-direction:column;padding:0;margin:0!important;position:relative!important}.block-loop-short-item .entry-actions .count{padding:.25rem 0 0 0;font-size:12px;font-weight:600}.block-loop-short-item .entry-actions .btn-svg-icon{padding:1rem;background-color:rgba(150,150,150,.15);border-radius:2rem}.block-loop-short-item .entry-actions .btn-svg-icon svg{width:20px;height:20px;fill:currentColor}.block-loop-snaps .scroller{margin-top:-1.25rem;margin-bottom:.25rem;border:none;background:0 0}@media (max-width:419px){.block-loop-slider{--loop-columns:1}.block-loop-snaps{--x-gap:0;--loop-radius:0;--loop-grid-gap:0;z-index:2}.block-loop-short-item{--loop-ratio:auto;--loop-radius:0;--text-secondary-color:#fff;width:100vw;height:inherit;flex-shrink:0}.plyr-short{--loop-radius:0}.block-loop-short-item .post-thumbnail{height:100%}.block-loop-short-item .entry-actions{left:auto;right:0;top:4rem;bottom:auto;z-index:999;color:#fff}}.block-loop-hover .entry-header{padding:.5rem .5rem 1rem .5rem!important}.block-loop-hover .entry-header-inner{display:flex;align-items:center;flex-direction:column;text-align:center}.block-loop-hover .block-loop-item.active,.block-loop-hover .block-loop-item:focus,.block-loop-hover .block-loop-item:hover{--text-secondary-color:#fff;background-color:#222;color:#fff}.block-loop-hover .block-loop-item.active .post-thumbnail:after,.block-loop-hover .block-loop-item:focus .post-thumbnail:after,.block-loop-hover .block-loop-item:hover .post-thumbnail:after{position:relative;z-index:1;background-color:#222;background:linear-gradient(180deg,rgba(22,22,22,.2),#222);border-radius:inherit;border-bottom-left-radius:0;border-bottom-right-radius:0}.block-loop-hover .entry-action{background-color:transparent}.block-loop-reverse .block-loop-item{flex-direction:column-reverse}.block-loop-reverse .block-loop-item .entry-header{padding-top:0}.block-loop-divider .block-loop-title{padding-top:1.5rem;border-top:.5px solid var(--color-border,rgba(150,160,170,.1))}.wp-block-loop.alignfull{margin-left:2rem;margin-right:2rem}.entry-title-lg .block-loop-item .entry-header-inner{font-size:clamp(1rem,3vw,1.25rem)}.wp-admin .display{font-weight:900;line-height:1;margin-top:0;margin-bottom:1rem}.wp-admin .circle{border-radius:50%}.wp-admin .rounded{border-radius:6px}.wp-admin .h-auto{min-height:auto}.white{color:#222;background-color:#fff}.text-white{color:#fff}.m-auto{margin-left:auto;margin-right:auto}.h-auto{min-height:auto}.border{border:1px solid var(--color-border,#eee)}.rounded,.rounded.wp-block-cover>span,.rounded:before{border-radius:var(--border-radius,8px)}.circle{border-radius:100%}.wp-block-cover{--y-gap:0}.wp-block-cover mark{padding:3px 4px;line-height:1;display:inline-flex;align-items:center;border-radius:3px}.is-position-top-bottom .wp-block-cover__inner-container{display:flex;flex-direction:column;justify-content:space-between;align-self:stretch;width:100%!important;position:static}.is-position-top-bottom .wp-block-video,.is-position-top-bottom .wp-block-video div,.is-position-top-bottom .wp-block-video video{position:absolute;top:0;bottom:0;left:0;right:0;margin:0;z-index:-1}.is-position-top-bottom .wp-block-video video{object-fit:cover;width:100%;height:100%}.is-align-self-start{align-self:flex-start}.is-align-self-end{align-self:flex-end;margin-bottom:0}.no-border{border:none}.no-padding{padding:0!important}.no-margin{margin:0!important}.no-gap{gap:0!important}.has-padding{padding:clamp(1rem,3vw,3rem)}.has-small-padding{padding:clamp(.5rem,2vw,1.5rem)}.has-large-padding{padding:clamp(2rem,4vw,5rem)}.has-container{--content-width:640px}#ffl-settings .postbox-header{border-bottom:none}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:var(--dropdown-menu-width,10rem);padding:.25rem;margin:.125rem 0 0;font-size:.875rem;color:#212529;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.05);box-shadow:0 3px 5px rgba(0,0,0,.05);border-radius:var(--dropdown-menu-radius,.5rem);text-shadow:none;text-align:initial}.dropdown-menu.show~.dropdown-backdrop{background-color:transparent;position:fixed;width:100vw;height:100vh;left:0;top:0;z-index:100000}.dropdown-toggle{cursor:pointer;display:inline-block;text-align:center;min-width:1.5rem;text-decoration:none;outline:0}.dropdown-toggle::after{display:inline-block;width:0;height:0;margin-inline-start:.3em;-webkit-margin-start:.3em;vertical-align:middle;content:"";border-top:.3em solid;border-right:.3em solid transparent;border-left:.3em solid transparent;opacity:.5}.dropdown-menu.show{display:block}.dropdown-menu[x-placement^=bottom],.dropdown-menu[x-placement^=left],.dropdown-menu[x-placement^=right],.dropdown-menu[x-placement^=top]{right:auto;bottom:auto}.dropdown-menu[x-out-of-boundaries]{display:none}.dropdown-menu ul{display:block!important;list-style:none;padding:0;margin-bottom:0}.dropdown-item,.dropdown-menu li a{display:block;width:100%;padding:.5rem 1rem;box-sizing:border-box;clear:both;font-weight:400;border-radius:6px;cursor:pointer;text-decoration:none;outline:0}.dropdown-item:hover,.dropdown-menu .cat-item a:hover,.dropdown-menu .play-notification-item:hover{color:inherit;background-color:var(--dropdown-menu-item-background,rgba(150,150,150,.1))}.dropdown-divider{height:0;margin:.5rem 0;overflow:hidden;border-top:1px solid var(--dropdown-menu-item-background)}.dropdown-menu .play-notification-item{border:none}.dropdown-term-filter,.loop-filter-item .dropdown-menu{max-height:15rem;overflow-y:scroll;-webkit-overflow-scrolling:touch;overflow:-moz-scrollbars-none;-ms-overflow-style:none;outline:0}.dropdown-term-filter::-webkit-scrollbar{display:none}.dropdown-term-filter ul ul a{padding-inline-start:2rem;-webkit-padding-start:2rem}.loop-filter{display:flex;flex-wrap:wrap;margin-bottom:1.5rem;grid-gap:1rem}.loop-filter-list{flex-direction:column}.loop-filter-item{position:relative}.loop-filter-list .loop-filter-item{display:flex;grid-gap:1rem}.loop-filter .list-menu{display:flex;flex-wrap:wrap;grid-gap:.5rem;grid-row-gap:.5rem}.loop-filter .list-item{white-space:nowrap;display:inline-flex;align-items:center;padding:1px 5px;border-radius:4px;text-decoration:none}.loop-filter .list-menu .selected{background-color:rgba(150,150,150,.2)}.loop-filter .loop-filter-item-heading{font-weight:600}.loop-filter .dropdown-menu .selected{position:relative}.loop-filter .loop-filter-item-search input{margin:0}.loop-toggle-hide{display:none!important}.loop-filter-more-less{cursor:pointer;font-weight:500}.loop-filter .dropdown-menu .selected:after{content:'';display:inline-block;width:.65em;height:.35em;border-left:.1em solid currentColor;border-bottom:.1em solid currentColor;transform:translate(-50%,-50%) rotate(-45deg);position:absolute;right:.5rem;top:45%;opacity:.6}.loop-filter-count{display:inline-block;background-color:rgba(150,160,170,.2);padding:0 .45em;margin-inline-start:.125rem;-webkit-margin-start:.125rem;font-size:11px;border-radius:1rem}.loop-filter-count:empty{display:none}.dropdown-menu .multi-range{margin:1rem}input[type=range].multirange{-webkit-appearance:none;height:2px;padding:0;margin:1rem 0 0;width:calc(100% - 0px);display:inline-block;vertical-align:top;background-color:rgba(150,150,150,.5);color:currentColor;outline:0;border:0;border-radius:6px}input[type=range].multirange.original{position:absolute}input[type=range].multirange::-webkit-slider-thumb{-webkit-appearance:none;position:relative;z-index:2;border:none;width:12px;height:12px;border-radius:100%;background-color:currentColor}input[type=range].multirange::-moz-range-thumb{border:none;width:12px;height:12px;border-radius:100%;background-color:currentColor}input[type=range].multirange.original::-moz-range-thumb{z-index:2}input[type=range].multirange.ghost{position:relative;background:var(--track-background);--track-background:linear-gradient(to right, transparent var(--low), var(--range-color) 0, var(--range-color) var(--high), transparent 0) no-repeat 0 100%/100% 100%;--range-color:currentColor}input[type=range].multirange.ghost::-webkit-slider-thumb{position:relative;z-index:2}input[type=range].multirange.ghost::-moz-range-thumb{z-index:2}.multi-range{position:relative}.range-max,.range-min{position:absolute;top:-6px;font-size:10px;width:10px;display:flex;justify-content:center;text-align:center;left:calc(var(--left) * 1%);margin-left:calc(0px - var(--left)/ 100 * 10px)}.spinner{display:inline-block;width:1rem;height:1rem;vertical-align:text-bottom;background-color:currentColor;border-radius:50%;opacity:0;-webkit-animation:spinner .75s linear infinite;animation:spinner .75s linear infinite}.loop-filter-keys{width:100%;display:flex;grid-gap:.5rem;flex-wrap:wrap}.loop-filter-keys a{font-weight:600;font-size:.9em;display:inline-flex;text-decoration:none}.loop-filter-keys a:after{content:'\00d7';font-family:arial;font-weight:400;display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;line-height:0;border-radius:100%;background-color:#666;color:#fff;opacity:0;margin:-4px -7px 0 -7px;transition:opacity .2s}.loop-filter-keys a:hover:after{opacity:1}.loop-filter-total{width:100%}a.loop-filter-clear{font-weight:400;align-items:center;opacity:.7}a.loop-filter-clear:hover{opacity:1}a.loop-filter-clear:after{order:-1;margin:2px;opacity:1}@keyframes spinner{0%{transform:scale(0)}50%{opacity:1}}@media (max-width:576px){:root{--loop-grid-gap:1rem}.block-loop-row .block-loop-items{--loop-columns:1}.block-loop-row:not(.has-loop-posts):not(.block-loop-xs):not(.block-loop-inline) .block-loop-item:not(.block-loop-inline) .entry-footer{flex:auto;width:100%}.block-loop-row:not(.has-loop-posts):not(.block-loop-xs):not(.block-loop-inline) .block-loop-item:not(.block-loop-inline) .post-thumbnail{width:4.5rem}.block-loop-row .entry-footer>:first-child:not(.btn-add){padding-inline-start:0}.block-loop-row .add_to_cart_inline,.block-loop-row .btn-purchase,.block-loop-row .entry-description,.block-loop-row .entry-info{display:none}.block-loop-inline .waveform,.block-loop-nav,.has-loop-posts .btn-download,.has-loop-posts .btn-like,.has-loop-posts .play-count{display:none}.modal-open .wp-block-loop-product .block-loop-slider{overflow:visible}.entry-content>.wp-block-loop-slider:not(.block-loop-center) .block-loop-items{padding:0 var(--x-gap,var(--wp--style--root--padding-left,1rem));margin:0 calc(var(--x-gap,var(--wp--style--root--padding-left,1rem)) * -1);scroll-snap-type:none;--loop-max-width:85%}}@media (min-width:577px){.block-loop-with-filter{display:flex;align-items:flex-start;height:100%}.block-loop-with-filter .block-loop-items{flex:1}.block-loop-with-filter .loop-filter{flex-direction:column;min-width:15rem;margin:0;height:100%}.is-series .has-loop-posts .post-thumbnail{border-radius:5px;width:5rem;height:5rem}}
  • loops-block/trunk/includes/class-loopsblock.php

    r3669702 r3725635  
    22
    33/**
    4  * Loops base class.
     4 * LoopsBlock class
    55 *
    66 * @since 1.0.0
    … …  
    1515
    1616    /**
     17     * Nonce action for filter click protection.
     18     */
     19    const NONCE_ACTION = 'loopsblock_filter_click';
     20
     21    /**
     22     * cache group
     23     */
     24    const CACHE_GROUP_RENDER   = 'loopsblock_render';
     25    const CACHE_GROUP_TERMS    = 'loopsblock_terms';
     26
     27    /**
    1728     * The name from the plugin file
    1829     *
    … …  
    6980    private $query_string = '';
    7081    /**
     82     * Cache version (self-incrementing int)
     83     *
     84     * @var int|null
     85     */
     86    private static $cache_version = null;
     87    /**
     88     * Per-request memo for is_user_context()
     89     *
     90     * @var array
     91     */
     92    private static $user_context_memo = array();
     93    /**
     94     * Per-request memo for get_normalized_query_string()
     95     *
     96     * @var string|null
     97     */
     98    private $normalized_qs = null;
     99    /**
    71100     * Instance.
    72      * 
     101     *
    73102     * @var object
    74103     */
    … …  
    120149        add_action( 'ffl_loop_template', array( $this, 'get_loopsblock_template' ) );
    121150
     151        /* ---------------- Cache invalidation hooks ---------------- */
     152        add_action( 'save_post',        array( $this, 'flush_cache' ) );
     153        add_action( 'clean_post_cache', array( $this, 'flush_cache' ) );
     154        add_action( 'set_object_terms', array( $this, 'flush_cache' ) );
     155        add_action( 'created_term',     array( $this, 'flush_cache' ) );
     156        add_action( 'edited_term',      array( $this, 'flush_cache' ) );
     157        add_action( 'delete_term',      array( $this, 'flush_cache' ) );
     158        add_action( 'profile_update',   array( $this, 'flush_cache' ) );
     159        add_action( 'user_register',    array( $this, 'flush_cache' ) );
     160        add_action( 'delete_user',      array( $this, 'flush_cache' ) );
     161        add_action( 'switch_theme',     array( $this, 'flush_all_caches' ) );
     162        add_action( 'activated_plugin',   array( $this, 'flush_all_caches' ) );
     163        add_action( 'deactivated_plugin', array( $this, 'flush_all_caches' ) );
     164
    122165        do_action( 'loopsblock_init', $this );
    123166    }
     167
     168    /* ================================================================== */
     169    /* Cache helpers                                                       */
     170    /* ================================================================== */
     171
     172    /**
     173     * Cache version (self-incrementing int).
     174     *
     175     * @return int
     176     */
     177    private static function cache_version() {
     178        if ( null === self::$cache_version ) {
     179            self::$cache_version = (int) get_option( 'loopsblock_cache_version', 1 );
     180        }
     181        return self::$cache_version;
     182    }
     183
     184    /**
     185     * Build a versioned cache key.
     186     * Payload is recursively ksort'd so key order in arrays doesn't matter.
     187     *
     188     * @param string $prefix
     189     * @param mixed  $payload
     190     * @return string
     191     */
     192    private static function cache_key( $prefix, $payload ) {
     193        return $prefix . '_v' . self::cache_version() . '_' . md5( wp_json_encode( self::ksort_recursive( $payload ) ) );
     194    }
     195
     196    /**
     197     * Recursively sort arrays by key so json_encode is stable.
     198     *
     199     * @param mixed $array
     200     * @return mixed
     201     */
     202    private static function ksort_recursive( $array ) {
     203        if ( ! is_array( $array ) ) {
     204            return $array;
     205        }
     206        ksort( $array );
     207        foreach ( $array as $k => $v ) {
     208            $array[ $k ] = self::ksort_recursive( $v );
     209        }
     210        return $array;
     211    }
     212
     213    /**
     214     * Bump cache version → invalidates all group caches at once.
     215     */
     216    public function flush_cache() {
     217        $v = (int) get_option( 'loopsblock_cache_version', 1 );
     218        $v++;
     219        update_option( 'loopsblock_cache_version', $v, false );
     220        self::$cache_version = $v;
     221
     222        // WP 6.1+ supports flushing a cache group (only with persistent cache).
     223        if ( function_exists( 'wp_cache_supports' ) && wp_cache_supports( 'flush_group' ) ) {
     224            wp_cache_flush_group( self::CACHE_GROUP_RENDER );
     225            wp_cache_flush_group( self::CACHE_GROUP_TERMS );
     226        }
     227    }
     228
     229    /**
     230     * Flush everything including editor transients.
     231     */
     232    public function flush_all_caches() {
     233        $this->flush_cache();
     234        delete_transient( 'loopsblock_tpls' );
     235        delete_transient( 'loopsblock_types' );
     236        delete_transient( 'loopsblock_taxonomies' );
     237        delete_transient( 'loopsblock_images' );
     238        delete_transient( 'loopsblock_user_roles' );
     239    }
     240
     241    /**
     242     * Is a persistent object cache available?
     243     *
     244     * @return bool
     245     */
     246    private static function has_persistent_object_cache() {
     247        return function_exists( 'wp_using_ext_object_cache' ) && wp_using_ext_object_cache();
     248    }
     249
     250    /**
     251     * Is transient caching allowed for this key/group/attributes?
     252     *
     253     * Behavior:
     254     *  - When a persistent object cache (Redis/Memcached) is available,
     255     *    transient is NEVER used — wp_cache_* is sufficient and we avoid
     256     *    polluting wp_options.
     257     *  - Otherwise (no persistent object cache), transient is written ONLY
     258     *    when the calling block opts in via `$attributes['transient_cache']`,
     259     *    or a filter forces it on.
     260     *
     261     * @param string $key
     262     * @param string $group
     263     * @param array  $attributes
     264     * @return bool
     265     */
     266    private static function is_transient_available( $key = '', $group = '', $attributes = array() ) {
     267        // Redis/Memcached present → always skip transient.
     268        if ( self::has_persistent_object_cache() ) {
     269            return false;
     270        }
     271
     272        $default = ! empty( $attributes['transient_cache'] );
     273        return (bool) apply_filters( 'loopsblock_enable_transient_cache', $default, $key, $group, $attributes );
     274    }
     275
     276    /**
     277     * Is filter-click nonce verification enabled?
     278     *
     279     * Default: enabled.
     280     *
     281     * Disable globally:
     282     *   add_filter( 'loopsblock_enable_filter_nonce', '__return_false' );
     283     *
     284     * @return bool
     285     */
     286    private static function is_filter_nonce_enabled() {
     287        return (bool) apply_filters( 'loopsblock_enable_filter_nonce', true );
     288    }
     289
     290    /**
     291     * Cache get: wp_cache_* first; transient fallback (opt-in, no-persistent-cache only).
     292     *
     293     * @param string $key
     294     * @param string $group
     295     * @param array  $attributes  Block attributes (for transient opt-in).
     296     * @return mixed|false
     297     */
     298    private static function cache_get( $key, $group, $attributes = array() ) {
     299        $v = wp_cache_get( $key, $group );
     300        if ( false !== $v ) {
     301            return $v;
     302        }
     303        if ( self::is_transient_available( $key, $group, $attributes ) ) {
     304            $v = get_transient( $key );
     305            if ( false !== $v ) {
     306                // warm the per-request object cache
     307                wp_cache_set( $key, $v, $group, MINUTE_IN_SECONDS * 5 );
     308                return $v;
     309            }
     310        }
     311        return false;
     312    }
     313
     314    /**
     315     * Cache set: write wp_cache_*; write transient only when opted in
     316     * AND no persistent object cache is available.
     317     *
     318     * Empty string / null / empty array values are skipped to avoid polluting wp_options.
     319     *
     320     * @param string $key
     321     * @param mixed  $val
     322     * @param string $group
     323     * @param int    $ttl
     324     * @param array  $attributes  Block attributes (for transient opt-in).
     325     */
     326    private static function cache_set( $key, $val, $group, $ttl, $attributes = array() ) {
     327        // FIX: don't pollute wp_options with empty values
     328        if ( '' === $val || null === $val || array() === $val ) {
     329            return;
     330        }
     331        wp_cache_set( $key, $val, $group, $ttl );
     332        if ( self::is_transient_available( $key, $group, $attributes ) ) {
     333            set_transient( $key, $val, $ttl );
     334        }
     335    }
     336
     337    /* ================================================================== */
     338    /* Query string normalization (nonce-aware)                            */
     339    /* ================================================================== */
     340
     341    /**
     342     * Get the normalized query string for cache key + query building.
     343     *
     344     * Behavior:
     345     *  - Strips `click` (nonce) from the returned string.
     346     *  - If filter nonce is enabled and the request lacks a valid `click`,
     347     *    all filter params (taxQuery/metaQuery/order/search/sort) are
     348     *    dropped, keeping only `id`. The resulting page is identical to a
     349     *    fresh (unfiltered) visit and shares the same cache entry.
     350     *  - If filter nonce is disabled, only `click` is stripped.
     351     *
     352     * Memoized per-request.
     353     *
     354     * @return string
     355     */
     356    private function get_normalized_query_string() {
     357        if ( null !== $this->normalized_qs ) {
     358            return $this->normalized_qs;
     359        }
     360
     361        $query_string = $this->query_string;
     362        if ( '' === $query_string ) {
     363            $this->normalized_qs = '';
     364            return '';
     365        }
     366
     367        parse_str( $query_string, $query );
     368
     369        // Extract block discriminator `id` (never subject to nonce check).
     370        $id = isset( $query['id'] ) ? $query['id'] : null;
     371
     372        if ( ! self::is_filter_nonce_enabled() ) {
     373            // Nonce disabled → just strip `click`, keep everything else.
     374            unset( $query['click'] );
     375            $this->normalized_qs = http_build_query( $query );
     376            return $this->normalized_qs;
     377        }
     378
     379        // Determine whether the request carries filter params
     380        // (excluding `id` and `click`).
     381        $filter_params = array_diff_key( $query, array( 'id' => 1, 'click' => 1 ) );
     382
     383        if ( empty( $filter_params ) ) {
     384            // No filter params → strip stray click, keep as-is.
     385            unset( $query['click'] );
     386            $this->normalized_qs = http_build_query( $query );
     387            return $this->normalized_qs;
     388        }
     389
     390        // Has filter params → require valid nonce.
     391        $nonce_ok = isset( $query['click'] ) && wp_verify_nonce( $query['click'], self::NONCE_ACTION );
     392
     393        if ( ! $nonce_ok ) {
     394            // Invalid / missing nonce → drop all filter params, keep `id`.
     395            $query = array();
     396            if ( null !== $id ) {
     397                $query['id'] = $id;
     398            }
     399
     400            if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
     401                error_log( '[loopsblock] invalid or missing filter nonce from ' . ( $_SERVER['REMOTE_ADDR'] ?? '?' ) );
     402            }
     403        } else {
     404            // Valid nonce → strip it, keep filter params + id.
     405            unset( $query['click'] );
     406        }
     407
     408        $this->normalized_qs = http_build_query( $query );
     409        return $this->normalized_qs;
     410    }
     411
     412    /**
     413     * Does this block declare a permission filter?
     414     * If yes → must NOT be cached.
     415     *
     416     * @param array $attributes
     417     * @return bool
     418     */
     419    private function has_permission_filter( $attributes ) {
     420        if ( empty( $attributes['displayPermission'] ) ) {
     421            return false;
     422        }
     423        return in_array(
     424            $attributes['displayPermission'],
     425            array( 'users', 'user_roles', 'php_func' ),
     426            true
     427        );
     428    }
     429
     430    /**
     431     * Contexts that must not be cached because they depend on the current user.
     432     *
     433     * @return array
     434     */
     435    private function get_user_contexts() {
     436        return apply_filters( 'loopsblock_user_contexts', array(
     437            'user_followers', 'user_following', 'user_likes', 'user_dislikes',
     438            'user_downloads', 'user_notifications', 'user_posts',
     439        ) );
     440    }
     441
     442    /**
     443     * Does this loop depend on the current user via its `context` attribute?
     444     * Memoized per-request.
     445     *
     446     * @param array $attributes
     447     * @return bool
     448     */
     449    private function is_user_context( $attributes ) {
     450        if ( empty( $attributes['context'] ) ) {
     451            return false;
     452        }
     453        $ctx = strtolower( (string) $attributes['context'] );
     454        if ( ! isset( self::$user_context_memo[ $ctx ] ) ) {
     455            self::$user_context_memo[ $ctx ] = in_array( $ctx, $this->get_user_contexts(), true );
     456        }
     457        return self::$user_context_memo[ $ctx ];
     458    }
     459
     460    /**
     461     * User salt for cache key: anon vs. user_id + role hash.
     462     *
     463     * @return string
     464     */
     465    private function user_salt() {
     466        if ( ! is_user_logged_in() ) {
     467            return 'anon';
     468        }
     469        $u = wp_get_current_user();
     470        return 'u' . $u->ID . '_' . md5( implode( ',', (array) $u->roles ) );
     471    }
     472
     473    /* ================================================================== */
     474    /* Registration                                                        */
     475    /* ================================================================== */
    124476
    125477    /**
    … …  
    162514     */
    163515    public function get_user_roles(){
     516        $cache_key = 'loopsblock_user_roles_v' . self::cache_version();
     517        $cached = get_transient( $cache_key );
     518        if ( false !== $cached ) {
     519            return $cached;
     520        }
     521
    164522        global $wp_roles;
    165523        $wp_roles_names = array_reverse( $wp_roles->role_names );
    166         return array_keys($wp_roles_names);
     524        $roles = array_keys( $wp_roles_names );
     525
     526        set_transient( $cache_key, $roles, DAY_IN_SECONDS );
     527        return $roles;
    167528    }
    168529
    169530    /**
    170531     * filter the permission from attributes.
    171      *
    172      * @param object block attributes
    173532     */
    174533    public function isPermissionFiltered($atts){
    … …  
    212571    /**
    213572     * render the permission block
    214      *
    215      * @param object block attributes
    216      * @param string block content
    217573     */
    218574    public function render_permission_block( $atts, $content ){
    … …  
    226582        $filtered_bool = (bool) $filtered;
    227583
    228         if ( $display xor $filtered ) {
     584        if ( $display xor $filtered_bool ) {
    229585            return '';
    230586        }
    … …  
    233589    }
    234590
     591    /* ================================================================== */
     592    /* Assets                                                              */
     593    /* ================================================================== */
     594
    235595    /**
    236596     * enqueue styles
    237597     */
    238598    public function enqueue_styles() {
     599        if ( wp_style_is( $this->name . '-style', 'registered' ) ) {
     600            wp_enqueue_style( $this->name . '-style' );
     601            return;
     602        }
    239603        wp_register_style(
    240604            $this->name . '-style',
    … …  
    243607            $this->version
    244608        );
    245 
    246609        wp_enqueue_style( $this->name . '-style' );
    247610    }
    … …  
    260623            true
    261624        );
    262 
    263625        wp_enqueue_script( $this->name );
    264626    }
    265627
    266     /**
    267      * render the loop block
    268      *
    269      * @param object block attributes
     628    /* ================================================================== */
     629    /* Render                                                              */
     630    /* ================================================================== */
     631
     632    /**
     633     * render the loop block (cached decorator).
     634     *
     635     * @param array $attributes
     636     * @return string
    270637     */
    271638    public function render_loop_block( $attributes ) {
     639        // permission-gated blocks are never cached
     640        $cacheable = ! $this->has_permission_filter( $attributes );
     641
     642        // user-context loops (my likes / my followers / …) are never cached
     643        if ( $this->is_user_context( $attributes ) ) {
     644            $cacheable = false;
     645        }
     646
     647        // admin debug / context messages are dynamic → skip cache
     648        if ( current_user_can( 'manage_options' )
     649            && ( ! empty( $_REQUEST['context'] ) || ! empty( $attributes['debug'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     650            $cacheable = false;
     651        }
     652
     653        $cacheable = apply_filters( 'loopsblock_enable_render_cache', $cacheable, $attributes );
     654
     655        $attributes = apply_filters( 'loopsblock_attributes', $attributes );
     656
     657        // Normalized query string (nonce-aware, no `click`)
     658        $normalized_qs = $this->get_normalized_query_string();
     659        $query_args    = $this->get_query_params( $attributes, $normalized_qs );
     660
     661        $cache_key = '';
     662        if ( $cacheable ) {
     663            // Cache key must include BOTH:
     664            //   - $attributes   → affects display (title, cols, slider, template, …)
     665            //   - $query_args   → affects query (post_type, tax_query, …)
     666            $cache_key = self::cache_key( 'loopsblock_render', array(
     667                'attr' => $attributes,
     668                'q'    => $query_args,
     669                'qs'   => $normalized_qs,
     670                'url'  => $this->query_url,
     671                'user' => $this->user_salt(),
     672            ) );
     673            $cached = self::cache_get( $cache_key, self::CACHE_GROUP_RENDER, $attributes );
     674            if ( false !== $cached ) {
     675                return apply_filters( 'loopsblock_content', $cached );
     676            }
     677        }
     678
     679        $block_content = $this->do_render_loop_block( $attributes, $query_args );
     680
     681        if ( $cacheable && '' !== $cache_key && '' !== $block_content ) {
     682            self::cache_set( $cache_key, $block_content, self::CACHE_GROUP_RENDER, 10 * MINUTE_IN_SECONDS, $attributes );
     683        }
     684
     685        return apply_filters( 'loopsblock_content', $block_content );
     686    }
     687
     688    /**
     689     * The actual render logic.
     690     *
     691     * @param array $attributes
     692     * @param array $query_args
     693     * @return string
     694     */
     695    private function do_render_loop_block( $attributes, $query_args ) {
    272696        $block_content = $className = $slick = $jscroll = $more = $pager = $title = $filter = $items = '';
    273697        $query = false;
    274         $attributes = apply_filters( 'loopsblock_attributes', $attributes );
    275698
    276699        do_action( 'loopsblock_before_render', $attributes );
    … …  
    279702            $block_content = __( 'No loop type.', 'loops-block' );
    280703        } else {
    281             $query_args = $this->get_query_params($attributes);
    282704            $total_pages = 0;
    283705            if ( $attributes[ 'type' ] == 'user' ) {
    … …  
    370792
    371793            if (isset($attributes[ 'pager' ]) && $attributes[ 'pager' ] == 'pagination' ) {
    372                 $pager = $this->get_pagination( $total_pages, $query_args[ 'paged' ] );
     794                $paged_arg = isset( $query_args[ 'paged' ] ) ? $query_args[ 'paged' ] : 1;
     795                $pager = $this->get_pagination( $total_pages, $paged_arg );
    373796            }
    374797
    … …  
    386809                    $jscroll = 'data-plugin="scroller" data-option="' . sprintf( '{autoTrigger: %1$s}"', $attributes[ 'pager' ] == 'scroll' ? 'true' : 'false' );
    387810                } else {
    388                     // overide wrapper
    389811                    $wrapper = '%1$s%2$s%3$s%4$s%5$s';
    390812                }
    391                 if ( $total_pages > $query_args[ 'paged' ] ) {
    392                     $attributes[ 'paged' ] = $query_args[ 'paged' ] + 1;
     813                $paged_arg = isset( $query_args[ 'paged' ] ) ? $query_args[ 'paged' ] : 1;
     814                if ( $total_pages > $paged_arg ) {
     815                    $attributes[ 'paged' ] = $paged_arg + 1;
    393816                    $attributes            = $this->normalize_load_more_attributes( $attributes );
    394                     $url                   = get_rest_url( null, '/loop/more' ). sprintf( '?%s', $this->http_build_query( $attributes ) );
     817                    $url                   = get_rest_url( null, '/loop/more' ). sprintf( '?%s', $this->build_more_query( $attributes ) );
    395818                    $url                   = apply_filters( 'loopsblock_more_link', $url, $attributes, $this );
    396819                    $more                  = '<a href="' . esc_url( $url ) . '" class="scroller no-ajax button"><span>• • •</span><span class="screen-reader-text">' . __( 'More', 'loops-block' ) . '</span></a>';
    397                     $more                  = apply_filters( 'loopsblock_more_button', $more, $url, $this ); 
     820                    $more                  = apply_filters( 'loopsblock_more_button', $more, $url, $this );
    398821                }
    399822            }
    … …  
    409832                    $block_content .= '<p>'.__( 'No loop item.', 'loops-block' ).'</p>';
    410833                }
    411                 if(!empty( $attributes[ 'debug' ] )){
    412                     $block_content .= '<pre style="font-size: 11px;order:10; white-space:normal">' . json_encode( $query_args ) . '</pre>';
     834                if(!empty( $attributes[ 'debug' ] ) && defined( 'WP_DEBUG' ) && WP_DEBUG ){
     835                    $block_content .= '<pre style="font-size: 11px;order:10; white-space:normal">' . esc_html( wp_json_encode( $query_args ) ) . '</pre>';
    413836                }
    414837            }
    415838        }
    416839        do_action( 'loopsblock_after_render', $attributes, $query );
    417         return apply_filters( 'loopsblock_content', $block_content );
     840        return $block_content;
    418841    }
    419842
    420843    /**
    421844     * output the loop block
    422      *
    423      * @param object block attributes
    424      * @param bolean echo content or not
    425845     */
    426846    public function the_block( $attributes, $echo = true ) {
    … …  
    436856    /**
    437857     * output the filter
    438      *
    439      * @param object block attributes
    440      * @param bolean echo filter or not
    441858     */
    442859    public function the_filter( $attributes, $echo = true ) {
    … …  
    448865    }
    449866
    450     /**
    451      * get the filter content
    452      *
    453      * @param object block attributes
     867    /* ================================================================== */
     868    /* Filter (cached)                                                     */
     869    /* ================================================================== */
     870
     871    /**
     872     * get the filter content (cached)
     873     *
     874     * @param array $attributes
     875     * @return string
    454876     */
    455877    private function get_filter( $attributes ) {
    … …  
    457879            return '';
    458880        }
    459        
     881
     882        // user-context filters are never cached
     883        $cacheable = ! $this->is_user_context( $attributes );
     884
     885        $cache_key = '';
     886        if ( $cacheable ) {
     887            // Only filter-relevant attributes affect the output.
     888            $filter_keys = array( 'filter', 'id', 'url', 'ids' );
     889            $filter_attr = array_intersect_key( $attributes, array_flip( $filter_keys ) );
     890
     891            $cache_key = self::cache_key( 'loopsblock_filter', array(
     892                'attr' => $filter_attr,
     893                'qs'   => $this->get_normalized_query_string(),
     894                'url'  => $this->query_url,
     895            ) );
     896            $cached = self::cache_get( $cache_key, self::CACHE_GROUP_RENDER, $attributes );
     897            if ( false !== $cached ) {
     898                return $cached;
     899            }
     900        }
     901
     902        $html = $this->do_get_filter( $attributes );
     903
     904        if ( $cacheable && '' !== $cache_key && '' !== $html ) {
     905            self::cache_set( $cache_key, $html, self::CACHE_GROUP_RENDER, 10 * MINUTE_IN_SECONDS, $attributes );
     906        }
     907        return $html;
     908    }
     909
     910    /**
     911     * Actually build filter HTML.
     912     *
     913     * Uses the normalized query string — nonce is already verified there.
     914     *
     915     * @param array $attributes
     916     * @return string
     917     */
     918    private function do_get_filter( $attributes ) {
    460919        $filter  = $attributes[ 'filter' ];
    461920        $url     = isset($attributes[ 'url' ]) ? $attributes[ 'url' ] : $this->query_url;
    … …  
    463922        $url = preg_replace($pattern, '', $url);
    464923        $id = isset($attributes[ 'id' ]) ? $attributes[ 'id' ] : '';
    465         // parse query string
    466         $query_string = $this->query_string;
     924
     925        // Use normalized query string — no `click`, already nonce-verified.
     926        $query_string = $this->get_normalized_query_string();
    467927        parse_str( $query_string, $query );
    468928        array_walk_recursive($query, 'sanitize_text_field');
    … …  
    473933            }
    474934        }
    475         // todo: parse the attribute meta/tax/order to menu
    476 
    477         // if we got ?s= and not on search page
     935
    478936        if(isset($query['s']) && !is_search()){
    479937            $query['search'] = $query['s'];
    … …  
    515973
    516974            // all taxonomy
    517             if( strpos( strtolower($value), '__all' ) ){
     975            if( strpos( strtolower($value), '__all' ) !== false ){
    518976                $reg = '/(.*?)__all\[(.*?)\]/';
    519977                if( preg_match($reg, $v, $m) ){
    … …  
    521979                    $default = (object) array( 'name' => (isset($m[2]) ? $m[2] : 'All'), 'slug' => '', 'count' => '' );
    522980                    if(!empty($attributes['ids'])) {
    523                         // get terms by ids to use connect filter
    524981                        $terms = $this->get_terms($i, $attributes['ids']);
    525982                    }else{
    526                         // get all terms
    527                         $terms = get_terms( $i );
     983                        $terms = $this->get_terms_cached( $i );
    528984                    }
    529985                    if( !empty($terms) && !is_wp_error( $terms ) ){
    … …  
    5461002                $j = isset($term[1]) ? $term[1] : $term[0];
    5471003                $item = array( 'name' => $ma[2] );
    548                 // set value for ranges
    5491004                $ranges = preg_match( '/^\d+-\d+$/', $j );
    5501005                if( $ranges ){
    … …  
    5611016
    5621017        if( empty($filters) ){
    563             return;
     1018            return '';
    5641019        }
    5651020
    … …  
    5761031
    5771032    /**
     1033     * Cached wrapper for get_terms() used by the filter.
     1034     *
     1035     * Note: term lists are global (not block-specific), so we don't pass
     1036     * block attributes. Transient opt-in must be done via filter if needed.
     1037     */
     1038    private function get_terms_cached( $taxonomy ) {
     1039        $cache_key = 'loopsblock_filter_terms_v' . self::cache_version() . '_' . $taxonomy;
     1040        $cached    = self::cache_get( $cache_key, self::CACHE_GROUP_TERMS );
     1041        if ( false !== $cached ) {
     1042            return $cached;
     1043        }
     1044
     1045        $terms = get_terms( array(
     1046            'taxonomy'   => $taxonomy,
     1047            'hide_empty' => false,
     1048        ) );
     1049
     1050        if ( is_wp_error( $terms ) ) {
     1051            return $terms;
     1052        }
     1053
     1054        self::cache_set( $cache_key, $terms, self::CACHE_GROUP_TERMS, HOUR_IN_SECONDS );
     1055        return $terms;
     1056    }
     1057
     1058    /**
    5781059     * build the filter item
    579      *
    580      * @param object filter item
    581      * @param string
    582      * @param string
    583      * @param array
    584      * @param string filter url
    585      * @param string attributes id
    5861060     */
    5871061    private function build_filter_item(&$item, $key, $term, $value, $q, $url, $id){
    … …  
    5981072                        unset( $q[$key][$term] );
    5991073                    }
    600                    
     1074
    6011075                    $q[$key][$term][$value] = '';
    6021076                }
    … …  
    6261100        }
    6271101
     1102        // Add nonce for filter click protection
     1103        if ( ! empty( $str ) && self::is_filter_nonce_enabled() ) {
     1104            $str['click'] = wp_create_nonce( self::NONCE_ACTION );
     1105        }
     1106
    6281107        $url = $url . '?' . http_build_query($str);
    6291108        $url = apply_filters( 'loopsblock_filter_link', $url, $item, $key, $term, $value, $q, $str );
    … …  
    6331112    /**
    6341113     * build the filter keys
    635      *
    636      * @param array
    637      * @param object
    638      * @param array
    6391114     */
    6401115    public function build_filter_keys($filters, $attributes, $keys){
    … …  
    6481123        $sep = apply_filters('loopsblock_filter_sep', ',');
    6491124        $clear = $attributes['filterClearText'];
    650        
     1125
    6511126        foreach ( $keys as $key ){
    6521127            if($key == end($keys)){
    … …  
    6681143    }
    6691144
    670     /**
    671      * get the ad content
    672      *
    673      * @param object
     1145    /* ================================================================== */
     1146    /* Ad (cached)                                                         */
     1147    /* ================================================================== */
     1148
     1149    /**
     1150     * get the ad content (cached)
    6741151     */
    6751152    private function get_ad_content($attributes){
    6761153        if(!isset($attributes['adTitle']) || $attributes['adTitle']===''){
    677             return;
     1154            return '';
     1155        }
     1156
     1157        $cacheable = ! $this->is_user_context( $attributes );
     1158
     1159        $cache_key = '';
     1160        if ( $cacheable ) {
     1161            $ad_keys = array( 'adImage', 'adTitle', 'adSubtitle', 'adSponsor', 'adLink', 'adOrder' );
     1162            $ad_attr = array_intersect_key( $attributes, array_flip( $ad_keys ) );
     1163
     1164            $cache_key = self::cache_key( 'loopsblock_ad', $ad_attr );
     1165            $cached = self::cache_get( $cache_key, self::CACHE_GROUP_RENDER, $attributes );
     1166            if ( false !== $cached ) {
     1167                return $cached;
     1168            }
    6781169        }
    6791170
    … …  
    6961187            include plugin_dir_path( dirname( __FILE__ ) ) . $tpl;
    6971188        }
    698 
    699         return ob_get_clean();
    700     }
     1189        $html = ob_get_clean();
     1190
     1191        if ( $cacheable && '' !== $cache_key && '' !== $html ) {
     1192            self::cache_set( $cache_key, $html, self::CACHE_GROUP_RENDER, 10 * MINUTE_IN_SECONDS, $attributes );
     1193        }
     1194        return $html;
     1195    }
     1196
     1197    /* ================================================================== */
     1198    /* Content / templates                                                 */
     1199    /* ================================================================== */
    7011200
    7021201    /**
    7031202     * get the content
    704      *
    705      * @param object query results
    706      * @param object block attributes
    707      * @param array query args
    7081203     */
    7091204    private function get_content( $query, $attributes, $query_args ) {
    … …  
    7341229        } else {
    7351230            foreach ( $query->posts as $post ) {
    736                 // avoid loop in loop
    7371231                $post->post_content = str_replace( "wp:block/loop", "wp:block/loop-disabled", $post->post_content );
    7381232                setup_postdata( $post );
    … …  
    7471241    /**
    7481242     * get the loop content
    749      *
    750      * @param object query results
    751      * @param object block attributes
    752      * @param array query args
    7531243     */
    7541244    public function get_loopsblock_template() {
    … …  
    7601250    /**
    7611251     * get the loop template
    762      *
    763      * @param string template file
    764      * @param string post/user/taxonomy
    7651252     */
    7661253    private function get_template( $tpl, $type ) {
    … …  
    7841271
    7851272    /**
    786      * locate the template file
    787      *
    788      * @param string template name
    789      * @param string template path
    790      * @param string default template path
     1273     * locate the template file (per-request static cache)
    7911274     */
    7921275    public function locate_template( $template_name, $template_path = '', $default_path = '' ) {
     1276        static $runtime = array();
     1277
     1278        $cache_key = $template_name . '|' . $template_path . '|' . $default_path;
     1279        if ( isset( $runtime[ $cache_key ] ) ) {
     1280            return $runtime[ $cache_key ];
     1281        }
     1282
    7931283        if ( ! $template_path ) {
    7941284            $template_path = '/templates/';
    … …  
    7991289        }
    8001290
    801         // Look within passed path within the theme - this is priority.
    8021291        $template = locate_template(
    8031292            array(
    … …  
    8071296        );
    8081297
    809         // Get default template/.
    8101298        if ( ! $template ) {
    811 
    8121299            $tpl_name = basename( $template_name );
    8131300
    814             // Force .php extension if template name is tampered with
    8151301            if ( 'php' != pathinfo( $tpl_name, PATHINFO_EXTENSION ) ) {
    8161302              $info = pathinfo( $tpl_name );
    … …  
    8181304            }
    8191305
    820             // Rebuild the template path removing anything nasty
    8211306            $tpl = $default_path . trailingslashit( $template_path ) . $tpl_name;
    8221307
    … …  
    8261311        }
    8271312
    828         // Return what we found.
    829         return apply_filters( 'loopsblock_locate_template', $template, $template_name, $template_path );
    830     }
     1313        $template = apply_filters( 'loopsblock_locate_template', $template, $template_name, $template_path );
     1314
     1315        $runtime[ $cache_key ] = $template;
     1316        return $template;
     1317    }
     1318
     1319    /* ================================================================== */
     1320    /* Query params                                                        */
     1321    /* ================================================================== */
    8311322
    8321323    /**
    8331324     * get loop query parameters
    834      *
    835      * @param object attributes
    836      */
    837     private function get_query_params( $args ) {
     1325     *
     1326     * @param array       $args
     1327     * @param string|null $query_string  Optional. Pre-normalized query string.
     1328     * @return array
     1329     */
     1330    private function get_query_params( $args, $query_string = null ) {
     1331        return $this->do_get_query_params( $args, $query_string );
     1332    }
     1333
     1334    /**
     1335     * Build query params.
     1336     */
     1337    private function do_get_query_params( $args, $query_string = null ) {
    8381338        $args = apply_filters( 'loopsblock_get_query_params_attributes', $args);
     1339
     1340        if ( null === $query_string ) {
     1341            $query_string = $this->get_normalized_query_string();
     1342        }
     1343
    8391344        $query_args = [];
    8401345        if ( $args[ 'type' ] == 'user' || $args[ 'type' ] == 'taxonomy' ) {
    … …  
    8491354            $query_args[ 'posts_per_page' ] = $args[ 'pages' ];
    8501355            $include                        = 'post__in';
    851             // ignore sticky post
    8521356            $query_args[ 'ignore_sticky_posts' ] = 1;
    8531357        }
    … …  
    8621366        }
    8631367
    864         // ids
    8651368        if ( !empty( $args[ 'ids' ] ) ) {
    8661369            $query_args[ $include ] = $args[ 'ids' ];
    8671370        }
    8681371
    869         // query (admin query field OR front-end 'query' arg)
    8701372        if ( !empty( $args[ 'query' ] ) ) {
    8711373            $query_args = wp_parse_args( $args[ 'query' ], $query_args );
    8721374        }
    8731375
    874         // get parameter from query_string
    875         // add the taxQuery/metaQuery
    876         // override order/orderby
    877         $query_string = $this->query_string;
     1376        // query_string → tax / meta / order
    8781377        parse_str( $query_string, $query );
    8791378        array_walk_recursive($query, 'sanitize_text_field');
    8801379        $query = apply_filters( 'loopsblock_query_string_raw', $query, $args );
    881         // only apply the front-end query on loop base on attribute id
    8821380        if(!empty($query['id'])){
    8831381            if(empty($args['id']) || $args['id'] !== $query['id']){
    … …  
    8861384        }
    8871385
    888         // build the params from the $query;
    889         // search
    8901386        if(!empty($query['search'])){
    8911387            $args['search'] = $query['search'];
    8921388        }
    893         // replace
    8941389        if(!empty($query['order'])){
    8951390            $args['order'] = $query['order'];
    … …  
    9061401        }
    9071402
    908         // add tax and meta from front-end query
    9091403        if(!empty($query['taxQuery'])){
    9101404            if(!is_array($args['taxQuery'])){
    … …  
    9211415        // taxonomy
    9221416        if ( ! empty( $args[ 'taxQuery' ] ) ) {
    923             // nested taxonomy handling, same using OR, diff using AND
    9241417            if(empty($query_args[ 'tax_query' ])){
    925                 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- use tax_query for filter
    9261418                $query_args[ 'tax_query' ] = [];
    9271419            }
    9281420            $queries = [];
    929             // parse taxonomy (admin/front)
    930             // taxQuery=genre__electronic,ambient+mood__feeling-blue,focus+station_tag__dance-hit
    931 
    9321421            foreach($args[ 'taxQuery' ] as $tax){
    9331422                if(is_string($tax)){
    … …  
    9371426                }
    9381427            }
    939             // prepare taxonomy
    9401428            $ts = [];
    9411429            foreach ($queries as $q) {
    … …  
    9481436                $ts[$key][] = implode(':', $matches);
    9491437            }
    950             // build taxonomy
    9511438            foreach ( $ts as $key => $value ) {
    9521439                $a = [];
    … …  
    9781465        // meta
    9791466        if ( ! empty( $args[ 'metaQuery' ] ) ) {
    980             // no nested meta handling
    9811467            if(empty($query_args[ 'meta_query' ])){
    982                 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- use meta_query for filter
    9831468                $query_args[ 'meta_query' ] = [];
    9841469            }
    … …  
    9921477            }
    9931478            foreach ( $queries as $q ) {
    994                 //match : or __
    995                 //eg: key:value:compare:type
    9961479                $matches = preg_split( '/\:|__/', $q );
    9971480                if(count( $matches ) < 2){
    … …  
    10021485                    'value' => $matches[ 1 ]
    10031486                );
    1004                 // in
    10051487                if(strpos($matches[ 1 ], ',') !== false){
    10061488                    $arr['value'] = explode(',', $matches[ 1 ]);
    10071489                    $arr['compare'] = 'IN';
    10081490                }
    1009                 // range
    10101491                $ranges = preg_match( '/^\d+-\d+$/', $matches[ 1 ] );
    10111492                if($ranges){
    … …  
    10451526            $query_args[ 'order' ] = $args[ 'order' ];
    10461527        }
    1047         // orderby
    10481528        if ( ! empty( $args[ 'orderby' ] ) ) {
    10491529            $query_args[ 'orderby' ] = $args[ 'orderby' ];
    … …  
    10571537        if ( isset( $args[ 'pager' ] ) ) {
    10581538            $query_args[ 'paged' ] = $this->get_paged($query_args[ 'paged' ]);
    1059             // use offset for taxonomy
    10601539            if ( $args[ 'type' ] == 'taxonomy' ) {
    10611540                $query_args[ 'offset' ] = ( $this->get_paged($query_args[ 'paged' ]) - 1 ) * $query_args[ 'number' ];
    10621541            }
    10631542        }
    1064         // reset to page 1 if not set pager
    10651543        if(empty($args['pager'])){
    10661544            $query_args[ 'paged' ] = 1;
    … …  
    10691547        $query_args = apply_filters( 'loopsblock_query_args', $query_args, $args );
    10701548
    1071         // fix long query string
    10721549        foreach ($this->http_query_arr as $value) {
    10731550            if( isset($query_args[$value]) && !is_array($query_args[$value]) ){
    … …  
    10761553        }
    10771554
    1078         // search
    10791555        if ( ! empty( $args[ 'search' ] ) ) {
    10801556            $query_args[ 's' ] = $args[ 'search' ];
    … …  
    10951571    /**
    10961572     * get loop sql query
    1097      *
    1098      * @param object attributes
    10991573     */
    11001574    private function get_sql_query( $args = array() ) {
    … …  
    11031577    }
    11041578
    1105     /**
    1106      * get loop types
    1107      *
     1579    /* ================================================================== */
     1580    /* Editor lists (cached via transient)                                 */
     1581    /* ================================================================== */
     1582
     1583    /**
     1584     * get loop types (cached 1 day)
    11081585     */
    11091586    private function get_types() {
     1587        $cache_key = 'loopsblock_types_v' . self::cache_version();
     1588        $cached = get_transient( $cache_key );
     1589        if ( false !== $cached ) {
     1590            return $cached;
     1591        }
     1592
    11101593        $types = [ array( 'label' => '— Select —' ) ];
    11111594        foreach ( get_post_types( array( 'public' => true ), 'objects' ) as $id => $type ) {
    … …  
    11181601        $types[] = array( 'label' => 'Taxonomies', 'value' => 'taxonomy' );
    11191602
    1120         return apply_filters( 'loopsblock_types', $types, $this );
    1121     }
    1122 
    1123     /**
    1124      * get loop taxonomies
    1125      *
     1603        $types = apply_filters( 'loopsblock_types', $types, $this );
     1604        set_transient( $cache_key, $types, DAY_IN_SECONDS );
     1605        return $types;
     1606    }
     1607
     1608    /**
     1609     * get loop taxonomies (cached 1 day)
    11261610     */
    11271611    private function get_taxonomies() {
     1612        $cache_key = 'loopsblock_taxonomies_v' . self::cache_version();
     1613        $cached = get_transient( $cache_key );
     1614        if ( false !== $cached ) {
     1615            return $cached;
     1616        }
     1617
    11281618        $taxonomies = [];
    11291619        foreach ( get_taxonomies( array( 'public' => true ) ) as $taxonomy ) {
    … …  
    11311621        }
    11321622
    1133         return apply_filters( 'loopsblock_taxonomies', $taxonomies, $this );
    1134     }
    1135 
    1136     /**
    1137      * get image sizes
    1138      *
     1623        $taxonomies = apply_filters( 'loopsblock_taxonomies', $taxonomies, $this );
     1624        set_transient( $cache_key, $taxonomies, DAY_IN_SECONDS );
     1625        return $taxonomies;
     1626    }
     1627
     1628    /**
     1629     * get image sizes (cached 1 day)
    11391630     */
    11401631    private function get_images() {
     1632        $cache_key = 'loopsblock_images_v' . self::cache_version();
     1633        $cached = get_transient( $cache_key );
     1634        if ( false !== $cached ) {
     1635            return $cached;
     1636        }
     1637
    11411638        $arr = [];
    11421639        foreach ( get_intermediate_image_sizes() as $size ) {
    … …  
    11441641        }
    11451642
    1146         return apply_filters( 'loopsblock_image_sizes', $arr );
    1147     }
    1148 
    1149     /**
    1150      * get template files
    1151      *
     1643        $arr = apply_filters( 'loopsblock_image_sizes', $arr );
     1644        set_transient( $cache_key, $arr, DAY_IN_SECONDS );
     1645        return $arr;
     1646    }
     1647
     1648    /**
     1649     * get template files (cached 1 day; glob scan is expensive)
    11521650     */
    11531651    private function get_tpls() {
     1652        $cache_key = 'loopsblock_tpls_v' . self::cache_version();
     1653        $cached = get_transient( $cache_key );
     1654        if ( false !== $cached ) {
     1655            return $cached;
     1656        }
     1657
    11541658        $tpls      = [ array( 'label' => '— Select —' ) ];
    11551659        $tpl_files = apply_filters( 'loopsblock_template_files', array(
    1156             // '*/content*.php',
    1157             // '*/*/content*.php',
    11581660            '*/loop*.php',
    11591661            '*/*/loop*.php',
    … …  
    11831685        sort( $tpls );
    11841686
    1185         return apply_filters( 'loopsblock_templates', $tpls );
    1186     }
    1187 
    1188     /**
    1189      * get pagination
    1190      *
    1191      * @param int total results
    1192      * @param int paged
    1193      * @param string block id
     1687        $tpls = apply_filters( 'loopsblock_templates', $tpls );
     1688        set_transient( $cache_key, $tpls, DAY_IN_SECONDS );
     1689        return $tpls;
     1690    }
     1691
     1692    /* ================================================================== */
     1693    /* Pagination (cached)                                                 */
     1694    /* ================================================================== */
     1695
     1696    /**
     1697     * get pagination (cached)
     1698     *
     1699     * Note: pagination is global (not block-specific). Transient opt-in
     1700     * must be done via filter if needed.
    11941701     */
    11951702    private function get_pagination( $total, $paged, $id='' ) {
     1703        $cache_key = self::cache_key( 'loopsblock_pager', array( $total, $paged, $id, $this->query_url ) );
     1704        $cached = self::cache_get( $cache_key, self::CACHE_GROUP_RENDER );
     1705        if ( false !== $cached ) {
     1706            return $cached;
     1707        }
     1708
    11961709        if ( get_option( 'permalink_structure' ) ) {
    11971710            $base   = str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) );
    … …  
    12251738            $pagination = sprintf( '<nav class="navigation pagination"><div class="nav-links">%1$s</div></nav>', $pagination );
    12261739        }
    1227         return apply_filters( 'loopsblock_pagination', $pagination, $total, $paged, $this );
     1740        $pagination = apply_filters( 'loopsblock_pagination', $pagination, $total, $paged, $this );
     1741
     1742        if ( '' !== $pagination ) {
     1743            self::cache_set( $cache_key, $pagination, self::CACHE_GROUP_RENDER, 10 * MINUTE_IN_SECONDS );
     1744        }
     1745        return $pagination;
    12281746    }
    12291747
    12301748    /**
    12311749     * get paged
    1232      *
    12331750     */
    12341751    private function get_paged($paged) {
    … …  
    12431760    }
    12441761
     1762    /* ================================================================== */
     1763    /* Misc                                                                */
     1764    /* ================================================================== */
     1765
    12451766    /**
    12461767     * set pages
    1247      *
    12481768     */
    12491769    public function set_pages(){
    … …  
    12521772            $page = ( int ) $wp_query->get( 'page' );
    12531773            if ( $page > 1 ) {
    1254                 // convert 'page' to 'paged'
    12551774                $wp_query->set( 'page', 1 );
    12561775                $wp_query->set( 'paged', $page );
    12571776            }
    1258             // prevent redirect
    12591777            remove_action( 'template_redirect', 'redirect_canonical' );
    12601778        }
    … …  
    12621780
    12631781    /**
    1264      * load more content
    1265      *
    1266      * @param array
     1782     * load more content (cached for anonymous users)
    12671783     */
    12681784    public function load_more( $request ) {
    1269         if ( isset( $request[ 'paged' ] ) ) {
    1270             $args = $request->get_params();
    1271             $args[ 'ajax' ] = 1;
    1272             return wp_send_json(
    1273                 array( 'content' => $this->render_loop_block( apply_filters( 'loopsblock_ajax_more', $args, $this ) ) )
    1274             );
    1275         }
    1276     }
    1277 
    1278     /**
    1279      * get terms for filter to use connect terms
    1280      *
    1281      * @param string
    1282      * @param array
     1785        if ( ! isset( $request[ 'paged' ] ) ) {
     1786            return;
     1787        }
     1788
     1789        $args = $request->get_params();
     1790        // sanitize: paged must be a positive integer
     1791        $args[ 'paged' ] = absint( $args[ 'paged' ] );
     1792        if ( ! $args[ 'paged' ] ) {
     1793            $args[ 'paged' ] = 1;
     1794        }
     1795        $args[ 'ajax' ] = 1;
     1796
     1797        // cache only for anonymous, non-user-context requests
     1798        $cache_enabled = ! is_user_logged_in()
     1799            && ! $this->is_user_context( $args )
     1800            && apply_filters( 'loopsblock_enable_more_cache', true, $args );
     1801
     1802        $cache_key = '';
     1803        if ( $cache_enabled ) {
     1804            $cache_key = self::cache_key( 'loopsblock_more', $args );
     1805            $cached = self::cache_get( $cache_key, self::CACHE_GROUP_RENDER, $args );
     1806            if ( false !== $cached ) {
     1807                return wp_send_json( $cached );
     1808            }
     1809        }
     1810
     1811        $data = array(
     1812            'content' => $this->render_loop_block(
     1813                apply_filters( 'loopsblock_ajax_more', $args, $this )
     1814            )
     1815        );
     1816
     1817        if ( $cache_enabled && '' !== $cache_key && ! empty( $data['content'] ) ) {
     1818            self::cache_set( $cache_key, $data, self::CACHE_GROUP_RENDER, 5 * MINUTE_IN_SECONDS, $args );
     1819        }
     1820
     1821        return wp_send_json( $data );
     1822    }
     1823
     1824    /* ================================================================== */
     1825    /* get_terms (FIXED + cached)                                          */
     1826    /* ================================================================== */
     1827
     1828    /**
     1829     * get terms for filter to use connect terms.
     1830     *
     1831     * Note: global resource, no block attributes. Transient opt-in via filter.
    12831832     */
    12841833    public function get_terms($taxonomy, $ids){
    … …  
    12871836            return [];
    12881837        }
    1289         $arr = implode(',', array_map( 'absint', $ids ));
    1290         $cache_key = $taxonomy.$arr;
    1291         $cached_terms = wp_cache_get( $cache_key, 'loopsblock_term_cache' );
    1292         if ( false !== $cached_terms ) {
    1293             return $cached_terms;
     1838        $arr = implode(',', array_map( 'absint', (array) $ids ));
     1839        $cache_key = 'loopsblock_terms_rel_v' . self::cache_version() . '_' . $taxonomy . '_' . md5( $arr );
     1840
     1841        $cached = self::cache_get( $cache_key, self::CACHE_GROUP_TERMS );
     1842        if ( false !== $cached ) {
     1843            return $cached;
    12941844        }
    12951845
    12961846        // phpcs:ignore WordPress.DB.DirectDatabaseQuery
    1297         $cached_terms = $wpdb->query(
     1847        $results = $wpdb->get_results(
    12981848            $wpdb->prepare(
    1299             " SELECT terms.name, terms.slug, COUNT(tr.object_id) as count FROM {$wpdb->terms} terms " .
    1300             " INNER JOIN {$wpdb->term_taxonomy} tt ON (tt.term_id = terms.term_id) " .
     1849            " SELECT t.name, t.slug, COUNT(tr.object_id) AS count FROM {$wpdb->terms} t " .
     1850            " INNER JOIN {$wpdb->term_taxonomy} tt ON (tt.term_id = t.term_id) " .
    13011851            " INNER JOIN {$wpdb->term_relationships} tr ON (tr.term_taxonomy_id = tt.term_taxonomy_id) " .
    1302             " WHERE tr.object_id IN (%s) AND tt.taxonomy = %s GROUP BY terms.term_id ",
    1303             $arr,
     1852            " WHERE tr.object_id IN ({$arr}) AND tt.taxonomy = %s " .
     1853            " GROUP BY t.term_id, t.name, t.slug ",
    13041854            $taxonomy )
    13051855        );
    13061856
    1307         wp_cache_set( $cache_key, $cached_terms, 'loopsblock_term_cache' );
    1308         return $cached_terms;
    1309     }
    1310 
    1311     /**
    1312      * add groupby filter
    1313      *
    1314      * @param array
    1315      */
     1857        self::cache_set( $cache_key, $results, self::CACHE_GROUP_TERMS, HOUR_IN_SECONDS );
     1858        return $results;
     1859    }
     1860
     1861    /* ================================================================== */
     1862    /* Query filters                                                       */
     1863    /* ================================================================== */
     1864
    13161865    public function add_query_filter( $query_args ){
    13171866        $this->args = $query_args;
    … …  
    13201869    }
    13211870
    1322     /**
    1323      * remove groupby filter
    1324      *
    1325      * @param array
    1326      */
    13271871    public function remove_query_filter( $query_args ){
    13281872        remove_filter( 'posts_groupby', array($this, 'posts_groupby') );
    13291873        remove_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
    13301874    }
    1331    
    1332     /**
    1333      * posts groupby
    1334      * https://developer.wordpress.org/reference/hooks/posts_groupby/
    1335      *
    1336      * @param string
    1337      */
     1875
    13381876    public function posts_groupby($groupby){
    13391877        global $wpdb;
    … …  
    13431881        return $groupby;
    13441882    }
    1345    
    1346     /**
    1347      * posts where
    1348      *
    1349      * @param string
    1350      * @param object
    1351      */
     1883
    13521884    public function posts_where( $where, $query ) {
    1353         // find_in_set for featured on
    13541885        global $wpdb;
     1886        // FIX: guard against null or empty meta_query
     1887        if ( empty( $query->meta_query ) || empty( $query->meta_query->queries ) ) {
     1888            return $where;
     1889        }
    13551890        foreach ( $query->meta_query->queries as $index => $meta_query ) {
    13561891            if ( isset( $meta_query[ 'compare' ] ) && 'find_in_set' == strtolower( $meta_query[ 'compare' ] ) ) {
    … …  
    13621897    }
    13631898
    1364     /**
    1365      * normalize arrtributes
    1366      *
    1367      * @param object
    1368      */
     1899    /* ================================================================== */
     1900    /* Helpers                                                             */
     1901    /* ================================================================== */
     1902
    13691903    public function normalize_load_more_attributes( $attributes = array() ) {
     1904      // IMPORTANT: do NOT add 'context' here — load_more() relies on it
     1905      // to skip user-context requests from caching.
    13701906      $exclusions = apply_filters( 'loopsblock_attribute_exclusions', array(
    13711907        'title',
    … …  
    13751911        'sliderOption',
    13761912        'align',
    1377         'action' // added automatically so can be removed to avoid duplicates
     1913        'action'
    13781914      ) );
    13791915
    … …  
    13921928
    13931929    /**
    1394      * build http query
    1395      *
    1396      * @param array
    1397      */
    1398     private function http_build_query($query_args){
    1399         // get query_string for load more / scroll
    1400         $query_string = $this->query_string;
     1930     * Build more query string.
     1931     *
     1932     * @param array $query_args
     1933     * @return string
     1934     */
     1935    private function build_more_query($query_args){
     1936        // Use normalized query string — nonce already verified/stripped.
     1937        $query_string = $this->get_normalized_query_string();
    14011938        parse_str( $query_string, $query );
    14021939        if( !empty($query['paged']) ){
    14031940            unset($query['paged']);
    14041941        }
     1942        // Defensive: strip click in case any leak
     1943        unset( $query['click'] );
    14051944        $query_args = array_merge( $query_args, $query );
    14061945        array_walk_recursive($query_args, 'sanitize_text_field');
    14071946
    1408         // fixed long query
    14091947        foreach ($this->http_query_arr as $value) {
    14101948            if( isset($query_args[$value]) && is_array($query_args[$value]) ){
    … …  
    14171955        return http_build_query($query_args);
    14181956    }
     1957
     1958    /**
     1959     * Backward-compat wrapper (private).
     1960     */
     1961    private function http_build_query($query_args){
     1962        return $this->build_more_query( $query_args );
     1963    }
    14191964}
    14201965
  • loops-block/trunk/loops-block.php

    r3671635 r3725635  
    55 * Description:       An advanced block that allows displaying posts, taxonomies and users based on different query parameters and visual configurations.
    66 * Author:                        wooscroll
    7  * Version:                       1.0.4
    8  * Tested up to:      7.1
     7 * Version:                       1.0.6
     8 * Tested up to:      7.1.2
    99 * License:           GPLv3
    1010 * License URI:       https://www.gnu.org/licenses/gpl-3.0.html
  • loops-block/trunk/readme.txt

    r3671635 r3725635  
    44Requires at least: 6.0
    55Requires PHP: 7.4
    6 Tested up to: 7.1
    7 Stable tag: 1.0.4
     6Tested up to: 7.1.2
     7Stable tag: 1.0.6
    88License: GPLv3
    99License URI: https://www.gnu.org/licenses/gpl-3.0.html
Note: See TracChangeset for help on using the changeset viewer.