shopic 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,6 +76,20 @@ src/*.ts → esbuild → dist/*.js → npm publish → cdn.jsdelivr.net/
76
76
  npm stores the versions; jsDelivr is the CDN that serves them. The published package
77
77
  is public even though this repository is not — that is the price of a free CDN.
78
78
 
79
+ ## Machine setup
80
+
81
+ Node and pnpm; `packageManager` pins the pnpm version and `corepack enable` installs
82
+ it. Publishing also needs **npm CLI 11.9 or newer** — older versions cannot drive the
83
+ passkey hand-off and ask for a code that does not exist.
84
+
85
+ ```bash
86
+ corepack enable
87
+ pnpm install
88
+ npm login # publishing only
89
+ ```
90
+
91
+ The environment is complete when `pnpm check`, `pnpm lint` and `pnpm build` pass.
92
+
79
93
  ## Local checks
80
94
 
81
95
  ```bash
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";(()=>{var G=new Map,y=(t,n)=>{if(G.has(t))throw new Error(`[shopic] Animation "${t}" is registered twice.`);G.set(t,n)},W=(t,n=document)=>{let a=n.querySelectorAll("[data-anim]");for(let e of a){let o=e.dataset.anim;if(!o||e.dataset.animState==="ready")continue;let c=G.get(o);if(!c){console.warn(`[shopic] No animation registered for data-anim="${o}".`,e);continue}e.dataset.animState="ready",c(e,t)}};var vt=2,St=150,Tt=4,Lt=1,xt=5e3,wt=.75,At="power3.out",Mt=[0,.25,.5,.6,.7,.8,.9,1],B="shopic:slide-enter";y("carousel",(t,{gsap:n,reducedMotion:a})=>{let e=Array.from(t.querySelectorAll(":scope > [data-slide]"));if(e.length<2)return;let o=t.closest("section")??t.parentElement??document.body,c=Array.from(o.querySelectorAll("[data-tab]")),s=a?0:wt,l=e.length,i=new Map(e.map((r,m)=>[r,m])),d=new Map;e.forEach((r,m)=>{let b=r.dataset.slide;b&&!d.has(b)&&d.set(b,m)});let f=[],x=()=>{let r=t.getBoundingClientRect().left,m=t.scrollLeft,b=parseFloat(getComputedStyle(t).paddingLeft)||0,L=t.scrollWidth-t.clientWidth;f=e.map(R=>Math.min(R.getBoundingClientRect().left-r+m-b,L))},E=r=>{for(let m of c){let b=m.dataset.tab===r;m.classList.toggle("is-active",b),b?m.setAttribute("aria-current","true"):m.removeAttribute("aria-current")}},M=-1,S=null,v=!1,u=!1,g,p,h=null,T=0,O=0,w=0,A=0,I=!1,H=()=>h!==null,P=()=>S!==null,C=()=>{clearTimeout(g),g=void 0},z=()=>!a&&!document.hidden&&u&&!H()&&!v&&!o.contains(document.activeElement),N=()=>{C(),z()&&(g=setTimeout(()=>{g=void 0,z()&&D((M+1)%l)},xt))},K=r=>{let m=e[r],b=m.dataset.slide;if(b&&E(b),r!==M){M=r;for(let L of e)L.classList.toggle("is-current",L===m);m.dispatchEvent(new CustomEvent(B))}},X=r=>{S=null,K(r),N()},Z=()=>{clearTimeout(p),n.killTweensOf(t),S=null};function D(r){if(Z(),S=r,s===0){t.scrollLeft=f[r],X(r);return}n.to(t,{scrollLeft:f[r],duration:s,ease:At,overwrite:"auto",onComplete:()=>X(r),onInterrupt:()=>{S=null}})}let j=()=>{let r=t.scrollLeft,m=0;return f.forEach((b,L)=>{Math.abs(b-r)<Math.abs(f[m]-r)&&(m=L)}),m},$=()=>{let r=j();Math.abs(f[r]-t.scrollLeft)<Lt?X(r):D(r)},yt=()=>{let r=T>0?f[T]-f[T-1]:1/0,m=T<l-1?f[T+1]-f[T]:1/0,b=Math.min(Math.abs(r),Math.abs(m));if(Math.abs(A)<b*.25){$();return}D((T+Math.sign(A)+l)%l)};for(let r of c)r.addEventListener("click",m=>{m.preventDefault();let b=r.dataset.tab??"",L=d.get(b);L!==void 0&&(C(),E(b),D(L))});let J=new Array(l).fill(0),Et=new IntersectionObserver(r=>{for(let L of r){let R=i.get(L.target);R!==void 0&&(J[R]=L.isIntersecting?L.intersectionRatio:0)}let m=-1,b=0;J.forEach((L,R)=>{L<=b||(b=L,m=R)}),m!==-1&&(S!==null&&m!==S||K(m))},{root:t,threshold:Mt});for(let r of e)Et.observe(r);x(),t.style.scrollSnapType="none",t.style.touchAction="pan-y",t.addEventListener("dragstart",r=>r.preventDefault());let[bt]=f;t.scrollLeft=bt;let Q=new ResizeObserver(x);Q.observe(t);for(let r of e)Q.observe(r);"onscrollend"in window?t.addEventListener("scrollend",()=>{!P()&&!H()&&$()}):t.addEventListener("scroll",()=>{P()||H()||(clearTimeout(p),p=setTimeout($,St))}),t.addEventListener("pointerdown",r=>{C(),Z(),h=r.pointerId,I=!1,O=r.clientX,w=t.scrollLeft,A=0,T=j()}),t.addEventListener("pointermove",r=>{if(r.pointerId!==h)return;let m=r.clientX-O;if(!I){if(Math.abs(m)<Tt)return;I=!0,t.classList.add("is-dragging"),t.setPointerCapture(r.pointerId)}A=-m*vt,t.scrollLeft=w+A,r.pointerType==="mouse"&&r.preventDefault()});let k=r=>{r.pointerId===h&&(h=null,t.hasPointerCapture(r.pointerId)&&t.releasePointerCapture(r.pointerId),I?(t.classList.remove("is-dragging"),yt()):$())};window.addEventListener("pointerup",k),window.addEventListener("pointercancel",k),t.addEventListener("click",r=>{I&&(I=!1,r.preventDefault(),r.stopPropagation())},!0),o.addEventListener("pointerenter",r=>{r.pointerType==="mouse"&&(v=!0,C())}),o.addEventListener("pointerleave",r=>{r.pointerType==="mouse"&&(v=!1,N())}),o.addEventListener("focusin",C),o.addEventListener("focusout",()=>queueMicrotask(N)),document.addEventListener("visibilitychange",()=>{document.hidden?C():N()}),new IntersectionObserver(r=>{u=r.some(m=>m.isIntersecting),u?N():C()},{threshold:.2}).observe(t)});var tt="!<>-_\\/[]{}=+*^?#$%01",q=new WeakMap,_=(t,{duration:n=1050,stagger:a=.75,text:e,reducedMotion:o=!1,relaunchOnHover:c=!1}={})=>{if(o){e!==void 0&&(t.textContent=e);return}if(e!==void 0)t.dataset.scrambleText=e;else if(!t.dataset.scrambleText){let v=t.textContent;if(!v||!v.trim())return;t.dataset.scrambleText=v}let s=t.dataset.scrambleText;if(!s||!s.trim())return;let l=Array.from(s),i=l.length,d=Array.from(t.children),f;d.length===i&&d.every(v=>v.tagName==="SPAN")?f=d:(f=l.map(v=>{let u=document.createElement("span");return u.textContent=v,u}),t.textContent="",t.append(...f));let x=Symbol("scramble");q.set(t,x);let E=l.map((v,u)=>i<=1?0:u/(i-1)*n*a),M=performance.now(),S=v=>{if(q.get(t)!==x)return;let u=v-M,g=!0;l.forEach((p,h)=>{if(p===" "){f[h].textContent=" ";return}u>=E[h]?f[h].textContent=p:(g=!1,f[h].textContent=tt[Math.random()*tt.length|0])}),g?q.delete(t):requestAnimationFrame(S)};requestAnimationFrame(S),c&&It(t,{duration:n,stagger:a})},It=(t,n)=>{t.dataset.scrambleHoverBound||(t.dataset.scrambleHoverBound="true",t.addEventListener("pointerenter",()=>{q.has(t)||_(t,n)}))};var Ot=.5,Ct="power2.out",Ht=".status-pill, .evidence_label, .evidence_sku",Rt={duration:630,stagger:.6,relaunchOnHover:!0};y("evidence",(t,{gsap:n,reducedMotion:a})=>{let e=Array.from(t.children);if(!e.length)return;if(a){for(let i of e)i.style.height="auto",i.style.opacity="1";return}let o=()=>{n.killTweensOf(e),n.set(e,{height:0,opacity:0,overflow:"hidden"});let i=n.timeline();for(let d of e)i.call(()=>{for(let f of d.querySelectorAll(Ht))_(f,Rt)}),i.to(d,{height:"auto",opacity:1,duration:Ot,ease:Ct,onComplete:()=>n.set(d,{height:"auto"})})},c=!1,s=!1,l=()=>{if(!c||s)return;let i=t.closest("[data-slide]");i&&!i.classList.contains("is-current")||(s=!0,o())};if("IntersectionObserver"in window){let i=new IntersectionObserver(d=>{for(let f of d)f.isIntersecting&&(c=!0,l(),s&&i.disconnect())},{threshold:.2});i.observe(t)}else c=!0,l();t.closest("[data-slide]")?.addEventListener(B,()=>{s=!1,l()})});var et=8;y("focus-drift",(t,{reducedMotion:n})=>{let a=t.querySelector(":scope > .camera_focus");!a||n||(t.addEventListener("pointermove",e=>{if(e.pointerType!=="mouse")return;let o=t.getBoundingClientRect(),c=(e.clientX-o.left)/o.width-.5,s=(e.clientY-o.top)/o.height-.5,l=(c*et*2).toFixed(1),i=(s*et*2).toFixed(1);a.style.transform=`translate(${l}px, ${i}px)`}),t.addEventListener("pointerleave",()=>{a.style.transform=""}))});var nt=42,ot=96,_t=2600,Nt="is-scanned",Pt="is-fresh";y("foundation-rail",(t,{gsap:n,reducedMotion:a})=>{let e=t.closest(".camera_photo"),o=Array.from(t.querySelectorAll(":scope > .foundation_slot"),u=>({element:u,parts:Array.from(u.querySelectorAll(".foundation_photo, .foundation_card")),tile:u.querySelector(".foundation_scan"),setX:n.quickSetter(u,"x","px"),home:0,turn:0,state:null}));if(!e||o.length===0){console.warn("[shopic] foundation-rail expects a .camera_photo tile around a track of .foundation_slot items.",t);return}let c=n.quickSetter(t,"x","px"),s=0,l=0,i=u=>u,d=()=>{let[u]=o,g=u.element.offsetWidth,p=g+(parseFloat(getComputedStyle(t).columnGap)||0);s=p*o.length,l=s/nt*(_t/1e3),i=n.utils.wrap(-s/2,s/2),s<e.offsetWidth+g&&console.warn(`[shopic] foundation-rail: ${o.length} slots span ${s}px but the tile needs ${e.offsetWidth+g}px to loop without a gap.`,t);let h=e.getBoundingClientRect(),T=h.width/e.offsetWidth||1,O=(u.element.getBoundingClientRect().left-h.left)/T+g/2-e.offsetWidth/2-(Number(n.getProperty(t,"x"))||0)-(Number(n.getProperty(u.element,"x"))||0);o.forEach((w,A)=>{w.home=O+A*p,w.setX(w.turn*s)})},f=u=>u>ot?"unseen":u>ot-l?"fresh":"seen",x=(u,g)=>{if(u.state!==g){u.state=g;for(let p of u.parts)p.classList.toggle(Nt,g!=="unseen");u.tile?.classList.toggle(Pt,g==="fresh")}},E=u=>{if(s){c(-u);for(let g of o){let p=i(g.home-u),h=Math.round((p-(g.home-u))/s);h!==g.turn&&(g.turn=h,g.setX(h*s)),x(g,f(p))}}},M={t:0},S=()=>M.t*s,v=a?null:n.to(M,{t:1,duration:nt,ease:"none",repeat:-1,paused:!0,onUpdate:()=>E(S())});new ResizeObserver(()=>{d(),E(S())}).observe(t),v&&new IntersectionObserver(u=>{v.paused(!u.some(g=>g.isIntersecting))}).observe(t)});var rt="split_line",Dt="split_word",st="split_word-inner",$t=t=>{let n=document.createDocumentFragment(),a=[],e=document.createElement("span");e.className=rt,n.appendChild(e);let o=(s,l)=>{if(!s)return;let i=document.createElement("span");i.className=Dt;let d=document.createElement("span");d.className=l?`${st} ${l}`:st,d.textContent=s,i.appendChild(d),e.appendChild(i),a.push(d)},c=(s,l)=>{for(let i of s.split(/(\s+)/))i&&(/^\s+$/.test(i)?e.appendChild(document.createTextNode(" ")):o(i,l))};for(let s of Array.from(t.childNodes))s.nodeType===Node.TEXT_NODE?c(s.textContent??""):s instanceof HTMLBRElement?(e=document.createElement("span"),e.className=rt,n.appendChild(e)):s instanceof HTMLElement&&c(s.textContent??"",s.className||void 0);return t.textContent="",t.appendChild(n),a},it={yPercent:0,duration:.9,ease:"power4.out",stagger:.035};y("headline",(t,{gsap:n,ScrollTrigger:a,reducedMotion:e})=>{if(e){t.style.visibility="visible";return}let o=$t(t);if(n.set(o,{yPercent:110}),t.style.visibility="visible",t.dataset.animTrigger==="load"||!a){n.to(o,{...it,delay:.3});return}n.to(o,{...it,scrollTrigger:{trigger:t,start:"top 85%"}})});var qt=26;y("marquee",(t,{gsap:n,reducedMotion:a})=>{if(a)return;let e=Number(t.dataset.animSets??4),o=Number(t.dataset.animDuration??qt);if(!Number.isFinite(e)||e<2)return;let c=()=>t.scrollWidth/e,s=n.to(t,{x:()=>-c(),duration:o,ease:"none",repeat:-1,modifiers:{x:i=>`${Number.parseFloat(i)%c()}px`}}),l=t.parentElement;l&&(l.addEventListener("pointerenter",()=>s.pause()),l.addEventListener("pointerleave",()=>s.resume()))});var at=1.15,lt=.18,F=8,Ft=.55,V=(t,n,a)=>Math.min(a,Math.max(n,t));y("photo-hover",(t,{reducedMotion:n})=>{let a=t.querySelector(":scope > img"),e=t.querySelector(":scope > .camera_focus");if(!a&&!e)return;let o=e?.querySelector(":scope > img:first-child")??null,c=e?.querySelector(":scope > img:nth-child(2)")??null;e&&(!o||!c)&&console.warn("[shopic] photo-hover expects two image layers inside the reticle.",e);let s=Array.from(t.querySelectorAll(".detect_box")),l=0,i=0,d=0,f=0,x=0,E=!1,M=p=>{let h=t.getBoundingClientRect(),T=t.offsetWidth,O=t.offsetHeight,w=h.width/T||1,A=(p.clientX-h.left)/w,I=(p.clientY-h.top)/w;return{x:A,y:I,width:T,height:O}},S=()=>{if(l=0,!!o){if(i-=i*lt,d-=d*lt,o.style.transform=`translate(${i.toFixed(2)}px, ${d.toFixed(2)}px)`,Math.abs(i)>.1||Math.abs(d)>.1){l=requestAnimationFrame(S);return}o.style.transform=""}},v=p=>{if(p.pointerType!=="mouse")return;let{x:h,y:T,width:O,height:w}=M(p);if(a){let H=at-1,P=-(h/O-.5)*O*H,C=-(T/w-.5)*w*H;a.style.transform=`translate(${P.toFixed(2)}px, ${C.toFixed(2)}px) scale(${at})`}if(!e||E)return;let A=V(h,0,O),I=V(T,0,w);if(e.style.left=`${A.toFixed(2)}px`,e.style.top=`${I.toFixed(2)}px`,n){f=A,x=I;return}i-=A-f,d-=I-x,f=A,x=I,l||(l=requestAnimationFrame(S))},u=()=>{a&&(a.style.transform=""),e&&(E=!1,e.style.left="",e.style.top="",e.style.width="",e.style.height="",e.style.transitionProperty="",c&&(c.style.transform=""),o&&(o.style.opacity="",o.style.transform=""),i=0,d=0,cancelAnimationFrame(l),l=0)},g=p=>{if(p.pointerType!=="mouse"||!e)return;e.style.transitionProperty="opacity, width, height";let{x:h,y:T,width:O,height:w}=M(p);f=V(h,0,O),x=V(T,0,w),i=0,d=0};t.addEventListener("pointerenter",g),t.addEventListener("pointermove",v),t.addEventListener("pointerleave",u);for(let p of s)p.addEventListener("pointerenter",h=>{h.pointerType!=="mouse"||!e||(E=!0,e.style.transitionProperty="",e.style.left=`${p.offsetLeft-F}px`,e.style.top=`${p.offsetTop-F}px`,e.style.width=`${p.offsetWidth+F*2}px`,e.style.height=`${p.offsetHeight+F*2}px`,o&&(o.style.opacity="0"),c&&(c.style.transform=`scale(${Ft})`))}),p.addEventListener("pointerleave",()=>{E=!1,o&&(o.style.opacity=""),c&&(c.style.transform="")})});var ct="is-visible";y("reveal",(t,{reducedMotion:n})=>{let a=Number(t.dataset.animDelay??0);if(a&&(t.style.transitionDelay=`${a}ms`),n||!("IntersectionObserver"in window)){t.classList.add(ct);return}let e=new IntersectionObserver(o=>{for(let c of o)c.isIntersecting&&(c.target.classList.add(ct),e.unobserve(c.target))},{threshold:.15});e.observe(t)});y("scramble",(t,{reducedMotion:n})=>{let a={duration:Number(t.dataset.animDuration??1050),stagger:Number(t.dataset.animStagger??.75),reducedMotion:n};if(n||!("IntersectionObserver"in window)){_(t,a);return}let e=new IntersectionObserver(o=>{for(let c of o)c.isIntersecting&&(_(t,{...a,relaunchOnHover:!0}),e.unobserve(c.target))},{threshold:.2});e.observe(t)});var U=({prefix:t="",suffix:n="",value:a})=>`${t}${Math.round(a)}${n}`;var Vt=.5,dt="power4.out",Xt=.18,Gt="power2.in",Wt=.35,Bt=1400,Ut=.15,Yt=t=>{let n=t.querySelector("[data-stat-value]");return n||console.warn("[shopic] stats row is missing [data-stat-value]",t),n},ft=t=>({prefix:t.dataset.statPrefix??t.closest('[data-anim="stats"]')?.dataset.statPrefix??"",suffix:t.dataset.statSuffix??t.closest('[data-anim="stats"]')?.dataset.statSuffix??""}),mt=(t,n)=>{t.textContent=U({...ft(t),value:n})},ut=(t,n,a,e)=>{if(a){mt(t,n);return}let o=performance.now(),c=s=>{if(e!==Number(t.dataset.statsGeneration))return;let l=Math.min((s-o)/Bt,1),i=1-(1-l)**3;t.textContent=U({...ft(t),value:n*i}),l<1&&requestAnimationFrame(c)};requestAnimationFrame(c)},zt=(t,{gsap:n,reducedMotion:a})=>{let e=t,o=Yt(e);if(!o)return;let c=Number(e.dataset.statCount??o.dataset.statCount??0),s=0,l=!1,i=()=>{s+=1,o.dataset.statsGeneration=String(s),mt(o,c),n.set(o,{clearProps:"transform"})},d=E=>{s+=1,o.dataset.statsGeneration=String(s),n.killTweensOf(o),n.set(o,{yPercent:110}),n.to(o,{duration:Vt,ease:dt,yPercent:0}),E&&ut(o,c,a,s)},f=E=>{e.classList.toggle("is-hovered",E),e.querySelector("[data-stat-label]")?.classList.toggle("is-hovered",E)};if(a){i();return}n.set(o,{yPercent:110});let x=()=>{l||(l=!0,d(!0))};if("IntersectionObserver"in window){let E=new IntersectionObserver(M=>{M.some(S=>S.isIntersecting)&&(x(),E.disconnect())},{threshold:Ut});E.observe(e)}else x();e.addEventListener("pointerenter",E=>{E.pointerType==="mouse"&&(f(!0),s+=1,o.dataset.statsGeneration=String(s),n.killTweensOf(o),n.timeline().to(o,{duration:Xt,ease:Gt,yPercent:-110}).set(o,{yPercent:110}).to(o,{duration:Wt,ease:dt,onStart:()=>ut(o,c,a,s),yPercent:0}))}),e.addEventListener("pointerleave",()=>f(!1))};y("stats",zt);var Y=t=>String(t).padStart(2,"0");y("timer",t=>{let n=()=>{let a=new Date;t.textContent=`${Y(a.getHours())}:${Y(a.getMinutes())}:${Y(a.getSeconds())}`};n(),setInterval(n,1e3)});var pt="is-active",Kt="(max-width: 991px)";y("versus-tabs",t=>{let n=Array.from(t.querySelectorAll('[role="tab"]')),a=t.nextElementSibling,e=a?Array.from(a.querySelectorAll(":scope > *")):[];if(n.length===0||n.length!==e.length){console.warn(`[shopic] versus-tabs expects one tab per panel; found ${n.length} tabs and ${e.length} panels.`,t);return}let o=window.matchMedia(Kt),c=l=>{n.forEach((i,d)=>{i.classList.toggle(pt,d===l),i.setAttribute("aria-selected",String(d===l))}),e.forEach((i,d)=>{i.hidden=o.matches&&d!==l})},s=()=>Math.max(0,n.indexOf(t.querySelector(`.${pt}`)));n.forEach((l,i)=>{l.addEventListener("click",()=>c(i)),l.addEventListener("keydown",d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),c(i))}),l.hasAttribute("tabindex")||(l.tabIndex=0)}),o.addEventListener("change",()=>c(s())),c(s())});var gt=()=>{let{gsap:t,ScrollTrigger:n}=window;if(!t)throw new Error("[shopic] GSAP is not on the page. Enable it in Webflow \u2192 Site Settings \u2192 Custom Code \u2192 GSAP.");return n&&t.registerPlugin(n),{gsap:t,ScrollTrigger:n}},ht=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;window.Webflow||(window.Webflow=[]);window.Webflow.push(()=>{let{gsap:t,ScrollTrigger:n}=gt();W({gsap:t,ScrollTrigger:n,reducedMotion:ht()})});})();
1
+ "use strict";(()=>{var tt=new Map,h=(t,o)=>{if(tt.has(t))throw new Error(`[shopic] Animation "${t}" is registered twice.`);tt.set(t,o)},et=(t,o=document)=>{let a=o.querySelectorAll("[data-anim]");for(let n of a){let e=n.dataset.anim;if(!e||n.dataset.animState==="ready")continue;let s=tt.get(e);if(!s){console.warn(`[shopic] No animation registered for data-anim="${e}".`,n);continue}n.dataset.animState="ready",s(n,t)}};var Mt=2,It=150,Ht=4,Ot=1,Ct=5e3,Rt=.75,_t="power3.out",Nt=[0,.25,.5,.6,.7,.8,.9,1],nt="shopic:slide-enter";h("carousel",(t,{gsap:o,reducedMotion:a})=>{let n=Array.from(t.querySelectorAll(":scope > [data-slide]"));if(n.length<2)return;let e=t.closest("section")??t.parentElement??document.body,s=Array.from(e.querySelectorAll("[data-tab]")),r=a?0:Rt,d=n.length,l=new Map(n.map((i,y)=>[i,y])),f=new Map;n.forEach((i,y)=>{let T=i.dataset.slide;T&&!f.has(T)&&f.set(T,y)});let m=[],S=()=>{let i=t.getBoundingClientRect().left,y=t.scrollLeft,T=parseFloat(getComputedStyle(t).paddingLeft)||0,I=t.scrollWidth-t.clientWidth;m=n.map(V=>Math.min(V.getBoundingClientRect().left-i+y-T,I))},L=i=>{for(let y of s){let T=y.dataset.tab===i;y.classList.toggle("is-active",T),T?y.setAttribute("aria-current","true"):y.removeAttribute("aria-current")}},H=-1,x=null,E=!1,u=!1,g,b,v=null,A=0,N=0,C=0,O=0,R=!1,X=()=>v!==null,B=()=>x!==null,_=()=>{clearTimeout(g),g=void 0},W=()=>!a&&!document.hidden&&u&&!X()&&!E&&!e.contains(document.activeElement),P=()=>{_(),W()&&(g=setTimeout(()=>{g=void 0,W()&&q((H+1)%d)},Ct))},K=i=>{let y=n[i],T=y.dataset.slide;if(T&&L(T),i!==H){H=i;for(let I of n)I.classList.toggle("is-current",I===y);y.dispatchEvent(new CustomEvent(nt))}},k=i=>{x=null,K(i),P()},U=()=>{clearTimeout(b),o.killTweensOf(t),x=null};function q(i){if(U(),x=i,r===0){t.scrollLeft=m[i],k(i);return}o.to(t,{scrollLeft:m[i],duration:r,ease:_t,overwrite:"auto",onComplete:()=>k(i),onInterrupt:()=>{x=null}})}let Z=()=>{let i=t.scrollLeft,y=0;return m.forEach((T,I)=>{Math.abs(T-i)<Math.abs(m[y]-i)&&(y=I)}),y},$=()=>{let i=Z();Math.abs(m[i]-t.scrollLeft)<Ot?k(i):q(i)},c=()=>{let i=A>0?m[A]-m[A-1]:1/0,y=A<d-1?m[A+1]-m[A]:1/0,T=Math.min(Math.abs(i),Math.abs(y));if(Math.abs(O)<T*.25){$();return}q((A+Math.sign(O)+d)%d)};for(let i of s)i.addEventListener("click",y=>{y.preventDefault();let T=i.dataset.tab??"",I=f.get(T);I!==void 0&&(_(),L(T),q(I))});let p=new Array(d).fill(0),w=new IntersectionObserver(i=>{for(let I of i){let V=l.get(I.target);V!==void 0&&(p[V]=I.isIntersecting?I.intersectionRatio:0)}let y=-1,T=0;p.forEach((I,V)=>{I<=T||(T=I,y=V)}),y!==-1&&(x!==null&&y!==x||K(y))},{root:t,threshold:Nt});for(let i of n)w.observe(i);S(),t.style.scrollSnapType="none",t.style.touchAction="pan-y",t.addEventListener("dragstart",i=>i.preventDefault());let[M]=m;t.scrollLeft=M;let D=new ResizeObserver(S);D.observe(t);for(let i of n)D.observe(i);"onscrollend"in window?t.addEventListener("scrollend",()=>{!B()&&!X()&&$()}):t.addEventListener("scroll",()=>{B()||X()||(clearTimeout(b),b=setTimeout($,It))}),t.addEventListener("pointerdown",i=>{_(),U(),v=i.pointerId,R=!1,N=i.clientX,C=t.scrollLeft,O=0,A=Z()}),t.addEventListener("pointermove",i=>{if(i.pointerId!==v)return;let y=i.clientX-N;if(!R){if(Math.abs(y)<Ht)return;R=!0,t.classList.add("is-dragging"),t.setPointerCapture(i.pointerId)}O=-y*Mt,t.scrollLeft=C+O,i.pointerType==="mouse"&&i.preventDefault()});let F=i=>{i.pointerId===v&&(v=null,t.hasPointerCapture(i.pointerId)&&t.releasePointerCapture(i.pointerId),R?(t.classList.remove("is-dragging"),c()):$())};window.addEventListener("pointerup",F),window.addEventListener("pointercancel",F),t.addEventListener("click",i=>{R&&(R=!1,i.preventDefault(),i.stopPropagation())},!0),e.addEventListener("pointerenter",i=>{i.pointerType==="mouse"&&(E=!0,_())}),e.addEventListener("pointerleave",i=>{i.pointerType==="mouse"&&(E=!1,P())}),e.addEventListener("focusin",_),e.addEventListener("focusout",()=>queueMicrotask(P)),document.addEventListener("visibilitychange",()=>{document.hidden?_():P()}),new IntersectionObserver(i=>{u=i.some(y=>y.isIntersecting),u?P():_()},{threshold:.2}).observe(t)});var it="!<>-_\\/[]{}=+*^?#$%01",j=new WeakMap,G=(t,{duration:o=1050,stagger:a=.75,text:n,reducedMotion:e=!1,relaunchOnHover:s=!1}={})=>{if(e){n!==void 0&&(t.textContent=n);return}if(n!==void 0)t.dataset.scrambleText=n;else if(!t.dataset.scrambleText){let E=t.textContent;if(!E||!E.trim())return;t.dataset.scrambleText=E}let r=t.dataset.scrambleText;if(!r||!r.trim())return;let d=Array.from(r),l=d.length,f=Array.from(t.children),m;f.length===l&&f.every(E=>E.tagName==="SPAN")?m=f:(m=d.map(E=>{let u=document.createElement("span");return u.textContent=E,u}),t.textContent="",t.append(...m));let S=Symbol("scramble");j.set(t,S);let L=d.map((E,u)=>l<=1?0:u/(l-1)*o*a),H=performance.now(),x=E=>{if(j.get(t)!==S)return;let u=E-H,g=!0;d.forEach((b,v)=>{if(b===" "){m[v].textContent=" ";return}u>=L[v]?m[v].textContent=b:(g=!1,m[v].textContent=it[Math.random()*it.length|0])}),g?j.delete(t):requestAnimationFrame(x)};requestAnimationFrame(x),s&&Pt(t,{duration:o,stagger:a})},Pt=(t,o)=>{t.dataset.scrambleHoverBound||(t.dataset.scrambleHoverBound="true",t.addEventListener("pointerenter",()=>{j.has(t)||G(t,o)}))};var qt=.5,$t="power2.out",Dt=".status-pill, .evidence_label, .evidence_sku",Ft={duration:630,stagger:.6,relaunchOnHover:!0};h("evidence",(t,{gsap:o,reducedMotion:a})=>{let n=Array.from(t.children);if(!n.length)return;if(a){for(let l of n)l.style.height="auto",l.style.opacity="1";return}let e=()=>{o.killTweensOf(n),o.set(n,{height:0,opacity:0,overflow:"hidden"});let l=o.timeline();for(let f of n)l.call(()=>{for(let m of f.querySelectorAll(Dt))G(m,Ft)}),l.to(f,{height:"auto",opacity:1,duration:qt,ease:$t,onComplete:()=>o.set(f,{height:"auto"})})},s=!1,r=!1,d=()=>{if(!s||r)return;let l=t.closest("[data-slide]");l&&!l.classList.contains("is-current")||(r=!0,e())};if("IntersectionObserver"in window){let l=new IntersectionObserver(f=>{for(let m of f)m.isIntersecting&&(s=!0,d(),r&&l.disconnect())},{threshold:.2});l.observe(t)}else s=!0,d();t.closest("[data-slide]")?.addEventListener(nt,()=>{r=!1,d()})});var at="is-open",lt=".faq_row",ct=".faq_toggle";h("faq",t=>{let o=t.querySelectorAll(lt);if(o.length===0){console.warn(`[shopic] faq found no ${lt} to open.`,t);return}let a=[];for(let s of o){let r=s.querySelector(ct);if(!r){console.warn(`[shopic] faq row has no ${ct} to click.`,s);continue}a.push({row:s,toggle:r})}if(a.length===0)return;let n=s=>{for(let{row:r,toggle:d}of a){let l=r===s;r.classList.toggle(at,l),d.setAttribute("aria-expanded",String(l))}};for(let{row:s,toggle:r}of a)r.addEventListener("click",()=>{n(s.classList.contains(at)?null:s)}),r.addEventListener("keydown",d=>{d.key!=="Enter"&&d.key!==" "||(d.preventDefault(),r.click())}),r.hasAttribute("tabindex")||(r.tabIndex=0);let e=a.find(({toggle:s})=>s.getAttribute("aria-expanded")==="true");n((e??a[0]).row)});var dt=8;h("focus-drift",(t,{reducedMotion:o})=>{let a=t.querySelector(":scope > .camera_focus");!a||o||(t.addEventListener("pointermove",n=>{if(n.pointerType!=="mouse")return;let e=t.getBoundingClientRect(),s=(n.clientX-e.left)/e.width-.5,r=(n.clientY-e.top)/e.height-.5,d=(s*dt*2).toFixed(1),l=(r*dt*2).toFixed(1);a.style.transform=`translate(${d}px, ${l}px)`}),t.addEventListener("pointerleave",()=>{a.style.transform=""}))});var ut=42,ft=96,Vt=2600,Gt="is-scanned",Xt="is-fresh";h("foundation-rail",(t,{gsap:o,reducedMotion:a})=>{let n=t.closest(".camera_photo"),e=Array.from(t.querySelectorAll(":scope > .foundation_slot"),u=>({element:u,parts:Array.from(u.querySelectorAll(".foundation_photo, .foundation_card")),tile:u.querySelector(".foundation_scan"),setX:o.quickSetter(u,"x","px"),home:0,turn:0,state:null}));if(!n||e.length===0){console.warn("[shopic] foundation-rail expects a .camera_photo tile around a track of .foundation_slot items.",t);return}let s=o.quickSetter(t,"x","px"),r=0,d=0,l=u=>u,f=()=>{let[u]=e,g=u.element.offsetWidth,b=g+(parseFloat(getComputedStyle(t).columnGap)||0);r=b*e.length,d=r/ut*(Vt/1e3),l=o.utils.wrap(-r/2,r/2),r<n.offsetWidth+g&&console.warn(`[shopic] foundation-rail: ${e.length} slots span ${r}px but the tile needs ${n.offsetWidth+g}px to loop without a gap.`,t);let v=n.getBoundingClientRect(),A=v.width/n.offsetWidth||1,N=(u.element.getBoundingClientRect().left-v.left)/A+g/2-n.offsetWidth/2-(Number(o.getProperty(t,"x"))||0)-(Number(o.getProperty(u.element,"x"))||0);e.forEach((C,O)=>{C.home=N+O*b,C.setX(C.turn*r)})},m=u=>u>ft?"unseen":u>ft-d?"fresh":"seen",S=(u,g)=>{if(u.state!==g){u.state=g;for(let b of u.parts)b.classList.toggle(Gt,g!=="unseen");u.tile?.classList.toggle(Xt,g==="fresh")}},L=u=>{if(r){s(-u);for(let g of e){let b=l(g.home-u),v=Math.round((b-(g.home-u))/r);v!==g.turn&&(g.turn=v,g.setX(v*r)),S(g,m(b))}}},H={t:0},x=()=>H.t*r,E=a?null:o.to(H,{t:1,duration:ut,ease:"none",repeat:-1,paused:!0,onUpdate:()=>L(x())});new ResizeObserver(()=>{f(),L(x())}).observe(t),E&&new IntersectionObserver(u=>{E.paused(!u.some(g=>g.isIntersecting))}).observe(t)});var mt="split_line",Bt="split_word",pt="split_word-inner",Wt=t=>{let o=document.createDocumentFragment(),a=[],n=document.createElement("span");n.className=mt,o.appendChild(n);let e=(r,d)=>{if(!r)return;let l=document.createElement("span");l.className=Bt;let f=document.createElement("span");f.className=d?`${pt} ${d}`:pt,f.textContent=r,l.appendChild(f),n.appendChild(l),a.push(f)},s=(r,d)=>{for(let l of r.split(/(\s+)/))l&&(/^\s+$/.test(l)?n.appendChild(document.createTextNode(" ")):e(l,d))};for(let r of Array.from(t.childNodes))r.nodeType===Node.TEXT_NODE?s(r.textContent??""):r instanceof HTMLBRElement?(n=document.createElement("span"),n.className=mt,o.appendChild(n)):r instanceof HTMLElement&&s(r.textContent??"",r.className||void 0);return t.textContent="",t.appendChild(o),a},gt={yPercent:0,duration:.9,ease:"power4.out",stagger:.035};h("headline",(t,{gsap:o,ScrollTrigger:a,reducedMotion:n})=>{if(n){t.style.visibility="visible";return}let e=Wt(t);if(o.set(e,{yPercent:110}),t.style.visibility="visible",t.dataset.animTrigger==="load"||!a){o.to(e,{...gt,delay:.3});return}o.to(e,{...gt,scrollTrigger:{trigger:t,start:"top 85%"}})});var kt=26;h("marquee",(t,{gsap:o,reducedMotion:a})=>{if(a)return;let n=Number(t.dataset.animSets??4),e=Number(t.dataset.animDuration??kt);if(!Number.isFinite(n)||n<2)return;let s=()=>t.scrollWidth/n,r=o.to(t,{x:()=>-s(),duration:e,ease:"none",repeat:-1,modifiers:{x:l=>`${Number.parseFloat(l)%s()}px`}}),d=t.parentElement;d&&(d.addEventListener("pointerenter",()=>r.pause()),d.addEventListener("pointerleave",()=>r.resume()))});var ot=1.15,yt=.18,J=8,z=.55,ht="is-visible",Et="opacity, width, height",Ut=["name","price","packaging","sku"];h("photo-hover",(t,{reducedMotion:o})=>{let a=t.querySelector(":scope > img"),n=t.querySelector(":scope > .detect_layer"),e=t.querySelector(":scope > .camera_focus");if(!a&&!e)return;let s=e?.querySelector(".is-ring")??null,r=e?.querySelector(".is-corners")??null;e&&(!s||!r)&&console.warn("[shopic] photo-hover expects is-ring and is-corners layers inside the reticle.",e);let d=Array.from(t.querySelectorAll(".detect_box")),l=t.querySelector('[data-match="card"]'),f=l?.querySelector('[data-match="thumb"]')??null,m=0,S=0,L=0,H=0,x=0,E=0,u=0,g=null,b=c=>c.width/t.offsetWidth||1,v=(c,p)=>{let w=t.getBoundingClientRect(),M=b(w);return{x:(c-w.left)/M,y:(p-w.top)/M,width:t.offsetWidth,height:t.offsetHeight}},A=c=>{let p=t.getBoundingClientRect(),w=c.getBoundingClientRect(),M=b(p);return{x:(w.left-p.left)/M-J,y:(w.top-p.top)/M-J,w:w.width/M+J*2,h:w.height/M+J*2}},N=()=>{let{x:c,y:p,width:w,height:M}=v(E,u),D=(c/w-.5)*w*(ot-1),F=(p/M-.5)*M*(ot-1),Y=`translate(${D.toFixed(2)}px, ${F.toFixed(2)}px) scale(${ot})`;a&&(a.style.transform=Y),n&&(n.style.transform=Y)},C=()=>{let{x:c,y:p}=v(E,u);return{x:c-(e?.offsetWidth??0)/2,y:p-(e?.offsetHeight??0)/2}},O=(c,p)=>{e&&(e.style.left=`${c.toFixed(2)}px`,e.style.top=`${p.toFixed(2)}px`)},R=()=>{let c=C();O(c.x,c.y),H=c.x,x=c.y,S=0,L=0,r&&(r.style.transform="")},X=()=>{let c=C();O(c.x,c.y),o||(S-=c.x-H,L-=c.y-x),H=c.x,x=c.y},B=c=>{if(!e)return;let p=A(c);O(p.x,p.y),e.style.width=`${p.w.toFixed(2)}px`,e.style.height=`${p.h.toFixed(2)}px`},_=()=>{if(r){if(S-=S*yt,L-=L*yt,Math.abs(S)>.1||Math.abs(L)>.1){r.style.transform=`translate(${S.toFixed(2)}px, ${L.toFixed(2)}px)`;return}S=0,L=0,r.style.transform=""}},W=()=>{g?B(g):X(),_(),m=requestAnimationFrame(W)},P=c=>{if(l){for(let p of Ut){let w=c.dataset[p],M=l.querySelector(`[data-match="${p}"]`);M&&w!==void 0&&(M.textContent=w)}if(f){let p=c.dataset.thumb;p&&(f.removeAttribute("srcset"),f.removeAttribute("sizes"),f.src=p),f.style.display=p?"":"none"}l.classList.add(ht)}},K=c=>{if(g=c,P(c),!!e&&(e.style.transitionProperty="",B(c),r&&(r.style.opacity="0"),s)){let p=(1-z)/2*100;s.style.width=`${z*100}%`,s.style.height=`${z*100}%`,s.style.left=`${p}%`,s.style.top=`${p}%`,s.style.right="auto",s.style.bottom="auto"}},k=c=>{if(!s)return;let p=A(c),{x:w,y:M}=v(E,u),D=(w-p.x)/p.w-.5,F=(M-p.y)/p.h-.5,Y=D*p.w*(1-z),i=F*p.h*(1-z);s.style.setProperty("translate",`${Y.toFixed(2)}px ${i.toFixed(2)}px`)},U=()=>{g=null,l?.classList.remove(ht),e&&(e.style.width="",e.style.height="",e.style.transitionProperty=Et,r&&(r.style.opacity=""),s&&(s.style.width="",s.style.height="",s.style.left="",s.style.top="",s.style.right="",s.style.bottom="",s.style.removeProperty("translate")))},q=c=>{c.pointerType==="mouse"&&(E=c.clientX,u=c.clientY,N(),e&&(e.style.transitionProperty=Et,R(),cancelAnimationFrame(m),m=requestAnimationFrame(W)))},Z=c=>{c.pointerType==="mouse"&&(E=c.clientX,u=c.clientY,N())},$=()=>{cancelAnimationFrame(m),m=0,a&&(a.style.transform=""),n&&(n.style.transform=""),U(),e&&(e.style.left="",e.style.top="",e.style.transitionProperty="",r&&(r.style.transform=""),S=0,L=0)};t.addEventListener("pointerenter",q),t.addEventListener("pointermove",Z),t.addEventListener("pointerleave",$);for(let c of d)c.addEventListener("pointerenter",p=>{p.pointerType==="mouse"&&K(c)}),c.addEventListener("pointermove",()=>{g===c&&k(c)}),c.addEventListener("pointerleave",()=>{g===c&&(U(),R())})});var bt="is-visible";h("reveal",(t,{reducedMotion:o})=>{let a=Number(t.dataset.animDelay??0);if(a&&(t.style.transitionDelay=`${a}ms`),o||!("IntersectionObserver"in window)){t.classList.add(bt);return}let n=new IntersectionObserver(e=>{for(let s of e)s.isIntersecting&&(s.target.classList.add(bt),n.unobserve(s.target))},{threshold:.15});n.observe(t)});h("scramble",(t,{reducedMotion:o})=>{let a={duration:Number(t.dataset.animDuration??1050),stagger:Number(t.dataset.animStagger??.75),reducedMotion:o};if(o||!("IntersectionObserver"in window)){G(t,a);return}let n=new IntersectionObserver(e=>{for(let s of e)s.isIntersecting&&(G(t,{...a,relaunchOnHover:!0}),n.unobserve(s.target))},{threshold:.2});n.observe(t)});var Q=({grouped:t=!1,prefix:o="",suffix:a="",value:n})=>{let e=Math.round(n),s=t?e.toLocaleString("en-US"):String(e);return`${o}${s}${a}`};var Yt=.5,vt="power4.out",zt=.18,Kt="power2.in",Zt=.35,jt=1400,Jt=.15,Qt=420,te=t=>{let o=t.querySelector("[data-stat-value]");return o||console.warn("[shopic] stats row is missing [data-stat-value]",t),o},rt=t=>({grouped:(t.dataset.statGrouped??t.closest('[data-anim="stats"]')?.dataset.statGrouped)==="true",prefix:t.dataset.statPrefix??t.closest('[data-anim="stats"]')?.dataset.statPrefix??"",suffix:t.dataset.statSuffix??t.closest('[data-anim="stats"]')?.dataset.statSuffix??""}),St=(t,o)=>{t.textContent=Q({...rt(t),value:o})},Tt=(t,o)=>{t.classList.toggle("is-hovered",o);for(let a of t.querySelectorAll("[data-stat-label], [data-stat-hover]"))a.classList.toggle("is-hovered",o)},Lt=(t,o,a,n)=>{if(a){St(t,o);return}let e=performance.now(),s=r=>{if(n!==Number(t.dataset.statsGeneration))return;let d=Math.min((r-e)/jt,1),l=1-(1-d)**3;t.textContent=Q({...rt(t),value:o*l}),d<1&&requestAnimationFrame(s)};requestAnimationFrame(s)},ee=(t,{gsap:o,reducedMotion:a})=>{let n=t,e=te(n);if(!e)return;let s=n.dataset.statCount??e.dataset.statCount,r=s===void 0?null:Number(s),d=n.dataset.statTicker??e.dataset.statTicker,l=d===void 0?null:Number(d),f=null,m=0,S=!1,L=()=>{l!==null&&(e.textContent=Q({...rt(e),value:l}))},H=()=>{a||l===null||f!==null||(f=setInterval(()=>{l!==null&&(l+=1+Math.floor(Math.random()*3),L())},Qt))},x=()=>{f!==null&&(clearInterval(f),f=null)},E=()=>{m+=1,e.dataset.statsGeneration=String(m),r!==null?St(e,r):L(),o.set(e,{clearProps:"transform"})},u=b=>{m+=1,e.dataset.statsGeneration=String(m),o.killTweensOf(e),o.set(e,{yPercent:110}),o.to(e,{duration:Yt,ease:vt,yPercent:0}),b&&r!==null&&Lt(e,r,a,m)};if(a){E();return}L(),o.set(e,{yPercent:110});let g=()=>{S||(S=!0,u(!0))};if("IntersectionObserver"in window){let b=new IntersectionObserver(v=>{v.some(A=>A.isIntersecting)&&(g(),b.disconnect())},{threshold:Jt});b.observe(n)}else g();l!==null&&("IntersectionObserver"in window?new IntersectionObserver(v=>{v.some(A=>A.isIntersecting)?H():x()}).observe(n):H()),n.addEventListener("pointerenter",b=>{b.pointerType==="mouse"&&(Tt(n,!0),m+=1,e.dataset.statsGeneration=String(m),o.killTweensOf(e),o.timeline().to(e,{duration:zt,ease:Kt,yPercent:-110}).set(e,{yPercent:110}).to(e,{duration:Zt,ease:vt,onStart:()=>{r!==null&&Lt(e,r,a,m)},yPercent:0}))}),n.addEventListener("pointerleave",()=>Tt(n,!1))};h("stats",ee);var st=t=>String(t).padStart(2,"0");h("timer",t=>{let o=()=>{let a=new Date;t.textContent=`${st(a.getHours())}:${st(a.getMinutes())}:${st(a.getSeconds())}`};o(),setInterval(o,1e3)});var xt="is-active",ne="(max-width: 991px)";h("versus-tabs",t=>{let o=Array.from(t.querySelectorAll('[role="tab"]')),a=t.nextElementSibling,n=a?Array.from(a.querySelectorAll(":scope > *")):[];if(o.length===0||o.length!==n.length){console.warn(`[shopic] versus-tabs expects one tab per panel; found ${o.length} tabs and ${n.length} panels.`,t);return}let e=window.matchMedia(ne),s=d=>{o.forEach((l,f)=>{l.classList.toggle(xt,f===d),l.setAttribute("aria-selected",String(f===d))}),n.forEach((l,f)=>{l.hidden=e.matches&&f!==d})},r=()=>Math.max(0,o.indexOf(t.querySelector(`.${xt}`)));o.forEach((d,l)=>{d.addEventListener("click",()=>s(l)),d.addEventListener("keydown",f=>{(f.key==="Enter"||f.key===" ")&&(f.preventDefault(),s(l))}),d.hasAttribute("tabindex")||(d.tabIndex=0)}),e.addEventListener("change",()=>s(r())),s(r())});var wt=()=>{let{gsap:t,ScrollTrigger:o}=window;if(!t)throw new Error("[shopic] GSAP is not on the page. Enable it in Webflow \u2192 Site Settings \u2192 Custom Code \u2192 GSAP.");return o&&t.registerPlugin(o),{gsap:t,ScrollTrigger:o}},At=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;window.Webflow||(window.Webflow=[]);window.Webflow.push(()=>{let{gsap:t,ScrollTrigger:o}=wt();et({gsap:t,ScrollTrigger:o,reducedMotion:At()})});})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopic",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Custom code bundle for the Shopic Webflow site.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,