zumly 0.92.6 → 0.97.0
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 +55 -18
- package/dist/zumly.cjs +2 -2
- package/dist/zumly.css +15 -0
- package/dist/zumly.js +2 -2
- package/dist/zumly.min.css +1 -1
- package/dist/zumly.mjs +2 -2
- package/package.json +9 -5
- package/src/drivers/anime-transition.js +5 -5
- package/src/drivers/driver-helpers.js +8 -3
- package/src/drivers/motion-transition.js +5 -5
- package/src/drivers/transform-matrix.js +34 -0
- package/src/view-lifecycle.js +70 -0
- package/src/view-visibility.js +43 -0
- package/types/zumly.d.ts +13 -10
package/dist/zumly.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* zumly
|
|
3
|
-
* v.0.
|
|
3
|
+
* v.0.97.0
|
|
4
4
|
* Author Juan Martin Muda - Zumerlab
|
|
5
5
|
* License MIT
|
|
6
6
|
*/
|
|
7
|
-
var ft=class{#t={};constructor(t={}){this.#t=t}#e(t){return typeof t=="function"?"function":t instanceof HTMLElement?"element":typeof t=="object"&&t!==null&&typeof t.render=="function"?"object":typeof t!="string"?"unknown":/^https?:\/\/|^\/|\.html$|\.php$/i.test(t)?"url":t.includes("<")?"html":t.includes("-")?"webcomponent":"unknown"}async resolve(t,e=null){if(typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#t,t)){let n=this.#t[t];return this.resolve(n,e)}switch(this.#e(t)){case"html":{let n=document.createElement("div");n.innerHTML=t.trim();let o=n.firstElementChild;if(!o)throw new Error("Zumly: view produced no element (html)");return o}case"url":{let n=new AbortController,o=setTimeout(()=>n.abort(),1e4),i;try{i=await fetch(t,{signal:n.signal})}finally{clearTimeout(o)}if(!i.ok)throw new Error(`Zumly: fetch failed for "${t}" (${i.status})`);let a=await i.text(),l=document.createElement("div");l.innerHTML=a.trim();let c=l.firstElementChild;if(!c)throw new Error("Zumly: view produced no element (url)");return c}case"function":{let n=e&&e.target||document.createElement("div"),o=await t({...e,target:n});if(typeof o=="string")return this.resolve(o,e);if(o instanceof HTMLElement)return o;let i=n.firstElementChild||n;return i.classList.contains("z-view")||i.classList.add("z-view"),i}case"object":{let n=await t.render(e);if(typeof n!="string")throw new Error("Zumly: view render() must return string");return this.resolve(n,e)}case"element":return t.cloneNode(!0);case"webcomponent":return await customElements.whenDefined(t),document.createElement(t);default:throw new Error("Zumly: unknown view type for source")}}};async function et(r,t,e,s,n,o){if(!r||!r.classList){let i=document.createElement("div");i.classList.add("z-view"),r&&i.appendChild(r),r=i}else r.classList.contains("z-view")||r.classList.add("z-view");return r.dataset.viewName=t,r.getAttribute("aria-label")||r.setAttribute("aria-label",`View: ${t}`),r.style.transformOrigin="0 0",r.style.position="absolute",s?r.classList.add("is-current-view"):r.classList.add("is-new-current-view","has-no-events","hide"),e.append(r),typeof n[t]=="object"&&typeof n[t].mounted=="function"&&await n[t].mounted(),r}function L(r,t,e){t&&e==="welcome"&&console.info(`%c Zumly %c ${t}`,"background: #424085; color: white; border-radius: 3px;","color: #424085"),t&&r&&(e==="info"||e===void 0)&&console.info(`%c Zumly %c ${t}`,"background: #6679A3; color: #304157; border-radius: 3px;","color: #6679A3"),t&&e==="warn"&&console.warn(`%c Zumly %c ${t}`,"background: #DCBF53; color: #424085; border-radius: 3px;","color: #424085"),t&&e==="error"&&console.error(`%c Zumly %c ${t}`,"background: #BE4747; color: white; border-radius: 3px;","color: #424085")}function Dt(r,t){if(t.isValid=!1,!r||typeof r!="object"){L(!1,"'options' object has to be provided when instance is defined","error");return}if(typeof r.mount!="string"){L(!1,"'mount' must be a string selector","error");return}if(t.mount=r.mount,typeof r.initialView!="string"){L(!1,"'initialView' must be a string","error");return}if(t.initialView=r.initialView,!r.views||typeof r.views!="object"){L(!1,"'views' must be an object","error");return}t.views=r.views,t.isValid=!0,t.preload=Array.isArray(r.preload)?r.preload:[],t.debug=typeof r.debug=="boolean"?r.debug:!1,t.componentContext=r.componentContext&&typeof r.componentContext=="object"?r.componentContext:new Map;let e=r.transitions&&typeof r.transitions=="object"?r.transitions:null,s=e&&e.cover,n=typeof s=="string"?s.toLowerCase():null,o=n==="width"||n==="height";t.cover=o?n:"width",!o&&e&&s!==void 0&&L(!1,`'transitions.cover' must be either "width" or "height". Falling back to "width".`,"warn"),t.duration=e&&typeof e.duration=="string"?e.duration:"1s",t.ease=e&&typeof e.ease=="string"?e.ease:"ease-in-out",t.deferred=typeof r.deferred=="boolean"?r.deferred:!1;let i=e&&e.hideTrigger;i===!0||i==="fade"?t.hideTrigger=i:(t.hideTrigger=!1,i!=null&&i!==!1&&L(!1,`'transitions.hideTrigger' must be true or "fade". Falling back to false.`,"warn"));let a=e&&e.effects;Array.isArray(a)&&a.length>=2&&typeof a[0]=="string"&&typeof a[1]=="string"?t.effects=[a[0],a[1]]:Array.isArray(a)&&a.length===1&&typeof a[0]=="string"?t.effects=[a[0],a[0]]:(t.effects=["none","none"],a!=null&&L(!1,`'transitions.effects' must be an array of 1-2 CSS filter strings (e.g. ["blur(3px)", "blur(8px) saturate(0)"]). Falling back to no effects.`,"warn"));let l=e&&e.driver,c=typeof l=="string"?l.toLowerCase():null,f=typeof l=="function"?l:null;if(c!==null){let d=["css","waapi","none","anime","gsap","motion"];t.transitionDriver=d.includes(c)?c:"css",d.includes(c)||L(!1,`'transitions.driver' must be "css", "waapi", "none", "anime", "gsap", "motion", or a function. Got "${l}". Falling back to "css".`,"warn")}else f!==null?t.transitionDriver=f:t.transitionDriver="css";let u=e&&e.stagger;typeof u=="number"&&u>0?t.stagger=u:(t.stagger=0,u!=null&&u!==0&&L(!1,"'transitions.stagger' must be a positive number (ms). Falling back to 0 (disabled).","warn")),t.parallax=0;let h=r.lateralNav;if(h===!1)t.lateralNav=!1;else if(h&&typeof h=="object"){let d=typeof h.mode=="string"?h.mode.toLowerCase():null,g=d==="auto"||d==="always";d&&!g&&L(!1,`'lateralNav.mode' must be "auto" or "always". Falling back to "auto".`,"warn");let v=null;if(Array.isArray(h.siblings))v=h.siblings.filter(w=>typeof w=="string"&&w),v.length<2&&(L(!1,"'lateralNav.siblings' needs at least 2 view names. Ignoring.","warn"),v=null);else if(h.siblings&&typeof h.siblings=="object"){v={};for(let[w,b]of Object.entries(h.siblings))if(Array.isArray(b)){let _=b.filter(S=>typeof S=="string"&&S);_.length>=2&&(v[w]=_)}Object.keys(v).length===0&&(v=null)}else h.siblings!==void 0&&L(!1,"'lateralNav.siblings' must be an array of view names or a { parentView: [...] } map. Ignoring.","warn");t.lateralNav={mode:g?d:"auto",arrows:typeof h.arrows=="boolean"?h.arrows:!0,dots:typeof h.dots=="boolean"?h.dots:!0,keepAlive:h.keepAlive===!0||h.keepAlive==="visible"?h.keepAlive:!1,siblings:v}}else t.lateralNav={mode:"auto",arrows:!0,dots:!0,keepAlive:!1,siblings:null};let m=r.depthNav;if(m===!1)t.depthNav=!1;else if(m&&typeof m=="object"){let d=typeof m.position=="string"?m.position.toLowerCase():null,g=d==="bottom-left"||d==="top-left";d&&!g&&L(!1,`'depthNav.position' must be "bottom-left" or "top-left". Falling back to "bottom-left".`,"warn"),t.depthNav={position:g?d:"bottom-left"}}else t.depthNav={position:"bottom-left"};let y=r.lateralNav&&typeof r.lateralNav=="object"?r.lateralNav.position:void 0;if(t.lateralNav&&typeof t.lateralNav=="object"){let d=y==="bottom-center"||y==="top-center";y&&!d&&L(!1,`'lateralNav.position' must be "bottom-center" or "top-center". Falling back to "bottom-center".`,"warn"),t.lateralNav.position=d?y:"bottom-center"}let p=r.inputs;p&&typeof p=="object"?t.inputs={wheel:typeof p.wheel=="boolean"?p.wheel:!0,keyboard:typeof p.keyboard=="boolean"?p.keyboard:!0,click:typeof p.click=="boolean"?p.click:!0,touch:typeof p.touch=="boolean"?p.touch:!0}:t.inputs={wheel:!0,keyboard:!0,click:!0,touch:!0}}function Ft(r,t,e,s,n){let o=e/r,i=s/t;return n==="height"?{scale:i,scaleInv:1/i}:{scale:o,scaleInv:1/o}}function Ht(r,t,e,s){let n=t.left,o=t.top,i=r.x-n+(r.width-e.width*s)/2,a=r.y-o+(r.height-e.height*s)/2;return`translate(${i}px, ${a}px) scale(${s})`}function jt(r,t,e){let s=t.left,n=t.top,o=r.x-s+(r.width-e.width)/2,i=r.y-n+(r.height-e.height)/2;return`translate(${o}px, ${i}px)`}function Rt(r,t){let e=r.x+r.width/2-t.x,s=r.y+r.height/2-t.y;return`${e}px ${s}px`}function qt(r,t,e,s,n=0){let o=r.width/2-t.width/2-t.x+e.x,i=r.height/2-t.height/2-t.y+e.y,a=1-n,l=o*a,c=i*a;return{x:o,y:i,transform:`translate(${l}px, ${c}px) scale(${s})`}}function Bt({canvasRect:r,canvasOffset:t,triggerRect:e,previousViewRectAtBaseTransform:s,lastViewZoomedElementRect:n,previousViewRectWithPreviousAtEndTransform:o,scale:i,preScale:a,parallax:l=0}){let c=t.left,f=t.top,u=r.width/2-e.width/2-e.x,h=r.height/2-e.height/2-e.y,m=u+(s.x-n.x)+o.x-c+(o.width-n.width)/2,y=h+(s.y-n.y)+o.y-f+(o.height-n.height)/2,p=1-Math.min(l*2,.9);return`translate(${m*p}px, ${y*p}px) scale(${i*a})`}function Vt(r,t,e,s,n){return`translate(${r-e.left}px, ${t-e.top}px) scale(${s*n})`}function ut(r){let t=r.split(/\s+/);return{x:parseFloat(t[0])||0,y:parseFloat(t[1])||0}}function st(r){let t=typeof r=="string"?r:"",e=t.match(/translate\s*\(\s*([-+\d.eE]+)px\s*,\s*([-+\d.eE]+)px\s*\)/);if(!e)return{tx:0,ty:0,rest:t.trim(),matched:!1};let s=t.replace(/translate\s*\([^)]+\)\s*/,"").trim();return{tx:parseFloat(e[1]),ty:parseFloat(e[2]),rest:s,matched:!0}}function rt(r){let t=st(r),e=r.match(/scale\s*\(\s*([-+\d.eE]+)\s*\)/);return{tx:t.matched?t.tx:0,ty:t.matched?t.ty:0,scale:e?parseFloat(e[1]):1}}function ht(r,t,e,s,n,o,i,a,l,c){let f=t.x-e.x*(1-o)-s,u=t.y-e.y*(1-o)-n,h=t.width/o,m=t.height/o,y=f+e.x+(r.x-f-e.x-s)/o,p=u+e.y+(r.y-u-e.y-n)/o,d=r.width/o,g=r.height/o,v=f+i.x+a+c*(y-f-i.x),w=u+i.y+l+c*(p-u-i.y),b=d*c,_=g*c;return{x:v,y:w,width:b,height:_,left:v,top:w,right:v+b,bottom:w+_}}function nt(r,t,e){return{viewName:r,backwardState:t,forwardState:e}}function Xt(r){return{detachedNode:r}}function Yt(r,t,e,s,n){let o=[];return t!==null&&o.push(t),e!==null&&o.push(e),s!==null&&o.push(s),n!==null&&o.push(n),{zoomLevel:r,views:o}}function Ut(r){let t=r.views?.[3];if(!(!t||!(t.detachedNode instanceof Node)))return t.detachedNode}var dt=class{#t=new Map;set(t,e,s=null){this.#t.set(t,{node:e,expires:s?Date.now()+s:null})}get(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>e.expires?(this.#t.delete(t),null):e.node.cloneNode(!0):null}has(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>e.expires?(this.#t.delete(t),!1):!0:!1}invalidate(t){this.#t.delete(t)}clear(){this.#t.clear()}};var xe=300*1e3,Le=/^https?:\/\/|^\/|\.html$|\.php$/i,mt=class{#t;#e;#r;#s=new Map;constructor(t={}){this.#r=t,this.#t=new ft(t),this.#e=new dt}#n(t){return typeof this.#r[t]=="string"}#o(t){return Le.test(t)?xe:null}async get(t,e=null){if(this.#n(t)){let s=this.#e.get(t);if(s)return s;if(this.#s.has(t))return this.#s.get(t);let n=(async()=>{try{let o=await this.#t.resolve(t,e),i=this.#r[t],a=this.#o(i);return this.#e.set(t,o,a),o}finally{this.#s.delete(t)}})();return this.#s.set(t,n),n}return this.#t.resolve(t,e)}async preloadEager(t,e=null){!Array.isArray(t)||t.length===0||await Promise.all(t.map(s=>this.get(s,e)))}prefetch(t,e=null){this.get(t,e).catch(()=>{})}prefetchOnHover(t,e=null){this.prefetch(t,e)}scanAndPrefetch(t,e=null){if(!t||!t.querySelectorAll)return;t.querySelectorAll(".zoom-me[data-to]").forEach(n=>{let o=n.dataset.to;o&&(n.hasAttribute("role")||n.setAttribute("role","button"),n.hasAttribute("aria-label")||n.setAttribute("aria-label",`Zoom to ${o}`),this.prefetch(o,e))})}};function K(r){r&&(r.style.contentVisibility="hidden")}function X(r){r&&(r.style.contentVisibility="visible")}function F(r){if(typeof r=="number"&&!Number.isNaN(r))return Math.max(0,r);let t=String(r).trim(),e=t.match(/^(\d*\.?\d+)\s*(ms|s)?$/i);if(!e)return typeof console<"u"&&console.warn(`[zumly] Could not parse duration "${t}" \u2014 falling back to 500ms.`),500;let s=parseFloat(e[1]);return(e[2]||"s").toLowerCase()==="ms"?Math.max(0,s):Math.max(0,s*1e3)}function pt(r){return F(r)/1e3}function T(r,t){if(r.classList.contains("is-new-current-view")){let e=t.views[0].forwardState;r.classList.replace("is-new-current-view","is-current-view"),r.classList.remove("zoom-current-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-previous-view")){let e=t.views[1].forwardState;r.classList.remove("zoom-previous-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-last-view")){let e=t.views[2].forwardState;r.classList.remove("zoom-last-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform}}function N(r,t){r.classList.remove("zoom-previous-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin="0 0",r.style.transform=t.transform}function $(r,t){r.classList.remove("zoom-last-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin=t.origin,r.style.transform=t.transform}function C(r,t){try{t&&t.removeChild(r)}catch{try{r.parentElement&&t.removeChild(r.parentElement)}catch{}}}function z(...r){for(let t of r)t&&(t.classList.remove("hide"),X(t))}function H(r,t){let{currentView:e,previousView:s,backView:n,backViewState:o,lastView:i,lastViewState:a,incomingTransformEnd:l,currentStage:c,canvas:f}=r,u=c.views[0];z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=u.forwardState.origin,e.style.transform=l||u.forwardState.transform,n&&o&&(n.style.transform=o.transformEnd),i&&a&&(i.style.transform=a.transformEnd),r.keepAlive||C(s,f),t()}var j=150;function R(r,t){let e=!1,s=setTimeout(()=>{e||(e=!0,r())},t);return{finish(){e||(e=!0,clearTimeout(s),r())},extend(n){e||(clearTimeout(s),s=setTimeout(()=>{e||(e=!0,r())},n))},safetyTimer:s}}function Wt(){return{a:1,b:0,c:0,d:1,e:0,f:0}}function ze(r){if(!r||r==="none")return Wt();let t=String(r).match(/matrix\(([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+)\)/);return t?{a:parseFloat(t[1])||1,b:parseFloat(t[2])||0,c:parseFloat(t[3])||0,d:parseFloat(t[4])||1,e:parseFloat(t[5])||0,f:parseFloat(t[6])||0}:Wt()}function Q(r){return`matrix(${r.a}, ${r.b}, ${r.c}, ${r.d}, ${r.e}, ${r.f})`}function G(r,t,e){return r+(t-r)*e}function J(r,t,e){let s=Math.max(0,Math.min(1,e));return{a:G(r.a,t.a,s),b:G(r.b,t.b,s),c:G(r.c,t.c,s),d:G(r.d,t.d,s),e:G(r.e,t.e,s),f:G(r.f,t.f,s)}}function Z(r,t,e){r.style.transformOrigin=t,r.style.transform=e;try{r.getBoundingClientRect()}catch{}return ze(getComputedStyle(r).transform)}function Gt(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,duration:a,ease:l,canvas:c}=r;if(!s||!n||!i){t();return}e==="lateral"?ke(r,t):e==="zoomIn"?Ce(s,n,o,i,a,l,t):e==="zoomOut"?Oe(s,n,o,i,a,l,c,t):t()}function ke(r,t){let{currentView:e,previousView:s,backView:n,backViewState:o,lastView:i,lastViewState:a,incomingTransformStart:l,incomingTransformEnd:c,outgoingTransform:f,outgoingTransformEnd:u,currentStage:h,duration:m,ease:y,canvas:p}=r,d=F(m),g=h.views[0];z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=g.forwardState.origin,n&&o&&(M(n,m,y,{"--lateral-from":o.transformStart,"--lateral-to":o.transformEnd}),n.classList.add("zoom-lateral-back")),i&&a&&(M(i,m,y,{"--lateral-from":a.transformStart,"--lateral-to":a.transformEnd}),i.classList.add("zoom-lateral-back")),r.keepAlive!=="visible"&&(M(s,m,y,{"--lateral-out-from":f,"--lateral-out-to":u}),s.classList.add("zoom-lateral-out")),M(e,m,y,{"--lateral-in-from":l,"--lateral-in-to":c}),e.classList.add("zoom-lateral-in");let v=r.keepAlive==="visible"?[e]:[s,e];n&&o&&v.push(n),i&&a&&v.push(i);let w=v.length,b=d+j,_=new Set(["zoom-lateral-in","zoom-lateral-out","zoom-lateral-back"]),{finish:S,extend:O}=R(()=>{Tt(v,I,P),r.keepAlive?(s.classList.remove("zoom-lateral-out"),s.style.opacity=""):C(s,p),n&&(n.classList.remove("zoom-lateral-back"),n.style.transform=o?.transformEnd||n.style.transform),i&&(i.classList.remove("zoom-lateral-back"),i.style.transform=a?.transformEnd||i.style.transform),e.classList.remove("zoom-lateral-in"),e.style.transform=c,t()},b);function P(x){x.target!==x.currentTarget||!_.has(x.animationName)||O(b)}function I(x){if(x.target!==x.currentTarget||!_.has(x.animationName))return;let q=x.currentTarget;q.removeEventListener("animationend",I),q.removeEventListener("animationstart",P),w--,w<=0&&S()}v.forEach(x=>{x.addEventListener("animationstart",P),x.addEventListener("animationend",I)})}function Ce(r,t,e,s,n,o,i){z(r,t,e);let a=s.stagger||0;M(r,n,o,{"--current-view-transform-start":s.views[0].backwardState.transform,"--current-view-transform-end":s.views[0].forwardState.transform}),a>0&&r.style.setProperty("animation-delay","0ms"),M(t,n,o,{"--previous-view-transform-start":s.views[1].backwardState.transform,"--previous-view-transform-end":s.views[1].forwardState.transform}),a>0&&t.style.setProperty("animation-delay",`${a}ms`),e&&(M(e,n,o,{"--last-view-transform-start":s.views[2].backwardState.transform,"--last-view-transform-end":s.views[2].forwardState.transform}),a>0&&e.style.setProperty("animation-delay",`${a*2}ms`)),r.classList.add("zoom-current-view"),t.classList.add("zoom-previous-view"),e&&e.classList.add("zoom-last-view");let l=e?[r,t,e]:[r,t],c=l.length,f=F(n),u=e?a*2:a,h=f+u+j,m=new Set(["zoom-current-view","zoom-previous-view","zoom-last-view"]),{finish:y,extend:p}=R(()=>{Tt(l,g,d),l.forEach(v=>v.style.removeProperty("animation-delay")),l.forEach(v=>{if(v?.isConnected)try{T(v,s)}catch{}}),i()},h);function d(v){v.target!==v.currentTarget||!m.has(v.animationName)||p(h)}function g(v){if(v.target!==v.currentTarget||!m.has(v.animationName))return;let w=v.currentTarget;if(w.removeEventListener("animationend",g),w.removeEventListener("animationstart",d),w.isConnected)try{T(w,s)}catch{}c--,c<=0&&y()}l.forEach(v=>{v.addEventListener("animationstart",d),v.addEventListener("animationend",g)})}function Oe(r,t,e,s,n,o,i,a){let l=s.views[0],c=s.views[1],f=e&&s.views[2]?s.views[2]:null,u=s.stagger||0;M(r,n,o,{"--current-view-transform-start":l.backwardState.transform,"--current-view-transform-end":l.forwardState.transform}),u>0&&r.style.setProperty("animation-delay","0ms"),M(t,n,o,{"--previous-view-transform-start":c.backwardState.transform,"--previous-view-transform-end":c.forwardState.transform}),u>0&&t.style.setProperty("animation-delay",`${u}ms`),e&&f&&(M(e,n,o,{"--last-view-transform-start":f.backwardState.transform,"--last-view-transform-end":f.forwardState.transform}),u>0&&e.style.setProperty("animation-delay",`${u*2}ms`)),r.classList.add("zoom-current-view-reverse"),t.classList.add("zoom-previous-view-reverse"),e&&e.classList.add("zoom-last-view-reverse");let h=e?[r,t,e]:[r,t],m=h.length,y=F(n),p=e?u*2:u,d=y+p+j,g=new Set(["zoom-current-view-reverse","zoom-previous-view-reverse","zoom-last-view-reverse"]),{finish:v,extend:w}=R(()=>{Tt(h,_,b),h.forEach(S=>S.style.removeProperty("animation-delay")),h.forEach(S=>{if(S?.isConnected)try{Kt(S,s,i)}catch{}}),a()},d);function b(S){S.target!==S.currentTarget||!g.has(S.animationName)||w(d)}function _(S){if(S.target!==S.currentTarget||!g.has(S.animationName))return;let O=S.currentTarget;if(O.removeEventListener("animationend",_),O.removeEventListener("animationstart",b),O.isConnected)try{Kt(O,s,i)}catch{}m--,m<=0&&v()}h.forEach(S=>{S.addEventListener("animationstart",b),S.addEventListener("animationend",_)})}function Kt(r,t,e){if(r.classList.contains("zoom-current-view-reverse")){C(r,e);return}if(r.classList.contains("zoom-previous-view-reverse")){N(r,t.views[1].backwardState);return}r.classList.contains("zoom-last-view-reverse")&&$(r,t.views[2].backwardState)}function M(r,t,e,s){r.style.setProperty("--zoom-duration",t),r.style.setProperty("--zoom-ease",e);for(let[n,o]of Object.entries(s))r.style.setProperty(n,o)}function Tt(r,t,e){for(let s of r)s?.removeEventListener&&(s.removeEventListener("animationend",t),s.removeEventListener("animationstart",e))}function Qt(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,canvas:a}=r;if(!s||!n||!i){t();return}if(e==="lateral"){H(r,t);return}if(e==="zoomIn"){z(s,n,o),T(s,i),T(n,i),o&&T(o,i),t();return}if(e==="zoomOut"){C(s,a),z(n,o),N(n,i.views[1].backwardState),o&&$(o,i.views[2].backwardState),t();return}t()}function Jt(r,t){let{type:e,currentView:s,previousView:n,lastView:o,currentStage:i,duration:a,ease:l,canvas:c}=r;if(!s||!n||!i){t();return}let f=F(a);if(e==="lateral"){Ie(r,f,l,t);return}if(e==="zoomIn"){Ae(s,n,o,i,f,l,t);return}if(e==="zoomOut"){Pe(s,n,o,i,f,l,c,t);return}t()}function Ae(r,t,e,s,n,o,i){z(r,t,e);let a=s.views[0],l=s.views[1],c=e&&s.views[2]?s.views[2]:null;r.style.transformOrigin=a.backwardState.origin,r.style.transform=a.backwardState.transform,t.style.transformOrigin=l.backwardState.origin,t.style.transform=l.backwardState.transform,c&&(e.style.transformOrigin=c.backwardState.origin,e.style.transform=c.backwardState.transform);let f=s.stagger||0,u=[];u.push(r.animate([{transform:a.backwardState.transform},{transform:a.forwardState.transform}],{duration:n,easing:o,fill:"forwards"})),u.push(t.animate([{transform:l.backwardState.transform},{transform:l.forwardState.transform}],{duration:n,delay:f,easing:o,fill:"forwards"})),c&&u.push(e.animate([{transform:c.backwardState.transform},{transform:c.forwardState.transform}],{duration:n,delay:f*2,easing:o,fill:"forwards"}));let h=c?f*2:f,{finish:m}=R(()=>{Et(u);try{T(r,s),T(t,s),e&&T(e,s)}catch{}i()},n+h+j);Promise.all(u.map(y=>y.finished)).then(m).catch(m)}function Pe(r,t,e,s,n,o,i,a){let l=s.views[0],c=s.views[1],f=e&&s.views[2]?s.views[2]:null,u=c.backwardState,h=f?f.backwardState:null;r.style.transformOrigin=l.forwardState.origin,r.style.transform=l.forwardState.transform,requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transformOrigin=c.forwardState.origin,e&&f&&(e.style.transformOrigin=f.forwardState.origin);let m=t.style.transform||getComputedStyle(t).transform||c.forwardState.transform,y=e&&f?e.style.transform||getComputedStyle(e).transform||f.forwardState.transform:null,p=s.stagger||0,d=[];d.push(r.animate([{transform:l.forwardState.transform},{transform:l.backwardState.transform}],{duration:n,easing:o,fill:"forwards"})),d.push(t.animate([{transform:m},{transform:u.transform}],{duration:n,delay:p,easing:o,fill:"both"})),e&&h&&d.push(e.animate([{transform:y},{transform:h.transform}],{duration:n,delay:p*2,easing:o,fill:"both"})),t.style.removeProperty("transform"),e&&e.style.removeProperty("transform");let g=e&&h?p*2:p,{finish:v}=R(()=>{Et(d);try{C(r,i),N(t,u),e&&h&&$(e,h)}catch{}a()},n+g+j);Promise.all(d.map(w=>w.finished)).then(v).catch(v)})})}function Ie(r,t,e,s){let{currentView:n,previousView:o,backView:i,backViewState:a,lastView:l,lastViewState:c,incomingTransformStart:f,incomingTransformEnd:u,outgoingTransform:h,outgoingTransformEnd:m,currentStage:y,canvas:p}=r,d=y.views[0];z(n),n.classList.replace("is-new-current-view","is-current-view"),n.classList.remove("zoom-current-view","has-no-events"),n.style.transformOrigin=d.forwardState.origin;let g=[];g.push(n.animate([{transform:f,opacity:0},{transform:u,opacity:1}],{duration:t,easing:e,fill:"forwards"})),r.keepAlive!=="visible"&&g.push(o.animate([{transform:h,opacity:1},{transform:m,opacity:0}],{duration:t,easing:e,fill:"forwards"})),i&&a&&g.push(i.animate([{transform:a.transformStart},{transform:a.transformEnd}],{duration:t,easing:e,fill:"forwards"})),l&&c&&g.push(l.animate([{transform:c.transformStart},{transform:c.transformEnd}],{duration:t,easing:e,fill:"forwards"}));let{finish:v}=R(()=>{Et(g),n.style.transform=u||d.forwardState.transform,i&&a&&(i.style.transform=a.transformEnd),l&&c&&(l.style.transform=c.transformEnd),r.keepAlive?(o.style.opacity="",o.style.transform=m):C(o,p),s()},t+j);Promise.all(g.map(w=>w.finished)).then(v).catch(v)}function Et(r){for(let t of r)try{t.cancel()}catch{}}function te(r,t){let e=typeof globalThis<"u"&&globalThis.anime;if(!e||typeof e!="function"){console.warn('Zumly anime driver: Anime.js not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=F(l);s==="lateral"?H(r,t):s==="zoomIn"?Ne(e,n,o,i,a,u,c,t):s==="zoomOut"?$e(e,n,o,i,a,u,c,f,t):t()}function Ne(r,t,e,s,n,o,i,a){z(t,e,s);let l=n.views[0],c=n.views[1],f=s&&n.views[2]?n.views[2]:null,u=ee([{el:t,backward:l.backwardState,forward:l.forwardState},{el:e,backward:c.backwardState,forward:c.forwardState},...f?[{el:s,backward:f.backwardState,forward:f.forwardState}]:[]],"forward");se(u,0);let h=n.stagger||0,m=o+(f?h*2:h),y={value:0};r({targets:y,value:1,duration:m,easing:ne(i),update:()=>{let p=y.value*m;re(u,p,o,h)},complete:()=>{T(t,n),T(e,n),s&&T(s,n),a()}})}function $e(r,t,e,s,n,o,i,a,l){let c=n.views[0],f=n.views[1],u=s&&n.views[2]?n.views[2]:null,h=f.backwardState,m=u?u.backwardState:null,y=ee([{el:t,backward:c.backwardState,forward:c.forwardState},{el:e,backward:f.backwardState,forward:f.forwardState},...u?[{el:s,backward:u.backwardState,forward:u.forwardState}]:[]],"backward");se(y,0);let p=n.stagger||0,d=o+(u?p*2:p),g={value:0};r({targets:g,value:1,duration:d,easing:ne(i),update:()=>{let v=g.value*d;re(y,v,o,p)},complete:()=>{C(t,a),N(e,h),s&&m&&$(s,m),l()}})}function ee(r,t){return r.map(({el:e,backward:s,forward:n})=>{if(t==="forward"){let o=Z(e,s.origin,s.transform),i=Z(e,s.origin,n.transform);return{el:e,from:o,to:i}}else{let o=Z(e,n.origin,n.transform),i=Z(e,n.origin,s.transform);return{el:e,from:o,to:i}}})}function se(r,t){for(let{el:e,from:s,to:n}of r)e.style.transform=Q(J(s,n,t))}function re(r,t,e,s){for(let n=0;n<r.length;n++){let{el:o,from:i,to:a}=r[n],l=n*s,c=Math.max(0,t-l),f=e>0?Math.min(1,c/e):1;o.style.transform=Q(J(i,a,f))}}function ne(r){if(typeof r!="string")return"easeInOutQuad";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOutQuad":t.includes("ease-in")?"easeInQuad":t.includes("ease-out")?"easeOutQuad":t}function oe(r,t){let e=typeof globalThis<"u"&&globalThis.gsap;if(!e||typeof e.to!="function"){console.warn('Zumly GSAP driver: GSAP not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=pt(l);s==="lateral"?H(r,t):s==="zoomIn"?Ze(e,n,o,i,a,u,c,t):s==="zoomOut"?Me(e,n,o,i,a,u,c,f,t):t()}function Ze(r,t,e,s,n,o,i,a){z(t,e,s);let l=n.views[0],c=n.views[1],f=s&&n.views[2]?n.views[2]:null;vt(t,l.backwardState),vt(e,c.backwardState),f&&vt(s,f.backwardState);let u=r.timeline({onComplete:()=>{T(t,n),T(e,n),s&&T(s,n),a()}}),h=ie(i),m=(n.stagger||0)/1e3;u.to(t,{transform:l.forwardState.transform,duration:o,ease:h},0),u.to(e,{transform:c.forwardState.transform,duration:o,ease:h},m),f&&u.to(s,{transform:f.forwardState.transform,duration:o,ease:h},m*2)}function Me(r,t,e,s,n,o,i,a,l){let c=n.views[0],f=n.views[1],u=s&&n.views[2]?n.views[2]:null,h=f.backwardState,m=u?u.backwardState:null;vt(t,c.forwardState);let y=e.style.transform||getComputedStyle(e).transform||f.forwardState.transform,p=s&&u?s.style.transform||getComputedStyle(s).transform||u.forwardState.transform:null;e.style.transformOrigin=f.forwardState.origin,s&&u&&(s.style.transformOrigin=u.forwardState.origin);let d=ie(i),g=r.timeline({onComplete:()=>{C(t,a),N(e,h),s&&m&&$(s,m),l()}}),v=(n.stagger||0)/1e3;r.set(e,{transform:y}),s&&p&&r.set(s,{transform:p}),g.fromTo(t,{transform:c.forwardState.transform},{transform:c.backwardState.transform,duration:o,ease:d},0),g.fromTo(e,{transform:y},{transform:h.transform,duration:o,ease:d},v),s&&m&&g.fromTo(s,{transform:p},{transform:m.transform,duration:o,ease:d},v*2)}function vt(r,t){r.style.transformOrigin=t.origin,r.style.transform=t.transform}function ie(r){if(typeof r!="string")return"power2.inOut";let t=r.toLowerCase();return t==="linear"?"none":t.includes("ease-in-out")?"power2.inOut":t.includes("ease-in")?"power2.in":t.includes("ease-out")?"power2.out":t}function ae(r,t){let e=He();if(!e||typeof e!="function"){console.warn('Zumly Motion driver: Motion not loaded. Add <script src="https://cdn.jsdelivr.net/npm/motion@11/dist/motion.min.js"><\/script>'),t();return}let{type:s,currentView:n,previousView:o,lastView:i,currentStage:a,duration:l,ease:c,canvas:f}=r;if(!n||!o||!a){t();return}let u=pt(l);s==="lateral"?H(r,t):s==="zoomIn"?De(e,n,o,i,a,u,c,t):s==="zoomOut"?Fe(e,n,o,i,a,u,c,f,t):t()}function De(r,t,e,s,n,o,i,a){z(t,e,s);let l=le(t,e,s,n,"forward");ce(l,0);let c=n.stagger||0,f=c/1e3,u=o*1e3,h=o+(l.length>2?f*2:f);r(0,1,{duration:h,ease:ue(i),onUpdate:y=>{let p=y*h*1e3;fe(l,p,u,c)}}).then(()=>{T(t,n),T(e,n),s&&T(s,n),a()}).catch(()=>a())}function Fe(r,t,e,s,n,o,i,a,l){let c=n.views[1],f=s&&n.views[2]?n.views[2]:null,u=c.backwardState,h=f?f.backwardState:null,m=le(t,e,s,n,"backward");ce(m,0);let y=n.stagger||0,p=y/1e3,d=o*1e3,g=o+(m.length>2?p*2:p);r(0,1,{duration:g,ease:ue(i),onUpdate:w=>{let b=w*g*1e3;fe(m,b,d,y)}}).then(()=>{C(t,a),N(e,u),s&&h&&$(s,h),l()}).catch(()=>l())}function le(r,t,e,s,n){let o=s.views[0],i=s.views[1],a=e&&s.views[2]?s.views[2]:null,l=[{el:r,backward:o.backwardState,forward:o.forwardState},{el:t,backward:i.backwardState,forward:i.forwardState}];return a&&l.push({el:e,backward:a.backwardState,forward:a.forwardState}),l.map(({el:c,backward:f,forward:u})=>n==="forward"?{el:c,from:Z(c,f.origin,f.transform),to:Z(c,f.origin,u.transform)}:{el:c,from:Z(c,u.origin,u.transform),to:Z(c,u.origin,f.transform)})}function ce(r,t){for(let{el:e,from:s,to:n}of r)e.style.transform=Q(J(s,n,t))}function fe(r,t,e,s){for(let n=0;n<r.length;n++){let{el:o,from:i,to:a}=r[n],l=n*s,c=Math.max(0,t-l),f=e>0?Math.min(1,c/e):1;o.style.transform=Q(J(i,a,f))}}function He(){let r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:{};return r.motion?.animate||r.Motion?.animate||r.animate}function ue(r){if(typeof r!="string")return"easeInOut";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOut":t.includes("ease-in")?"easeIn":t.includes("ease-out")?"easeOut":r}var he={css:Gt,waapi:Jt,none:Qt,anime:te,gsap:oe,motion:ae};function de(r){if(typeof r=="function")return{runTransition(s,n){r(s,n)}};let t=typeof r=="string"?r.toLowerCase():"css";return{runTransition:he[t]||he.css}}function je(r){if(typeof r!="string"||r.trim()==="")return{tx:0,ty:0,rest:""};let t=st(r);return t.matched?{tx:t.tx,ty:t.ty,rest:t.rest}:null}function xt(r,t,e){let s=je(r);if(s===null)return r;let n=s.tx*t,o=s.ty*e,i=s.rest?` ${s.rest}`:"";return`translate(${n}px, ${o}px)${i}`.trim()}function Re(r){if(typeof r!="string"||!r.trim())return null;let t=r.trim().match(/^([-\d.eE]+)px\s+([-\d.eE]+)px$/);return t?{x:parseFloat(t[1]),y:parseFloat(t[2])}:null}function Lt(r,t,e){let s=Re(r);return s===null?r:`${s.x*t}px ${s.y*e}px`}function zt(r,t,e,s,n){if(!r.storedViews?.length||!r.canvas||t<=0||e<=0)return;let o=s/t,i=n/e;for(let m of r.storedViews){let y=m.views;if(Array.isArray(y))for(let p=0;p<y.length;p++){let d=y[p];!d||d.detachedNode||(d.backwardState&&(d.backwardState.transform=xt(d.backwardState.transform,o,i),d.backwardState.origin!=null&&(d.backwardState.origin=Lt(d.backwardState.origin,o,i))),d.forwardState&&(d.forwardState.transform=xt(d.forwardState.transform,o,i),d.forwardState.origin!=null&&(d.forwardState.origin=Lt(d.forwardState.origin,o,i))))}}let a=r.canvas,l=a.querySelector(".is-current-view"),c=a.querySelector(".is-previous-view"),f=a.querySelector(".is-last-view"),u=a.querySelector(".is-new-current-view"),h=[l,c,f,u].filter(Boolean);for(let m of h){if(!m.style)continue;let y=m.style.transform;y!=null&&y!==""&&(m.style.transform=xt(y,o,i));let p=m.style.transformOrigin;p!=null&&p!==""&&(m.style.transformOrigin=Lt(p,o,i))}}var qe=8e3,it=class{constructor(t){if(this.storedViews=[],this.currentStage=null,this.debug=!1,this.trace=[],this.blockEvents=!1,this._blockEventsSafetyTimer=null,this.touchstartX=0,this.touchstartY=0,this.touchendX=0,this.touchendY=0,this.touching=!1,this.lateralHistory=[],this._lastCanvasWidth=0,this._lastCanvasHeight=0,this._pendingResizeCorrection=!1,this._destroyed=!1,this._trackedTimers=new Set,this._pendingTransitionComplete=null,this._hooks={},this._plugins=[],Dt(t,this),!this.isValid){this.notify("is unable to start: invalid or missing required options (mount, initialView, views).","error");return}if(this.canvas=document.querySelector(this.mount),!this.canvas){this.notify(`mount selector "${this.mount}" did not match any element.`,"error"),this.isValid=!1;return}this.transitionDriver=de(this.transitionDriver),this._onZoom=this.onZoom.bind(this),this._onTouchStart=this.onTouchStart.bind(this),this._onTouchEnd=this.onTouchEnd.bind(this),this._onTouchCancel=()=>{this.touching=!1},this._onKeyUp=this.onKeyUp.bind(this),this._onWheel=this.onWheel.bind(this),this._wheelCooldown=!1,this._onPrefetchTrigger=e=>{e.target.classList.contains("zoom-me")&&e.target.dataset.to&&this.prefetcher.prefetch(e.target.dataset.to,{trigger:e.target,...e.target.dataset})},this._onResize=this._handleResize.bind(this),this._resizeDebounceTimer=null,this._RESIZE_DEBOUNCE_MS=80,this.prefetcher=new mt(this.views),this._bindEvents()}_bindEvents(){let t=this.canvas;t&&(t.setAttribute("tabindex","0"),t.setAttribute("role","application"),t.setAttribute("aria-roledescription","zoomable interface"),t.setAttribute("aria-live","polite"),t.addEventListener("mouseup",this._onZoom,!1),t.addEventListener("touchend",this._onZoom,!1),t.addEventListener("touchstart",this._onTouchStart,{passive:!0}),t.addEventListener("touchend",this._onTouchEnd,!1),t.addEventListener("touchcancel",this._onTouchCancel,{passive:!0}),t.addEventListener("keyup",this._onKeyUp,!1),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("mouseover",this._onPrefetchTrigger,{passive:!0}),t.addEventListener("focusin",this._onPrefetchTrigger,{passive:!0}),window.addEventListener("resize",this._onResize,{passive:!0}),typeof ResizeObserver<"u"&&(this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(t)))}_unbindEvents(){let t=this.canvas;t&&(t.removeEventListener("mouseup",this._onZoom,!1),t.removeEventListener("touchend",this._onZoom,!1),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchend",this._onTouchEnd,!1),t.removeEventListener("touchcancel",this._onTouchCancel),t.removeEventListener("keyup",this._onKeyUp,!1),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("mouseover",this._onPrefetchTrigger),t.removeEventListener("focusin",this._onPrefetchTrigger)),window.removeEventListener("resize",this._onResize),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null)}_resetCanvasScroll(t){if(t&&((t.scrollLeft!==0||t.scrollTop!==0)&&(this.notify(`canvas had a residual scroll (${t.scrollLeft}, ${t.scrollTop}) \u2014 resetting. Something scrolled the canvas mid-transition.`,"warn"),t.scrollLeft=0,t.scrollTop=0),!this._warnedScrolledAncestor)){for(let e=t.parentElement;e&&e!==document.body;e=e.parentElement)if(e.scrollLeft!==0||e.scrollTop!==0){let s=e.className?`.${String(e.className).trim().split(/\s+/).join(".")}`:e.tagName.toLowerCase();this.notify(`an ancestor of the canvas (${s}) is scrolled (${e.scrollLeft}, ${e.scrollTop}): all zooms will land displaced. Use 'overflow: clip' (not 'hidden') on containers around the canvas.`,"warn"),this._warnedScrolledAncestor=!0;break}}}_setBlockEvents(){this.blockEvents=!0,this._clearBlockEventsSafety(),this._blockEventsSafetyTimer=setTimeout(()=>{if(this.blockEvents&&!this._destroyed){this.notify("blockEvents safety timeout: driver did not call onComplete. Force-resetting.","warn"),this.blockEvents=!1;let t=this._pendingTransitionComplete;t?t():this._onTransitionComplete()}},qe)}_clearBlockEventsSafety(){this._blockEventsSafetyTimer!==null&&(clearTimeout(this._blockEventsSafetyTimer),this._blockEventsSafetyTimer=null)}_setTrackedTimeout(t,e){let s=setTimeout(()=>{this._trackedTimers.delete(s),!this._destroyed&&t()},e);return this._trackedTimers.add(s),s}_clearTrackedTimeouts(){for(let t of this._trackedTimers)clearTimeout(t);this._trackedTimers.clear()}storeViews(t){this.tracing("storedViews()"),this.storedViews.push(t),this.debug&&console.debug("Zumly storedViews",t)}tracing(t){if(this.debug)if(t==="ended"){let e=this.trace.map((s,n)=>`${n===0?`Instance ${this.mount}: ${s}`:`${s}`}`).join(" > ");this.notify(e),this.trace=[]}else this.trace.push(t)}notify(t,e){return L(this.debug,t,e)}_recordCanvasSize(){if(!this.canvas)return;let t=this.canvas.getBoundingClientRect();this._lastCanvasWidth=t.width,this._lastCanvasHeight=t.height}_handleResize(){this._destroyed||(this._resizeDebounceTimer&&clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=setTimeout(()=>{if(this._resizeDebounceTimer=null,!this.isValid||!this.canvas||this._lastCanvasWidth===0)return;let t=this.canvas.getBoundingClientRect(),e=t.width,s=t.height;if(!(e===this._lastCanvasWidth&&s===this._lastCanvasHeight)){if(this.blockEvents){this._pendingResizeCorrection=!0;return}zt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}},this._RESIZE_DEBOUNCE_MS))}_onTransitionComplete(){if(this._clearBlockEventsSafety(),this._pendingResizeCorrection&&!this.blockEvents){this._pendingResizeCorrection=!1;let t=this.canvas?.getBoundingClientRect();if(t&&this._lastCanvasWidth>0){let e=t.width,s=t.height;(e!==this._lastCanvasWidth||s!==this._lastCanvasHeight)&&zt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}}else this._recordCanvasSize();this._manageFocus()}_manageFocus(){if(!this.canvas)return;let t=this.canvas.querySelector(".is-current-view");if(!t)return;let e=t.querySelector('a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])');e?e.focus({preventScroll:!0}):(t.setAttribute("tabindex","-1"),t.focus({preventScroll:!0}))}_resolveEffects(t){let e=t?.dataset?.withEffects;if(e&&typeof e=="string"){let s=e.split("|").map(n=>n.trim());return[s[0]||"none",s[1]||s[0]||"none"]}return this.effects}_applyEffects(t,e,s,n,o){!s||s[0]==="none"&&s[1]==="none"||(t&&s[0]!=="none"&&(t.style.setProperty("--z-effect-filter",s[0]),t.style.setProperty("--zoom-duration",n),t.style.setProperty("--zoom-ease",o),t.classList.add("has-effect")),e&&s[1]!=="none"&&(e.style.setProperty("--z-effect-filter",s[1]),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("has-effect")))}_removeEffect(t){if(!t||!t.classList.contains("has-effect"))return;t.classList.remove("has-effect"),t.classList.add("has-effect-reverse");let e=()=>{t.classList.remove("has-effect-reverse"),t.style.removeProperty("--z-effect-filter"),t.removeEventListener("transitionend",e)};t.addEventListener("transitionend",e,{once:!0});let s=t.style.getPropertyValue("--zoom-duration");this._setTrackedTimeout(e,s?parseFloat(s)*(s.includes("ms")?1:1e3)+100:1100)}_resolveHideTrigger(t){return t?.dataset?.hideTrigger!==void 0?t.dataset.hideTrigger==="fade"?"fade":!0:this.hideTrigger}_applyHideTrigger(t,e,s,n,o){!s||!t||(s==="fade"?(t.style.setProperty("--zoom-duration",n),t.style.setProperty("--zoom-ease",o),t.classList.add("z-trigger-fade"),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("z-view-fade-in"),e.offsetHeight,e.classList.remove("hide")):t.classList.add("z-trigger-hidden"))}_restoreHideTrigger(t,e,s,n){if(!(!e||!t))if(e==="fade"){t.classList.remove("z-trigger-fade"),t.style.setProperty("--zoom-duration",s),t.style.setProperty("--zoom-ease",n),t.classList.add("z-trigger-fade-reverse");let o=()=>{t.classList.remove("z-trigger-fade-reverse"),t.style.removeProperty("--zoom-duration"),t.style.removeProperty("--zoom-ease"),t.removeEventListener("transitionend",o)};t.addEventListener("transitionend",o,{once:!0}),this._setTrackedTimeout(o,parseFloat(s)*(s.includes("ms")?1:1e3)+100)}else t.classList.remove("z-trigger-hidden")}on(t,e){return typeof e!="function"?this:((this._hooks[t]||=[]).push(e),this)}use(t,e){if(!t)return this;let s={plugin:t,options:e};return this._plugins.push(s),this._initialized&&this._installPlugin(s),this}_installPlugin(t){let{plugin:e,options:s}=t;try{typeof e=="function"?e(this,s):typeof e.install=="function"&&e.install(this,s)}catch(n){this.notify(`plugin install error: ${n.message}`,"error")}}off(t,e){return e?this._hooks[t]&&(this._hooks[t]=this._hooks[t].filter(s=>s!==e)):delete this._hooks[t],this}_emit(t,e={}){let s=this._hooks[t];if(!(!s||s.length===0))for(let n of s)try{n(e)}catch(o){this.debug&&console.error(`Zumly hook "${t}" threw:`,o)}}zoomLevel(){return this.storedViews.length}getZoomLevel(){return this.zoomLevel()}getCurrentViewName(){return!this.storedViews||this.storedViews.length===0?null:this.storedViews[this.storedViews.length-1]?.views?.[0]?.viewName??null}back(){if(!this._destroyed){if(this.blockEvents){this.notify("back ignored: a transition is already running.","warn");return}if(this.lateralHistory&&this.lateralHistory.length>0){let t=this.lateralHistory.pop(),e=t&&typeof t=="object"?t.name:t,s=t&&typeof t=="object"?t.entry:void 0,n=t&&typeof t=="object"?t.node:void 0;return this._doLateral(e,!0,{savedEntry:s,keepAliveNode:n})}this.zoomOut()}}async goTo(t,e={}){return this._destroyed?void 0:(e.mode==="lateral"?"lateral":"depth")==="depth"?this.zoomTo(t,e):this._doLateral(t,!1,e)}async zoomTo(t,e={}){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("zoomTo() cannot run: instance is invalid or canvas not found.","error");return}if(typeof t!="string"||!t){this.notify("zoomTo() requires a non-empty view name.","warn");return}if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`zoomTo("${t}"): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}if(this.getCurrentViewName()===t)return;let n=this.canvas.getBoundingClientRect(),o=Math.max(40,n.width*.1),i=Math.max(40,n.height*.1),l={rect:{x:n.left+(n.width-o)/2,y:n.top+(n.height-i)/2,width:o,height:i},duration:e.duration??this.duration,ease:e.ease??this.ease,props:e.props??{}};await this._doZoomIn(t,l)}async init(){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("init() cannot run: instance is invalid or canvas element was not found.","error");return}this.tracing("init()"),this.preload&&this.preload.length&&await this.prefetcher.preloadEager(this.preload,null).catch(e=>{this.notify(`preload failed: ${e.message}`,"warn")});let t;try{let e=await this.prefetcher.get(this.initialView,null);t=await et(e,this.initialView,this.canvas,!0,this.views,this.componentContext)}catch(e){this.notify(`init() failed to resolve initial view "${this.initialView}": ${e.message}`,"error");return}this._emit("viewMounted",{viewName:this.initialView,node:t}),this.prefetcher.scanAndPrefetch(t,null),this.storeViews({zoomLevel:this.storedViews.length,scale:1,views:[{viewName:this.initialView,backwardState:{origin:"0 0",transform:""}}]}),this.currentStage=this.storedViews[this.storedViews.length-1],this._recordCanvasSize(),this._initialized=!0;for(let e of this._plugins)this._installPlugin(e)}destroy(){this._destroyed||(this._emit("destroy"),this._destroyed=!0,this._clearBlockEventsSafety(),this._clearTrackedTimeouts(),this._pendingTransitionComplete=null,this._resizeDebounceTimer&&(clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=null),this._unbindEvents(),this._removeNav(),this._cleanupLateralKeepAlive(),this.blockEvents=!1,this.storedViews=[],this.currentStage=null,this.lateralHistory=[],this.trace=[],this._hooks={},this.prefetcher=null,this.transitionDriver=null,this.canvas&&(this.canvas.removeAttribute("tabindex"),this.canvas.removeAttribute("role"),this.canvas.removeAttribute("aria-roledescription"),this.canvas.removeAttribute("aria-live")),this.isValid=!1)}async _doZoomIn(t,e){if(this._destroyed)return;if(this.blockEvents){this.notify("zoomIn ignored: a transition is already running.","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this._emit("beforeZoomIn",{viewName:t}),this.tracing("zoomIn()");let s=this.canvas,n=e.el;this._resetCanvasScroll(s);let o=s.getBoundingClientRect(),i=o.left,a=o.top,c=(this.storedViews.length>0?this.storedViews[this.storedViews.length-1]:null)?.scale??1;this.tracing("getView()");let f=n?{trigger:n,target:document.createElement("div"),context:this.componentContext,props:Object.assign({},n.dataset)}:{target:document.createElement("div"),context:this.componentContext,props:e.props??{}},u=n?.dataset?.deferred!==void 0?!0:this.deferred,h,m=null;try{if(u){let E=await this.prefetcher.get(t,f);if(this._destroyed)return;for(m=document.createDocumentFragment();E.firstChild;)m.appendChild(E.firstChild);h=await et(E,t,s,!1,{},this.componentContext)}else{let E=await this.prefetcher.get(t,f);if(this._destroyed)return;this.prefetcher.scanAndPrefetch(E,f),h=await et(E,t,s,!1,this.views,this.componentContext)}}catch(E){this.notify(`zoomIn aborted: failed to resolve view "${t}": ${E.message}`,"error");return}if(!h)return;u||this._emit("viewMounted",{viewName:t,node:h}),n&&n.classList.add("zoomed");let y=n?(()=>{let E=n.getBoundingClientRect();return{x:E.x,y:E.y,width:E.width,height:E.height}})():e.rect,p=n?n.dataset.withDuration||this.duration:e.duration??this.duration,d=n?n.dataset.withEase||this.ease:e.ease??this.ease,g=n?n.dataset.withCover||this.cover:e.cover??this.cover,v=n?parseInt(n.dataset.withStagger,10)||this.stagger:e.stagger??this.stagger,w=s.querySelector(".is-current-view"),b=s.querySelector(".is-previous-view"),_=s.querySelector(".is-last-view");if(!w){this.notify("zoomIn aborted: no current view found in canvas. Call init() before navigating and keep Zumly view classes intact.","error"),n&&n.classList.remove("zoomed");try{s.removeChild(h)}catch{}return}K(h),K(w),K(b),_&&(K(_),s.removeChild(_));let S,O,P,I,x,q,B,tt=w.style.transform,k=w.style.transformOrigin,D=b?b.style.transform:null,A=b?b.style.transformOrigin:null;try{w.classList.replace("is-current-view","is-previous-view"),b&&b.classList.replace("is-previous-view","is-last-view");let E=h.getBoundingClientRect(),V=w.getBoundingClientRect(),bt=null,Ct=null,lt=null;b&&(bt=b.getBoundingClientRect(),lt=b.querySelector(".zoomed"),Ct=lt&<.getBoundingClientRect?lt.getBoundingClientRect():bt);let ct={left:i,top:a},Ot={width:o.width,height:o.height},At={width:E.width,height:E.height},Pt=Ft(y.width,y.height,E.width,E.height,g);B=Pt.scale;let _e=Pt.scaleInv;S=Ht(y,ct,At,_e),P=w.style.transform;let It=Rt(y,V);I=qt(Ot,y,V,B,this.parallax);let Nt=ut(k||"0 0"),U=rt(P||""),$t=ut(It),W=rt(I.transform),Zt=y;if(n&&(Zt=ht(y,V,Nt,U.tx,U.ty,U.scale,$t,W.tx,W.ty,W.scale)),O=jt(Zt,ct,At),b){x=b.style.transform;let Se=ht(V,V,Nt,U.tx,U.ty,U.scale,$t,W.tx,W.ty,W.scale),Te=Vt(I.x,I.y,ct,B,c),Mt=ut(A||"0 0"),_t=rt(x||""),St=rt(Te),Ee=ht(Ct,bt,Mt,_t.tx,_t.ty,_t.scale,Mt,St.tx,St.ty,St.scale);q=Bt({canvasRect:Ot,canvasOffset:ct,triggerRect:y,previousViewRectAtBaseTransform:V,lastViewZoomedElementRect:Ee,previousViewRectWithPreviousAtEndTransform:Se,scale:B,preScale:c,parallax:this.parallax})}h.style.transform=S,w.style.transformOrigin=It}catch(E){this.notify(`zoomIn geometry computation failed: ${E.message}. Aborting zoom.`,"error"),this.debug&&console.error("Zumly _doZoomIn error:",E),w.style.transform=tt,w.style.transformOrigin=k,w.classList.contains("is-previous-view")&&w.classList.replace("is-previous-view","is-current-view"),b&&(b.style.transform=D,b.style.transformOrigin=A,b.classList.contains("is-last-view")&&b.classList.replace("is-last-view","is-previous-view"));try{s.removeChild(h)}catch{}n&&n.classList.remove("zoomed"),X(w),X(b);return}let Y=nt(h.dataset.viewName,{origin:h.style.transformOrigin,duration:p,ease:d,transform:S},{origin:h.style.transformOrigin,duration:p,ease:d,transform:O}),ve=nt(w.dataset.viewName,{origin:w.style.transformOrigin,duration:p,ease:d,transform:P},{origin:w.style.transformOrigin,duration:p,ease:d,transform:I.transform}),ye=b?nt(b.dataset.viewName,{origin:b.style.transformOrigin,duration:p,ease:d,transform:x},{origin:b.style.transformOrigin,duration:p,ease:d,transform:q}):null,we=_?Xt(_):null,at=Yt(this.storedViews.length,Y,ve,ye,we);at.scale=B,at.stagger=v||0,this.storeViews(at),this.currentStage=this.storedViews[this.storedViews.length-1],this.tracing("setCSSVariables()");let ge=this._resolveEffects(n);this._applyEffects(w,b,ge,p,d);let wt=this._resolveHideTrigger(n);this._applyHideTrigger(n,h,wt,p,d),wt&&(at.hideTriggerMode=wt),this._setBlockEvents();let be={type:"zoomIn",currentView:h,previousView:w,lastView:b,currentStage:this.currentStage,duration:p,ease:d},gt=async()=>{this._pendingTransitionComplete===gt&&(this._pendingTransitionComplete=null,!this._destroyed&&(u&&m&&h&&(h.appendChild(m),this.prefetcher.scanAndPrefetch(h,f),typeof this.views[t]=="object"&&typeof this.views[t].mounted=="function"&&await this.views[t].mounted(),this._emit("viewMounted",{viewName:t,node:h})),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterZoomIn",{viewName:t,zoomLevel:this.zoomLevel()}),this.tracing("ended")))};this._pendingTransitionComplete=gt,this.transitionDriver.runTransition(be,gt)}async zoomIn(t){this._destroyed||t?.dataset?.to&&await this._doZoomIn(t.dataset.to,{el:t})}async _doLateral(t,e=!1,s={}){if(this._destroyed)return;if(this.blockEvents){this.notify("lateral navigation ignored: a transition is already running.","warn");return}if(!this.isValid||!this.canvas)return;if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`goTo("${t}", { mode: 'lateral' }): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}let n=this.canvas.querySelector(".is-current-view");if(!n)return;let o=n.dataset?.viewName;if(o===t)return;this._emit("beforeLateral",{viewName:t,from:o,isBack:e});let i=this.lateralNav&&this.lateralNav.keepAlive,a=null;if(!e){this.lateralHistory=this.lateralHistory||[];let k=this.storedViews[this.storedViews.length-1];a={name:o,entry:k.views[0],node:i?n:null}}this.tracing("lateral()");let l=s.duration??this.duration,c=s.ease??this.ease,f=this.canvas.querySelector(".is-previous-view"),u=this.canvas.querySelector(".is-last-view"),h=0,m=0,y=this._declaredSiblings(),p=y?y.indexOf(o):-1,d=y?y.indexOf(t):-1;if(p!==-1&&d!==-1){let k=this.canvas.getBoundingClientRect();h=(p-d)*k.width*.15}else if(f){let k=f.querySelector(`.zoom-me[data-to="${o}"]`),D=f.querySelector(`.zoom-me[data-to="${t}"]`);if(k&&D){let A=k.getBoundingClientRect(),Y=D.getBoundingClientRect();h=A.left+A.width/2-(Y.left+Y.width/2),m=A.top+A.height/2-(Y.top+Y.height/2)}else h=this.canvas.getBoundingClientRect().width*.15}let g=null,v=null;if(i&&(e&&s.keepAliveNode?v=s.keepAliveNode:v=this.canvas.querySelector(`.is-lateral-hidden[data-view-name="${t}"]`)),v){if(v.style.display="",v.style.opacity="",v.classList.remove("is-lateral-hidden","zoom-lateral-out"),v.classList.add("is-new-current-view","has-no-events"),g=v,!e&&this.lateralHistory){let k=this.lateralHistory.findIndex(D=>D.node===v);k!==-1&&this.lateralHistory.splice(k,1)}}else{let k=()=>{e&&this.lateralHistory.push({name:t,entry:s.savedEntry,node:s.keepAliveNode??null})},D={target:document.createElement("div"),context:this.componentContext,props:s.props??{}};try{let A=await this.prefetcher.get(t,D);if(this._destroyed)return;this.prefetcher.scanAndPrefetch(A,D),g=await et(A,t,this.canvas,!1,this.views,this.componentContext)}catch(A){this.notify(`lateral navigation aborted: failed to resolve view "${t}": ${A.message}`,"error"),k();return}if(!g){k();return}this._emit("viewMounted",{viewName:t,node:g})}a&&this.lateralHistory.push(a),K(g);let w=n.style.transform||"",b=n.style.transformOrigin||"0 0";g.style.transform=w,g.style.transformOrigin=b;let _=this.storedViews[this.storedViews.length-1],S=e&&s.savedEntry?{...s.savedEntry,viewName:t}:nt(t,{origin:b,duration:l,ease:c,transform:w},{origin:b,duration:l,ease:c,transform:w});_.views[0]=S,this.currentStage=_;let O=f?{transformStart:f.style.transform||"",transformEnd:this._computeLateralBackTransform(f.style.transform||"",h,m)}:null,P=u&&_.views[2]?{transformStart:u.style.transform||"",transformEnd:this._computeLateralBackTransform(u.style.transform||"",h*.7,m*.7)}:null;O&&_.views[1]&&(_.views[1].forwardState={..._.views[1].forwardState,transform:O.transformEnd}),P&&_.views[2]&&(_.views[2].forwardState={..._.views[2].forwardState,transform:P.transformEnd});let I=w,x=this._computeLateralBackTransform(I,-h,-m),q=this._computeLateralBackTransform(w,h,m);this._setBlockEvents();let B={type:"lateral",currentView:g,previousView:n,lastView:u||null,backView:f||null,backViewState:O,lastViewState:P,incomingTransformStart:x,incomingTransformEnd:I,outgoingTransform:w,outgoingTransformEnd:q,currentStage:this.currentStage,duration:l,ease:c,canvas:this.canvas,slideDeltaX:h,slideDeltaY:m,keepAlive:i&&!e?i:!1},tt=()=>{this._pendingTransitionComplete===tt&&(this._pendingTransitionComplete=null,!this._destroyed&&(i&&!e&&(n.classList.remove("is-current-view","is-new-current-view","has-no-events"),n.classList.add("is-lateral-hidden"),i!=="visible"?n.style.display="none":(n.style.transform=w,n.style.opacity="")),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterLateral",{viewName:t,from:o,isBack:e}),this.tracing("ended")))};this._pendingTransitionComplete=tt,this.transitionDriver.runTransition(B,tt)}_computeLateralBackTransform(t,e,s){let n=st(t);return n.matched?`translate(${n.tx+e}px, ${n.ty+s}px) ${n.rest}`.trim():`translate(${e}px, ${s}px) ${t}`.trim()}zoomOut(){if(this._destroyed)return;if(this.blockEvents){this.notify("zoomOut ignored: a transition is already running.","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this._emit("beforeZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("zoomOut()");let t=this.canvas;this._resetCanvasScroll(t);let e=t.querySelector(".is-current-view"),s=t.querySelector(".is-previous-view");if(!e||!s){this.notify("zoomOut: current or previous view not found (animation may still be running)","warn");return}this._setBlockEvents(),this.currentStage=this.storedViews[this.storedViews.length-1];let n=t.querySelector(".is-last-view");this.tracing("setCSSVariables()");let o=this.currentStage.views[0]?.forwardState?.duration??this.duration,i=this.currentStage.views[0]?.forwardState?.ease??this.ease,a=s.querySelector(".zoomed");a&&a.classList.remove("zoomed");let l=this.currentStage.hideTriggerMode;l&&a&&this._restoreHideTrigger(a,l,o,i),l==="fade"?(e.classList.remove("z-view-fade-in"),e.style.setProperty("--zoom-duration",o),e.style.setProperty("--zoom-ease",i),e.classList.add("z-view-fade-out")):(e.classList.remove("z-view-fade-in"),e.style.removeProperty("opacity")),this._removeEffect(s),s.classList.replace("is-previous-view","is-current-view"),n!==null&&(n.classList.contains("has-effect")&&this.effects[0]!=="none"&&n.style.setProperty("--z-effect-filter",this.effects[0]),n.classList.replace("is-last-view","is-previous-view"),n.classList.remove("hide"),X(n));let c=Ut(this.currentStage);if(c){t.prepend(c);let h=t.querySelector(".z-view:first-child");h&&(X(h),h.classList.add("hide"))}let f={type:"zoomOut",currentView:e,previousView:s,lastView:n,currentStage:this.currentStage,duration:o,ease:i,canvas:t},u=()=>{this._pendingTransitionComplete===u&&(this._pendingTransitionComplete=null,!this._destroyed&&(this.blockEvents=!1,this._onTransitionComplete(),this.storedViews.pop(),this._updateNav(),this._emit("afterZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("ended")))};this._pendingTransitionComplete=u,this.transitionDriver.runTransition(f,u)}onZoom(t){if(this._destroyed||t.type==="mouseup"&&!this.inputs.click||t.type==="touchend"&&!this.inputs.touch)return;let e=t.target;if(e.closest(".z-depth-nav")||e.closest(".z-lateral-nav"))return;let s=e.classList.contains("zoom-me")||e.closest(".zoom-me");if(!this.blockEvents&&s&&!this.touching){this.tracing("onZoom() \u2192 zoomIn"),t.stopPropagation();let n=e.classList.contains("zoom-me")?e:e.closest(".zoom-me");this.zoomIn(n);return}if(this.storedViews.length>1&&!this.blockEvents&&!s&&!this.touching){let n=this.canvas.querySelector(".is-current-view");if(n&&n.contains(e))return;let o=this._findSiblingTriggerAtPoint(t.clientX,t.clientY);if(o){this.tracing("onZoom() \u2192 lateral"),t.stopPropagation(),this._doLateral(o.dataset.to);return}this.tracing("onZoom() \u2192 zoomOut"),t.stopPropagation(),this.zoomOut()}}_findSiblingTriggerAtPoint(t,e){let s=this.canvas.querySelector(".is-previous-view");if(!s)return null;let o=this.canvas.querySelector(".is-current-view")?.dataset?.viewName;if(!o)return null;let i=s.querySelectorAll(".zoom-me[data-to]");for(let a of i){if(a.dataset.to===o)continue;let l=a.getBoundingClientRect();if(t>=l.left&&t<=l.right&&e>=l.top&&e<=l.bottom)return a}return null}_getSiblings(){let e=this.canvas.querySelector(".is-current-view")?.dataset?.viewName,s=this._declaredSiblings();if(s&&s.indexOf(e)!==-1)return{siblings:s,currentIndex:s.indexOf(e)};let n=this.canvas.querySelector(".is-previous-view");if(!n)return{siblings:[],currentIndex:-1};let o=n.querySelectorAll(".zoom-me[data-to]"),i=[];for(let l of o)l.dataset.to&&i.push(l.dataset.to);let a=i.indexOf(e);return{siblings:i,currentIndex:a}}_declaredSiblings(){let t=this.lateralNav&&typeof this.lateralNav=="object"?this.lateralNav.siblings:null;if(!t)return null;if(Array.isArray(t))return t;let e=this.canvas.querySelector(".is-previous-view")?.dataset?.viewName;return e&&Array.isArray(t[e])?t[e]:null}_updateNav(){this._destroyed||(this._removeNav(),this._updateDepthNav(),this._updateLateralNav())}_updateDepthNav(){if(!this.depthNav||this.storedViews.length-1<1)return;let e=this.canvas.querySelector(".z-view.is-current-view");if(e&&e.querySelector(".z-depth-nav"))return;let s=this.depthNav.position||"bottom-left",n=document.createElement("div");n.className="z-depth-nav z-depth-nav--"+s;let o=document.createElement("button");o.className="z-nav-back",o.setAttribute("aria-label","Zoom out (go back)"),o.innerHTML="‹",o.addEventListener("mouseup",i=>{i.stopPropagation(),!this.blockEvents&&this.storedViews.length>1&&this.zoomOut()}),n.appendChild(o),this.canvas.appendChild(n)}_updateLateralNav(){if(!this.lateralNav)return;let t=this.storedViews.length-1,e=this._getSiblings();if(e.siblings.length<2)return;if(this.lateralNav.mode==="auto"&&t>=1){let a=this.canvas.querySelector(".z-view.is-current-view");if(a&&a.offsetWidth>=this.canvas.offsetWidth&&a.offsetHeight>=this.canvas.offsetHeight)return}let{siblings:s,currentIndex:n}=e,o=this.lateralNav.position||"bottom-center",i=document.createElement("div");if(i.className="z-lateral-nav z-lateral-nav--"+o,this.lateralNav.arrows){let a=document.createElement("button");a.className="z-nav-arrow z-nav-prev",a.setAttribute("aria-label","Previous sibling view"),a.innerHTML="‹",a.disabled=n<=0,a.addEventListener("mouseup",l=>{l.stopPropagation(),n>0&&this._doLateral(s[n-1])}),i.appendChild(a)}if(this.lateralNav.dots){let a=document.createElement("div");a.className="z-nav-lateral-dots";for(let l=0;l<s.length;l++){let c=document.createElement("button");c.className="z-nav-dot z-nav-lat-dot"+(l===n?" is-active":""),c.setAttribute("aria-label",`Go to ${s[l]}`),c.dataset.to=s[l],c.addEventListener("mouseup",(f=>u=>{u.stopPropagation(),f!==n&&this._doLateral(s[f])})(l)),a.appendChild(c)}i.appendChild(a)}if(this.lateralNav.arrows){let a=document.createElement("button");a.className="z-nav-arrow z-nav-next",a.setAttribute("aria-label","Next sibling view"),a.innerHTML="›",a.disabled=n>=s.length-1,a.addEventListener("mouseup",l=>{l.stopPropagation(),n<s.length-1&&this._doLateral(s[n+1])}),i.appendChild(a)}this.canvas.appendChild(i)}_removeNav(){this.canvas&&this.canvas.querySelectorAll(".z-depth-nav, .z-lateral-nav").forEach(t=>t.remove())}_cleanupLateralKeepAlive(){if(!this.canvas)return;let t=this.canvas.querySelectorAll(".is-lateral-hidden");for(let e of t)e.remove()}onKeyUp(t){this._destroyed||this.inputs.keyboard&&(this.tracing("onKeyUp()"),(t.key==="ArrowLeft"||t.key==="ArrowDown")&&(t.preventDefault(),this.storedViews.length>1&&!this.blockEvents?this.zoomOut():this.notify(`is on level zero. Can't zoom out. Trigger: ${t.key}`,"warn")),(t.key==="ArrowRight"||t.key==="ArrowUp")&&(t.preventDefault(),this.notify(t.key+" has no actions defined")))}onWheel(t){this._destroyed||this.inputs.wheel&&(this._isInsideScrollable(t.target,t.deltaY)||(t.preventDefault(),!(this.blockEvents||this._wheelCooldown)&&t.deltaY>0&&this.storedViews.length>1&&(this.tracing("onWheel() \u2192 zoomOut"),this._wheelCooldown=!0,this._setTrackedTimeout(()=>{this._wheelCooldown=!1},500),this.zoomOut())))}_isInsideScrollable(t,e){let s=t,n=this.canvas.querySelector(".is-current-view");for(;s&&s!==this.canvas;){if(s===n||n&&n.contains(s)){let{overflowY:o}=window.getComputedStyle(s);if((o==="auto"||o==="scroll")&&(e>0?s.scrollTop+s.clientHeight<s.scrollHeight-1:s.scrollTop>0))return!0}s=s.parentElement}return!1}onTouchStart(t){this._destroyed||this.inputs.touch&&(this.tracing("onTouchStart()"),this.touching=!0,this.touchstartX=t.changedTouches[0].screenX,this.touchstartY=t.changedTouches[0].screenY)}onTouchEnd(t){this._destroyed||this.inputs.touch&&(this.blockEvents||(this.tracing("onTouchEnd()"),this.touchendX=t.changedTouches[0].screenX,this.touchendY=t.changedTouches[0].screenY,this.handleGesture(t)),this.touching=!1)}handleGesture(t){t.stopPropagation(),this.tracing("handleGesture()");let e=this.touchendX-this.touchstartX,s=this.touchendY-this.touchstartY,n=Math.abs(e)<10&&Math.abs(s)<10;e<-30&&(this.storedViews.length>1&&!this.blockEvents?(this.tracing("swipe left"),this.zoomOut()):this.notify("is on level zero. Can't zoom out. Trigger: Swipe left","warn"));let o=t.target.classList.contains("zoom-me")?t.target:t.target.closest(".zoom-me");n&&!this.blockEvents&&o&&this.touching&&(this.touching=!1,this.tracing("tap"),t.preventDefault(),this.zoomIn(o)),n&&this.storedViews.length>1&&!this.blockEvents&&!o&&t.target.closest(".is-current-view")===null&&this.touching&&(this.touching=!1,this.tracing("tap"),this.zoomOut())}};var Be={separator:"/",prefix:"/"};function me(r,t){let e=[];for(let s of r.storedViews){let n=s.views&&s.views[0];n&&n.viewName&&e.push(n.viewName)}return e.join(t)}function Ve(r,t){let e=window.location.hash.slice(1);return e.startsWith(r)&&(e=e.slice(r.length)),e?e.split(t).filter(Boolean):[]}var pe={install(r,t){let e=Object.assign({},Be,t),s=e.separator,n=e.prefix,o=!1;function i(f){if(o)return;let u=me(r,s),h="#"+n+u;window.location.hash!==h&&(o=!0,window.history[f](null,"",h),o=!1)}function a(){i("pushState")}function l(){i("replaceState")}r.on("afterZoomIn",a),r.on("afterLateral",a),r.on("afterZoomOut",l);function c(){if(o)return;o=!0;let f=Ve(n,s),u=me(r,s).split(s).filter(Boolean);if(f.join(s)===u.join(s)){o=!1;return}if(f.length<u.length){let h=u.length-f.length;for(let m=0;m<h;m++)r.zoomOut()}else if(f.length===u.length&&f.length>0){let h=f[f.length-1];h!==u[u.length-1]&&r.goTo(h,{mode:"lateral"})}else f.length>u.length&&window.history.back();o=!1}window.addEventListener("popstate",c),l(),r.on("destroy",function(){r.off("afterZoomIn",a),r.off("afterLateral",a),r.off("afterZoomOut",l),window.removeEventListener("popstate",c)})}};it.Router=pe;var Zs=it;export{it as Zumly,pe as ZumlyRouter,Zs as default};
|
|
7
|
+
var it=Symbol.for("zumly.viewLifecycles");function ee(r){try{let t=r();t&&typeof t.then=="function"&&t.catch(e=>console.error("Zumly: view cleanup failed:",e))}catch(t){console.error("Zumly: view cleanup failed:",t)}}function se(){let r=!1,t=[],e={onCleanup(s){if(typeof s!="function")throw new TypeError("Zumly: onCleanup expects a function");r?ee(s):t.push(s)},attach(s){let i=s[it];i||(i=new Set,Object.defineProperty(s,it,{value:i,configurable:!0})),i.add(e)},dispose(){if(!r){r=!0;for(let s of t.splice(0).reverse())ee(s)}}};return e}function C(r){if(!r)return;let t=[];r[it]&&t.push(r);let s=(r.ownerDocument||r).createTreeWalker(r,1),i;for(;i=s.nextNode();)i[it]&&t.push(i);for(let n=t.length-1;n>=0;n--){let o=t[n],a=o[it];if(a){for(let c of a)c.dispose();delete o[it]}}}var Ve=1e4,xt=class{#t={};constructor(t={}){this.#t=t}#e(t){return typeof t=="function"?"function":t instanceof HTMLElement?"element":typeof t=="object"&&t!==null&&typeof t.render=="function"?"object":typeof t!="string"?"unknown":/^https?:\/\/|^\/|\.(?:html|php)(?:[?#].*)?$/i.test(t)?"url":t.includes("<")?"html":t.includes("-")?"webcomponent":"unknown"}async resolve(t,e=null){let s=new Set;for(;typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#t,t);){if(s.has(t))throw new Error(`Zumly: circular view alias "${t}"`);s.add(t),t=this.#t[t]}let i=this.#e(t);switch(i){case"html":{let n=document.createElement("div");n.innerHTML=t.trim();let o=n.firstElementChild;if(!o)throw new Error("Zumly: view produced no element (html)");return o}case"url":{let n=new AbortController,o=setTimeout(()=>n.abort(),Ve),a;try{let f=await fetch(t,{signal:n.signal});if(!f.ok)throw new Error(`Zumly: fetch failed for "${t}" (${f.status})`);a=await f.text()}finally{clearTimeout(o)}let c=document.createElement("div");c.innerHTML=a.trim();let l=c.firstElementChild;if(!l)throw new Error("Zumly: view produced no element (url)");return l}case"function":case"object":{let n=se(),o=e?.target||document.createElement("div");n.attach(o);let a={...e,target:o,props:e?.props||{},context:e?.context||new Map,onCleanup:n.onCleanup};try{let c=await(i==="function"?t(a):t.render(a)),l;if(typeof c=="string")l=await this.resolve(c,a);else if(c instanceof HTMLElement)l=c;else if(i==="function")l=o,o.classList.length||(o.style.width||(o.style.width="100%"),o.style.height||(o.style.height="100%"));else throw new Error("Zumly: view render() must return a string or HTMLElement");return n.attach(l),l}catch(c){throw n.dispose(),c}}case"element":return t.cloneNode(!0);case"webcomponent":return await customElements.whenDefined(t),document.createElement(t);default:throw new Error("Zumly: unknown view type for source")}}};async function ut(r,t,e,s,i,n){if(!r||!r.classList){let o=document.createElement("div");o.classList.add("z-view"),r&&o.appendChild(r),r=o}else r.classList.contains("z-view")||r.classList.add("z-view");r.dataset.viewName=t,r.getAttribute("aria-label")||r.setAttribute("aria-label",`View: ${t}`),r.style.transformOrigin="0 0",r.style.position="absolute",s?r.classList.add("is-current-view"):r.classList.add("is-new-current-view","has-no-events","hide"),e.append(r);try{i[t]&&typeof i[t]=="object"&&typeof i[t].mounted=="function"&&await i[t].mounted()}catch(o){throw C(r),r.remove(),o}return r}function $(r,t,e){t&&e==="welcome"&&console.info(`%c Zumly %c ${t}`,"background: #424085; color: white; border-radius: 3px;","color: #424085"),t&&r&&(e==="info"||e===void 0)&&console.info(`%c Zumly %c ${t}`,"background: #6679A3; color: #304157; border-radius: 3px;","color: #6679A3"),t&&e==="warn"&&console.warn(`%c Zumly %c ${t}`,"background: #DCBF53; color: #424085; border-radius: 3px;","color: #424085"),t&&e==="error"&&console.error(`%c Zumly %c ${t}`,"background: #BE4747; color: white; border-radius: 3px;","color: #424085")}function re(r,t){if(t.isValid=!1,!r||typeof r!="object"){$(!1,"'options' object has to be provided when instance is defined","error");return}if(typeof r.mount!="string"){$(!1,"'mount' must be a string selector","error");return}if(t.mount=r.mount,typeof r.initialView!="string"){$(!1,"'initialView' must be a string","error");return}if(t.initialView=r.initialView,!r.views||typeof r.views!="object"){$(!1,"'views' must be an object","error");return}t.views=r.views,t.isValid=!0,t.preload=Array.isArray(r.preload)?r.preload:[],t.debug=typeof r.debug=="boolean"?r.debug:!1,t.componentContext=r.componentContext&&typeof r.componentContext=="object"?r.componentContext:new Map;let e=r.transitions&&typeof r.transitions=="object"?r.transitions:null,s=e&&e.cover,i=typeof s=="string"?s.toLowerCase():null,n=i==="width"||i==="height";t.cover=n?i:"width",!n&&e&&s!==void 0&&$(!1,`'transitions.cover' must be either "width" or "height". Falling back to "width".`,"warn"),t.duration=e&&typeof e.duration=="string"?e.duration:"1s",t.ease=e&&typeof e.ease=="string"?e.ease:"ease-in-out",t.deferred=typeof r.deferred=="boolean"?r.deferred:!1;let o=e&&e.hideTrigger;o===!0||o==="fade"?t.hideTrigger=o:(t.hideTrigger=!1,o!=null&&o!==!1&&$(!1,`'transitions.hideTrigger' must be true or "fade". Falling back to false.`,"warn"));let a=e&&e.effects;Array.isArray(a)&&a.length>=2&&typeof a[0]=="string"&&typeof a[1]=="string"?t.effects=[a[0],a[1]]:Array.isArray(a)&&a.length===1&&typeof a[0]=="string"?t.effects=[a[0],a[0]]:(t.effects=["none","none"],a!=null&&$(!1,`'transitions.effects' must be an array of 1-2 CSS filter strings (e.g. ["blur(3px)", "blur(8px) saturate(0)"]). Falling back to no effects.`,"warn"));let c=e&&e.driver,l=typeof c=="string"?c.toLowerCase():null,f=typeof c=="function"?c:null;if(l!==null){let p=["css","waapi","none","anime","gsap","motion"];t.transitionDriver=p.includes(l)?l:"css",p.includes(l)||$(!1,`'transitions.driver' must be "css", "waapi", "none", "anime", "gsap", "motion", or a function. Got "${c}". Falling back to "css".`,"warn")}else f!==null?t.transitionDriver=f:t.transitionDriver="css";let h=e&&e.stagger;typeof h=="number"&&h>0?t.stagger=h:(t.stagger=0,h!=null&&h!==0&&$(!1,"'transitions.stagger' must be a positive number (ms). Falling back to 0 (disabled).","warn")),t.parallax=0;let u=r.lateralNav;if(u===!1)t.lateralNav=!1;else if(u&&typeof u=="object"){let p=typeof u.mode=="string"?u.mode.toLowerCase():null,y=p==="auto"||p==="always";p&&!y&&$(!1,`'lateralNav.mode' must be "auto" or "always". Falling back to "auto".`,"warn");let g=null;if(Array.isArray(u.siblings))g=u.siblings.filter(x=>typeof x=="string"&&x),g.length<2&&($(!1,"'lateralNav.siblings' needs at least 2 view names. Ignoring.","warn"),g=null);else if(u.siblings&&typeof u.siblings=="object"){g={};for(let[x,b]of Object.entries(u.siblings))if(Array.isArray(b)){let _=b.filter(S=>typeof S=="string"&&S);_.length>=2&&(g[x]=_)}Object.keys(g).length===0&&(g=null)}else u.siblings!==void 0&&$(!1,"'lateralNav.siblings' must be an array of view names or a { parentView: [...] } map. Ignoring.","warn");t.lateralNav={mode:y?p:"auto",arrows:typeof u.arrows=="boolean"?u.arrows:!0,dots:typeof u.dots=="boolean"?u.dots:!0,keepAlive:u.keepAlive===!0||u.keepAlive==="visible"?u.keepAlive:!1,siblings:g}}else t.lateralNav={mode:"auto",arrows:!0,dots:!0,keepAlive:!1,siblings:null};let d=r.depthNav;if(d===!1)t.depthNav=!1;else if(d&&typeof d=="object"){let p=typeof d.position=="string"?d.position.toLowerCase():null,y=p==="bottom-left"||p==="top-left";p&&!y&&$(!1,`'depthNav.position' must be "bottom-left" or "top-left". Falling back to "bottom-left".`,"warn"),t.depthNav={position:y?p:"bottom-left"}}else t.depthNav={position:"bottom-left"};let v=r.lateralNav&&typeof r.lateralNav=="object"?r.lateralNav.position:void 0;if(t.lateralNav&&typeof t.lateralNav=="object"){let p=v==="bottom-center"||v==="top-center";v&&!p&&$(!1,`'lateralNav.position' must be "bottom-center" or "top-center". Falling back to "bottom-center".`,"warn"),t.lateralNav.position=p?v:"bottom-center"}let m=r.inputs;m===!1?t.inputs={wheel:!1,keyboard:!1,click:!1,touch:!1}:m&&typeof m=="object"?t.inputs={wheel:typeof m.wheel=="boolean"?m.wheel:!0,keyboard:typeof m.keyboard=="boolean"?m.keyboard:!0,click:typeof m.click=="boolean"?m.click:!0,touch:typeof m.touch=="boolean"?m.touch:!0}:t.inputs={wheel:!0,keyboard:!0,click:!0,touch:!0}}function St(r,t,e,s,i){let n=e/r,o=s/t;return i==="height"?{scale:o,scaleInv:1/o}:{scale:n,scaleInv:1/n}}function Dt(r,t,e,s){let i=t.left,n=t.top,o=r.x-i+(r.width-e.width*s)/2,a=r.y-n+(r.height-e.height*s)/2;return`translate(${o}px, ${a}px) scale(${s})`}function ie(r,t,e){let s=t.left,i=t.top,n=r.x-s+(r.width-e.width)/2,o=r.y-i+(r.height-e.height)/2;return`translate(${n}px, ${o}px)`}function ne(r,t){let e=r.x+r.width/2-t.x,s=r.y+r.height/2-t.y;return`${e}px ${s}px`}function oe(r,t,e,s,i=0){let n=r.width/2-t.width/2-t.x+e.x,o=r.height/2-t.height/2-t.y+e.y,a=1-i,c=n*a,l=o*a;return{x:n,y:o,transform:`translate(${c}px, ${l}px) scale(${s})`}}function ae({canvasRect:r,canvasOffset:t,triggerRect:e,previousViewRectAtBaseTransform:s,lastViewZoomedElementRect:i,previousViewRectWithPreviousAtEndTransform:n,scale:o,preScale:a,parallax:c=0}){let l=t.left,f=t.top,h=r.width/2-e.width/2-e.x,u=r.height/2-e.height/2-e.y,d=h+(s.x-i.x)+n.x-l+(n.width-i.width)/2,v=u+(s.y-i.y)+n.y-f+(n.height-i.height)/2,m=1-Math.min(c*2,.9);return`translate(${d*m}px, ${v*m}px) scale(${o*a})`}function le(r,t,e,s,i){return`translate(${r-e.left}px, ${t-e.top}px) scale(${s*i})`}function nt(r){let t=r.split(/\s+/);return{x:parseFloat(t[0])||0,y:parseFloat(t[1])||0}}function et(r){let t=typeof r=="string"?r:"",e=t.match(/translate\s*\(\s*([-+\d.eE]+)px\s*,\s*([-+\d.eE]+)px\s*\)/);if(!e)return{tx:0,ty:0,rest:t.trim(),matched:!1};let s=t.replace(/translate\s*\([^)]+\)\s*/,"").trim();return{tx:parseFloat(e[1]),ty:parseFloat(e[2]),rest:s,matched:!0}}function Y(r){let t=et(r),e=r.match(/scale\s*\(\s*([-+\d.eE]+)\s*\)/);return{tx:t.matched?t.tx:0,ty:t.matched?t.ty:0,scale:e?parseFloat(e[1]):1}}function dt(r,t,e,s,i,n,o,a,c,l){let f=t.x-e.x*(1-n)-s,h=t.y-e.y*(1-n)-i,u=t.width/n,d=t.height/n,v=f+e.x+(r.x-f-e.x-s)/n,m=h+e.y+(r.y-h-e.y-i)/n,p=r.width/n,y=r.height/n,g=f+o.x+a+l*(v-f-o.x),x=h+o.y+c+l*(m-h-o.y),b=p*l,_=y*l;return{x:g,y:x,width:b,height:_,left:g,top:x,right:g+b,bottom:x+_}}function mt(r,t,e){return{viewName:r,backwardState:t,forwardState:e}}function ce(r){return{detachedNode:r}}function fe(r,t,e,s,i){let n=[];return t!==null&&n.push(t),e!==null&&n.push(e),s!==null&&n.push(s),i!==null&&n.push(i),{zoomLevel:r,views:n}}function Ft(r){let t=r.views?.[3];if(!(!t||!(t.detachedNode instanceof Node)))return t.detachedNode}var Tt=class{#t=new Map;#e;constructor({maxEntries:t=64}={}){this.#e=Number.isInteger(t)&&t>=0?t:64}set(t,e,s=null){this.#e!==0&&this.adopt(t,e.cloneNode(!0),s)}adopt(t,e,s=null){let i=Date.now();for(let[n,o]of this.#t)o.expires!==null&&i>=o.expires&&this.#t.delete(n);if(this.#e!==0)for(this.#t.delete(t),this.#t.set(t,{node:e,expires:s===null?null:i+s});this.#t.size>this.#e;)this.#t.delete(this.#t.keys().next().value)}get(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>=e.expires?(this.#t.delete(t),null):(this.#t.delete(t),this.#t.set(t,e),e.node.cloneNode(!0)):null}has(t){let e=this.#t.get(t);return e?e.expires!==null&&Date.now()>=e.expires?(this.#t.delete(t),!1):!0:!1}invalidate(t){this.#t.delete(t)}clear(){this.#t.clear()}};var je="button, input, select, textarea, a[href], summary";function kt(r){return r?.matches?.(je)||!1}function Vt(r){return!!r?.closest?.('input, textarea, select, [contenteditable]:not([contenteditable="false"]), [role="textbox"], [role="combobox"], [role="slider"], [role="spinbutton"]')}function he(r){let t=r.querySelectorAll(".zoom-me[data-to]");return t.forEach(e=>{kt(e)||(e.hasAttribute("role")||e.setAttribute("role","button"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0")),!e.hasAttribute("aria-label")&&!e.hasAttribute("aria-labelledby")&&!e.textContent.trim()&&e.setAttribute("aria-label",`Zoom to ${e.dataset.to}`)}),t}var Et=class{constructor(){this.backgrounds=new Map}sync(t){for(let e of t.children)e.classList.contains("z-view")&&(e.classList.contains("is-current-view")?this.restore(e):(this.backgrounds.has(e)||this.backgrounds.set(e,{inert:e.inert,hidden:e.getAttribute("aria-hidden")}),e.inert=!0,e.setAttribute("aria-hidden","true")));for(let e of this.backgrounds.keys())t.contains(e)||this.restore(e)}restore(t){let e=this.backgrounds.get(t);e&&(t.inert=e.inert,e.hidden===null?t.removeAttribute("aria-hidden"):t.setAttribute("aria-hidden",e.hidden),this.backgrounds.delete(t))}destroy(){for(let t of this.backgrounds.keys())this.restore(t)}};var Be=300*1e3,ue=/^https?:\/\/|^\/|\.(?:html|php)(?:[?#].*)?$/i,zt=class{#t;#e;#l;#n=new Map;#s=new Map;#r=null;#c=0;#d;#f;#i=!1;#o=!1;constructor(t={},{maxCacheEntries:e=64,prefetchConcurrency:s=2,maxPendingPrefetch:i=32}={}){this.#l=t,this.#t=new xt(t),this.#e=new Tt({maxEntries:e}),this.#d=Number.isInteger(s)&&s>0?s:2,this.#f=Number.isInteger(i)&&i>=0?i:32}#h(t){let e=new Set;for(;typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.#l,t);){if(e.has(t))return null;e.add(t),t=this.#l[t]}return typeof t=="string"&&(t.includes("<")||ue.test(t))?t:null}#v(t){return ue.test(t)?Be:null}async get(t,e=null){if(this.#i)throw new Error("Zumly: view prefetcher has been destroyed");this.#s.delete(t);let s=this.#h(t);if(s!==null){let i=this.#e.get(t);return i||(await this.#m(t,s,e)).cloneNode(!0)}return this.#t.resolve(t,e)}#m(t,e,s){if(this.#n.has(t))return this.#n.get(t);let i=(async()=>{try{let n=await this.#t.resolve(t,s);return this.#i||this.#e.adopt(t,n,this.#v(e)),n}finally{this.#n.delete(t)}})();return this.#n.set(t,i),i}async#u(t,e){if(this.#i)return;this.#s.delete(t);let s=this.#h(t);s===null||this.#e.has(t)||await this.#m(t,s,e)}async preloadEager(t,e=null){!Array.isArray(t)||t.length===0||await Promise.all([...new Set(t)].map(s=>this.#u(s,e)))}prefetch(t,e=null){if(this.#o){this.#p(t,e);return}this.#u(t,e).catch(()=>{})}prefetchOnHover(t,e=null){this.prefetch(t,e)}scanAndPrefetch(t,e=null){if(this.#i||!t||!t.querySelectorAll)return;let s=he(t);this.#s.clear();let i=new Set;for(let n of s){let o=n.dataset.to;if(!(!o||i.has(o))){if(i.add(o),this.#s.size>=this.#f)break;this.#p(o,e)}}this.#a()}#p(t,e){this.#i||this.#s.size>=this.#f||this.#s.has(t)||this.#h(t)===null||this.#e.has(t)||this.#n.has(t)||this.#s.set(t,e)}#a(){this.#i||this.#o||this.#r!==null||this.#s.size===0||this.#c>=this.#d||(this.#r=setTimeout(()=>{if(this.#r=null,this.#i||this.#s.size===0)return;let[t,e]=this.#s.entries().next().value;this.#s.delete(t),this.#c++,this.#u(t,e).catch(()=>{}).finally(()=>{this.#c--,this.#a()}),this.#a()},0))}pause(){this.#o=!0,this.#r!==null&&clearTimeout(this.#r),this.#r=null}resume(){this.#o=!1,this.#a()}destroy(){this.#i=!0,this.#r!==null&&clearTimeout(this.#r),this.#r=null,this.#s.clear(),this.#e.clear()}};var Lt=Symbol.for("zumly.viewVisibility");function de(r){r[Lt]||Object.defineProperty(r,Lt,{configurable:!0,value:{value:r.style.getPropertyValue("content-visibility"),priority:r.style.getPropertyPriority("content-visibility")}})}function Ct(r){r&&(de(r),r.style.contentVisibility="hidden")}function pt(r){r&&(de(r),r.style.contentVisibility="visible")}function vt(r){let t=r?.[Lt];t&&(t.value?r.style.setProperty("content-visibility",t.value,t.priority):r.style.removeProperty("content-visibility"),delete r[Lt])}function K(r){if(typeof r=="number"&&!Number.isNaN(r))return Math.max(0,r);let t=String(r).trim(),e=t.match(/^(\d*\.?\d+)\s*(ms|s)?$/i);if(!e)return typeof console<"u"&&console.warn(`[zumly] Could not parse duration "${t}" \u2014 falling back to 500ms.`),500;let s=parseFloat(e[1]);return(e[2]||"s").toLowerCase()==="ms"?Math.max(0,s):Math.max(0,s*1e3)}function Nt(r){return K(r)/1e3}function k(r,t){if(r.classList.contains("is-new-current-view")){let e=t.views[0].forwardState;r.classList.replace("is-new-current-view","is-current-view"),r.classList.remove("zoom-current-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-previous-view")){let e=t.views[1].forwardState;r.classList.remove("zoom-previous-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform;return}if(r.classList.contains("is-last-view")){let e=t.views[2].forwardState;r.classList.remove("zoom-last-view","has-no-events"),r.style.transformOrigin=e.origin,r.style.transform=e.transform}}function V(r,t){r.classList.remove("zoom-previous-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin="0 0",r.style.transform=t.transform}function j(r,t){r.classList.remove("zoom-last-view-reverse","has-no-events","has-effect","has-effect-reverse"),r.style.removeProperty("--z-effect-filter"),r.style.transformOrigin=t.origin,r.style.transform=t.transform}function H(r,t){C(r);try{t&&t.removeChild(r)}catch{try{r?.parentElement&&t&&(C(r.parentElement),t.removeChild(r.parentElement))}catch{}}}function Z(...r){for(let t of r)t&&(t.classList.remove("hide"),pt(t))}function G(r,t){let{currentView:e,previousView:s,backView:i,backViewState:n,lastView:o,lastViewState:a,incomingTransformEnd:c,currentStage:l,canvas:f}=r,h=l.views[0];Z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=h.forwardState.origin,e.style.transform=c||h.forwardState.transform,i&&n&&(i.style.transform=n.transformEnd),o&&a&&(o.style.transform=a.transformEnd),r.keepAlive||H(s,f),t()}var Q=150;function J(r,t){let e=!1,s=setTimeout(()=>{e||(e=!0,r())},t);return{finish(){e||(e=!0,clearTimeout(s),r())},extend(i){e||(clearTimeout(s),s=setTimeout(()=>{e||(e=!0,r())},i))},safetyTimer:s}}function Ot(){return{a:1,b:0,c:0,d:1,e:0,f:0}}function Re(r){if(!r||r==="none")return Ot();let t=String(r).match(/matrix\(([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+),\s*([-\d.eE]+)\)/);return t?{a:parseFloat(t[1]),b:parseFloat(t[2])||0,c:parseFloat(t[3])||0,d:parseFloat(t[4]),e:parseFloat(t[5])||0,f:parseFloat(t[6])||0}:Ot()}function at(r){return`matrix(${r.a}, ${r.b}, ${r.c}, ${r.d}, ${r.e}, ${r.f})`}function ot(r,t,e){return r+(t-r)*e}function lt(r,t,e){let s=Math.max(0,Math.min(1,e));return{a:ot(r.a,t.a,s),b:ot(r.b,t.b,s),c:ot(r.c,t.c,s),d:ot(r.d,t.d,s),e:ot(r.e,t.e,s),f:ot(r.f,t.f,s)}}function me(r,t,e){r.style.transformOrigin=t,r.style.transform=e;try{r.getBoundingClientRect()}catch{}return Re(getComputedStyle(r).transform)}function ve(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,duration:a,ease:c,canvas:l}=r;if(!s||!i||!o){t();return}e==="lateral"?qe(r,t):e==="zoomIn"?We(s,i,n,o,a,c,t):e==="zoomOut"?Xe(s,i,n,o,a,c,l,t):t()}function qe(r,t){let{currentView:e,previousView:s,backView:i,backViewState:n,lastView:o,lastViewState:a,incomingTransformStart:c,incomingTransformEnd:l,outgoingTransform:f,outgoingTransformEnd:h,currentStage:u,duration:d,ease:v,canvas:m}=r,p=K(d),y=u.views[0];Z(e),e.classList.replace("is-new-current-view","is-current-view"),e.classList.remove("zoom-current-view","has-no-events"),e.style.transformOrigin=y.forwardState.origin,i&&n&&(R(i,d,v,{"--lateral-from":n.transformStart,"--lateral-to":n.transformEnd}),i.classList.add("zoom-lateral-back")),o&&a&&(R(o,d,v,{"--lateral-from":a.transformStart,"--lateral-to":a.transformEnd}),o.classList.add("zoom-lateral-back")),r.keepAlive!=="visible"&&(R(s,d,v,{"--lateral-out-from":f,"--lateral-out-to":h}),s.classList.add("zoom-lateral-out")),R(e,d,v,{"--lateral-in-from":c,"--lateral-in-to":l}),e.classList.add("zoom-lateral-in");let g=r.keepAlive==="visible"?[e]:[s,e];i&&n&&g.push(i),o&&a&&g.push(o);let x=g.length,b=p+Q,_=new Set(["zoom-lateral-in","zoom-lateral-out","zoom-lateral-back"]),{finish:S,extend:O}=J(()=>{jt(g,E,A),r.keepAlive?(s.classList.remove("zoom-lateral-out"),s.style.opacity=""):H(s,m),i&&(i.classList.remove("zoom-lateral-back"),i.style.transform=n?.transformEnd||i.style.transform),o&&(o.classList.remove("zoom-lateral-back"),o.style.transform=a?.transformEnd||o.style.transform),e.classList.remove("zoom-lateral-in"),e.style.transform=l,t()},b);function A(T){T.target!==T.currentTarget||!_.has(T.animationName)||O(b)}function E(T){if(T.target!==T.currentTarget||!_.has(T.animationName))return;let P=T.currentTarget;P.removeEventListener("animationend",E),P.removeEventListener("animationstart",A),x--,x<=0&&S()}g.forEach(T=>{T.addEventListener("animationstart",A),T.addEventListener("animationend",E)})}function We(r,t,e,s,i,n,o){Z(r,t,e);let a=s.stagger||0;R(r,i,n,{"--current-view-transform-start":s.views[0].backwardState.transform,"--current-view-transform-end":s.views[0].forwardState.transform}),a>0&&r.style.setProperty("animation-delay","0ms"),R(t,i,n,{"--previous-view-transform-start":s.views[1].backwardState.transform,"--previous-view-transform-end":s.views[1].forwardState.transform}),a>0&&t.style.setProperty("animation-delay",`${a}ms`),e&&(R(e,i,n,{"--last-view-transform-start":s.views[2].backwardState.transform,"--last-view-transform-end":s.views[2].forwardState.transform}),a>0&&e.style.setProperty("animation-delay",`${a*2}ms`)),r.classList.add("zoom-current-view"),t.classList.add("zoom-previous-view"),e&&e.classList.add("zoom-last-view");let c=e?[r,t,e]:[r,t],l=c.length,f=K(i),h=e?a*2:a,u=f+h+Q,d=new Set(["zoom-current-view","zoom-previous-view","zoom-last-view"]),{finish:v,extend:m}=J(()=>{jt(c,y,p),c.forEach(g=>g.style.removeProperty("animation-delay")),c.forEach(g=>{if(g?.isConnected)try{k(g,s)}catch{}}),o()},u);function p(g){g.target!==g.currentTarget||!d.has(g.animationName)||m(u)}function y(g){if(g.target!==g.currentTarget||!d.has(g.animationName))return;let x=g.currentTarget;if(x.removeEventListener("animationend",y),x.removeEventListener("animationstart",p),x.isConnected)try{k(x,s)}catch{}l--,l<=0&&v()}c.forEach(g=>{g.addEventListener("animationstart",p),g.addEventListener("animationend",y)})}function Xe(r,t,e,s,i,n,o,a){let c=s.views[0],l=s.views[1],f=e&&s.views[2]?s.views[2]:null,h=s.stagger||0;R(r,i,n,{"--current-view-transform-start":c.backwardState.transform,"--current-view-transform-end":c.forwardState.transform}),h>0&&r.style.setProperty("animation-delay","0ms"),R(t,i,n,{"--previous-view-transform-start":l.backwardState.transform,"--previous-view-transform-end":l.forwardState.transform}),h>0&&t.style.setProperty("animation-delay",`${h}ms`),e&&f&&(R(e,i,n,{"--last-view-transform-start":f.backwardState.transform,"--last-view-transform-end":f.forwardState.transform}),h>0&&e.style.setProperty("animation-delay",`${h*2}ms`)),r.classList.add("zoom-current-view-reverse"),t.classList.add("zoom-previous-view-reverse"),e&&e.classList.add("zoom-last-view-reverse");let u=e?[r,t,e]:[r,t],d=u.length,v=K(i),m=e?h*2:h,p=v+m+Q,y=new Set(["zoom-current-view-reverse","zoom-previous-view-reverse","zoom-last-view-reverse"]),{finish:g,extend:x}=J(()=>{jt(u,_,b),u.forEach(S=>S.style.removeProperty("animation-delay")),u.forEach(S=>{if(S?.isConnected)try{pe(S,s,o)}catch{}}),a()},p);function b(S){S.target!==S.currentTarget||!y.has(S.animationName)||x(p)}function _(S){if(S.target!==S.currentTarget||!y.has(S.animationName))return;let O=S.currentTarget;if(O.removeEventListener("animationend",_),O.removeEventListener("animationstart",b),O.isConnected)try{pe(O,s,o)}catch{}d--,d<=0&&g()}u.forEach(S=>{S.addEventListener("animationstart",b),S.addEventListener("animationend",_)})}function pe(r,t,e){if(r.classList.contains("zoom-current-view-reverse")){H(r,e);return}if(r.classList.contains("zoom-previous-view-reverse")){V(r,t.views[1].backwardState);return}r.classList.contains("zoom-last-view-reverse")&&j(r,t.views[2].backwardState)}function R(r,t,e,s){r.style.setProperty("--zoom-duration",t),r.style.setProperty("--zoom-ease",e);for(let[i,n]of Object.entries(s))r.style.setProperty(i,n)}function jt(r,t,e){for(let s of r)s?.removeEventListener&&(s.removeEventListener("animationend",t),s.removeEventListener("animationstart",e))}function ye(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,canvas:a}=r;if(!s||!i||!o){t();return}if(e==="lateral"){G(r,t);return}if(e==="zoomIn"){Z(s,i,n),k(s,o),k(i,o),n&&k(n,o),t();return}if(e==="zoomOut"){H(s,a),Z(i,n),V(i,o.views[1].backwardState),n&&j(n,o.views[2].backwardState),t();return}t()}function ge(r,t){let{type:e,currentView:s,previousView:i,lastView:n,currentStage:o,duration:a,ease:c,canvas:l}=r;if(!s||!i||!o){t();return}let f=K(a);if(e==="lateral"){Ue(r,f,c,t);return}if(e==="zoomIn"){Ye(s,i,n,o,f,c,t);return}if(e==="zoomOut"){Ke(s,i,n,o,f,c,l,t);return}t()}function Ye(r,t,e,s,i,n,o){Z(r,t,e);let a=s.views[0],c=s.views[1],l=e&&s.views[2]?s.views[2]:null;r.style.transformOrigin=a.backwardState.origin,r.style.transform=a.backwardState.transform,t.style.transformOrigin=c.backwardState.origin,t.style.transform=c.backwardState.transform,l&&(e.style.transformOrigin=l.backwardState.origin,e.style.transform=l.backwardState.transform);let f=s.stagger||0,h=[];h.push(r.animate([{transform:a.backwardState.transform},{transform:a.forwardState.transform}],{duration:i,easing:n,fill:"forwards"})),h.push(t.animate([{transform:c.backwardState.transform},{transform:c.forwardState.transform}],{duration:i,delay:f,easing:n,fill:"forwards"})),l&&h.push(e.animate([{transform:l.backwardState.transform},{transform:l.forwardState.transform}],{duration:i,delay:f*2,easing:n,fill:"forwards"}));let u=l?f*2:f,{finish:d}=J(()=>{Bt(h);try{k(r,s),k(t,s),e&&k(e,s)}catch{}o()},i+u+Q);Promise.all(h.map(v=>v.finished)).then(d).catch(d)}function Ke(r,t,e,s,i,n,o,a){let c=s.views[0],l=s.views[1],f=e&&s.views[2]?s.views[2]:null,h=l.backwardState,u=f?f.backwardState:null;r.style.transformOrigin=c.forwardState.origin,r.style.transform=c.forwardState.transform,requestAnimationFrame(()=>{requestAnimationFrame(()=>{t.style.transformOrigin=l.forwardState.origin,e&&f&&(e.style.transformOrigin=f.forwardState.origin);let d=t.style.transform||getComputedStyle(t).transform||l.forwardState.transform,v=e&&f?e.style.transform||getComputedStyle(e).transform||f.forwardState.transform:null,m=s.stagger||0,p=[];p.push(r.animate([{transform:c.forwardState.transform},{transform:c.backwardState.transform}],{duration:i,easing:n,fill:"forwards"})),p.push(t.animate([{transform:d},{transform:h.transform}],{duration:i,delay:m,easing:n,fill:"both"})),e&&u&&p.push(e.animate([{transform:v},{transform:u.transform}],{duration:i,delay:m*2,easing:n,fill:"both"})),t.style.removeProperty("transform"),e&&e.style.removeProperty("transform");let y=e&&u?m*2:m,{finish:g}=J(()=>{Bt(p);try{H(r,o),V(t,h),e&&u&&j(e,u)}catch{}a()},i+y+Q);Promise.all(p.map(x=>x.finished)).then(g).catch(g)})})}function Ue(r,t,e,s){let{currentView:i,previousView:n,backView:o,backViewState:a,lastView:c,lastViewState:l,incomingTransformStart:f,incomingTransformEnd:h,outgoingTransform:u,outgoingTransformEnd:d,currentStage:v,canvas:m}=r,p=v.views[0];Z(i),i.classList.replace("is-new-current-view","is-current-view"),i.classList.remove("zoom-current-view","has-no-events"),i.style.transformOrigin=p.forwardState.origin;let y=[];y.push(i.animate([{transform:f,opacity:0},{transform:h,opacity:1}],{duration:t,easing:e,fill:"forwards"})),r.keepAlive!=="visible"&&y.push(n.animate([{transform:u,opacity:1},{transform:d,opacity:0}],{duration:t,easing:e,fill:"forwards"})),o&&a&&y.push(o.animate([{transform:a.transformStart},{transform:a.transformEnd}],{duration:t,easing:e,fill:"forwards"})),c&&l&&y.push(c.animate([{transform:l.transformStart},{transform:l.transformEnd}],{duration:t,easing:e,fill:"forwards"}));let{finish:g}=J(()=>{Bt(y),i.style.transform=h||p.forwardState.transform,o&&a&&(o.style.transform=a.transformEnd),c&&l&&(c.style.transform=l.transformEnd),r.keepAlive?(n.style.opacity="",n.style.transform=d):H(n,m),s()},t+Q);Promise.all(y.map(x=>x.finished)).then(g).catch(g)}function Bt(r){for(let t of r)try{t.cancel()}catch{}}var be="[-+]?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?",we=`(${be})(px)?`,Ge=new RegExp(`^(?:translate\\(\\s*${we}\\s*,\\s*${we}\\s*\\)\\s*)?(?:scale\\(\\s*(${be})\\s*\\))?$`);function Qe(r){if(typeof r!="string")return null;let t=r.trim();if(t==="none")return Ot();if(!t)return null;let e=t.match(Ge);if(!e)return null;let s=Number(e[1]??0),i=Number(e[3]??0),n=Number(e[5]??1);return s!==0&&!e[2]||i!==0&&!e[4]||![s,i,n].every(Number.isFinite)?null:{a:n,b:0,c:0,d:n,e:s,f:i}}function q(r,t,e){let s=Qe(e);return s?(r.style.transformOrigin=t,r.style.transform=e,s):me(r,t,e)}function _e(r,t){let e=typeof globalThis<"u"&&globalThis.anime;if(!e||typeof e!="function"){console.warn('Zumly anime driver: Anime.js not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=K(c);s==="lateral"?G(r,t):s==="zoomIn"?Je(e,i,n,o,a,h,l,t):s==="zoomOut"?ts(e,i,n,o,a,h,l,f,t):t()}function Je(r,t,e,s,i,n,o,a){Z(t,e,s);let c=i.views[0],l=i.views[1],f=s&&i.views[2]?i.views[2]:null,h=xe([{el:t,backward:c.backwardState,forward:c.forwardState},{el:e,backward:l.backwardState,forward:l.forwardState},...f?[{el:s,backward:f.backwardState,forward:f.forwardState}]:[]],"forward");Se(h,0);let u=i.stagger||0,d=n+(f?u*2:u),v={value:0};r({targets:v,value:1,duration:d,easing:Ee(o),update:()=>{let m=v.value*d;Te(h,m,n,u)},complete:()=>{k(t,i),k(e,i),s&&k(s,i),a()}})}function ts(r,t,e,s,i,n,o,a,c){let l=i.views[0],f=i.views[1],h=s&&i.views[2]?i.views[2]:null,u=f.backwardState,d=h?h.backwardState:null,v=xe([{el:t,backward:l.backwardState,forward:l.forwardState},{el:e,backward:f.backwardState,forward:f.forwardState},...h?[{el:s,backward:h.backwardState,forward:h.forwardState}]:[]],"backward");Se(v,0);let m=i.stagger||0,p=n+(h?m*2:m),y={value:0};r({targets:y,value:1,duration:p,easing:Ee(o),update:()=>{let g=y.value*p;Te(v,g,n,m)},complete:()=>{H(t,a),V(e,u),s&&d&&j(s,d),c()}})}function xe(r,t){return r.map(({el:e,backward:s,forward:i})=>{if(t==="forward"){let n=q(e,s.origin,s.transform),o=q(e,s.origin,i.transform);return{el:e,from:n,to:o}}else{let n=q(e,i.origin,i.transform),o=q(e,i.origin,s.transform);return{el:e,from:n,to:o}}})}function Se(r,t){for(let{el:e,from:s,to:i}of r)e.style.transform=at(lt(s,i,t))}function Te(r,t,e,s){for(let i=0;i<r.length;i++){let{el:n,from:o,to:a}=r[i],c=i*s,l=Math.max(0,t-c),f=e>0?Math.min(1,l/e):1;n.style.transform=at(lt(o,a,f))}}function Ee(r){if(typeof r!="string")return"easeInOutQuad";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOutQuad":t.includes("ease-in")?"easeInQuad":t.includes("ease-out")?"easeOutQuad":t}function ke(r,t){let e=typeof globalThis<"u"&&globalThis.gsap;if(!e||typeof e.to!="function"){console.warn('Zumly GSAP driver: GSAP not loaded. Add <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=Nt(c);s==="lateral"?G(r,t):s==="zoomIn"?es(e,i,n,o,a,h,l,t):s==="zoomOut"?ss(e,i,n,o,a,h,l,f,t):t()}function es(r,t,e,s,i,n,o,a){Z(t,e,s);let c=i.views[0],l=i.views[1],f=s&&i.views[2]?i.views[2]:null;At(t,c.backwardState),At(e,l.backwardState),f&&At(s,f.backwardState);let h=r.timeline({onComplete:()=>{k(t,i),k(e,i),s&&k(s,i),a()}}),u=ze(o),d=(i.stagger||0)/1e3;h.to(t,{transform:c.forwardState.transform,duration:n,ease:u},0),h.to(e,{transform:l.forwardState.transform,duration:n,ease:u},d),f&&h.to(s,{transform:f.forwardState.transform,duration:n,ease:u},d*2)}function ss(r,t,e,s,i,n,o,a,c){let l=i.views[0],f=i.views[1],h=s&&i.views[2]?i.views[2]:null,u=f.backwardState,d=h?h.backwardState:null;At(t,l.forwardState);let v=e.style.transform||getComputedStyle(e).transform||f.forwardState.transform,m=s&&h?s.style.transform||getComputedStyle(s).transform||h.forwardState.transform:null;e.style.transformOrigin=f.forwardState.origin,s&&h&&(s.style.transformOrigin=h.forwardState.origin);let p=ze(o),y=r.timeline({onComplete:()=>{H(t,a),V(e,u),s&&d&&j(s,d),c()}}),g=(i.stagger||0)/1e3;r.set(e,{transform:v}),s&&m&&r.set(s,{transform:m}),y.fromTo(t,{transform:l.forwardState.transform},{transform:l.backwardState.transform,duration:n,ease:p},0),y.fromTo(e,{transform:v},{transform:u.transform,duration:n,ease:p},g),s&&d&&y.fromTo(s,{transform:m},{transform:d.transform,duration:n,ease:p},g*2)}function At(r,t){r.style.transformOrigin=t.origin,r.style.transform=t.transform}function ze(r){if(typeof r!="string")return"power2.inOut";let t=r.toLowerCase();return t==="linear"?"none":t.includes("ease-in-out")?"power2.inOut":t.includes("ease-in")?"power2.in":t.includes("ease-out")?"power2.out":t}function Le(r,t){let e=ns();if(!e||typeof e!="function"){console.warn('Zumly Motion driver: Motion not loaded. Add <script src="https://cdn.jsdelivr.net/npm/motion@11/dist/motion.min.js"><\/script>'),t();return}let{type:s,currentView:i,previousView:n,lastView:o,currentStage:a,duration:c,ease:l,canvas:f}=r;if(!i||!n||!a){t();return}let h=Nt(c);s==="lateral"?G(r,t):s==="zoomIn"?rs(e,i,n,o,a,h,l,t):s==="zoomOut"?is(e,i,n,o,a,h,l,f,t):t()}function rs(r,t,e,s,i,n,o,a){Z(t,e,s);let c=Ce(t,e,s,i,"forward");Oe(c,0);let l=i.stagger||0,f=l/1e3,h=n*1e3,u=n+(c.length>2?f*2:f);r(0,1,{duration:u,ease:Ae(o),onUpdate:v=>{let m=v*u*1e3;Ne(c,m,h,l)}}).then(()=>{k(t,i),k(e,i),s&&k(s,i),a()}).catch(()=>a())}function is(r,t,e,s,i,n,o,a,c){let l=i.views[1],f=s&&i.views[2]?i.views[2]:null,h=l.backwardState,u=f?f.backwardState:null,d=Ce(t,e,s,i,"backward");Oe(d,0);let v=i.stagger||0,m=v/1e3,p=n*1e3,y=n+(d.length>2?m*2:m);r(0,1,{duration:y,ease:Ae(o),onUpdate:x=>{let b=x*y*1e3;Ne(d,b,p,v)}}).then(()=>{H(t,a),V(e,h),s&&u&&j(s,u),c()}).catch(()=>c())}function Ce(r,t,e,s,i){let n=s.views[0],o=s.views[1],a=e&&s.views[2]?s.views[2]:null,c=[{el:r,backward:n.backwardState,forward:n.forwardState},{el:t,backward:o.backwardState,forward:o.forwardState}];return a&&c.push({el:e,backward:a.backwardState,forward:a.forwardState}),c.map(({el:l,backward:f,forward:h})=>i==="forward"?{el:l,from:q(l,f.origin,f.transform),to:q(l,f.origin,h.transform)}:{el:l,from:q(l,h.origin,h.transform),to:q(l,h.origin,f.transform)})}function Oe(r,t){for(let{el:e,from:s,to:i}of r)e.style.transform=at(lt(s,i,t))}function Ne(r,t,e,s){for(let i=0;i<r.length;i++){let{el:n,from:o,to:a}=r[i],c=i*s,l=Math.max(0,t-c),f=e>0?Math.min(1,l/e):1;n.style.transform=at(lt(o,a,f))}}function ns(){let r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:{};return r.motion?.animate||r.Motion?.animate||r.animate}function Ae(r){if(typeof r!="string")return"easeInOut";let t=r.toLowerCase();return t==="linear"?"linear":t.includes("ease-in-out")?"easeInOut":t.includes("ease-in")?"easeIn":t.includes("ease-out")?"easeOut":r}var Pe={css:ve,waapi:ge,none:ye,anime:_e,gsap:ke,motion:Le};function Pt(r){if(typeof r=="function")return{runTransition(s,i){r(s,i)}};let t=typeof r=="string"?r.toLowerCase():"css";return{runTransition:Pe[t]||Pe.css}}function os(r){if(typeof r!="string"||r.trim()==="")return{tx:0,ty:0,rest:""};let t=et(r);return t.matched?{tx:t.tx,ty:t.ty,rest:t.rest}:null}function Ie(r,t,e){let s=os(r);if(s===null)return r;let i=s.tx*t,n=s.ty*e,o=s.rest?` ${s.rest}`:"";return`translate(${i}px, ${n}px)${o}`.trim()}function as(r){if(typeof r!="string"||!r.trim())return null;let t=r.trim().match(/^([-\d.eE]+)px\s+([-\d.eE]+)px$/);return t?{x:parseFloat(t[1]),y:parseFloat(t[2])}:null}function $e(r,t,e){let s=as(r);return s===null?r:`${s.x*t}px ${s.y*e}px`}function Rt(r,t,e,s,i){if(!r.storedViews?.length||!r.canvas||t<=0||e<=0)return;let n=s/t,o=i/e,a=new Set,c=p=>{if(!(!p||p.detachedNode))for(let y of[p.backwardState,p.forwardState])!y||a.has(y)||(a.add(y),y.transform=Ie(y.transform,n,o),y.origin!=null&&(y.origin=$e(y.origin,n,o)))},l=[...r.storedViews];for(let p of r.lateralHistory||[])p.stage&&l.push(p.stage),c(p.entry);for(let p of l)Array.isArray(p.views)&&p.views.forEach(c);let f=r.canvas,h=f.querySelector(".is-current-view"),u=f.querySelector(".is-previous-view"),d=f.querySelector(".is-last-view"),v=f.querySelector(".is-new-current-view"),m=[h,u,d,v].filter(Boolean);for(let p of m){if(!p.style)continue;let y=p.style.transform;y!=null&&y!==""&&(p.style.transform=Ie(y,n,o));let g=p.style.transformOrigin;g!=null&&g!==""&&(p.style.transformOrigin=$e(g,n,o))}}var ls=8e3,gt=class{constructor(t){if(this.storedViews=[],this.currentStage=null,this.debug=!1,this.trace=[],this.blockEvents=!1,this._blockEventsSafetyTimer=null,this.touchstartX=0,this.touchstartY=0,this.touchendX=0,this.touchendY=0,this.touching=!1,this.lateralHistory=[],this._lastCanvasWidth=0,this._lastCanvasHeight=0,this._pendingResizeCorrection=!1,this._destroyed=!1,this._trackedTimers=new Set,this._pendingTransitionComplete=null,this._navigationTask=null,this._initPromise=null,this._accessibility=new Et,this._hooks={},this._plugins=[],re(t,this),!this.isValid){this.notify("is unable to start: invalid or missing required options (mount, initialView, views).","error");return}if(this.canvas=document.querySelector(this.mount),!this.canvas){this.notify(`mount selector "${this.mount}" did not match any element.`,"error"),this.isValid=!1;return}this.transitionDriver=Pt(this.transitionDriver),this._onZoom=this.onZoom.bind(this),this._onTouchStart=this.onTouchStart.bind(this),this._onTouchEnd=this.onTouchEnd.bind(this),this._onTouchCancel=()=>{this.touching=!1},this._onKeyUp=this.onKeyUp.bind(this),this._onKeyDown=this.onKeyDown.bind(this),this._onKeyboardClick=e=>{e.target.closest?.(".zoom-me[data-to]")&&((e.detail===0?!this.inputs.keyboard:!this.inputs.click)||(e.preventDefault(),e.detail===0&&this.onZoom(e)))},this._onWheel=this.onWheel.bind(this),this._wheelCooldown=!1,this._onPrefetchTrigger=e=>{let s=e.target.closest?.(".zoom-me[data-to]");!this._destroyed&&s&&this.canvas.contains(s)&&this.prefetcher.prefetch(s.dataset.to,{trigger:s,context:this.componentContext,props:{...s.dataset}})},this._onResize=this._handleResize.bind(this),this._resizeDebounceTimer=null,this._RESIZE_DEBOUNCE_MS=80,this.prefetcher=new zt(this.views),this._bindEvents()}_bindEvents(){let t=this.canvas;t&&(this._canvasAttributes=new Map(["tabindex","role","aria-roledescription","aria-live"].map(e=>[e,t.getAttribute(e)])),t.setAttribute("tabindex","0"),t.setAttribute("role","application"),t.setAttribute("aria-roledescription","zoomable interface"),t.setAttribute("aria-live","polite"),t.addEventListener("mouseup",this._onZoom,!1),t.addEventListener("touchend",this._onZoom,!1),t.addEventListener("touchstart",this._onTouchStart,{passive:!0}),t.addEventListener("touchend",this._onTouchEnd,!1),t.addEventListener("touchcancel",this._onTouchCancel,{passive:!0}),t.addEventListener("keyup",this._onKeyUp,!1),t.addEventListener("keydown",this._onKeyDown,!1),t.addEventListener("click",this._onKeyboardClick,!1),t.addEventListener("wheel",this._onWheel,{passive:!1}),t.addEventListener("mouseover",this._onPrefetchTrigger,{passive:!0}),t.addEventListener("focusin",this._onPrefetchTrigger,{passive:!0}),window.addEventListener("resize",this._onResize,{passive:!0}),typeof ResizeObserver<"u"&&(this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(t)))}_unbindEvents(){let t=this.canvas;t&&(t.removeEventListener("mouseup",this._onZoom,!1),t.removeEventListener("touchend",this._onZoom,!1),t.removeEventListener("touchstart",this._onTouchStart),t.removeEventListener("touchend",this._onTouchEnd,!1),t.removeEventListener("touchcancel",this._onTouchCancel),t.removeEventListener("keyup",this._onKeyUp,!1),t.removeEventListener("keydown",this._onKeyDown,!1),t.removeEventListener("click",this._onKeyboardClick,!1),t.removeEventListener("wheel",this._onWheel),t.removeEventListener("mouseover",this._onPrefetchTrigger),t.removeEventListener("focusin",this._onPrefetchTrigger)),window.removeEventListener("resize",this._onResize),this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null)}_resetCanvasScroll(t){if(t&&((t.scrollLeft!==0||t.scrollTop!==0)&&(this.notify(`canvas had a residual scroll (${t.scrollLeft}, ${t.scrollTop}) \u2014 resetting. Something scrolled the canvas mid-transition.`,"warn"),t.scrollLeft=0,t.scrollTop=0),!this._warnedScrolledAncestor)){for(let e=t.parentElement;e&&e!==document.body;e=e.parentElement)if(e.scrollLeft!==0||e.scrollTop!==0){let s=e.className?`.${String(e.className).trim().split(/\s+/).join(".")}`:e.tagName.toLowerCase();this.notify(`an ancestor of the canvas (${s}) is scrolled (${e.scrollLeft}, ${e.scrollTop}): all zooms will land displaced. Use 'overflow: clip' (not 'hidden') on containers around the canvas.`,"warn"),this._warnedScrolledAncestor=!0;break}}}_setBlockEvents(){this.blockEvents=!0,this._clearBlockEventsSafety(),this._blockEventsSafetyTimer=setTimeout(()=>{if(this.blockEvents&&!this._destroyed){this.notify("blockEvents safety timeout: driver did not call onComplete. Force-resetting.","warn"),this.blockEvents=!1;let t=this._pendingTransitionComplete;t?t():this._onTransitionComplete()}},ls)}_clearBlockEventsSafety(){this._blockEventsSafetyTimer!==null&&(clearTimeout(this._blockEventsSafetyTimer),this._blockEventsSafetyTimer=null)}_setTrackedTimeout(t,e){let s=setTimeout(()=>{this._trackedTimers.delete(s),!this._destroyed&&t()},e);return this._trackedTimers.add(s),s}_clearTrackedTimeouts(){for(let t of this._trackedTimers)clearTimeout(t);this._trackedTimers.clear()}storeViews(t){this.tracing("storedViews()"),this.storedViews.push(t),this.debug&&console.debug("Zumly storedViews",t)}tracing(t){if(this.debug)if(t==="ended"){let e=this.trace.map((s,i)=>`${i===0?`Instance ${this.mount}: ${s}`:`${s}`}`).join(" > ");this.notify(e),this.trace=[]}else this.trace.push(t)}notify(t,e){return $(this.debug,t,e)}_recordCanvasSize(){this.canvas&&(this._lastCanvasWidth=this.canvas.offsetWidth,this._lastCanvasHeight=this.canvas.offsetHeight)}_handleResize(){this._destroyed||(this._resizeDebounceTimer&&clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=setTimeout(()=>{if(this._resizeDebounceTimer=null,!this.isValid||!this.canvas||this._lastCanvasWidth===0)return;let t=this.canvas.offsetWidth,e=this.canvas.offsetHeight;if(!(t===this._lastCanvasWidth&&e===this._lastCanvasHeight)){if(this.blockEvents){this._pendingResizeCorrection=!0;return}Rt(this,this._lastCanvasWidth,this._lastCanvasHeight,t,e),this._lastCanvasWidth=t,this._lastCanvasHeight=e}},this._RESIZE_DEBOUNCE_MS))}_onTransitionComplete(){if(this._clearBlockEventsSafety(),this._pendingResizeCorrection&&!this.blockEvents){if(this._pendingResizeCorrection=!1,this.canvas&&this._lastCanvasWidth>0){let e=this.canvas.offsetWidth,s=this.canvas.offsetHeight;(e!==this._lastCanvasWidth||s!==this._lastCanvasHeight)&&Rt(this,this._lastCanvasWidth,this._lastCanvasHeight,e,s),this._lastCanvasWidth=e,this._lastCanvasHeight=s}}else this._recordCanvasSize();for(let e of this.canvas?.children||[])e.classList.contains("z-view")&&vt(e);let t=this.canvas?.querySelector(".is-current-view");t&&this._accessibility.restore(t),this._manageFocus(),this.canvas&&this._accessibility.sync(this.canvas)}_manageFocus(){if(!this.canvas)return;let t=this.canvas.querySelector(".is-current-view");if(!t)return;let e='a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',s=n=>!n||n.closest("[inert], [hidden]")?!1:(n.focus({preventScroll:!0}),document.activeElement===n||n.contains(document.activeElement)),i=t.querySelector(e);if(!s(i)){for(let n of t.querySelectorAll(e))if(n!==i&&s(n))return;t.setAttribute("tabindex","-1"),t.focus({preventScroll:!0})}}_prefersReducedMotion(){return typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}_resolveEffects(t){if(this._prefersReducedMotion())return["none","none"];let e=t?.dataset?.withEffects;if(e&&typeof e=="string"){let s=e.split("|").map(i=>i.trim());return[s[0]||"none",s[1]||s[0]||"none"]}return this.effects}_applyEffects(t,e,s,i,n){!s||s[0]==="none"&&s[1]==="none"||(t&&s[0]!=="none"&&(t.style.setProperty("--z-effect-filter",s[0]),t.style.setProperty("--zoom-duration",i),t.style.setProperty("--zoom-ease",n),t.classList.add("has-effect")),e&&s[1]!=="none"&&(e.style.setProperty("--z-effect-filter",s[1]),e.style.setProperty("--zoom-duration",i),e.style.setProperty("--zoom-ease",n),e.classList.add("has-effect")))}_removeEffect(t){if(!t||!t.classList.contains("has-effect"))return;t.classList.remove("has-effect"),t.classList.add("has-effect-reverse");let e=()=>{t.classList.remove("has-effect-reverse"),t.style.removeProperty("--z-effect-filter"),t.removeEventListener("transitionend",e)};t.addEventListener("transitionend",e,{once:!0});let s=t.style.getPropertyValue("--zoom-duration");this._setTrackedTimeout(e,s?parseFloat(s)*(s.includes("ms")?1:1e3)+100:1100)}_resolveHideTrigger(t){return t?.dataset?.hideTrigger!==void 0?t.dataset.hideTrigger==="fade"?"fade":!0:this.hideTrigger}_applyHideTrigger(t,e,s,i,n,o=!0){if(!(!s||!t))if(s==="fade"){if(t.style.setProperty("--zoom-duration",i),t.style.setProperty("--zoom-ease",n),t.classList.add("z-trigger-fade"),!o)return;e.style.setProperty("--zoom-duration",i),e.style.setProperty("--zoom-ease",n),e.classList.add("z-view-fade-in"),e.offsetHeight,e.classList.remove("hide")}else t.classList.add("z-trigger-hidden")}_restoreHideTrigger(t,e,s,i){if(!(!e||!t))if(e==="fade"){t.classList.remove("z-trigger-fade"),t.style.setProperty("--zoom-duration",s),t.style.setProperty("--zoom-ease",i),t.classList.add("z-trigger-fade-reverse");let n=()=>{t.classList.remove("z-trigger-fade-reverse"),t.style.removeProperty("--zoom-duration"),t.style.removeProperty("--zoom-ease"),t.removeEventListener("transitionend",n)};t.addEventListener("transitionend",n,{once:!0}),this._setTrackedTimeout(n,parseFloat(s)*(s.includes("ms")?1:1e3)+100)}else t.classList.remove("z-trigger-hidden")}on(t,e){return typeof e!="function"?this:((this._hooks[t]||=[]).push(e),this)}use(t,e){if(!t)return this;let s={plugin:t,options:e};return this._plugins.push(s),this._initialized&&this._installPlugin(s),this}_installPlugin(t){let{plugin:e,options:s}=t;try{typeof e=="function"?e(this,s):typeof e.install=="function"&&e.install(this,s)}catch(i){this.notify(`plugin install error: ${i.message}`,"error")}}off(t,e){return e?this._hooks[t]&&(this._hooks[t]=this._hooks[t].filter(s=>s!==e)):delete this._hooks[t],this}_emit(t,e={}){let s=this._hooks[t];if(!(!s||s.length===0))for(let i of s)try{i(e)}catch(n){this.debug&&console.error(`Zumly hook "${t}" threw:`,n)}}_runNavigation(t){if(this._destroyed||this.blockEvents)return Promise.resolve();let e={pendingViews:new Set};e.promise=new Promise(i=>{e.resolve=i}),this._navigationTask=e,this.blockEvents=!0,this.prefetcher?.pause();let s=()=>{this._navigationTask===e&&(this._navigationTask=null,this.blockEvents=!1,this._clearBlockEventsSafety(),this.prefetcher?.resume()),e.resolve()};try{Promise.resolve(t()).then(s,i=>{this.notify(`navigation aborted: ${i.message}`,"error"),s()})}catch(i){this.notify(`navigation aborted: ${i.message}`,"error"),s()}return e.promise}_cancelNavigation(){let t=this._navigationTask;if(this._navigationTask=null,this._pendingTransitionComplete=null,this._clearBlockEventsSafety(),this.blockEvents=!1,t){for(let e of t.pendingViews)C(e);t.pendingViews.clear(),t.releaseTransition?.(),t.resolve()}}_createViewContext(t={},e){let s={target:document.createElement("div"),context:this.componentContext,props:t};return e&&(s.trigger=e),this._navigationTask?.pendingViews.add(s.target),s}_runNavigationTransition(t,e){if(this._destroyed)return Promise.resolve();let s=this._navigationTask;return new Promise(i=>{s&&(s.releaseTransition=i);let n=()=>{if(this._pendingTransitionComplete===n){if(this._pendingTransitionComplete=null,this._destroyed){i();return}try{Promise.resolve(e()).then(i,l=>{this.notify(`transition completion failed: ${l.message}`,"error"),i()})}catch(l){this.notify(`transition completion failed: ${l.message}`,"error"),i()}}};this._setBlockEvents(),this._pendingTransitionComplete=n;let o=this._prefersReducedMotion?.(),a=o?Pt("none"):this.transitionDriver,c=o?{...t,duration:"0s",currentStage:{...t.currentStage,stagger:0}}:t;try{a.runTransition(c,n)}catch(l){this.notify(`transition driver failed: ${l.message}. Finishing without animation.`,"error");try{Pt("none").runTransition(c,n)}catch{n()}}})}zoomLevel(){return this.storedViews.length}getZoomLevel(){return this.zoomLevel()}getCurrentViewName(){return!this.storedViews||this.storedViews.length===0?null:this.storedViews[this.storedViews.length-1]?.views?.[0]?.viewName??null}async back(){if(!this._destroyed){if(this.blockEvents){this.notify("back ignored: a transition is already running.","warn");return}if(this.lateralHistory&&this.lateralHistory.length>0){let t=this.lateralHistory.pop(),e=t&&typeof t=="object"?t.name:t,s=t&&typeof t=="object"?t.entry:void 0,i=t&&typeof t=="object"?t.node:void 0;return this._doLateral(e,!0,{savedEntry:s,keepAliveNode:i,savedStage:t?.stage})}return this.zoomOut()}}async goTo(t,e={}){return this._destroyed?void 0:(e.mode==="lateral"?"lateral":"depth")==="depth"?this.zoomTo(t,e):this._doLateral(t,!1,e)}async zoomTo(t,e={}){if(this._destroyed)return;if(!this.isValid||!this.canvas){this.notify("zoomTo() cannot run: instance is invalid or canvas not found.","error");return}if(typeof t!="string"||!t){this.notify("zoomTo() requires a non-empty view name.","warn");return}if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`zoomTo("${t}"): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}if(this.getCurrentViewName()===t)return;let i=this.canvas.getBoundingClientRect(),n=Math.max(40,i.width*.1),o=Math.max(40,i.height*.1),c={rect:{x:i.left+(i.width-n)/2,y:i.top+(i.height-o)/2,width:n,height:o},duration:e.duration??this.duration,ease:e.ease??this.ease,props:e.props??{}};await this._doZoomIn(t,c)}init(){return this._destroyed||this._initialized?Promise.resolve():this._initPromise?this._initPromise:!this.isValid||!this.canvas?(this.notify("init() cannot run: instance is invalid or canvas element was not found.","error"),Promise.resolve()):(this._initPromise=this._runNavigation(()=>this._initialize()).finally(()=>{this._initPromise=null}),this._initPromise)}async _initialize(){this.tracing("init()");let t=this.prefetcher,e=this._createViewContext();if(this.preload&&this.preload.length&&(await t.preloadEager(this.preload,null).catch(i=>{this.notify(`preload failed: ${i.message}`,"warn")}),this._destroyed))return;let s;try{let i=await t.get(this.initialView,e);if(this._destroyed){C(i);return}if(s=await ut(i,this.initialView,this.canvas,!0,this.views,this.componentContext),this._destroyed){C(s),s.remove();return}}catch(i){this.notify(`init() failed to resolve initial view "${this.initialView}": ${i.message}`,"error");return}if(this._emit("viewMounted",{viewName:this.initialView,node:s}),!this._destroyed){t.scanAndPrefetch(s,e),this.storeViews({zoomLevel:this.storedViews.length,scale:1,views:[{viewName:this.initialView,backwardState:{origin:"0 0",transform:""}}]}),this.currentStage=this.storedViews[this.storedViews.length-1],this._recordCanvasSize(),this._accessibility.sync(this.canvas),this._initialized=!0;for(let i of this._plugins)this._installPlugin(i)}}destroy(){if(!this._destroyed){this._destroyed=!0,this._emit("destroy"),this._cancelNavigation(),this._clearBlockEventsSafety(),this._clearTrackedTimeouts(),this._pendingTransitionComplete=null,this._resizeDebounceTimer&&(clearTimeout(this._resizeDebounceTimer),this._resizeDebounceTimer=null),this._unbindEvents(),this._removeNav(),this._cleanupLateralKeepAlive(),this._accessibility.destroy(),this.canvas&&C(this.canvas);for(let t of this.storedViews){let e=Ft(t);e&&C(e)}if(this.blockEvents=!1,this.storedViews=[],this.currentStage=null,this.lateralHistory=[],this.trace=[],this._hooks={},this.prefetcher?.destroy(),this.prefetcher=null,this.transitionDriver=null,this.canvas)for(let[t,e]of this._canvasAttributes||[])e===null?this.canvas.removeAttribute(t):this.canvas.setAttribute(t,e);this.isValid=!1}}async _doZoomIn(t,e){return this._runNavigation(()=>this._performZoomIn(t,e))}async _performZoomIn(t,e){if(this._emit("beforeZoomIn",{viewName:t}),this._destroyed)return;this.tracing("zoomIn()");let s=this.canvas,i=e.el;this._resetCanvasScroll(s);let o=(this.storedViews.length>0?this.storedViews[this.storedViews.length-1]:null)?.scale??1;this.tracing("getView()");let a=this._createViewContext(i?{...i.dataset}:e.props??{},i),c=i?.dataset?.deferred!==void 0?!0:this.deferred,l,f=null,h=()=>{C(f),C(l),l?.remove()};try{if(c){let w=await this.prefetcher.get(t,a);if(this._destroyed){C(w);return}for(f=document.createDocumentFragment();w.firstChild;)f.appendChild(w.firstChild);l=await ut(w,t,s,!1,{},this.componentContext)}else{let w=await this.prefetcher.get(t,a);if(this._destroyed){C(w);return}this.prefetcher.scanAndPrefetch(w,a),l=await ut(w,t,s,!1,this.views,this.componentContext)}}catch(w){h(),this.notify(`zoomIn aborted: failed to resolve view "${t}": ${w.message}`,"error");return}if(!l){h();return}if(this._destroyed){h();return}if(c||this._emit("viewMounted",{viewName:t,node:l}),this._destroyed)return;i&&i.classList.add("zoomed");let u=s.getBoundingClientRect(),d=u.left,v=u.top,m=i?(()=>{let w=i.getBoundingClientRect();return{x:w.x,y:w.y,width:w.width,height:w.height}})():e.rect,p=i?i.dataset.withDuration||this.duration:e.duration??this.duration,y=i?i.dataset.withEase||this.ease:e.ease??this.ease,g=i?i.dataset.withCover||this.cover:e.cover??this.cover,x=i?parseInt(i.dataset.withStagger,10)||this.stagger:e.stagger??this.stagger,b=s.querySelector(".is-current-view"),_=s.querySelector(".is-previous-view"),S=s.querySelector(".is-last-view");if(!b){this.notify("zoomIn aborted: no current view found in canvas. Call init() before navigating and keep Zumly view classes intact.","error"),i&&i.classList.remove("zoomed"),h();return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],Ct(l),S&&(Ct(S),s.removeChild(S));let O,A,E,T,P,B,z,D=b.style.transform,N=b.style.transformOrigin,I=_?_.style.transform:null,F=_?_.style.transformOrigin:null;try{b.classList.replace("is-current-view","is-previous-view"),_&&_.classList.replace("is-previous-view","is-last-view");let w=l.getBoundingClientRect(),L=b.getBoundingClientRect(),X=null,Wt=null,bt=null;_&&(X=_.getBoundingClientRect(),bt=_.querySelector(".zoomed"),Wt=bt&&bt.getBoundingClientRect?bt.getBoundingClientRect():X);let _t={left:d,top:v},Xt={width:u.width,height:u.height},Yt={width:w.width,height:w.height},Kt=St(m.width,m.height,w.width,w.height,g);z=Kt.scale;let Me=Kt.scaleInv;O=Dt(m,_t,Yt,Me),E=b.style.transform;let Ut=ne(m,L);T=oe(Xt,m,L,z,this.parallax);let Gt=nt(N||"0 0"),st=Y(E||""),Qt=nt(Ut),rt=Y(T.transform),Jt=m;if(i&&(Jt=dt(m,L,Gt,st.tx,st.ty,st.scale,Qt,rt.tx,rt.ty,rt.scale)),A=ie(Jt,_t,Yt),_){P=_.style.transform;let He=dt(L,L,Gt,st.tx,st.ty,st.scale,Qt,rt.tx,rt.ty,rt.scale),De=le(T.x,T.y,_t,z,o),te=nt(F||"0 0"),Mt=Y(P||""),Ht=Y(De),Fe=dt(Wt,X,te,Mt.tx,Mt.ty,Mt.scale,te,Ht.tx,Ht.ty,Ht.scale);B=ae({canvasRect:Xt,canvasOffset:_t,triggerRect:m,previousViewRectAtBaseTransform:L,lastViewZoomedElementRect:Fe,previousViewRectWithPreviousAtEndTransform:He,scale:z,preScale:o,parallax:this.parallax})}l.style.transform=O,b.style.transformOrigin=Ut}catch(w){this.notify(`zoomIn geometry computation failed: ${w.message}. Aborting zoom.`,"error"),this.debug&&console.error("Zumly _doZoomIn error:",w),b.style.transform=D,b.style.transformOrigin=N,b.classList.contains("is-previous-view")&&b.classList.replace("is-previous-view","is-current-view"),_&&(_.style.transform=I,_.style.transformOrigin=F,_.classList.contains("is-last-view")&&_.classList.replace("is-last-view","is-previous-view")),h(),S&&s.prepend(S),i&&i.classList.remove("zoomed"),vt(b),vt(_),vt(S);return}let M=mt(l.dataset.viewName,{origin:l.style.transformOrigin,duration:p,ease:y,transform:O},{origin:l.style.transformOrigin,duration:p,ease:y,transform:A}),wt=mt(b.dataset.viewName,{origin:b.style.transformOrigin,duration:p,ease:y,transform:E},{origin:b.style.transformOrigin,duration:p,ease:y,transform:T.transform}),ft=_?mt(_.dataset.viewName,{origin:_.style.transformOrigin,duration:p,ease:y,transform:P},{origin:_.style.transformOrigin,duration:p,ease:y,transform:B}):null,U=S?ce(S):null,W=fe(this.storedViews.length,M,wt,ft,U);W.scale=z,W.stagger=x||0,this.storeViews(W),this.currentStage=this.storedViews[this.storedViews.length-1],this.tracing("setCSSVariables()");let It=this._resolveEffects(i);this._applyEffects(b,_,It,p,y);let ht=this._resolveHideTrigger(i);this._applyHideTrigger(i,l,ht,p,y),ht&&(W.hideTriggerMode=ht);let $t={type:"zoomIn",currentView:l,previousView:b,lastView:_,currentStage:this.currentStage,duration:p,ease:y},Zt=async()=>{if(c&&f&&l){if(l.appendChild(f),this.prefetcher.scanAndPrefetch(l,a),typeof this.views[t]=="object"&&typeof this.views[t].mounted=="function")try{await this.views[t].mounted()}catch(w){this.notify(`deferred view mounted() failed: ${w.message}`,"error")}if(this._destroyed)return;this._emit("viewMounted",{viewName:t,node:l})}this._destroyed||(this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterZoomIn",{viewName:t,zoomLevel:this.zoomLevel()}),this.tracing("ended"))};await this._runNavigationTransition($t,Zt),this._destroyed&&f&&C(f)}async zoomIn(t){this._destroyed||t?.dataset?.to&&await this._doZoomIn(t.dataset.to,{el:t})}async _doLateral(t,e=!1,s={}){return this._runNavigation(()=>this._performLateral(t,e,s))}async _performLateral(t,e=!1,s={}){if(!this.isValid||!this.canvas)return;if(!Object.prototype.hasOwnProperty.call(this.views,t)){this.notify(`goTo("${t}", { mode: 'lateral' }): view not found in views. Available: ${Object.keys(this.views).join(", ")}`,"warn");return}let i=this.canvas.querySelector(".is-current-view");if(!i)return;let n=i.dataset?.viewName;if(n===t||(this._emit("beforeLateral",{viewName:t,from:n,isBack:e}),this._destroyed))return;let o=this.lateralNav&&this.lateralNav.keepAlive,a=null;if(!e){this.lateralHistory=this.lateralHistory||[];let w=this.storedViews[this.storedViews.length-1];a={name:n,stage:this._copyLateralStage(w),node:o?i:null},a.entry=a.stage.views[0]}this.tracing("lateral()");let c=s.duration??this.duration,l=s.ease??this.ease,f=this.canvas.querySelector(".is-previous-view"),h=this.canvas.querySelector(".is-last-view"),u=null,d=null;if(o&&(e&&s.keepAliveNode?d=s.keepAliveNode:d=this.canvas.querySelector(`.is-lateral-hidden[data-view-name="${t}"]`)),d){if(d.style.display="",d.style.opacity="",d.classList.remove("is-lateral-hidden","zoom-lateral-out"),d.classList.add("is-new-current-view","has-no-events"),u=d,!e&&this.lateralHistory){let w=this.lateralHistory.findIndex(L=>L.node===d);w!==-1&&this.lateralHistory.splice(w,1)}}else{let w=()=>{e&&this.lateralHistory.push({name:t,entry:s.savedEntry,stage:s.savedStage,node:s.keepAliveNode??null})},L=this._createViewContext(s.props??{});try{let X=await this.prefetcher.get(t,L);if(this._destroyed){C(X);return}this.prefetcher.scanAndPrefetch(X,L),u=await ut(X,t,this.canvas,!1,this.views,this.componentContext)}catch(X){this.notify(`lateral navigation aborted: failed to resolve view "${t}": ${X.message}`,"error"),w();return}if(!u){w();return}if(this._destroyed){C(u),u.remove();return}if(this._emit("viewMounted",{viewName:t,node:u}),this._destroyed)return}let v=i.style.transform||"",m=this.storedViews[this.storedViews.length-1];u.style.transform="",u.style.transformOrigin="0 0";let p=new Map,y=w=>(p.has(w)||p.set(w,w.getBoundingClientRect()),p.get(w)),g=y(u),x=y(i),b=y(this.canvas),_=b.width/this.canvas.offsetWidth||1,S=b.height/this.canvas.offsetHeight||1,O=f?f.querySelectorAll(".zoom-me[data-to]"):[],A,E;for(let w of O)if(!A&&w.dataset.to===n&&(A=w),!E&&w.dataset.to===t&&(E=w),A&&E)break;let T=0,P=0,B=this._declaredSiblings(),z=B?B.indexOf(n):-1,D=B?B.indexOf(t):-1;if(z!==-1&&D!==-1)T=(z-D)*b.width*.15;else if(f)if(A&&E){let w=y(A),L=y(E);T=w.left+w.width/2-(L.left+L.width/2),P=w.top+w.height/2-(L.top+L.height/2)}else T=b.width*.15;let N=f?{transformStart:f.style.transform||"",transformEnd:this._computeLateralBackTransform(f.style.transform||"",T,P)}:null,I=h&&m.views[2]?{transformStart:h.style.transform||"",transformEnd:this._computeLateralBackTransform(h.style.transform||"",T*.7,P*.7)}:null,F=m.views[0],M=this._computeLateralBackTransform("",(x.x-g.x+(x.width-g.width)/2)/_,(x.y-g.y+(x.height-g.height)/2)/S),wt=Y(F.backwardState.transform||"").scale,ft=this._computeLateralBackTransform(F.backwardState.transform||"",(x.width-g.width)*wt/(2*_),(x.height-g.height)*wt/(2*S)),U=f?.querySelector(".zoomed");if(E&&N&&!(e&&s.savedStage)){let w=this._lateralTargetGeometry(u,E,f,h,m,{measure:y,outgoingView:i,canvasRect:b,sx:_,sy:S});w&&(M=w.currentEnd,ft=w.currentBack,N.transformEnd=w.previousEnd,I&&w.lastEnd&&(I.transformEnd=w.lastEnd),m.scale=w.scale)}if(e&&s.savedStage){Object.assign(m,this._copyLateralStage(s.savedStage)),M=m.views[0].forwardState?.transform||"",ft=m.views[0].backwardState.transform,N&&(N.transformEnd=m.views[1].forwardState.transform),I&&(I.transformEnd=m.views[2].forwardState.transform);let w=et(N?.transformStart||v),L=et(N?.transformEnd||M);T=L.tx-w.tx,P=L.ty-w.ty}else m.views[0]=mt(t,{origin:"0 0",duration:c,ease:l,transform:ft},{origin:"0 0",duration:c,ease:l,transform:M});this.currentStage=m,a&&this.lateralHistory.push(a),U?.classList.remove("zoomed");let W=E?this._resolveHideTrigger(E):!1;m.hideTriggerMode=W,E&&(E.classList.add("zoomed"),this._applyHideTrigger(E,u,W,c,l,!1),W&&E.classList.add("z-trigger-hidden")),Ct(u),N&&m.views[1]&&(m.views[1].forwardState={...m.views[1].forwardState,transform:N.transformEnd}),I&&m.views[2]&&(m.views[2].forwardState={...m.views[2].forwardState,transform:I.transformEnd});let It=this._computeLateralBackTransform(M,-T,-P),ht=this._computeLateralBackTransform(v,T,P),$t={type:"lateral",currentView:u,previousView:i,lastView:h||null,backView:f||null,backViewState:N,lastViewState:I,incomingTransformStart:It,incomingTransformEnd:M,outgoingTransform:v,outgoingTransformEnd:ht,currentStage:this.currentStage,duration:c,ease:l,canvas:this.canvas,slideDeltaX:T,slideDeltaY:P,keepAlive:o&&!e?o:!1},Zt=()=>{U&&U!==E&&(U.classList.remove("z-trigger-hidden","z-trigger-fade","z-trigger-fade-reverse"),U.style.removeProperty("--zoom-duration"),U.style.removeProperty("--zoom-ease")),W==="fade"&&E.classList.remove("z-trigger-hidden"),o&&!e&&(i.classList.remove("is-current-view","is-new-current-view","has-no-events"),i.classList.add("is-lateral-hidden"),o!=="visible"?i.style.display="none":(i.style.transform=v,i.style.opacity="")),this.blockEvents=!1,this._onTransitionComplete(),this._updateNav(),this._emit("afterLateral",{viewName:t,from:n,isBack:e}),this.tracing("ended")};return this._runNavigationTransition($t,Zt)}_copyLateralStage(t){return{...t,views:t.views.map(e=>({...e,...e.backwardState&&{backwardState:{...e.backwardState}},...(e.forwardState||e.backwardState)&&{forwardState:{...e.forwardState||e.backwardState}}}))}}_lateralTargetGeometry(t,e,s,i,n,o){let{measure:a,outgoingView:c,canvasRect:l,sx:f,sy:h}=o,u=z=>{let D=a(z);return{x:(D.x-l.x)/f,y:(D.y-l.y)/h,width:D.width/f,height:D.height/h}},d=u(t),v=u(c),m=u(s),p=u(e);if(!d.width||!d.height||!p.width||!p.height)return null;let y=Y(s.style.transform||""),g=nt(s.style.transformOrigin||"0 0"),x=e.dataset.withCover||this.cover,b=St(p.width,p.height,d.width,d.height,x).scale,_=y.scale*b,S=(z,D,N,I,F,M)=>dt(z,D,N,I.tx,I.ty,I.scale,F,M.tx,M.ty,M.scale),O=S(p,m,g,y,g,{...y,scale:_}),A={tx:y.tx+v.x+v.width/2-O.x-O.width/2,ty:y.ty+v.y+v.height/2-O.y-O.height/2,scale:_},E=z=>`translate(${z.tx}px, ${z.ty}px) scale(${z.scale})`,T=S(p,m,g,y,{x:0,y:0},Y(n.views[1].backwardState.transform||"")),P=St(T.width,T.height,d.width,d.height,x).scaleInv,B={currentEnd:`translate(${v.x-d.x+(v.width-d.width)/2}px, ${v.y-d.y+(v.height-d.height)/2}px)`,currentBack:Dt(T,{left:d.x,top:d.y},d,P),previousEnd:E(A),scale:_};if(i&&n.views[2]){let z=u(i),D=nt(i.style.transformOrigin||"0 0"),N=Y(i.style.transform||""),I=S(m,m,g,y,g,A),F={...N,scale:N.scale*b},M=S(z,z,D,N,D,F);F.tx+=I.x+b*(z.x-m.x)-M.x,F.ty+=I.y+b*(z.y-m.y)-M.y,B.lastEnd=E(F)}return B}_computeLateralBackTransform(t,e,s){let i=et(t);return i.matched?`translate(${i.tx+e}px, ${i.ty+s}px) ${i.rest}`.trim():`translate(${e}px, ${s}px) ${t}`.trim()}zoomOut(){return this._runNavigation(()=>this._performZoomOut())}_performZoomOut(){if(this._emit("beforeZoomOut",{zoomLevel:this.zoomLevel()}),this._destroyed)return;this.tracing("zoomOut()");let t=this.canvas;this._resetCanvasScroll(t);let e=t.querySelector(".is-current-view"),s=t.querySelector(".is-previous-view");if(!e||!s){this.notify("zoomOut: current or previous view not found (animation may still be running)","warn");return}this._cleanupLateralKeepAlive(),this.lateralHistory=[],this.currentStage=this.storedViews[this.storedViews.length-1];let i=t.querySelector(".is-last-view");this.tracing("setCSSVariables()");let n=this.currentStage.views[0]?.forwardState?.duration??this.duration,o=this.currentStage.views[0]?.forwardState?.ease??this.ease,a=s.querySelector(".zoomed");a&&a.classList.remove("zoomed");let c=this.currentStage.hideTriggerMode;c&&a&&this._restoreHideTrigger(a,c,n,o),c==="fade"?(e.classList.remove("z-view-fade-in"),e.style.setProperty("--zoom-duration",n),e.style.setProperty("--zoom-ease",o),e.classList.add("z-view-fade-out")):(e.classList.remove("z-view-fade-in"),e.style.removeProperty("opacity")),this._removeEffect(s),s.classList.replace("is-previous-view","is-current-view"),i!==null&&(i.classList.contains("has-effect")&&this.effects[0]!=="none"&&i.style.setProperty("--z-effect-filter",this.effects[0]),i.classList.replace("is-last-view","is-previous-view"),i.classList.remove("hide"),pt(i));let l=Ft(this.currentStage);if(l){t.prepend(l);let u=t.querySelector(".z-view:first-child");u&&(pt(u),u.classList.add("hide"))}let f={type:"zoomOut",currentView:e,previousView:s,lastView:i,currentStage:this.currentStage,duration:n,ease:o,canvas:t},h=()=>{this.blockEvents=!1,this._onTransitionComplete(),this.storedViews.pop(),this._updateNav(),this._emit("afterZoomOut",{zoomLevel:this.zoomLevel()}),this.tracing("ended")};return this._runNavigationTransition(f,h)}onZoom(t){if(this._destroyed||t.type==="mouseup"&&t.button!==0||t.type==="click"&&!this.inputs.keyboard||t.type==="mouseup"&&!this.inputs.click||t.type==="touchend"&&!this.inputs.touch)return;let e=t.target;if(e.closest?.("[inert]")||e.closest(".z-depth-nav")||e.closest(".z-lateral-nav"))return;let s=e.classList.contains("zoom-me")||e.closest(".zoom-me");if(!this.blockEvents&&s&&!this.touching){this.tracing("onZoom() \u2192 zoomIn"),t.preventDefault(),t.stopPropagation();let i=e.classList.contains("zoom-me")?e:e.closest(".zoom-me");this.zoomIn(i);return}if(this.storedViews.length>1&&!this.blockEvents&&!s&&!this.touching){let i=this.canvas.querySelector(".is-current-view");if(i&&i.contains(e))return;let n=this._findSiblingTriggerAtPoint(t.clientX,t.clientY);if(n){this.tracing("onZoom() \u2192 lateral"),t.stopPropagation(),this._doLateral(n.dataset.to);return}this.tracing("onZoom() \u2192 zoomOut"),t.stopPropagation(),this.zoomOut()}}_findSiblingTriggerAtPoint(t,e){let s=this.canvas.querySelector(".is-previous-view");if(!s)return null;let n=this.canvas.querySelector(".is-current-view")?.dataset?.viewName;if(!n)return null;let o=s.querySelectorAll(".zoom-me[data-to]");for(let a of o){if(a.dataset.to===n)continue;let c=a.getBoundingClientRect();if(t>=c.left&&t<=c.right&&e>=c.top&&e<=c.bottom)return a}return null}_getSiblings(){let e=this.canvas.querySelector(".is-current-view")?.dataset?.viewName,s=this._declaredSiblings();if(s&&s.indexOf(e)!==-1)return{siblings:s,currentIndex:s.indexOf(e)};let i=this.canvas.querySelector(".is-previous-view");if(!i)return{siblings:[],currentIndex:-1};let n=i.querySelectorAll(".zoom-me[data-to]"),o=[];for(let c of n)c.dataset.to&&o.push(c.dataset.to);let a=o.indexOf(e);return{siblings:o,currentIndex:a}}_declaredSiblings(){let t=this.lateralNav&&typeof this.lateralNav=="object"?this.lateralNav.siblings:null;if(!t)return null;if(Array.isArray(t))return t;let e=this.canvas.querySelector(".is-previous-view")?.dataset?.viewName;return e&&Array.isArray(t[e])?t[e]:null}_updateNav(){if(this._destroyed)return;let t=this.storedViews.length-1,e=this.canvas.querySelector(":scope > .z-view.is-current-view"),s=!!this.depthNav&&t>=1&&!e?.querySelector(".z-depth-nav"),i=this.lateralNav?this._getSiblings():null;i?.siblings.length<2&&(i=null),i&&this.lateralNav.mode==="auto"&&t>=1&&e&&e.offsetWidth>=this.canvas.offsetWidth&&e.offsetHeight>=this.canvas.offsetHeight&&(i=null),this._updateDepthNav(s),this._updateLateralNav(i)}_updateDepthNav(t){if(t===void 0){let n=this.canvas.querySelector(":scope > .z-view.is-current-view");t=!!this.depthNav&&this.storedViews.length>1&&!n?.querySelector(".z-depth-nav")}if(!t){this._depthNavElement?.remove();return}let e=this.depthNav.position||"bottom-left",s=this._depthNavElement;if(!s){s=document.createElement("div");let n=document.createElement("button");n.className="z-nav-back",n.setAttribute("aria-label","Zoom out (go back)"),n.innerHTML="‹",n.type="button",n.addEventListener("click",o=>{o.stopPropagation(),!this._destroyed&&s.parentNode===this.canvas&&!this.blockEvents&&this.storedViews.length>1&&this.zoomOut()}),s.appendChild(n),this._depthNavElement=s}let i="z-depth-nav z-depth-nav--"+e;s.className!==i&&(s.className=i),s.parentNode!==this.canvas&&this.canvas.appendChild(s)}_updateLateralNav(t){if(t===void 0&&(t=this.lateralNav?this._getSiblings():null,t?.siblings.length<2&&(t=null),t&&this.lateralNav.mode==="auto"&&this.storedViews.length>1)){let l=this.canvas.querySelector(":scope > .z-view.is-current-view");l&&l.offsetWidth>=this.canvas.offsetWidth&&l.offsetHeight>=this.canvas.offsetHeight&&(t=null)}if(!t){this._lateralNavState?.element.remove();return}let{siblings:e,currentIndex:s}=t,i=this.lateralNav.position||"bottom-center",n=!!this.lateralNav.arrows,o=!!this.lateralNav.dots,a=this._lateralNavState;if(!a||a.arrows!==n||a.dots!==o||a.siblings.length!==e.length||a.siblings.some((l,f)=>l!==e[f])){a?.element.remove();let l=document.createElement("div");a={element:l,siblings:[...e],currentIndex:-1,arrows:n,dots:o,dotButtons:[]};let f=(h,u,d)=>{let v=document.createElement("button");return v.className="z-nav-arrow z-nav-"+h,v.setAttribute("aria-label",u),v.innerHTML=d,v.type="button",v};if(n&&(a.prevButton=f("prev","Previous sibling view","‹"),l.appendChild(a.prevButton)),o){let h=document.createElement("div");h.className="z-nav-lateral-dots";for(let u of e){let d=document.createElement("button");d.className="z-nav-dot z-nav-lat-dot",d.setAttribute("aria-label",`Go to ${u}`),d.dataset.to=u,d.type="button",a.dotButtons.push(d),h.appendChild(d)}l.appendChild(h)}n&&(a.nextButton=f("next","Next sibling view","›"),l.appendChild(a.nextButton)),l.addEventListener("click",h=>{let u=h.target.closest?.("button");if(!u||!l.contains(u))return;h.stopPropagation();let d=this._lateralNavState;if(this._destroyed||this.blockEvents||d?.element!==l||l.parentNode!==this.canvas)return;let v=u===d.prevButton?d.currentIndex-1:u===d.nextButton?d.currentIndex+1:d.dotButtons.indexOf(u);v>=0&&v<d.siblings.length&&v!==d.currentIndex&&this._doLateral(d.siblings[v])}),this._lateralNavState=a}if(a.currentIndex!==s){let l=a.dotButtons[a.currentIndex];l?.classList.remove("is-active"),l?.removeAttribute("aria-current");let f=a.dotButtons[s];f?.classList.add("is-active"),f?.setAttribute("aria-current","true"),a.currentIndex=s}a.prevButton&&a.prevButton.disabled!==s<=0&&(a.prevButton.disabled=s<=0),a.nextButton&&a.nextButton.disabled!==s>=e.length-1&&(a.nextButton.disabled=s>=e.length-1);let c="z-lateral-nav z-lateral-nav--"+i;a.element.className!==c&&(a.element.className=c),a.element.parentNode!==this.canvas&&this.canvas.appendChild(a.element)}_removeNav(){this._depthNavElement?.remove(),this._lateralNavState?.element.remove(),this._depthNavElement=null,this._lateralNavState=null}_cleanupLateralKeepAlive(){if(!this.canvas)return;let t=this.canvas.querySelectorAll(".is-lateral-hidden");for(let e of t)this._accessibility.restore(e),C(e),e.remove()}onKeyDown(t){if(this._destroyed||!this.inputs.keyboard||t.defaultPrevented||Vt(t.target))return;let e=t.target.closest?.(".zoom-me[data-to]");!e||kt(e)||e.closest("[inert]")||(t.key===" "||t.key==="Enter")&&(t.preventDefault(),t.key==="Enter"&&!t.repeat&&!this.blockEvents&&this.zoomIn(e))}onKeyUp(t){if(this._destroyed||!this.inputs.keyboard||t.defaultPrevented||Vt(t.target)||t.target.closest?.("[inert]"))return;let e=t.target.closest?.(".zoom-me[data-to]");if(t.key===" "&&e&&!kt(e)){t.preventDefault(),this.blockEvents||this.zoomIn(e);return}this.tracing("onKeyUp()"),(t.key==="ArrowLeft"||t.key==="ArrowDown")&&(t.preventDefault(),this.storedViews.length>1&&!this.blockEvents?this.zoomOut():this.notify(`is on level zero. Can't zoom out. Trigger: ${t.key}`,"warn"))}onWheel(t){this._destroyed||this.inputs.wheel&&(this._isInsideScrollable(t.target,t.deltaY)||(t.preventDefault(),!(this.blockEvents||this._wheelCooldown)&&t.deltaY>0&&this.storedViews.length>1&&(this.tracing("onWheel() \u2192 zoomOut"),this._wheelCooldown=!0,this._setTrackedTimeout(()=>{this._wheelCooldown=!1},500),this.zoomOut())))}_isInsideScrollable(t,e){let s=t,i=this.canvas.querySelector(".is-current-view");for(;s&&s!==this.canvas;){if(s===i||i&&i.contains(s)){let{overflowY:n}=window.getComputedStyle(s);if((n==="auto"||n==="scroll")&&(e>0?s.scrollTop+s.clientHeight<s.scrollHeight-1:s.scrollTop>0))return!0}s=s.parentElement}return!1}onTouchStart(t){this._destroyed||this.inputs.touch&&(this.tracing("onTouchStart()"),this.touching=!0,this.touchstartX=t.changedTouches[0].screenX,this.touchstartY=t.changedTouches[0].screenY)}onTouchEnd(t){this._destroyed||this.inputs.touch&&(this.blockEvents||(this.tracing("onTouchEnd()"),this.touchendX=t.changedTouches[0].screenX,this.touchendY=t.changedTouches[0].screenY,this.handleGesture(t)),this.touching=!1)}handleGesture(t){if(t.target.closest?.(".z-depth-nav, .z-lateral-nav"))return;t.stopPropagation(),this.tracing("handleGesture()");let e=this.touchendX-this.touchstartX,s=this.touchendY-this.touchstartY,i=Math.abs(e)<10&&Math.abs(s)<10;e<-30&&(this.storedViews.length>1&&!this.blockEvents?(this.tracing("swipe left"),this.zoomOut()):this.notify("is on level zero. Can't zoom out. Trigger: Swipe left","warn"));let n=t.target.classList.contains("zoom-me")?t.target:t.target.closest(".zoom-me");i&&!this.blockEvents&&n&&this.touching&&(this.touching=!1,this.tracing("tap"),t.preventDefault(),this.zoomIn(n)),i&&this.storedViews.length>1&&!this.blockEvents&&!n&&t.target.closest(".is-current-view")===null&&this.touching&&(this.touching=!1,this.tracing("tap"),this.zoomOut())}};var cs={separator:"/",prefix:"/"};function qt(r,t){let e=[];for(let s of r.storedViews){let i=s.views&&s.views[0];i&&i.viewName&&e.push(i.viewName)}return e.join(t)}function fs(r,t){let e=window.location.hash.slice(1);return e.startsWith(r)&&(e=e.slice(r.length)),e?e.split(t).filter(Boolean):[]}var Ze={install(r,t){let e=Object.assign({},cs,t),s=e.separator,i=e.prefix,n=!1,o=!1,a=null,c=!1;function l(v){if(n)return;let m=qt(r,s),p="#"+i+m;window.location.hash!==p&&(n=!0,window.history[v](null,"",p),n=!1)}function f(){l("pushState")}function h(){l("replaceState")}r.on("afterZoomIn",f),r.on("afterLateral",f),r.on("afterZoomOut",h);async function u(){if(!(o||c)){o=!0,n=!0;try{for(;a&&!c;){let v=a;if(a=null,await r._navigationTask?.promise,c)return;if(a)continue;let m=qt(r,s).split(s).filter(Boolean);if(v.join(s)!==m.join(s)){if(v.length>m.length){window.history.back();continue}for(;m.length>v.length&&m.length>1;){let p=m.length;if(await r.zoomOut(),c)return;if(m=qt(r,s).split(s).filter(Boolean),a||m.length>=p)break}if(!a&&v.length===m.length&&v.length>0){let p=v[v.length-1];if(p!==m[m.length-1]){let y=r.lateralHistory||[],g=b=>typeof b=="object"?b?.name:b,x=y.map(g).lastIndexOf(p);if(x!==-1)for(;r.lateralHistory.length>x;){let b=r.lateralHistory.length;if(await r.back(),c||a||r.lateralHistory.length>=b)break}else await r.goTo(p,{mode:"lateral"})}}}}}finally{n=!1,o=!1}}}function d(){c||(a=fs(i,s),u())}window.addEventListener("popstate",d),h(),r.on("destroy",function(){c=!0,a=null,r.off("afterZoomIn",f),r.off("afterLateral",f),r.off("afterZoomOut",h),window.removeEventListener("popstate",d)})}};gt.Router=Ze;var dr=gt;export{gt as Zumly,Ze as ZumlyRouter,dr as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zumly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "Javascript library for building zooming user interfaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Juan Martin Muda - Zumerlab",
|
|
@@ -47,20 +47,24 @@
|
|
|
47
47
|
],
|
|
48
48
|
"scripts": {
|
|
49
49
|
"compile": "node esbuild.config.mjs",
|
|
50
|
-
"build": "npm run compile && npm pack",
|
|
51
50
|
"dev": "npm run compile && npx serve . -p 9090 -c ./serve.json",
|
|
52
51
|
"test": "npx vitest run --browser.headless --reporter=verbose",
|
|
52
|
+
"test:browsers": "node scripts/test-browsers.mjs",
|
|
53
|
+
"test:pack": "npm run compile && node scripts/verify-package.mjs",
|
|
53
54
|
"test:unit": "npx vitest run __tests__/utils.test.js --reporter=verbose",
|
|
54
55
|
"test:coverage": "npx vitest run --browser.headless --coverage",
|
|
55
|
-
"test:install-browsers": "npx playwright install chromium",
|
|
56
|
+
"test:install-browsers": "npx playwright install chromium firefox webkit",
|
|
56
57
|
"bump": "npx @zumerbox/bump && npx @zumerbox/changelog",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
58
|
+
"prepack": "npm run compile",
|
|
59
|
+
"build": "npm run compile && npm pack",
|
|
60
|
+
"release:push": "git add . && git commit -m \"Bumped version\" && git push --follow-tags"
|
|
59
61
|
},
|
|
60
62
|
"files": [
|
|
61
63
|
"dist",
|
|
62
64
|
"types",
|
|
63
65
|
"src/drivers",
|
|
66
|
+
"src/view-visibility.js",
|
|
67
|
+
"src/view-lifecycle.js",
|
|
64
68
|
"docs/DRIVER_API.md",
|
|
65
69
|
"README.md"
|
|
66
70
|
],
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
applyZoomOutLastState,
|
|
18
18
|
removeViewFromCanvas,
|
|
19
19
|
runLateralInstant,
|
|
20
|
-
readComputedMatrix,
|
|
21
20
|
interpolateMatrix,
|
|
22
21
|
matrixToString,
|
|
23
22
|
} from './driver-helpers.js'
|
|
23
|
+
import { readTransitionMatrix } from './transform-matrix.js'
|
|
24
24
|
|
|
25
25
|
export function runTransition (spec, onComplete) {
|
|
26
26
|
const anime = typeof globalThis !== 'undefined' && globalThis.anime
|
|
@@ -145,12 +145,12 @@ function runZoomOut (anime, currentView, previousView, lastView, currentStage, d
|
|
|
145
145
|
function computeMatrixPairs (views, direction) {
|
|
146
146
|
return views.map(({ el, backward, forward }) => {
|
|
147
147
|
if (direction === 'forward') {
|
|
148
|
-
const from =
|
|
149
|
-
const to =
|
|
148
|
+
const from = readTransitionMatrix(el, backward.origin, backward.transform)
|
|
149
|
+
const to = readTransitionMatrix(el, backward.origin, forward.transform)
|
|
150
150
|
return { el, from, to }
|
|
151
151
|
} else {
|
|
152
|
-
const from =
|
|
153
|
-
const to =
|
|
152
|
+
const from = readTransitionMatrix(el, forward.origin, forward.transform)
|
|
153
|
+
const to = readTransitionMatrix(el, forward.origin, backward.transform)
|
|
154
154
|
return { el, from, to }
|
|
155
155
|
}
|
|
156
156
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { showViewContent } from '../view-visibility.js'
|
|
2
|
+
import { disposeView } from '../view-lifecycle.js'
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Shared helpers for Zumly transition drivers.
|
|
@@ -129,11 +130,15 @@ export function applyZoomOutLastState (element, backwardState) {
|
|
|
129
130
|
* @param {HTMLElement} canvas - The canvas container
|
|
130
131
|
*/
|
|
131
132
|
export function removeViewFromCanvas (element, canvas) {
|
|
133
|
+
disposeView(element)
|
|
132
134
|
try {
|
|
133
135
|
if (canvas) canvas.removeChild(element)
|
|
134
136
|
} catch (e) {
|
|
135
137
|
try {
|
|
136
|
-
if (element
|
|
138
|
+
if (element?.parentElement && canvas) {
|
|
139
|
+
disposeView(element.parentElement)
|
|
140
|
+
canvas.removeChild(element.parentElement)
|
|
141
|
+
}
|
|
137
142
|
} catch (e2) {
|
|
138
143
|
// Element already removed or re-parented — safe to ignore.
|
|
139
144
|
}
|
|
@@ -273,10 +278,10 @@ export function parseMatrixString (mStr) {
|
|
|
273
278
|
)
|
|
274
279
|
if (!m) return identityMatrix()
|
|
275
280
|
return {
|
|
276
|
-
a: parseFloat(m[1])
|
|
281
|
+
a: parseFloat(m[1]),
|
|
277
282
|
b: parseFloat(m[2]) || 0,
|
|
278
283
|
c: parseFloat(m[3]) || 0,
|
|
279
|
-
d: parseFloat(m[4])
|
|
284
|
+
d: parseFloat(m[4]),
|
|
280
285
|
e: parseFloat(m[5]) || 0,
|
|
281
286
|
f: parseFloat(m[6]) || 0,
|
|
282
287
|
}
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
applyZoomOutLastState,
|
|
16
16
|
removeViewFromCanvas,
|
|
17
17
|
runLateralInstant,
|
|
18
|
-
readComputedMatrix,
|
|
19
18
|
interpolateMatrix,
|
|
20
19
|
matrixToString,
|
|
21
20
|
} from './driver-helpers.js'
|
|
21
|
+
import { readTransitionMatrix } from './transform-matrix.js'
|
|
22
22
|
|
|
23
23
|
export function runTransition (spec, onComplete) {
|
|
24
24
|
const animate = getMotionAnimate()
|
|
@@ -131,14 +131,14 @@ function computeMatrixPairs (currentView, previousView, lastView, currentStage,
|
|
|
131
131
|
if (direction === 'forward') {
|
|
132
132
|
return {
|
|
133
133
|
el,
|
|
134
|
-
from:
|
|
135
|
-
to:
|
|
134
|
+
from: readTransitionMatrix(el, backward.origin, backward.transform),
|
|
135
|
+
to: readTransitionMatrix(el, backward.origin, forward.transform),
|
|
136
136
|
}
|
|
137
137
|
} else {
|
|
138
138
|
return {
|
|
139
139
|
el,
|
|
140
|
-
from:
|
|
141
|
-
to:
|
|
140
|
+
from: readTransitionMatrix(el, forward.origin, forward.transform),
|
|
141
|
+
to: readTransitionMatrix(el, forward.origin, backward.transform),
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { identityMatrix, readComputedMatrix } from './driver-helpers.js'
|
|
2
|
+
|
|
3
|
+
// Zumly emits translate(px, px) followed by an optional uniform scale. These
|
|
4
|
+
// matrices are independent of layout and transform-origin: the browser applies
|
|
5
|
+
// the origin separately when it paints the matrix. Keep other CSS syntax on the
|
|
6
|
+
// computed-style path, including an empty inline value that can expose author CSS.
|
|
7
|
+
const number = '[-+]?(?:\\d*\\.\\d+|\\d+)(?:[eE][-+]?\\d+)?'
|
|
8
|
+
const length = `(${number})(px)?`
|
|
9
|
+
const zumlyTransform = new RegExp(`^(?:translate\\(\\s*${length}\\s*,\\s*${length}\\s*\\)\\s*)?(?:scale\\(\\s*(${number})\\s*\\))?$`)
|
|
10
|
+
|
|
11
|
+
function parseZumlyMatrix (transformStr) {
|
|
12
|
+
if (typeof transformStr !== 'string') return null
|
|
13
|
+
const value = transformStr.trim()
|
|
14
|
+
if (value === 'none') return identityMatrix()
|
|
15
|
+
if (!value) return null
|
|
16
|
+
const match = value.match(zumlyTransform)
|
|
17
|
+
if (!match) return null
|
|
18
|
+
const tx = Number(match[1] ?? 0)
|
|
19
|
+
const ty = Number(match[3] ?? 0)
|
|
20
|
+
const scale = Number(match[5] ?? 1)
|
|
21
|
+
// CSS permits unitless zero lengths, but not other unitless translations.
|
|
22
|
+
if ((tx !== 0 && !match[2]) || (ty !== 0 && !match[4])) return null
|
|
23
|
+
if (![tx, ty, scale].every(Number.isFinite)) return null
|
|
24
|
+
return { a: scale, b: 0, c: 0, d: scale, e: tx, f: ty }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Apply a driver state, resolving engine transforms without layout reads. */
|
|
28
|
+
export function readTransitionMatrix (element, origin, transformStr) {
|
|
29
|
+
const matrix = parseZumlyMatrix(transformStr)
|
|
30
|
+
if (!matrix) return readComputedMatrix(element, origin, transformStr)
|
|
31
|
+
element.style.transformOrigin = origin
|
|
32
|
+
element.style.transform = transformStr
|
|
33
|
+
return matrix
|
|
34
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** Cleanup belongs to a resolved view instance, never to a cached template. */
|
|
2
|
+
// Drivers can be imported from a separate package entry point, so a module-local
|
|
3
|
+
// WeakMap would not see registrations made by the bundled core. A non-enumerable
|
|
4
|
+
// symbol property shares the scope through the node and is not copied by cloneNode.
|
|
5
|
+
const lifecycleKey = Symbol.for('zumly.viewLifecycles')
|
|
6
|
+
|
|
7
|
+
function runCleanup (cleanup) {
|
|
8
|
+
try {
|
|
9
|
+
const result = cleanup()
|
|
10
|
+
if (result && typeof result.then === 'function') {
|
|
11
|
+
result.catch(error => console.error('Zumly: view cleanup failed:', error)) // eslint-disable-line no-console
|
|
12
|
+
}
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error('Zumly: view cleanup failed:', error) // eslint-disable-line no-console
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Internal scope: accepts registrations before or after resolution finishes. */
|
|
19
|
+
export function createViewLifecycle () {
|
|
20
|
+
let disposed = false
|
|
21
|
+
const callbacks = []
|
|
22
|
+
const lifecycle = {
|
|
23
|
+
onCleanup (cleanup) {
|
|
24
|
+
if (typeof cleanup !== 'function') throw new TypeError('Zumly: onCleanup expects a function')
|
|
25
|
+
if (disposed) runCleanup(cleanup)
|
|
26
|
+
else callbacks.push(cleanup)
|
|
27
|
+
},
|
|
28
|
+
attach (node) {
|
|
29
|
+
let entries = node[lifecycleKey]
|
|
30
|
+
if (!entries) {
|
|
31
|
+
entries = new Set()
|
|
32
|
+
Object.defineProperty(node, lifecycleKey, { value: entries, configurable: true })
|
|
33
|
+
}
|
|
34
|
+
entries.add(lifecycle)
|
|
35
|
+
},
|
|
36
|
+
dispose () {
|
|
37
|
+
if (disposed) return
|
|
38
|
+
disposed = true
|
|
39
|
+
for (const cleanup of callbacks.splice(0).reverse()) runCleanup(cleanup)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return lifecycle
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Dispose a view and registered descendants once. Call before permanent removal,
|
|
47
|
+
* or for an unused async result; temporary detach/keepAlive must not call this.
|
|
48
|
+
* Async cleanup is started here, with rejections handled, but is not awaited.
|
|
49
|
+
*/
|
|
50
|
+
export function disposeView (node) {
|
|
51
|
+
if (!node) return
|
|
52
|
+
// Snapshot only registered nodes before callbacks can mutate the subtree.
|
|
53
|
+
// A TreeWalker keeps the old reverse document order without allocating an
|
|
54
|
+
// array/NodeList containing every element of a large component.
|
|
55
|
+
const nodes = []
|
|
56
|
+
if (node[lifecycleKey]) nodes.push(node)
|
|
57
|
+
const document = node.ownerDocument || node
|
|
58
|
+
const walker = document.createTreeWalker(node, 1) // NodeFilter.SHOW_ELEMENT
|
|
59
|
+
let descendant
|
|
60
|
+
while ((descendant = walker.nextNode())) {
|
|
61
|
+
if (descendant[lifecycleKey]) nodes.push(descendant)
|
|
62
|
+
}
|
|
63
|
+
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
64
|
+
const child = nodes[i]
|
|
65
|
+
const entries = child[lifecycleKey]
|
|
66
|
+
if (!entries) continue
|
|
67
|
+
for (const lifecycle of entries) lifecycle.dispose()
|
|
68
|
+
delete child[lifecycleKey]
|
|
69
|
+
}
|
|
70
|
+
}
|