popupable 1.7.0 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -305,6 +305,18 @@ window.popupableAnimTypes.myAnim = {
305
305
  }
306
306
  ```
307
307
 
308
+ ### Shadow DOM
309
+
310
+ popupable works inside open shadow roots out of the box. Clicks, attribute inheritance, and gallery grouping all cross shadow boundaries. Place `data-popupable-*` attributes on any ancestor and they will inherit into images inside shadow DOM.
311
+
312
+ The one thing that can't be auto-injected is the hover cursor, because document-level CSS doesn't reach into shadow roots. Add this one-liner to any shadow root that hosts popupable elements:
313
+
314
+ ```css
315
+ [data-popupable], [data-popupable] * { cursor: pointer }
316
+ ```
317
+
318
+ Closed shadow roots (`mode: "closed"`) are not supported from the outside. To use popupable inside a closed shadow root, load it from within that root yourself so it has direct access to the contents.
319
+
308
320
  ## Customization
309
321
 
310
322
  Popups can be styled using CSS variables:
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * popupable
3
- * Version : 1.7.0
3
+ * Version : 1.7.2
4
4
  * License : MIT
5
5
  * Copyright: 2026 Ewan Howell
6
6
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * popupable
3
- * Version : 1.7.0
3
+ * Version : 1.7.2
4
4
  * License : MIT
5
5
  * Copyright: 2026 Ewan Howell
6
6
  */
7
- {let e,t,n,o=0;const a=3;let r;function triggerHaptic(){if("function"!=typeof navigator.vibrate){if(!r){r=document.createElement("label"),r.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none";const e=document.createElement("input");e.type="checkbox",e.setAttribute("switch",""),r.append(e),document.body.append(r)}r.click()}else navigator.vibrate([10])}function disableScroll(){window.addEventListener("wheel",prevent,{passive:!1}),window.addEventListener("touchmove",prevent,{passive:!1}),window.addEventListener("keydown",blockKeys,!0)}function enableScroll(){window.removeEventListener("wheel",prevent),window.removeEventListener("touchmove",prevent),window.removeEventListener("keydown",blockKeys,!0)}function prevent(e){e.preventDefault()}function blockKeys(e){["ArrowUp","ArrowDown","PageUp","PageDown","Home","End"," "].includes(e.key)&&e.preventDefault()}function calcExpandedRect(t){const n=t.original,o=visualViewport?.width||window.innerWidth,a=visualViewport?.height||window.innerHeight,r=visualViewport?.offsetTop||0,i=visualViewport?.offsetLeft||0,s=visualViewport?.scale||1,l=1/s,p=e.popup,c=(parseFloat(getComputedStyle(p).getPropertyValue("--popupable-screen-padding"))||40)/s,u=Math.max(0,o-2*c),d=a-2*c,m=Math.max(0,d);let b;if(t.maintainAspect){const e=n.getBoundingClientRect();b=e.width/e.height}else{b=(t.source.naturalWidth||t.source.videoWidth)/(t.source.naturalHeight||t.source.videoHeight)||1}let f=0,g=0;if(e.orderPlacement){const n=e.popup.querySelector(".popupable-counter"),o=n?n.getBoundingClientRect().height/l:0,a=e.thumbnailsContainer?e.thumbnailsContainer.getBoundingClientRect().height/l:0,r=e.contentContainer,i=t.content?t.content.getBoundingClientRect().height/l:r?.previousElementSibling&&r?.nextElementSibling&&parseFloat(getComputedStyle(r,"::after").height)||0,{counterTop:s,contentTop:p,thumbnailsTop:c,counterBottom:u,contentBottom:d,thumbnailsBottom:m}=e.orderPlacement;f=(s?o:0)+(p?i:0)+(c?a:0),g=(u?o:0)+(d?i:0)+(m?a:0)}const h=Math.max(0,a-f-g-2*c);let v=u,y=v/b;if(y>m&&(y=m,v=y*b),y>h&&(y=h,v=y*b),t.noUpscale){const e=t.cloneLayer||n,o=e.naturalWidth||e.videoWidth,a=e.naturalHeight||e.videoHeight;if(o&&a){const e=o/s,t=a/s,n=Math.min(1,e/v,t/y);n<1&&(v*=n,y*=n)}}let x=r+c+(m-y)/2;const w=r+a-g-c-y;return x=Math.min(x,w),x=Math.max(x,r+f+c),{top:x,left:i+c+(u-v)/2,width:v,height:y}}function setCloneToOriginalRect(t,n){const o=calcExpandedRect(e),{top:a,left:r,width:i,height:s}=e.animation.position(n,o);t.style.top=a+"px",t.style.left=r+"px",t.style.width=i+"px",t.style.height=s+"px"}window.popupableAnimTypes={expand:{styles:!0,hideSource:!0,crossfade:!0,position(e){const t=e.getBoundingClientRect();return{top:visualViewport.offsetTop+t.top,left:visualViewport.offsetLeft+t.left,width:t.width,height:t.height}}},pop:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+.05*a,left:n+.05*o,width:.9*o,height:.9*a})},line:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+a/2,left:n+.05*o,width:.9*o,height:0})},float:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+40,left:n,width:o,height:a})}};const i=3;function parseCssTime(e){if(!e)return 0;const t=parseFloat(e);return Number.isNaN(t)?0:/ms\s*$/i.test(e)?t:1e3*t}function getReleaseDelay(e){const t=e?.popup||document.documentElement;return parseCssTime(getComputedStyle(t).getPropertyValue("--popupable-switch-duration"))}function buildDecodeQueue(e,t=e.group?.currentIndex,{delayRelease:n=!0}={}){if(!e.group)return;const o=e.group.length,a=n?getReleaseDelay(e):0;for(let n=0;n<o;n++){const o=e.group[n];Math.abs(n-t)>i?o.releaseDecode&&!o._releaseTimer&&(a<=0?o.releaseDecode():o._releaseTimer=setTimeout(()=>{o._releaseTimer=null,o.releaseDecode()},a)):o._releaseTimer&&(clearTimeout(o._releaseTimer),o._releaseTimer=null)}const r=[];t!==e.group.currentIndex&&t>=0&&t<o&&r.push(e.group[t]);for(let n=1;n<=i;n++)t+n<o&&r.push(e.group[t+n]),t-n>=0&&r.push(e.group[t-n]);e.decodeQueue=r,runDecodeQueue(e)}function projectSnapIndex(e,t){const n=window.innerWidth,o=Math.abs(t);if(o<=Math.max(.1*n,64))return e.currentIndex;const a=Math.max(0,Math.floor((o-n/2)/n))+1,r=t>0?-1:1;return Math.max(0,Math.min(e.length-1,e.currentIndex+r*a))}const s=100;let l=0,p=null,c=-1;function scheduleDragDecodeQueue(t){if(c=t,p)return;const n=Math.max(0,s-(performance.now()-l));p=setTimeout(()=>{p=null,l=performance.now();const t=c;c=-1,t>=0&&e?.group&&t!==e.group.currentIndex&&buildDecodeQueue(e,t,{delayRelease:!1})},n)}function cancelDragDecodeQueue(){p&&(clearTimeout(p),p=null),c=-1}async function runDecodeQueue(e){if(!e.decodeQueueRunning){for(e.decodeQueueRunning=!0;e.decodeQueue&&e.decodeQueue.length&&!e.decodeAborted;){const t=e.decodeQueue.shift();try{await t.triggerDecode()}catch{}}e.decodeQueueRunning=!1}}function openPopupable(e){if("open"===e.state)return;e.state="open",triggerHaptic();const{cloneContainer:t,popup:n,transition:o,group:a,listeners:r}=e;n.classList.add("popupable-active"),e.clearNavInactive?.(),updateExpandedSize(),e.closingContainer?.removeEventListener("transitionend",o.listener);const i=e.closingContainer??t;o.listener=t=>{if(t&&t.target!==t.currentTarget)return;i.removeEventListener("transitionend",o.listener),n.classList.add("popupable-open");const s=a?a[a.currentIndex]:e;if(s.video&&(s.zoomable?s.source.controls=!1:s.explicitControls||(s.source.controls=!0)),a)for(const e of a)e.cloneContainer.style.display=null;for(const e of r)e.target.addEventListener(e.event,e.func,e.args);e.scheduleNavHide?.()},o.duration?i.addEventListener("transitionend",o.listener):o.listener()}function closePopupable(){if(!e||"close"===e.state)return;if(o++,e.state="close",e.decodeAborted=!0,e.decodeQueue=null,e.group)for(const t of e.group)t._releaseTimer&&(clearTimeout(t._releaseTimer),t._releaseTimer=null);document.body.classList.add("popupable-block-touch"),setTimeout(()=>document.body.classList.remove("popupable-block-touch"),300);const{cloneContainer:n,original:a,popup:r,transition:i,group:s,listeners:l}=e;a.classList.remove("popupable-loading"),r.classList.remove("popupable-active"),r.classList.remove("popupable-open");const p=s?s[s.currentIndex].cloneContainer:n;if(e.closingContainer=p,setCloneToOriginalRect(p,a),s)for(const e of s)e.cloneContainer!==p&&(e.cloneContainer.style.display="none");for(const e of l)e.target.removeEventListener(e.event,e.func);n.removeEventListener("transitionend",i.listener);const c=s?s[s.currentIndex]:e;c.video&&c.source&&(c.source.controls=!1);const u=c.original===a,d=e;i.listener=n=>{n&&n.target!==n.currentTarget||(p.removeEventListener("transitionend",i.listener),a.classList.remove("popupable-hide"),u&&c.video&&"VIDEO"===a.tagName&&!c.cloneLayer&&(a.currentTime=c.source.currentTime),u&&c.wasPlaying&&"VIDEO"===a.tagName&&a.play(),r.remove(),d===e&&(enableScroll(),t=e,e=null))},i.duration?p.addEventListener("transitionend",i.listener):i.listener()}function updateExpandedSize(){if(!e||"close"===e.state)return;const t=visualViewport?.width||window.innerWidth,n=visualViewport?.height||window.innerHeight,o=visualViewport?.offsetTop||0,a=visualViewport?.offsetLeft||0,r=visualViewport?.scale||1;document.documentElement.style.setProperty("--popupable-view-width",t+"px"),e.popup.style.setProperty("--popupable-vv-width",t+"px"),e.popup.style.setProperty("--popupable-vv-height",n+"px"),e.popup.style.setProperty("--popupable-vv-top",o+"px"),e.popup.style.setProperty("--popupable-vv-left",a+"px"),e.popup.style.setProperty("--popupable-vv-scale",r),e.popup.style.setProperty("--popupable-vv-ui-scale",1/r);const i=1/r;let s;s=e.group?e.group:[e];for(const e of s){const{top:t,left:n,width:o,height:a}=calcExpandedRect(e);e.cloneContainer.style.top=t+"px",e.cloneContainer.style.left=n+"px",e.cloneContainer.style.width=o+"px",e.cloneContainer.style.height=a+"px"}if(e.contentContainer){let t;if(t=e.group?e.group[e.group.currentIndex]:e,t.content){const n=t.content.getBoundingClientRect();e.contentContainer.style.height=n.height/i+"px"}else{const t=e.contentContainer,n=t.previousElementSibling&&t.nextElementSibling&&parseFloat(getComputedStyle(t,"::after").height)||0;t.style.height=n+"px"}}}const u=/\.(mp4|m4v|webm|ogv|mov|3gp|m3u8|flv)(\?|#|$)/i;function isVideo(e){const t=inheritAttr(e,"data-popupable-type");if(t)return"video"===t;if("VIDEO"===e.tagName)return!0;if("IMG"===e.tagName)return!1;const n=e.getAttribute("data-popupable-src")||e.getAttribute("src")||"";return u.test(n)}const d=e=>e.getAttribute("currentSrc")||e.getAttribute("src")||e.getAttribute("data-popupable-src");function inheritAttr(e,t){const n=e.closest(`[${t}]`);if(!n)return;const o=n.getAttribute(t);return"false"!==o?o||!0:void 0}function parsePopupableOrder(e){const t=["counter","image","content","thumbnails"],n=new Set(t),o=[];if(e)for(const t of e.split(",")){const e=t.trim().toLowerCase();e&&n.has(e)&&!o.includes(e)&&o.push(e)}for(const e of t)o.includes(e)||o.push(e);const a=o.indexOf("image");return{top:o.slice(0,a),bottom:o.slice(a+1)}}function cloneElement(e,t=e){const n=inheritAttr(e,"data-popupable-anim"),o=popupableAnimTypes[n]?n:"expand",a=popupableAnimTypes[o],r=inheritAttr(e,"data-popupable-src"),i=d(e),s=inheritAttr(e,"data-popupable-title"),l=inheritAttr(e,"data-popupable-description"),p=inheritAttr(e,"data-popupable-zoomable"),c=getComputedStyle(e),m=t===e?c:getComputedStyle(t),b=t!==e?d(t):null,f=t===e,g=document.createElement("div");g.className="popupable-clone-container",inheritAttr(e,"data-popupable-transparent")&&g.classList.add("popupable-transparent"),p&&g.classList.add("popupable-zoomable"),g.style.borderRadius=c.borderRadius,a.styles&&(g.style.border=c.border,g.style.outline=c.outline,g.style.boxShadow=c.boxShadow);const h=isVideo(e);let v=!1;const y=inheritAttr(e,"data-popupable-poster"),x=("string"==typeof y?y:null)||("VIDEO"===e.tagName?e.getAttribute("poster"):null),w=b||i||r,L=u.test(w)||h&&w===i,E=r&&i||b;let I,C,P;if(L?(I=document.createElement("video"),I.className="popupable-clone",f&&(I.src=w),I.playsInline=!0,I.controls=!1,h&&!E||(I.muted=!0,I.loop=!0,I.autoplay=!0),f&&x&&w===i&&(I.poster=x)):(I=new Image,I.className="popupable-clone",f&&(I.src=w),I.style.imageRendering=m.imageRendering),I.style.objectFit=m.objectFit,I.style.objectPosition=m.objectPosition,I.style.background=m.background,g.append(I),"VIDEO"===I.tagName?I.addEventListener("loadedmetadata",()=>updateExpandedSize()):I.addEventListener("load",()=>updateExpandedSize()),E){const t=r||i;if(u.test(t)||h&&t===i?(C=document.createElement("video"),C.className="popupable-clone-layer",f&&(C.src=t),C.playsInline=!0,C.controls=!1,h||(C.muted=!0,C.loop=!0,C.autoplay=!0),f&&x&&t===i&&(C.poster=x)):(C=new Image,C.className="popupable-clone-layer",f&&(C.src=t),C.style.imageRendering=c.imageRendering),g.append(C),"VIDEO"===C.tagName?C.addEventListener("loadedmetadata",()=>updateExpandedSize()):C.addEventListener("load",()=>updateExpandedSize()),"fill"===I.style.objectFit&&"IMG"===I.tagName){const t=e.getBoundingClientRect();e.naturalWidth&&e.naturalHeight&&Math.abs(t.width/t.height-e.naturalWidth/e.naturalHeight)<.01&&(I.style.objectFit="cover")}P=C}else P=I;h&&"VIDEO"===e.tagName&&t===e&&(L&&(I.currentTime=e.currentTime),v=!e.paused,e.pause());const A=inheritAttr(e,"data-popupable-attr");let M,N=!1;if("string"==typeof A)for(const e of A.split(",")){const t=e.trim();if(!t)continue;const n=t.indexOf("=");if(-1===n)P[t]=!0,"controls"===t&&(N=!0);else{const e=t.slice(0,n).trim(),o=t.slice(n+1).trim(),a=Number(o);"true"===o?P[e]=!0:"false"===o?P[e]=!1:""===o||Number.isNaN(a)?P[e]=o:P[e]=a,"controls"===e&&(N=!0)}}if(s||l){if(M=document.createElement("div"),M.classList="popupable-content",s){const e=document.createElement("div");e.className="popupable-title",e.textContent=s,M.append(e)}if(l){const e=document.createElement("div");e.className="popupable-description",e.textContent=l,M.append(e)}}const D=[I,C].filter(Boolean),T=Promise.all(D.filter(e=>"VIDEO"===e.tagName).map(e=>{const t=new Promise(t=>{if(e.readyState>=1)return t();e.addEventListener("loadedmetadata",t,{once:!0}),e.addEventListener("error",t,{once:!0})});if(e.poster){const n=new Promise(t=>{const n=new Image;n.addEventListener("load",t,{once:!0}),n.addEventListener("error",t,{once:!0}),n.src=e.poster});return Promise.all([n,t])}return t})),z=w,k=C?r||i:null;let S=f||!C;const F="VIDEO"===I.tagName&&x&&w===i?x:null,V=C&&"VIDEO"===C.tagName&&x&&(r||i)===i?x:null;let R=!f,O=null;const X=(e,t)=>e+Math.random()*(t-e),Y=(e,t,n)=>`hsl(${e.toFixed(0)} ${t.toFixed(0)}% ${n.toFixed(0)}%)`,$=Math.random();let W,H,B;$<.2?(W=X(6,14),H=X(22,38),B=X(20,45)):$<.55?(W=X(14,26),H=X(38,58),B=X(25,55)):$<.85?(W=X(22,38),H=X(58,75),B=X(35,65)):(W=X(32,50),H=X(72,90),B=X(40,75));const Q=X(0,360),_=(Q+X(20,140))%360,j=(Q+X(-40,220)+360)%360;function q(){R&&(R=!1,g.classList.remove("popupable-clone-loading"),S&&z&&!I.getAttribute("src")&&(I.src=z,"VIDEO"===I.tagName&&F&&(I.poster=F)),C&&k&&!C.getAttribute("src")&&(C.src=k,"VIDEO"===C.tagName&&V&&(C.poster=V)))}function U(){if(q(),O)return O;const e=D.filter(e=>"VIDEO"!==e.tagName);return e.length?(O=Promise.all(e.map(e=>e.decode?e.decode().catch(()=>{}):new Promise(t=>{if(e.complete)return t();e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}))).then(()=>T),O):(O=T,O)}return g.style.setProperty("--popupable-loading-x1",X(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-y1",X(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-x2",X(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-y2",X(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-c1",`hsla(${j.toFixed(0)} ${Math.min(95,B+X(10,25)).toFixed(0)}% ${H.toFixed(0)}% / ${X(.55,.9).toFixed(2)})`),g.style.setProperty("--popupable-loading-c2",`hsla(${_.toFixed(0)} ${B.toFixed(0)}% ${(.8*H).toFixed(0)}% / ${X(.4,.75).toFixed(2)})`),g.style.setProperty("--popupable-loading-angle",X(0,360).toFixed(0)+"deg"),g.style.setProperty("--popupable-loading-a",Y(Q,.6*B,W)),g.style.setProperty("--popupable-loading-b",Y(_,.8*B,(W+H)/2)),R&&g.classList.add("popupable-clone-loading"),{id:e.dataset.popupable,original:e,cloneContainer:g,clone:I,cloneLayer:C,maintainAspect:inheritAttr(e,"data-popupable-maintain-aspect"),noUpscale:inheritAttr(e,"data-popupable-no-upscale"),counter:inheritAttr(e,"data-popupable-counter"),thumbnails:inheritAttr(e,"data-popupable-thumbnails"),order:parsePopupableOrder(inheritAttr(e,"data-popupable-order")),animationName:o,animation:a,get ready(){return U()},triggerDecode:U,ensureLoaded:q,markAsActiveInGroup:function(){S=!0,R||!z||I.getAttribute("src")||(I.src=z,"VIDEO"===I.tagName&&F&&(I.poster=F))},releaseDecode:function(){R||(R=!0,O=null,g.classList.add("popupable-clone-loading"),"VIDEO"===I.tagName?(I.paused||I.pause(),I.removeAttribute("src"),I.removeAttribute("poster"),I.load()):I.removeAttribute("src"),C&&("VIDEO"===C.tagName?(C.paused||C.pause(),C.removeAttribute("src"),C.removeAttribute("poster"),C.load()):C.removeAttribute("src")))},content:M,zoomable:p,source:P,video:h,explicitControls:N,wasPlaying:v}}let m,b,f;document.addEventListener("pointerdown",t=>{0===t.button&&(m||(n=t.target,b=t.clientX,f=t.clientY),m||"open"!==e?.state||t.target.closest(".popupable-header, .popupable-footer")||(m=!0))});let g=!1;function handleMove(t){if("open"!==e?.state||!e.group||!m)return;if(!e.popup?.classList.contains("popupable-open"))return b=t.touches?.[0].clientX??t.clientX,void(f=t.touches?.[0].clientY??t.clientY);const n=e.group[e.group.currentIndex],o=t.touches?.[0].clientX??t.clientX;!g&&Math.abs(o-b)>a&&n.video&&(g=!0,n.source.style.pointerEvents="none"),n.cloneContainer.parentElement.style.transition="initial",n.cloneContainer.parentElement.style.transform=`translateX(${o-b}px)`;const r=projectSnapIndex(e.group,o-b);r!==e.lastProjectedIndex&&(e.lastProjectedIndex=r,scheduleDragDecodeQueue(r))}document.addEventListener("mousemove",handleMove),document.addEventListener("touchmove",handleMove,{passive:!0}),document.addEventListener("pointerup",async r=>{if(0!==r.button)return;if(m){m=!1,cancelDragDecodeQueue();const Z=e.group?e.group[e.group.currentIndex]:e;g&&(g=!1,Z.source.style.pointerEvents=null),Z.cloneContainer.parentElement.style.transition=null,Z.cloneContainer.parentElement.style.transform=null;const J=r.clientX-b,ee=Math.abs(J),te=r.clientY-f,ne=Math.abs(te);if("touch"===r.pointerType&&ne>56&&ne>1.1*ee)return void closePopupable();if(e.group&&ee>a){const oe=Math.max(0,Math.floor((ee-window.innerWidth/2)/window.innerWidth));if(J>Math.max(.1*window.innerWidth,64))for(let ae=0;ae<=oe;ae++)e.goPrev();else if(J<-Math.max(.1*window.innerWidth,64))for(let re=0;re<=oe;re++)e.goNext();return void(e.blocked=!0)}}const i=r.target.closest(".popupable-viewport")&&!n.closest(".popupable-viewport");if(!i&&r.target!=n&&(!n.classList.contains("popupable-clone-container")||r.target!==t?.original)&&(!n.closest(".popupable-container")||r.target.closest(".popupable-container"))||Math.abs(r.clientX-b)>a||Math.abs(r.clientY-f)>a)return;const s=(i?n.closest("[data-popupable]"):null)||r.target.closest("[data-popupable]");if(!s){if(i)return void closePopupable();if(r.target.closest(".popupable-container"))return;return void(e&&("zoomed"===e.state?e.unzoom():closePopupable()))}if(r.preventDefault(),e&&"close"!==e.state&&e.original===s)return;e&&closePopupable();const l=++o;e={transition:{},listeners:[]};const p=e,c=document.createElement("div");c.className="popupable-clones";const u=cloneElement(s),{cloneContainer:h,content:v}=u;let y;const x=s.closest("[data-popupable-group]"),w=x?.getAttribute("data-popupable-group"),L=w&&"false"!==w?w:null;if(L){const ie=[],se=new Set;for(const le of document.querySelectorAll(`[data-popupable-group="${L}"]`)){le.hasAttribute("data-popupable")&&!se.has(le)&&(se.add(le),ie.push(le));for(const pe of le.querySelectorAll("[data-popupable]")){if(se.has(pe))continue;const ce=pe.getAttribute("data-popupable-group");null!==ce&&ce!==L||pe.closest("[data-popupable-group]")!==le||(se.add(pe),ie.push(pe))}}if(ie.length){y=[];for(const[ue,de]of ie.entries())if(de===s)y.push(u),y.currentIndex=ue,c.append(h);else{const me=cloneElement(de,s);me.cloneContainer.style.display="none",y.push(me),c.append(me.cloneContainer)}for(const[be,fe]of y.entries()){if(!fe.content)continue;const ge=be-y.currentIndex;ge>0?fe.content.classList.add("popupable-content-after"):ge<0&&fe.content.classList.add("popupable-content-before")}}}else c.append(h);const E=document.createElement("div");E.className=`popupable-container popupable-anim-${u.animationName}`,u.id&&(E.id=u.id);const I=document.createElement("div");let C,P,A,M,N,D,T,z,k,S,F;I.className="popupable-viewport",(v||y&&y.some(e=>e.content))&&(C=document.createElement("div"),C.classList="popupable-content-container");const V={};if(y){u.counter&&(M=document.createElement("div"),M.className="popupable-counter"),u.thumbnails&&(N=document.createElement("div"),N.className="popupable-thumbnails",D=y.map((e,t)=>{let n;if(e.video){const t=inheritAttr(e.original,"data-popupable-poster"),o=("string"==typeof t?t:null)||("VIDEO"===e.original.tagName?e.original.getAttribute("poster"):null);o?(n=new Image,n.src=o):(n=document.createElement("video"),n.src=inheritAttr(e.original,"data-popupable-src")||d(e.original),n.muted=!0,n.playsInline=!0,n.preload="metadata",n.disablePictureInPicture=!0,n.disableRemotePlayback=!0)}else n=new Image,n.src=inheritAttr(e.original,"data-popupable-src")||d(e.original);return n.className="popupable-thumbnail",n.dataset.thumbnailIndex=t,N.append(n),n})),I.innerHTML=`\n <div class="popupable-button-container popupable-prev-container${y.currentIndex?"":" popupable-button-disabled"}">\n <div class="popupable-button popupable-prev">\n <svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor">\n <path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/>\n </svg>\n </div>\n </div>\n <div class="popupable-button-container popupable-next-container${y.currentIndex===y.length-1?" popupable-button-disabled":""}">\n <div class="popupable-button popupable-next">\n <svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor">\n <path d="M647-440H160v-80h487L423-744l57-56 320 320-320 320-57-56 224-224Z"/>\n </svg>\n </div>\n </div>\n `;const he=I.querySelector(".popupable-next-container"),ve=I.querySelector(".popupable-prev-container");let ye,xe,we,Le;const Ee=!(navigator.maxTouchPoints>0||window.matchMedia("(hover: none)").matches);function R(){he.classList.remove("popupable-button-inactive"),ve.classList.remove("popupable-button-inactive"),e.scheduleNavHide()}function O(e){const t=y[y.currentIndex];t.video&&t.source&&(t.source.paused||(t.swipePaused=!0,t.source.pause()),t.source.controls=!1),y.currentIndex=e;const n=y[y.currentIndex];n.video&&n.source&&(n.zoomable||(n.source.controls=!0),n.source.play().catch(()=>{}),n.swipePaused=!1),F()}if(e.scheduleNavHide=()=>{Ee&&(clearTimeout(ye),Le||(ye=setTimeout(()=>{Le||(he.classList.add("popupable-button-inactive"),ve.classList.add("popupable-button-inactive"))},1500)))},e.clearNavInactive=()=>{he.classList.remove("popupable-button-inactive"),ve.classList.remove("popupable-button-inactive")},F=async()=>{const t=y[y.currentIndex];t.markAsActiveInGroup(),await t.ready,y.currentIndex?ve.classList.remove("popupable-button-disabled"):ve.classList.add("popupable-button-disabled"),y.currentIndex===y.length-1?he.classList.add("popupable-button-disabled"):he.classList.remove("popupable-button-disabled");for(const[e,t]of y.entries()){const n=e-y.currentIndex;t.cloneContainer.style.setProperty("--popupable-offset-multiplier",n),t.cloneContainer.style.zIndex=-1*Math.abs(n),t.content&&(n?n>0?(t.content.classList.add("popupable-content-after"),t.content.classList.remove("popupable-content-before")):(t.content.classList.add("popupable-content-before"),t.content.classList.remove("popupable-content-after")):(t.content.classList.remove("popupable-content-before"),t.content.classList.remove("popupable-content-after")))}if(t.id?E.id=t.id:E.removeAttribute("id"),M&&(M.textContent=`${y.currentIndex+1} / ${y.length}`),D){for(const[e,t]of D.entries())t.classList.toggle("popupable-thumbnail-active",e===y.currentIndex);const e=D[y.currentIndex];requestAnimationFrame(()=>{if(!e||!N?.isConnected)return;const t=getComputedStyle(N),n=parseFloat(t.paddingLeft)||0,o=parseFloat(t.paddingRight)||0,a=N.scrollLeft+n,r=N.scrollLeft+N.clientWidth-o,i=e.offsetLeft,s=i+e.offsetWidth;let l=N.scrollLeft;i<a?l=Math.max(0,i-n):s>r&&(l=s-N.clientWidth+o),l!==N.scrollLeft&&(T?N.scrollTo({left:l,behavior:"smooth"}):N.scrollLeft=l),T=!0})}e.closeContainer.classList.toggle("popupable-button-inactive",!t.zoomable&&!t.video),updateExpandedSize(),e.lastProjectedIndex=e.group.currentIndex,buildDecodeQueue(e)},z=()=>{y.currentIndex>=y.length-1||O(y.currentIndex+1)},k=()=>{y.currentIndex<=0||O(y.currentIndex-1)},e.listeners.push({target:he,event:"click",func:()=>z()},{target:ve,event:"click",func:()=>k()},{target:document,event:"keydown",func:t=>{if("zoomed"!==e.state)switch(t.key){case"ArrowRight":case"ArrowDown":case"PageDown":case"d":case"s":z();break;case"ArrowLeft":case"ArrowUp":case"PageUp":case"a":case"w":k();break;case"Home":y.currentIndex=0,F();break;case"End":y.currentIndex=y.length-1,F();break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":y.currentIndex=Math.min(Math.max(Number(t.key),1)-1,y.length-1),F()}}},{target:document,event:"wheel",func:t=>{if("zoomed"===e.state)return;const n=performance.now();n-(S||0)<80||(t.deltaY>50?(S=n,z()):t.deltaY<-50&&(S=n,k()))},args:{passive:!0}}),N){let Ie,Ce,Pe,Ae,Me,Ne,De,Te,ze;function X(){ze&&(cancelAnimationFrame(ze),ze=null)}function Y(){if(X(),Math.abs(Te)<.01)return;let e=performance.now();ze=requestAnimationFrame(function t(n){if(!N.isConnected)return void X();const o=N.scrollWidth-N.clientWidth;if(o<=0)return void X();const a=Math.min(32,n-e);e=n;let r=N.scrollLeft+Te*a;r<0&&(r=0),r>o&&(r=o),N.scrollLeft=r,N.scrollLeft<=.1&&Te<0||N.scrollLeft>=o-.1&&Te>0?X():(Te*=Math.pow(.8,a/16.67),Math.abs(Te)<=.002?X():ze=requestAnimationFrame(t))})}e.listeners.push({target:N,event:"pointerdown",func:e=>{if(0!==e.button)return;const t=N.scrollWidth-N.clientWidth;Pe=t>0,X(),Ie=!0,Ce=!1,Ae=e.clientX,Me=N.scrollLeft,Ne=N.scrollLeft,De=performance.now(),Te=0,Pe&&N.classList.add("popupable-thumbnails-dragging"),N.setPointerCapture(e.pointerId)}},{target:N,event:"pointermove",func:e=>{if(!Ie)return;const t=e.clientX-Ae;Math.abs(t)>a&&(Ce=!0);const n=performance.now(),o=n-De,r=Me-t;if(N.scrollLeft=r,o>0){const e=(N.scrollLeft-Ne)/o;Te=.65*Te+.35*e,Ne=N.scrollLeft,De=n}}},{target:N,event:"pointerup",func:e=>{if(!Ie)return;if(Ie=!1,Pe&&N.classList.remove("popupable-thumbnails-dragging"),N.hasPointerCapture(e.pointerId)&&N.releasePointerCapture(e.pointerId),Ce)return performance.now()-De>10&&(Te=0),void Y();const t=document.elementFromPoint(e.clientX,e.clientY)?.closest?.(".popupable-thumbnail");t&&(y.currentIndex=Number(t.dataset.thumbnailIndex),F())}},{target:N,event:"pointercancel",func:e=>{Ie&&(Ie=!1,Pe&&N.classList.remove("popupable-thumbnails-dragging"),N.hasPointerCapture(e.pointerId)&&N.releasePointerCapture(e.pointerId),X())}},{target:N,event:"wheel",func:e=>{e.stopPropagation(),e.preventDefault();const t=N.scrollWidth-N.clientWidth;if(t<=0)return;const n=Math.abs(e.deltaX)>Math.abs(e.deltaY)?e.deltaX:e.deltaY,o=N.scrollLeft<=.1,a=N.scrollLeft>=t-.1;if(o&&n<0||a&&n>0)return;o&&n>0&&Te<0&&(Te=0),a&&n<0&&Te>0&&(Te=0);Te=(Te||0)+.015*n,ze||Y()},args:{passive:!1}})}Ee&&(e.listeners.push({target:he,event:"pointerenter",func:()=>{Le=!0,R()}},{target:ve,event:"pointerenter",func:()=>{Le=!0,R()}},{target:he,event:"pointerleave",func:()=>{Le=!1,e.scheduleNavHide()}},{target:ve,event:"pointerleave",func:()=>{Le=!1,e.scheduleNavHide()}}),e.listeners.push({target:E,event:"pointermove",func:t=>{if("zoomed"!==e.state)return null==xe||null==we?(xe=t.clientX,void(we=t.clientY)):void(Math.abs(t.clientX-xe)<a&&Math.abs(t.clientY-we)<a||(xe=t.clientX,we=t.clientY,R()))},args:{passive:!0}}));for(const ke of y)ke.content&&C&&C.append(ke.content)}else v&&C.append(v);const $={counter:!!M,content:!!C,thumbnails:!!N},W=u.order.top.filter(e=>$[e]),H=u.order.bottom.filter(e=>$[e]);function B(e,t){e&&("counter"===t&&M?(V[e===P?"counterTop":"counterBottom"]=!0,e.append(M)):"content"===t&&C?(V[e===P?"contentTop":"contentBottom"]=!0,e.append(C)):"thumbnails"===t&&N&&(V[e===P?"thumbnailsTop":"thumbnailsBottom"]=!0,e.append(N)))}P=document.createElement("div"),P.className="popupable-header",A=document.createElement("div"),A.className="popupable-footer";for(const Se of W)B(P,Se);for(const Fe of H)B(A,Fe);I.append(P),I.append(A);const Q=document.createElement("div");Q.className="popupable-button-container popupable-close-container",Q.innerHTML='<div class="popupable-button popupable-close"><svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></div>',Q.addEventListener("click",closePopupable),u.zoomable||u.video||Q.classList.add("popupable-button-inactive"),P.append(Q),E.append(c,I),Object.assign(p,u,{popup:E,group:y,contentContainer:C,thumbnailsContainer:N,orderPlacement:V,closeContainer:Q,goNext:z,goPrev:k});const _=setTimeout(()=>{l===o&&s.classList.add("popupable-loading")},250);if(await p.ready,clearTimeout(_),s.classList.remove("popupable-loading"),l!==o||e!==p||"close"===p.state)return;h.classList.add("popupable-block-transitions"),u.animation.hideSource&&s.classList.add("popupable-hide"),u.animation.crossfade&&E.classList.add("popupable-crossfade"),u.animation.fade&&E.classList.add("popupable-fade"),document.body.append(E),setCloneToOriginalRect(h,s),u.video&&u.source.play().catch(()=>{}),disableScroll();const j=getComputedStyle(E);p.transition.duration=1e3*parseFloat(j.transitionDuration)+1e3*parseFloat(j.transitionDelay),E._state=p,requestAnimationFrame(()=>{requestAnimationFrame(()=>{h.classList.remove("popupable-block-transitions"),openPopupable(E._state),y&&(F(),buildDecodeQueue(E._state))})});let q,U=0;y&&E.addEventListener("dragstart",e=>e.preventDefault());const G=new Map;function K(e,t,n,o,r=[]){if("open"!==e.state)return;let i=0;const s=t.cloneContainer.parentElement,l=s.style.transform;if(l){const e=l.match(/translateX\((-?\d+(?:\.\d+)?)px\)/);e&&(i=Number(e[1])||0)}const p=Math.abs(i)>.5;m=!1,p?(t.cloneContainer.style.translate="0 0",t.cloneContainer.style.transition="translate var(--popupable-switch-duration), transform 0s",s.style.transition=null,s.style.transform=null,t.cloneContainer.style.translate=`${i}px 0`):(s.style.transition=null,s.style.transform=null),e.state="zoomed",E.classList.add("popupable-locked");let c,u,d=o;const b=new Map;let f,g,h,v,y,x,w,L,C,P,A=!1;const M=t.cloneContainer.getBoundingClientRect(),N=n?.clientX??M.left+M.width/2,D=n?.clientY??M.top+M.height/2;c=(N-M.left)*(1-d),u=(D-M.top)*(1-d);const T=()=>t.cloneContainer.style.transform=`translate(${c}px, ${u}px) scale(${d})`;function z(e,n,o){const a=d;var r;if(r=e,d=Math.min(6,Math.max(.5,r)),d===a)return!1;const i=t.cloneContainer.getBoundingClientRect(),s=d/a,l=n-i.left,p=o-i.top;return c+=l*(1-s),u+=p*(1-s),!0}function k(){if(1===b.size){const e=b.values().next().value;return f=e.id,g=e.x,h=e.y,v=null,y=null,void(x=null)}if(b.size>=2){f=null;const[e,t]=[...b.values()];return v=(e.x+t.x)/2,y=(e.y+t.y)/2,void(x=Math.hypot(t.x-e.x,t.y-e.y))}f=null,g=null,h=null,v=null,y=null,x=null}if(t.cloneContainer.classList.add("popupable-zoomed"),T(),r.length){p||(t.cloneContainer.style.transition="none"),P=!0;for(const e of r)b.set(e.id,{id:e.id,x:e.x,y:e.y}),E.setPointerCapture(e.id);k()}e.unzoom=()=>{e.state="open",E.classList.remove("popupable-locked");for(const e of b.keys())E.hasPointerCapture(e)&&E.releasePointerCapture(e);b.clear(),t.cloneContainer.classList.remove("popupable-zoomed"),t.cloneContainer.style.transition=null,t.cloneContainer.style.transform=null,t.cloneContainer.style.translate=null;for(const t of e.zoomListeners)t.target.removeEventListener(t.event,t.func)},e.zoomListeners=[{target:E,event:"pointerdown",func:e=>{0===e.button&&(t.cloneContainer.style.transition="none",E.setPointerCapture(e.pointerId),b.set(e.pointerId,{id:e.pointerId,x:e.clientX,y:e.clientY}),1===b.size?(w=e.target,L=e.clientX,C=e.clientY,P=!1):P=!0,k(),e.preventDefault())}},{target:E,event:"pointermove",func:e=>{const t=b.get(e.pointerId);if(t){if(t.x=e.clientX,t.y=e.clientY,!P&&(Math.abs(e.clientX-L)>a||Math.abs(e.clientY-C)>a)&&(P=!0),1===b.size&&f===e.pointerId){const t=e.clientX-g,n=e.clientY-h;if(!t&&!n)return;return c+=t,u+=n,g=e.clientX,h=e.clientY,void T()}if(b.size>=2){const[e,t]=[...b.values()],n=(e.x+t.x)/2,o=(e.y+t.y)/2,a=Math.hypot(t.x-e.x,t.y-e.y);if(!x)return v=n,y=o,void(x=a);c+=n-v,u+=o-y,z(d*(a/x),n,o),A=!0,v=n,y=o,x=a,T()}}}},{target:E,event:"pointerup",func:n=>{if(b.has(n.pointerId)){if(b.delete(n.pointerId),E.hasPointerCapture(n.pointerId)&&E.releasePointerCapture(n.pointerId),A&&d<=1.01&&b.size<2)return e.skipOpenTouchPointerUps=b.size,void e.unzoom();if(!b.size&&!P&&Math.abs(n.clientX-L)<a&&Math.abs(n.clientY-C)<a){if(w?.closest?.(".popupable-clone-container")===t.cloneContainer||(w===E||w===I))return void e.unzoom()}k()}}},{target:E,event:"pointercancel",func:e=>{b.has(e.pointerId)&&(b.delete(e.pointerId),E.hasPointerCapture(e.pointerId)&&E.releasePointerCapture(e.pointerId),k())}},{target:E,event:"wheel",func:e=>{t.cloneContainer.style.transition="none",z(d*Math.exp(.002*-e.deltaY),e.clientX,e.clientY)&&T()},args:{passive:!0}}];for(const t of e.zoomListeners)t.target.addEventListener(t.event,t.func,t.args)}e.listeners.push({target:E,event:"pointerdown",func:e=>{if("open"!==E._state.state||"touch"!==e.pointerType)return;const t=E._state,n=t.group?t.group[t.group.currentIndex]:t;e.target.closest(".popupable-clone-container")===n.cloneContainer&&(G.set(e.pointerId,{id:e.pointerId,x:e.clientX,y:e.clientY}),G.size>=2&&(K(t,n,e,1,[...G.values()].slice(0,2)),G.clear(),e.preventDefault()))}},{target:E,event:"pointermove",func:e=>{const t=G.get(e.pointerId);t&&(t.x=e.clientX,t.y=e.clientY)}},{target:E,event:"pointerup",func:e=>{G.delete(e.pointerId)}},{target:E,event:"pointercancel",func:e=>{G.delete(e.pointerId)}}),E.addEventListener("pointerup",t=>{if("zoomed"===E._state.state)return;if("touch"===t.pointerType&&(E._state.skipOpenTouchPointerUps||0)>0)return void E._state.skipOpenTouchPointerUps--;const o=performance.now(),a=null!=t.target.closest(".popupable-next-container, .popupable-prev-container");if(q&&o-U<250)return void(U=o);if(a?(q=!0,U=o):(q=!1,U=o),0!==t.button||!((t.target.classList.contains("popupable-clone")||t.target.classList.contains("popupable-clone-layer"))&&n.classList.contains("popupable-clone-container")||t.target==n&&(t.target.closest(".popupable-clone-container")||t.target.classList.contains("popupable-viewport")||t.target.classList.contains("popupable-container"))||t.target.classList.contains("popupable-container")&&n===e.original.parentElement))return;const r=E._state,i=r.group?r.group[r.group.currentIndex]:r;r.blocked&&(r.blocked=!1),"open"!==r.state?(t.stopPropagation(),e!==r&&(closePopupable(),e=r),openPopupable(e)):requestAnimationFrame(()=>{r.blocked?r.blocked=!1:i.zoomable&&(t.target.classList.contains("popupable-clone")||t.target.classList.contains("popupable-clone-layer"))?K(r,i,t,2):i.video&&(t.target.classList.contains("popupable-clone")||t.target.closest(".popupable-clone-container")===i.cloneContainer)||closePopupable()})})}),document.addEventListener("keydown",t=>{if("Escape"===t.key||"Backspace"===t.key||" "===t.key||"Delete"===t.key){if("zoomed"===e.state)return void e.unzoom();closePopupable()}}),window.addEventListener("resize",updateExpandedSize),visualViewport&&visualViewport.addEventListener("resize",updateExpandedSize)}
7
+ {let e,t,n,o=0;const a=3;let r;function triggerHaptic(){if("function"!=typeof navigator.vibrate){if(!r){r=document.createElement("label"),r.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none";const e=document.createElement("input");e.type="checkbox",e.setAttribute("switch",""),r.append(e),document.body.append(r)}r.click()}else navigator.vibrate([10])}function disableScroll(){window.addEventListener("wheel",prevent,{passive:!1}),window.addEventListener("touchmove",prevent,{passive:!1}),window.addEventListener("keydown",blockKeys,!0)}function enableScroll(){window.removeEventListener("wheel",prevent),window.removeEventListener("touchmove",prevent),window.removeEventListener("keydown",blockKeys,!0)}function prevent(e){e.preventDefault()}function blockKeys(e){["ArrowUp","ArrowDown","PageUp","PageDown","Home","End"," "].includes(e.key)&&e.preventDefault()}function calcExpandedRect(t){const n=t.original,o=visualViewport?.width||window.innerWidth,a=visualViewport?.height||window.innerHeight,r=visualViewport?.offsetTop||0,i=visualViewport?.offsetLeft||0,s=visualViewport?.scale||1,l=1/s,p=e.popup,c=(parseFloat(getComputedStyle(p).getPropertyValue("--popupable-screen-padding"))||40)/s,u=Math.max(0,o-2*c),d=a-2*c,m=Math.max(0,d);let b;if(t.maintainAspect){const e=n.getBoundingClientRect();b=e.width/e.height}else{b=(t.source.naturalWidth||t.source.videoWidth)/(t.source.naturalHeight||t.source.videoHeight)||1}let f=0,g=0;if(e.orderPlacement){const n=e.popup.querySelector(".popupable-counter"),o=n?n.getBoundingClientRect().height/l:0,a=e.thumbnailsContainer?e.thumbnailsContainer.getBoundingClientRect().height/l:0,r=e.contentContainer,i=t.content?t.content.getBoundingClientRect().height/l:r?.previousElementSibling&&r?.nextElementSibling&&parseFloat(getComputedStyle(r,"::after").height)||0,{counterTop:s,contentTop:p,thumbnailsTop:c,counterBottom:u,contentBottom:d,thumbnailsBottom:m}=e.orderPlacement;f=(s?o:0)+(p?i:0)+(c?a:0),g=(u?o:0)+(d?i:0)+(m?a:0)}const h=Math.max(0,a-f-g-2*c);let v=u,y=v/b;if(y>m&&(y=m,v=y*b),y>h&&(y=h,v=y*b),t.noUpscale){const e=t.cloneLayer||n,o=e.naturalWidth||e.videoWidth,a=e.naturalHeight||e.videoHeight;if(o&&a){const e=o/s,t=a/s,n=Math.min(1,e/v,t/y);n<1&&(v*=n,y*=n)}}let x=r+c+(m-y)/2;const w=r+a-g-c-y;return x=Math.min(x,w),x=Math.max(x,r+f+c),{top:x,left:i+c+(u-v)/2,width:v,height:y}}function setCloneToOriginalRect(t,n){const o=calcExpandedRect(e),{top:a,left:r,width:i,height:s}=e.animation.position(n,o);t.style.top=a+"px",t.style.left=r+"px",t.style.width=i+"px",t.style.height=s+"px"}window.popupableAnimTypes={expand:{styles:!0,hideSource:!0,crossfade:!0,position(e){const t=e.getBoundingClientRect();return{top:visualViewport.offsetTop+t.top,left:visualViewport.offsetLeft+t.left,width:t.width,height:t.height}}},pop:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+.05*a,left:n+.05*o,width:.9*o,height:.9*a})},line:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+a/2,left:n+.05*o,width:.9*o,height:0})},float:{fade:!0,position:(e,{top:t,left:n,width:o,height:a})=>({top:t+40,left:n,width:o,height:a})}};const i=3;function parseCssTime(e){if(!e)return 0;const t=parseFloat(e);return Number.isNaN(t)?0:/ms\s*$/i.test(e)?t:1e3*t}function getReleaseDelay(e){const t=e?.popup||document.documentElement;return parseCssTime(getComputedStyle(t).getPropertyValue("--popupable-switch-duration"))}function buildDecodeQueue(e,t=e.group?.currentIndex,{delayRelease:n=!0}={}){if(!e.group)return;const o=e.group.length,a=n?getReleaseDelay(e):0;for(let n=0;n<o;n++){const o=e.group[n];Math.abs(n-t)>i?o.releaseDecode&&!o._releaseTimer&&(a<=0?o.releaseDecode():o._releaseTimer=setTimeout(()=>{o._releaseTimer=null,o.releaseDecode()},a)):o._releaseTimer&&(clearTimeout(o._releaseTimer),o._releaseTimer=null)}const r=[];t!==e.group.currentIndex&&t>=0&&t<o&&r.push(e.group[t]);for(let n=1;n<=i;n++)t+n<o&&r.push(e.group[t+n]),t-n>=0&&r.push(e.group[t-n]);e.decodeQueue=r,runDecodeQueue(e)}function projectSnapIndex(e,t){const n=window.innerWidth,o=Math.abs(t);if(o<=Math.max(.1*n,64))return e.currentIndex;const a=Math.max(0,Math.floor((o-n/2)/n))+1,r=t>0?-1:1;return Math.max(0,Math.min(e.length-1,e.currentIndex+r*a))}const s=100;let l=0,p=null,c=-1;function scheduleDragDecodeQueue(t){if(c=t,p)return;const n=Math.max(0,s-(performance.now()-l));p=setTimeout(()=>{p=null,l=performance.now();const t=c;c=-1,t>=0&&e?.group&&t!==e.group.currentIndex&&buildDecodeQueue(e,t,{delayRelease:!1})},n)}function cancelDragDecodeQueue(){p&&(clearTimeout(p),p=null),c=-1}async function runDecodeQueue(e){if(!e.decodeQueueRunning){for(e.decodeQueueRunning=!0;e.decodeQueue&&e.decodeQueue.length&&!e.decodeAborted;){const t=e.decodeQueue.shift();try{await t.triggerDecode()}catch{}}e.decodeQueueRunning=!1}}function openPopupable(e){if("open"===e.state)return;e.state="open",triggerHaptic();const{cloneContainer:t,popup:n,transition:o,group:a,listeners:r}=e;n.classList.add("popupable-active"),e.clearNavInactive?.(),updateExpandedSize(),e.closingContainer?.removeEventListener("transitionend",o.listener);const i=e.closingContainer??t;o.listener=t=>{if(t&&t.target!==t.currentTarget)return;i.removeEventListener("transitionend",o.listener),n.classList.add("popupable-open");const s=a?a[a.currentIndex]:e;if(s.video&&(s.zoomable?s.source.controls=!1:s.explicitControls||(s.source.controls=!0)),a)for(const e of a)e.cloneContainer.style.display=null;for(const e of r)e.target.addEventListener(e.event,e.func,e.args);e.scheduleNavHide?.()},o.duration?i.addEventListener("transitionend",o.listener):o.listener()}function closePopupable(){if(!e||"close"===e.state)return;if(o++,e.state="close",e.decodeAborted=!0,e.decodeQueue=null,e.group)for(const t of e.group)t._releaseTimer&&(clearTimeout(t._releaseTimer),t._releaseTimer=null);document.body.classList.add("popupable-block-touch"),setTimeout(()=>document.body.classList.remove("popupable-block-touch"),300);const{cloneContainer:n,original:a,popup:r,transition:i,group:s,listeners:l}=e;a.classList.remove("popupable-loading"),r.classList.remove("popupable-active"),r.classList.remove("popupable-open");const p=s?s[s.currentIndex].cloneContainer:n;if(e.closingContainer=p,setCloneToOriginalRect(p,a),s)for(const e of s)e.cloneContainer!==p&&(e.cloneContainer.style.display="none");for(const e of l)e.target.removeEventListener(e.event,e.func);n.removeEventListener("transitionend",i.listener);const c=s?s[s.currentIndex]:e;c.video&&c.source&&(c.source.controls=!1);const u=c.original===a,d=e;i.listener=n=>{n&&n.target!==n.currentTarget||(p.removeEventListener("transitionend",i.listener),a.classList.remove("popupable-hide"),u&&c.video&&"VIDEO"===a.tagName&&!c.cloneLayer&&(a.currentTime=c.source.currentTime),u&&c.wasPlaying&&"VIDEO"===a.tagName&&a.play(),r.remove(),d===e&&(enableScroll(),t=e,e=null))},i.duration?p.addEventListener("transitionend",i.listener):i.listener()}function updateExpandedSize(){if(!e||"close"===e.state)return;if((e.group??[e]).some(e=>e.cloneContainer?.classList.contains("popupable-block-transitions")))return;const t=visualViewport?.width||window.innerWidth,n=visualViewport?.height||window.innerHeight,o=visualViewport?.offsetTop||0,a=visualViewport?.offsetLeft||0,r=visualViewport?.scale||1;document.documentElement.style.setProperty("--popupable-view-width",t+"px"),e.popup.style.setProperty("--popupable-vv-width",t+"px"),e.popup.style.setProperty("--popupable-vv-height",n+"px"),e.popup.style.setProperty("--popupable-vv-top",o+"px"),e.popup.style.setProperty("--popupable-vv-left",a+"px"),e.popup.style.setProperty("--popupable-vv-scale",r),e.popup.style.setProperty("--popupable-vv-ui-scale",1/r);const i=1/r;let s;s=e.group?e.group:[e];for(const e of s){const{top:t,left:n,width:o,height:a}=calcExpandedRect(e);e.cloneContainer.style.top=t+"px",e.cloneContainer.style.left=n+"px",e.cloneContainer.style.width=o+"px",e.cloneContainer.style.height=a+"px"}if(e.contentContainer){let t;if(t=e.group?e.group[e.group.currentIndex]:e,t.content){const n=t.content.getBoundingClientRect();e.contentContainer.style.height=n.height/i+"px"}else{const t=e.contentContainer,n=t.previousElementSibling&&t.nextElementSibling&&parseFloat(getComputedStyle(t,"::after").height)||0;t.style.height=n+"px"}}}const u=/\.(mp4|m4v|webm|ogv|mov|3gp|m3u8|flv)(\?|#|$)/i;function isVideo(e){const t=inheritAttr(e,"data-popupable-type");if(t)return"video"===t;if("VIDEO"===e.tagName)return!0;if("IMG"===e.tagName)return!1;const n=e.getAttribute("data-popupable-src")||e.getAttribute("src")||"";return u.test(n)}const d=e=>e.getAttribute("currentSrc")||e.getAttribute("src")||e.getAttribute("data-popupable-src");function ancestorClosest(e,t){let n=e;for(;n;){const e=n.closest?.(t);if(e)return e;const o=n.getRootNode?.();n=o instanceof ShadowRoot?o.host:null}return null}function composedClosest(e,t){for(const n of e.composedPath())if(1===n.nodeType&&n.matches?.(t))return n;return null}function inheritAttr(e,t){const n=ancestorClosest(e,`[${t}]`);if(!n)return;const o=n.getAttribute(t);return"false"!==o?o||!0:void 0}function parsePopupableOrder(e){const t=["counter","image","content","thumbnails"],n=new Set(t),o=[];if(e)for(const t of e.split(",")){const e=t.trim().toLowerCase();e&&n.has(e)&&!o.includes(e)&&o.push(e)}for(const e of t)o.includes(e)||o.push(e);const a=o.indexOf("image");return{top:o.slice(0,a),bottom:o.slice(a+1)}}function cloneElement(e,t=e){const n=inheritAttr(e,"data-popupable-anim"),o=popupableAnimTypes[n]?n:"expand",a=popupableAnimTypes[o],r=inheritAttr(e,"data-popupable-src"),i=d(e),s=inheritAttr(e,"data-popupable-title"),l=inheritAttr(e,"data-popupable-description"),p=inheritAttr(e,"data-popupable-zoomable"),c=getComputedStyle(e),m=t===e?c:getComputedStyle(t),b=t!==e?d(t):null,f=t===e,g=document.createElement("div");g.className="popupable-clone-container",inheritAttr(e,"data-popupable-transparent")&&g.classList.add("popupable-transparent"),p&&g.classList.add("popupable-zoomable"),g.style.borderRadius=c.borderRadius,a.styles&&(g.style.border=c.border,g.style.outline=c.outline,g.style.boxShadow=c.boxShadow);const h=isVideo(e);let v=!1;const y=inheritAttr(e,"data-popupable-poster"),x=("string"==typeof y?y:null)||("VIDEO"===e.tagName?e.getAttribute("poster"):null),w=b||i||r,L=u.test(w)||h&&w===i,C=r&&i||b;let E,I,P;L?(E=document.createElement("video"),E.className="popupable-clone",f&&(E.src=w),E.playsInline=!0,E.controls=!1,h&&!C||(E.muted=!0,E.loop=!0,E.autoplay=!0),f&&x&&w===i&&(E.poster=x)):(E=new Image,E.className="popupable-clone",f&&(E.src=w),E.style.imageRendering=m.imageRendering);const A="IMG"===t.tagName||"VIDEO"===t.tagName;if(E.style.objectFit=A?m.objectFit:"cover",A&&(E.style.objectPosition=m.objectPosition),E.style.background=m.background,g.append(E),"VIDEO"===E.tagName?E.addEventListener("loadedmetadata",()=>updateExpandedSize()):E.addEventListener("load",()=>updateExpandedSize()),C){const t=r||i;if(u.test(t)||h&&t===i?(I=document.createElement("video"),I.className="popupable-clone-layer",f&&(I.src=t),I.playsInline=!0,I.controls=!1,h||(I.muted=!0,I.loop=!0,I.autoplay=!0),f&&x&&t===i&&(I.poster=x)):(I=new Image,I.className="popupable-clone-layer",f&&(I.src=t),I.style.imageRendering=c.imageRendering),g.append(I),"VIDEO"===I.tagName?I.addEventListener("loadedmetadata",()=>updateExpandedSize()):I.addEventListener("load",()=>updateExpandedSize()),"fill"===E.style.objectFit&&"IMG"===E.tagName){const t=e.getBoundingClientRect();e.naturalWidth&&e.naturalHeight&&Math.abs(t.width/t.height-e.naturalWidth/e.naturalHeight)<.01&&(E.style.objectFit="cover")}P=I}else P=E;h&&"VIDEO"===e.tagName&&t===e&&(L&&(E.currentTime=e.currentTime),v=!e.paused,e.pause());const M=inheritAttr(e,"data-popupable-attr");let N,D=!1;if("string"==typeof M)for(const e of M.split(",")){const t=e.trim();if(!t)continue;const n=t.indexOf("=");if(-1===n)P[t]=!0,"controls"===t&&(D=!0);else{const e=t.slice(0,n).trim(),o=t.slice(n+1).trim(),a=Number(o);"true"===o?P[e]=!0:"false"===o?P[e]=!1:""===o||Number.isNaN(a)?P[e]=o:P[e]=a,"controls"===e&&(D=!0)}}if(s||l){if(N=document.createElement("div"),N.classList="popupable-content",s){const e=document.createElement("div");e.className="popupable-title",e.textContent=s,N.append(e)}if(l){const e=document.createElement("div");e.className="popupable-description",e.textContent=l,N.append(e)}}const T=[E,I].filter(Boolean),z=Promise.all(T.filter(e=>"VIDEO"===e.tagName).map(e=>{const t=new Promise(t=>{if(e.readyState>=1)return t();e.addEventListener("loadedmetadata",t,{once:!0}),e.addEventListener("error",t,{once:!0})});if(e.poster){const n=new Promise(t=>{const n=new Image;n.addEventListener("load",t,{once:!0}),n.addEventListener("error",t,{once:!0}),n.src=e.poster});return Promise.all([n,t])}return t})),k=w,S=I?r||i:null;let F=f||!I;const V="VIDEO"===E.tagName&&x&&w===i?x:null,R=I&&"VIDEO"===I.tagName&&x&&(r||i)===i?x:null;let O=!f,X=null;const Y=(e,t)=>e+Math.random()*(t-e),$=(e,t,n)=>`hsl(${e.toFixed(0)} ${t.toFixed(0)}% ${n.toFixed(0)}%)`,W=Math.random();let H,B,Q;W<.2?(H=Y(6,14),B=Y(22,38),Q=Y(20,45)):W<.55?(H=Y(14,26),B=Y(38,58),Q=Y(25,55)):W<.85?(H=Y(22,38),B=Y(58,75),Q=Y(35,65)):(H=Y(32,50),B=Y(72,90),Q=Y(40,75));const _=Y(0,360),j=(_+Y(20,140))%360,q=(_+Y(-40,220)+360)%360;function U(){O&&(O=!1,g.classList.remove("popupable-clone-loading"),F&&k&&!E.getAttribute("src")&&(E.src=k,"VIDEO"===E.tagName&&V&&(E.poster=V)),I&&S&&!I.getAttribute("src")&&(I.src=S,"VIDEO"===I.tagName&&R&&(I.poster=R)))}function G(){if(U(),X)return X;const e=T.filter(e=>"VIDEO"!==e.tagName);return e.length?(X=Promise.all(e.map(e=>e.decode?e.decode().catch(()=>{}):new Promise(t=>{if(e.complete)return t();e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}))).then(()=>z),X):(X=z,X)}return g.style.setProperty("--popupable-loading-x1",Y(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-y1",Y(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-x2",Y(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-y2",Y(0,100).toFixed(0)+"%"),g.style.setProperty("--popupable-loading-c1",`hsla(${q.toFixed(0)} ${Math.min(95,Q+Y(10,25)).toFixed(0)}% ${B.toFixed(0)}% / ${Y(.55,.9).toFixed(2)})`),g.style.setProperty("--popupable-loading-c2",`hsla(${j.toFixed(0)} ${Q.toFixed(0)}% ${(.8*B).toFixed(0)}% / ${Y(.4,.75).toFixed(2)})`),g.style.setProperty("--popupable-loading-angle",Y(0,360).toFixed(0)+"deg"),g.style.setProperty("--popupable-loading-a",$(_,.6*Q,H)),g.style.setProperty("--popupable-loading-b",$(j,.8*Q,(H+B)/2)),O&&g.classList.add("popupable-clone-loading"),{id:e.dataset.popupable,original:e,cloneContainer:g,clone:E,cloneLayer:I,maintainAspect:inheritAttr(e,"data-popupable-maintain-aspect"),noUpscale:inheritAttr(e,"data-popupable-no-upscale"),counter:inheritAttr(e,"data-popupable-counter"),thumbnails:inheritAttr(e,"data-popupable-thumbnails"),order:parsePopupableOrder(inheritAttr(e,"data-popupable-order")),animationName:o,animation:a,get ready(){return G()},triggerDecode:G,ensureLoaded:U,markAsActiveInGroup:function(){F=!0,O||!k||E.getAttribute("src")||(E.src=k,"VIDEO"===E.tagName&&V&&(E.poster=V))},releaseDecode:function(){O||(O=!0,X=null,g.classList.add("popupable-clone-loading"),"VIDEO"===E.tagName?(E.paused||E.pause(),E.removeAttribute("src"),E.removeAttribute("poster"),E.load()):E.removeAttribute("src"),I&&("VIDEO"===I.tagName?(I.paused||I.pause(),I.removeAttribute("src"),I.removeAttribute("poster"),I.load()):I.removeAttribute("src")))},content:N,zoomable:p,source:P,video:h,explicitControls:D,wasPlaying:v}}let m,b,f;document.addEventListener("pointerdown",t=>{0===t.button&&(m||(n=t.composedPath()[0]??t.target,b=t.clientX,f=t.clientY),m||"open"!==e?.state||composedClosest(t,".popupable-header, .popupable-footer")||(m=!0))});let g=!1;function handleMove(t){if("open"!==e?.state||!e.group||!m)return;if(!e.popup?.classList.contains("popupable-open"))return b=t.touches?.[0].clientX??t.clientX,void(f=t.touches?.[0].clientY??t.clientY);const n=e.group[e.group.currentIndex],o=t.touches?.[0].clientX??t.clientX;!g&&Math.abs(o-b)>a&&n.video&&(g=!0,n.source.style.pointerEvents="none"),n.cloneContainer.parentElement.style.transition="initial",n.cloneContainer.parentElement.style.transform=`translateX(${o-b}px)`;const r=projectSnapIndex(e.group,o-b);r!==e.lastProjectedIndex&&(e.lastProjectedIndex=r,scheduleDragDecodeQueue(r))}document.addEventListener("mousemove",handleMove),document.addEventListener("touchmove",handleMove,{passive:!0}),document.addEventListener("pointerup",async r=>{if(0!==r.button)return;if(m){m=!1,cancelDragDecodeQueue();const J=e.group?e.group[e.group.currentIndex]:e;g&&(g=!1,J.source.style.pointerEvents=null),J.cloneContainer.parentElement.style.transition=null,J.cloneContainer.parentElement.style.transform=null;const ee=r.clientX-b,te=Math.abs(ee),ne=r.clientY-f,oe=Math.abs(ne);if("touch"===r.pointerType&&oe>56&&oe>1.1*te)return void closePopupable();if(e.group&&te>a){const ae=Math.max(0,Math.floor((te-window.innerWidth/2)/window.innerWidth));if(ee>Math.max(.1*window.innerWidth,64))for(let re=0;re<=ae;re++)e.goPrev();else if(ee<-Math.max(.1*window.innerWidth,64))for(let ie=0;ie<=ae;ie++)e.goNext();return void(e.blocked=!0)}}const i=r.composedPath()[0]??r.target,s=composedClosest(r,".popupable-viewport")&&!ancestorClosest(n,".popupable-viewport");if(!s&&i!=n&&(!n.classList.contains("popupable-clone-container")||i!==t?.original)&&(!ancestorClosest(n,".popupable-container")||composedClosest(r,".popupable-container"))||Math.abs(r.clientX-b)>a||Math.abs(r.clientY-f)>a)return;const l=(s?ancestorClosest(n,"[data-popupable]"):null)||composedClosest(r,"[data-popupable]");if(!l){if(s)return void closePopupable();if(composedClosest(r,".popupable-container"))return;return void(e&&("zoomed"===e.state?e.unzoom():closePopupable()))}if(r.preventDefault(),e&&"close"!==e.state&&e.original===l)return;e&&closePopupable();const p=++o;e={transition:{},listeners:[]};const c=e,u=document.createElement("div");u.className="popupable-clones";const h=cloneElement(l),{cloneContainer:v,content:y}=h;let x;const w=ancestorClosest(l,"[data-popupable-group]"),L=w?.getAttribute("data-popupable-group"),C=L&&"false"!==L?L:null;if(C){const se=[],le=new Set,pe=l.getRootNode?.()??document;for(const ce of pe.querySelectorAll(`[data-popupable-group="${C}"]`)){ce.hasAttribute("data-popupable")&&!le.has(ce)&&(le.add(ce),se.push(ce));for(const ue of ce.querySelectorAll("[data-popupable]")){if(le.has(ue))continue;const de=ue.getAttribute("data-popupable-group");null!==de&&de!==C||ancestorClosest(ue,"[data-popupable-group]")!==ce||(le.add(ue),se.push(ue))}}if(se.length){x=[];for(const[me,be]of se.entries())if(be===l)x.push(h),x.currentIndex=me,u.append(v);else{const fe=cloneElement(be,l);fe.cloneContainer.style.display="none",x.push(fe),u.append(fe.cloneContainer)}for(const[ge,he]of x.entries()){if(!he.content)continue;const ve=ge-x.currentIndex;ve>0?he.content.classList.add("popupable-content-after"):ve<0&&he.content.classList.add("popupable-content-before")}}}else u.append(v);const E=document.createElement("div");E.className=`popupable-container popupable-anim-${h.animationName}`,h.id&&(E.id=h.id);const I=document.createElement("div");let P,A,M,N,D,T,z,k,S,F,V;I.className="popupable-viewport",(y||x&&x.some(e=>e.content))&&(P=document.createElement("div"),P.classList="popupable-content-container");const R={};if(x){h.counter&&(N=document.createElement("div"),N.className="popupable-counter"),h.thumbnails&&(D=document.createElement("div"),D.className="popupable-thumbnails",T=x.map((e,t)=>{let n;if(e.video){const t=inheritAttr(e.original,"data-popupable-poster"),o=("string"==typeof t?t:null)||("VIDEO"===e.original.tagName?e.original.getAttribute("poster"):null);o?(n=new Image,n.src=o):(n=document.createElement("video"),n.src=inheritAttr(e.original,"data-popupable-src")||d(e.original),n.muted=!0,n.playsInline=!0,n.preload="metadata",n.disablePictureInPicture=!0,n.disableRemotePlayback=!0)}else n=new Image,n.src=inheritAttr(e.original,"data-popupable-src")||d(e.original);return n.className="popupable-thumbnail",n.dataset.thumbnailIndex=t,D.append(n),n})),I.innerHTML=`\n <div class="popupable-button-container popupable-prev-container${x.currentIndex?"":" popupable-button-disabled"}">\n <div class="popupable-button popupable-prev">\n <svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor">\n <path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/>\n </svg>\n </div>\n </div>\n <div class="popupable-button-container popupable-next-container${x.currentIndex===x.length-1?" popupable-button-disabled":""}">\n <div class="popupable-button popupable-next">\n <svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor">\n <path d="M647-440H160v-80h487L423-744l57-56 320 320-320 320-57-56 224-224Z"/>\n </svg>\n </div>\n </div>\n `;const ye=I.querySelector(".popupable-next-container"),xe=I.querySelector(".popupable-prev-container");let we,Le,Ce,Ee;const Ie=!(navigator.maxTouchPoints>0||window.matchMedia("(hover: none)").matches);function O(){ye.classList.remove("popupable-button-inactive"),xe.classList.remove("popupable-button-inactive"),e.scheduleNavHide()}function X(e){const t=x[x.currentIndex];t.video&&t.source&&(t.source.paused||(t.swipePaused=!0,t.source.pause()),t.source.controls=!1),x.currentIndex=e;const n=x[x.currentIndex];n.video&&n.source&&(n.zoomable||(n.source.controls=!0),n.source.play().catch(()=>{}),n.swipePaused=!1),V()}if(e.scheduleNavHide=()=>{Ie&&(clearTimeout(we),Ee||(we=setTimeout(()=>{Ee||(ye.classList.add("popupable-button-inactive"),xe.classList.add("popupable-button-inactive"))},1500)))},e.clearNavInactive=()=>{ye.classList.remove("popupable-button-inactive"),xe.classList.remove("popupable-button-inactive")},V=async()=>{const t=x[x.currentIndex];t.markAsActiveInGroup(),await t.ready,x.currentIndex?xe.classList.remove("popupable-button-disabled"):xe.classList.add("popupable-button-disabled"),x.currentIndex===x.length-1?ye.classList.add("popupable-button-disabled"):ye.classList.remove("popupable-button-disabled");for(const[e,t]of x.entries()){const n=e-x.currentIndex;t.cloneContainer.style.setProperty("--popupable-offset-multiplier",n),t.cloneContainer.style.zIndex=-1*Math.abs(n),t.content&&(n?n>0?(t.content.classList.add("popupable-content-after"),t.content.classList.remove("popupable-content-before")):(t.content.classList.add("popupable-content-before"),t.content.classList.remove("popupable-content-after")):(t.content.classList.remove("popupable-content-before"),t.content.classList.remove("popupable-content-after")))}if(t.id?E.id=t.id:E.removeAttribute("id"),N&&(N.textContent=`${x.currentIndex+1} / ${x.length}`),T){for(const[e,t]of T.entries())t.classList.toggle("popupable-thumbnail-active",e===x.currentIndex);const e=T[x.currentIndex];requestAnimationFrame(()=>{if(!e||!D?.isConnected)return;const t=getComputedStyle(D),n=parseFloat(t.paddingLeft)||0,o=parseFloat(t.paddingRight)||0,a=D.scrollLeft+n,r=D.scrollLeft+D.clientWidth-o,i=e.offsetLeft,s=i+e.offsetWidth;let l=D.scrollLeft;i<a?l=Math.max(0,i-n):s>r&&(l=s-D.clientWidth+o),l!==D.scrollLeft&&(z?D.scrollTo({left:l,behavior:"smooth"}):D.scrollLeft=l),z=!0})}e.closeContainer.classList.toggle("popupable-button-inactive",!t.zoomable&&!t.video),updateExpandedSize(),e.lastProjectedIndex=e.group.currentIndex,buildDecodeQueue(e)},k=()=>{x.currentIndex>=x.length-1||X(x.currentIndex+1)},S=()=>{x.currentIndex<=0||X(x.currentIndex-1)},e.listeners.push({target:ye,event:"click",func:()=>k()},{target:xe,event:"click",func:()=>S()},{target:document,event:"keydown",func:t=>{if("zoomed"!==e.state)switch(t.key){case"ArrowRight":case"ArrowDown":case"PageDown":case"d":case"s":k();break;case"ArrowLeft":case"ArrowUp":case"PageUp":case"a":case"w":S();break;case"Home":x.currentIndex=0,V();break;case"End":x.currentIndex=x.length-1,V();break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":x.currentIndex=Math.min(Math.max(Number(t.key),1)-1,x.length-1),V()}}},{target:document,event:"wheel",func:t=>{if("zoomed"===e.state)return;const n=performance.now();n-(F||0)<80||(t.deltaY>50?(F=n,k()):t.deltaY<-50&&(F=n,S()))},args:{passive:!0}}),D){let Pe,Ae,Me,Ne,De,Te,ze,ke,Se;function Y(){Se&&(cancelAnimationFrame(Se),Se=null)}function $(){if(Y(),Math.abs(ke)<.01)return;let e=performance.now();Se=requestAnimationFrame(function t(n){if(!D.isConnected)return void Y();const o=D.scrollWidth-D.clientWidth;if(o<=0)return void Y();const a=Math.min(32,n-e);e=n;let r=D.scrollLeft+ke*a;r<0&&(r=0),r>o&&(r=o),D.scrollLeft=r,D.scrollLeft<=.1&&ke<0||D.scrollLeft>=o-.1&&ke>0?Y():(ke*=Math.pow(.8,a/16.67),Math.abs(ke)<=.002?Y():Se=requestAnimationFrame(t))})}e.listeners.push({target:D,event:"pointerdown",func:e=>{if(0!==e.button)return;const t=D.scrollWidth-D.clientWidth;Me=t>0,Y(),Pe=!0,Ae=!1,Ne=e.clientX,De=D.scrollLeft,Te=D.scrollLeft,ze=performance.now(),ke=0,Me&&D.classList.add("popupable-thumbnails-dragging"),D.setPointerCapture(e.pointerId)}},{target:D,event:"pointermove",func:e=>{if(!Pe)return;const t=e.clientX-Ne;Math.abs(t)>a&&(Ae=!0);const n=performance.now(),o=n-ze,r=De-t;if(D.scrollLeft=r,o>0){const e=(D.scrollLeft-Te)/o;ke=.65*ke+.35*e,Te=D.scrollLeft,ze=n}}},{target:D,event:"pointerup",func:e=>{if(!Pe)return;if(Pe=!1,Me&&D.classList.remove("popupable-thumbnails-dragging"),D.hasPointerCapture(e.pointerId)&&D.releasePointerCapture(e.pointerId),Ae)return performance.now()-ze>10&&(ke=0),void $();const t=document.elementFromPoint(e.clientX,e.clientY)?.closest?.(".popupable-thumbnail");t&&(x.currentIndex=Number(t.dataset.thumbnailIndex),V())}},{target:D,event:"pointercancel",func:e=>{Pe&&(Pe=!1,Me&&D.classList.remove("popupable-thumbnails-dragging"),D.hasPointerCapture(e.pointerId)&&D.releasePointerCapture(e.pointerId),Y())}},{target:D,event:"wheel",func:e=>{e.stopPropagation(),e.preventDefault();const t=D.scrollWidth-D.clientWidth;if(t<=0)return;const n=Math.abs(e.deltaX)>Math.abs(e.deltaY)?e.deltaX:e.deltaY,o=D.scrollLeft<=.1,a=D.scrollLeft>=t-.1;if(o&&n<0||a&&n>0)return;o&&n>0&&ke<0&&(ke=0),a&&n<0&&ke>0&&(ke=0);ke=(ke||0)+.015*n,Se||$()},args:{passive:!1}})}Ie&&(e.listeners.push({target:ye,event:"pointerenter",func:()=>{Ee=!0,O()}},{target:xe,event:"pointerenter",func:()=>{Ee=!0,O()}},{target:ye,event:"pointerleave",func:()=>{Ee=!1,e.scheduleNavHide()}},{target:xe,event:"pointerleave",func:()=>{Ee=!1,e.scheduleNavHide()}}),e.listeners.push({target:E,event:"pointermove",func:t=>{if("zoomed"!==e.state)return null==Le||null==Ce?(Le=t.clientX,void(Ce=t.clientY)):void(Math.abs(t.clientX-Le)<a&&Math.abs(t.clientY-Ce)<a||(Le=t.clientX,Ce=t.clientY,O()))},args:{passive:!0}}));for(const Fe of x)Fe.content&&P&&P.append(Fe.content)}else y&&P.append(y);const W={counter:!!N,content:!!P,thumbnails:!!D},H=h.order.top.filter(e=>W[e]),B=h.order.bottom.filter(e=>W[e]);function Q(e,t){e&&("counter"===t&&N?(R[e===A?"counterTop":"counterBottom"]=!0,e.append(N)):"content"===t&&P?(R[e===A?"contentTop":"contentBottom"]=!0,e.append(P)):"thumbnails"===t&&D&&(R[e===A?"thumbnailsTop":"thumbnailsBottom"]=!0,e.append(D)))}A=document.createElement("div"),A.className="popupable-header",M=document.createElement("div"),M.className="popupable-footer";for(const Ve of H)Q(A,Ve);for(const Re of B)Q(M,Re);I.append(A),I.append(M);const _=document.createElement("div");_.className="popupable-button-container popupable-close-container",_.innerHTML='<div class="popupable-button popupable-close"><svg width="24px" height="24px" viewBox="0 -960 960 960" fill="currentColor"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg></div>',_.addEventListener("click",closePopupable),h.zoomable||h.video||_.classList.add("popupable-button-inactive"),A.append(_),E.append(u,I),Object.assign(c,h,{popup:E,group:x,contentContainer:P,thumbnailsContainer:D,orderPlacement:R,closeContainer:_,goNext:k,goPrev:S});const j=setTimeout(()=>{p===o&&l.classList.add("popupable-loading")},250);if(await c.ready,clearTimeout(j),l.classList.remove("popupable-loading"),p!==o||e!==c||"close"===c.state)return;v.classList.add("popupable-block-transitions"),h.animation.hideSource&&l.classList.add("popupable-hide"),h.animation.crossfade&&E.classList.add("popupable-crossfade"),h.animation.fade&&E.classList.add("popupable-fade"),document.body.append(E),setCloneToOriginalRect(v,l),h.video&&h.source.play().catch(()=>{}),disableScroll();const q=getComputedStyle(E);c.transition.duration=1e3*parseFloat(q.transitionDuration)+1e3*parseFloat(q.transitionDelay),E._state=c,requestAnimationFrame(()=>{requestAnimationFrame(()=>{v.classList.remove("popupable-block-transitions"),openPopupable(E._state),x&&(V(),buildDecodeQueue(E._state))})});let U,G=0;x&&E.addEventListener("dragstart",e=>e.preventDefault());const K=new Map;function Z(e,t,n,o,r=[]){if("open"!==e.state)return;let i=0;const s=t.cloneContainer.parentElement,l=s.style.transform;if(l){const e=l.match(/translateX\((-?\d+(?:\.\d+)?)px\)/);e&&(i=Number(e[1])||0)}const p=Math.abs(i)>.5;m=!1,p?(t.cloneContainer.style.translate="0 0",t.cloneContainer.style.transition="translate var(--popupable-switch-duration), transform 0s",s.style.transition=null,s.style.transform=null,t.cloneContainer.style.translate=`${i}px 0`):(s.style.transition=null,s.style.transform=null),e.state="zoomed",E.classList.add("popupable-locked");let c,u,d=o;const b=new Map;let f,g,h,v,y,x,w,L,C,P,A=!1;const M=t.cloneContainer.getBoundingClientRect(),N=n?.clientX??M.left+M.width/2,D=n?.clientY??M.top+M.height/2;c=(N-M.left)*(1-d),u=(D-M.top)*(1-d);const T=()=>t.cloneContainer.style.transform=`translate(${c}px, ${u}px) scale(${d})`;function z(e,n,o){const a=d;var r;if(r=e,d=Math.min(6,Math.max(.5,r)),d===a)return!1;const i=t.cloneContainer.getBoundingClientRect(),s=d/a,l=n-i.left,p=o-i.top;return c+=l*(1-s),u+=p*(1-s),!0}function k(){if(1===b.size){const e=b.values().next().value;return f=e.id,g=e.x,h=e.y,v=null,y=null,void(x=null)}if(b.size>=2){f=null;const[e,t]=[...b.values()];return v=(e.x+t.x)/2,y=(e.y+t.y)/2,void(x=Math.hypot(t.x-e.x,t.y-e.y))}f=null,g=null,h=null,v=null,y=null,x=null}if(t.cloneContainer.classList.add("popupable-zoomed"),T(),r.length){p||(t.cloneContainer.style.transition="none"),P=!0;for(const e of r)b.set(e.id,{id:e.id,x:e.x,y:e.y}),E.setPointerCapture(e.id);k()}e.unzoom=()=>{e.state="open",E.classList.remove("popupable-locked");for(const e of b.keys())E.hasPointerCapture(e)&&E.releasePointerCapture(e);b.clear(),t.cloneContainer.classList.remove("popupable-zoomed"),t.cloneContainer.style.transition=null,t.cloneContainer.style.transform=null,t.cloneContainer.style.translate=null;for(const t of e.zoomListeners)t.target.removeEventListener(t.event,t.func)},e.zoomListeners=[{target:E,event:"pointerdown",func:e=>{0===e.button&&(t.cloneContainer.style.transition="none",E.setPointerCapture(e.pointerId),b.set(e.pointerId,{id:e.pointerId,x:e.clientX,y:e.clientY}),1===b.size?(w=e.target,L=e.clientX,C=e.clientY,P=!1):P=!0,k(),e.preventDefault())}},{target:E,event:"pointermove",func:e=>{const t=b.get(e.pointerId);if(t){if(t.x=e.clientX,t.y=e.clientY,!P&&(Math.abs(e.clientX-L)>a||Math.abs(e.clientY-C)>a)&&(P=!0),1===b.size&&f===e.pointerId){const t=e.clientX-g,n=e.clientY-h;if(!t&&!n)return;return c+=t,u+=n,g=e.clientX,h=e.clientY,void T()}if(b.size>=2){const[e,t]=[...b.values()],n=(e.x+t.x)/2,o=(e.y+t.y)/2,a=Math.hypot(t.x-e.x,t.y-e.y);if(!x)return v=n,y=o,void(x=a);c+=n-v,u+=o-y,z(d*(a/x),n,o),A=!0,v=n,y=o,x=a,T()}}}},{target:E,event:"pointerup",func:n=>{if(b.has(n.pointerId)){if(b.delete(n.pointerId),E.hasPointerCapture(n.pointerId)&&E.releasePointerCapture(n.pointerId),A&&d<=1.01&&b.size<2)return e.skipOpenTouchPointerUps=b.size,void e.unzoom();if(!b.size&&!P&&Math.abs(n.clientX-L)<a&&Math.abs(n.clientY-C)<a){if(w?.closest?.(".popupable-clone-container")===t.cloneContainer||(w===E||w===I))return void e.unzoom()}k()}}},{target:E,event:"pointercancel",func:e=>{b.has(e.pointerId)&&(b.delete(e.pointerId),E.hasPointerCapture(e.pointerId)&&E.releasePointerCapture(e.pointerId),k())}},{target:E,event:"wheel",func:e=>{t.cloneContainer.style.transition="none",z(d*Math.exp(.002*-e.deltaY),e.clientX,e.clientY)&&T()},args:{passive:!0}}];for(const t of e.zoomListeners)t.target.addEventListener(t.event,t.func,t.args)}e.listeners.push({target:E,event:"pointerdown",func:e=>{if("open"!==E._state.state||"touch"!==e.pointerType)return;const t=E._state,n=t.group?t.group[t.group.currentIndex]:t;e.target.closest(".popupable-clone-container")===n.cloneContainer&&(K.set(e.pointerId,{id:e.pointerId,x:e.clientX,y:e.clientY}),K.size>=2&&(Z(t,n,e,1,[...K.values()].slice(0,2)),K.clear(),e.preventDefault()))}},{target:E,event:"pointermove",func:e=>{const t=K.get(e.pointerId);t&&(t.x=e.clientX,t.y=e.clientY)}},{target:E,event:"pointerup",func:e=>{K.delete(e.pointerId)}},{target:E,event:"pointercancel",func:e=>{K.delete(e.pointerId)}}),E.addEventListener("pointerup",t=>{if("zoomed"===E._state.state)return;if("touch"===t.pointerType&&(E._state.skipOpenTouchPointerUps||0)>0)return void E._state.skipOpenTouchPointerUps--;const o=performance.now(),a=null!=t.target.closest(".popupable-next-container, .popupable-prev-container");if(U&&o-G<250)return void(G=o);if(a?(U=!0,G=o):(U=!1,G=o),0!==t.button||!((t.target.classList.contains("popupable-clone")||t.target.classList.contains("popupable-clone-layer"))&&n.classList.contains("popupable-clone-container")||t.target==n&&(t.target.closest(".popupable-clone-container")||t.target.classList.contains("popupable-viewport")||t.target.classList.contains("popupable-container"))||t.target.classList.contains("popupable-container")&&n===e.original.parentElement))return;const r=E._state,i=r.group?r.group[r.group.currentIndex]:r;r.blocked&&(r.blocked=!1),"open"!==r.state?(t.stopPropagation(),e!==r&&(closePopupable(),e=r),openPopupable(e)):requestAnimationFrame(()=>{r.blocked?r.blocked=!1:i.zoomable&&(t.target.classList.contains("popupable-clone")||t.target.classList.contains("popupable-clone-layer"))?Z(r,i,t,2):i.video&&(t.target.classList.contains("popupable-clone")||t.target.closest(".popupable-clone-container")===i.cloneContainer)||closePopupable()})})}),document.addEventListener("keydown",t=>{if("Escape"===t.key||"Backspace"===t.key||" "===t.key||"Delete"===t.key){if("zoomed"===e.state)return void e.unzoom();closePopupable()}}),window.addEventListener("resize",updateExpandedSize),visualViewport&&visualViewport.addEventListener("resize",updateExpandedSize)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "popupable",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "A lightweight, zero-dependency lightbox library using modern JavaScript and CSS.",
5
5
  "author": "Ewan Howell <ewanhowell5195>",
6
6
  "license": "MIT",