svg-scroll-draw 1.6.0 → 1.7.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.
@@ -1,13 +1,13 @@
1
- 'use strict';function ie({bounces:e=3,decay:n=.5}={}){let r=Math.max(1,Math.round(e)),o=Math.max(.01,Math.min(.99,n)),p=Math.sqrt(o),m=0,y=[];for(let a=0;a<r;a++){let c=Math.pow(p,a);y.push(c),m+=c;}let d=[0],h=0;for(let a=0;a<r;a++)h+=y[a]/m,d.push(h);return a=>{if(a<=0)return 0;if(a>=1)return 1;for(let c=0;c<r;c++)if(a<=d[c+1]){let f=(a-d[c])/(d[c+1]-d[c]);if(c===0)return f*(2-f);let T=1-Math.pow(o,c);return T+(1-T)*(2*f-1)*(2*f-1)}return 1}}function se({amplitude:e=1,period:n=.4}={}){let r=Math.max(1,e),o=Math.max(.1,n),p=r<=1?o/4:o/(2*Math.PI)*Math.asin(1/r);return m=>m<=0?0:m>=1?1:r*Math.pow(2,-10*m)*Math.sin((m-p)*(2*Math.PI)/o)+1}var R={linear:e=>e,"ease-in":e=>e*e,"ease-out":e=>e*(2-e),"ease-in-out":e=>e<.5?2*e*e:-1+(4-2*e)*e,spring:e=>1-Math.cos(e*Math.PI*2.5)*Math.pow(1-e,2.2),bounce:ie(),elastic:se()};function G(e="top bottom"){let n=e.trim();if(/^\d+(\.\d+)?%$/.test(n))return {element:"top",viewport:n};let[r="top",o="bottom"]=n.split(/\s+/).filter(Boolean);return {element:r,viewport:o}}function X(e,n,r,o){switch(o){case "top":return e+r;case "center":return e+r+n/2;case "bottom":return e+r+n;default:return e+r}}function _(e,n){if(/^\d+(\.\d+)?%$/.test(e))return n*(parseFloat(e)/100);switch(e){case "top":return 0;case "center":return n/2;case "bottom":return n;default:return n}}function q(e){let n=e.tagName.toLowerCase();if(n==="rect"){let r=parseFloat(e.getAttribute("width")??"0"),o=parseFloat(e.getAttribute("height")??"0");return 2*(r+o)}if(n==="circle"){let r=parseFloat(e.getAttribute("r")??"0");return 2*Math.PI*r}return e.getTotalLength()}function ae(e,n,r){return Math.min(r,Math.max(n,e))}function J(e,n,r,o){return r===n?0:ae((e-n)/(r-n)*o,0,1)}function K(e,n,r,o,p){let m=X(e.top,e.height,n,o.element)-_(o.viewport,r),y=X(e.top,e.height,n,p.element)-_(p.viewport,r);return {tStart:m,tEnd:y}}var Q=["#ff90e8","#ffc900","#5865F2","#22c55e","#f59e0b","#ef4444","#aaa","#60a5fa"];function ce(e,n){let r={destroy:()=>{},replay:()=>{},pause:()=>{},resume:()=>{},seek:()=>{},getProgress:()=>0};if(typeof window>"u")return r;let o=typeof e=="string"?document.querySelector(e):e;if(!o)return console.warn("[svg-scroll-draw/timeline] Container not found:",e),r;let p=o,{trigger:m={},speed:y=1,once:d=false,axis:h="y",tracks:a,onComplete:c,repeat:f,repeatDelay:T=0,debug:Z=false,label:Y}=n,ee=G(m.start??"top bottom"),te=G(m.end??"bottom top"),I=f==="infinite"?1/0:f??0,k,L=a.map(t=>{let u=typeof t.easing=="function"?t.easing:R[t.easing??"linear"]??R.linear,l=Array.from(p.querySelectorAll(t.selector)),s=l.map(i=>q(i));return l.forEach((i,b)=>{i.style.strokeDasharray=`${s[b]}`,i.style.strokeDashoffset=`${s[b]}`,t.fade&&(i.style.opacity="0");}),{...t,elements:l,lengths:s,easeFn:u}}),O=0,N=0,$=false,x=false,w=0,S=false,M=-1,E=0,g=null;Z&&(g=document.createElement("div"),Object.assign(g.style,{position:"fixed",bottom:"16px",left:"16px",zIndex:"9999",background:"rgba(0,0,0,0.88)",backdropFilter:"blur(8px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"10px",padding:"10px 14px",fontFamily:"monospace",fontSize:"11px",color:"#fff",minWidth:"240px",pointerEvents:"none",lineHeight:"1.4"}),document.body.appendChild(g));function ne(t){if(!g)return;let u=Y??(typeof e=="string"?e:"timeline"),l=a.map(({selector:s,from:i,to:b},C)=>{let v=Q[C%Q.length],A=b>i?Math.min(1,Math.max(0,(t-i)/(b-i))):0,F=Math.round(A*100);return `<div style="margin:4px 0">
1
+ 'use strict';function pe({bounces:e=3,decay:n=.5}={}){let r=Math.max(1,Math.round(e)),o=Math.max(.01,Math.min(.99,n)),p=Math.sqrt(o),m=0,M=[];for(let a=0;a<r;a++){let c=Math.pow(p,a);M.push(c),m+=c;}let d=[0],x=0;for(let a=0;a<r;a++)x+=M[a]/m,d.push(x);return a=>{if(a<=0)return 0;if(a>=1)return 1;for(let c=0;c<r;c++)if(a<=d[c+1]){let b=(a-d[c])/(d[c+1]-d[c]);if(c===0)return b*(2-b);let E=1-Math.pow(o,c);return E+(1-E)*(2*b-1)*(2*b-1)}return 1}}function me({amplitude:e=1,period:n=.4}={}){let r=Math.max(1,e),o=Math.max(.1,n),p=r<=1?o/4:o/(2*Math.PI)*Math.asin(1/r);return m=>m<=0?0:m>=1?1:r*Math.pow(2,-10*m)*Math.sin((m-p)*(2*Math.PI)/o)+1}var B={linear:e=>e,"ease-in":e=>e*e,"ease-out":e=>e*(2-e),"ease-in-out":e=>e<.5?2*e*e:-1+(4-2*e)*e,spring:e=>1-Math.cos(e*Math.PI*2.5)*Math.pow(1-e,2.2),bounce:pe(),elastic:me()};function V(e="top bottom"){let n=e.trim();if(/^\d+(\.\d+)?%$/.test(n))return {element:"top",viewport:n};let[r="top",o="bottom"]=n.split(/\s+/).filter(Boolean);return {element:r,viewport:o}}function Z(e,n,r,o){switch(o){case "top":return e+r;case "center":return e+r+n/2;case "bottom":return e+r+n;default:return e+r}}function Y(e,n){if(/^\d+(\.\d+)?%$/.test(e))return n*(parseFloat(e)/100);switch(e){case "top":return 0;case "center":return n/2;case "bottom":return n;default:return n}}function W(e){let n=e.tagName.toLowerCase();if(n==="rect"){let r=parseFloat(e.getAttribute("width")??"0"),o=parseFloat(e.getAttribute("height")??"0");return 2*(r+o)}if(n==="circle"){let r=parseFloat(e.getAttribute("r")??"0");return 2*Math.PI*r}return e.getTotalLength()}function fe(e,n,r){return Math.min(r,Math.max(n,e))}function ee(e,n,r,o){return r===n?0:fe((e-n)/(r-n)*o,0,1)}function te(e,n,r,o,p){let m=Z(e.top,e.height,n,o.element)-Y(o.viewport,r),M=Z(e.top,e.height,n,p.element)-Y(p.viewport,r);return {tStart:m,tEnd:M}}var ne=["#ff90e8","#ffc900","#5865F2","#22c55e","#f59e0b","#ef4444","#aaa","#60a5fa"];function ge(e,n){let r={destroy:()=>{},replay:()=>{},pause:()=>{},resume:()=>{},seek:()=>{},getProgress:()=>0};if(typeof window>"u")return r;let o=typeof e=="string"?document.querySelector(e):e;if(!o)return console.warn("[svg-scroll-draw/timeline] Container not found:",e),r;let p=o,{trigger:m={},speed:M=1,once:d=false,axis:x="y",tracks:a,onComplete:c,repeat:b,repeatDelay:E=0,loop:R=false,loopDuration:re=1500,debug:oe=false,label:ie}=n,se=V(m.start??"top bottom"),ae=V(m.end??"bottom top"),A=b==="infinite"?1/0:b??0,f,L=R===true?1/0:typeof R=="number"?R:0,h=false,G=0,T=L,q=a.map(t=>{let u=typeof t.easing=="function"?t.easing:B[t.easing??"linear"]??B.linear,l=Array.from(p.querySelectorAll(t.selector)),s=l.map(i=>W(i));return l.forEach((i,g)=>{i.style.strokeDasharray=`${s[g]}`,i.style.strokeDashoffset=`${s[g]}`,t.fade&&(i.style.opacity="0");}),{...t,elements:l,lengths:s,easeFn:u}}),H=0,U=0,F=false,y=false,v=0,S=false,D=-1,I=0,w=null;oe&&(w=document.createElement("div"),Object.assign(w.style,{position:"fixed",bottom:"16px",left:"16px",zIndex:"9999",background:"rgba(0,0,0,0.88)",backdropFilter:"blur(8px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"10px",padding:"10px 14px",fontFamily:"monospace",fontSize:"11px",color:"#fff",minWidth:"240px",pointerEvents:"none",lineHeight:"1.4"}),document.body.appendChild(w));function ue(t){if(!w)return;let u=ie??(typeof e=="string"?e:"timeline"),l=a.map(({selector:s,from:i,to:g},j)=>{let $=ne[j%ne.length],z=g>i?Math.min(1,Math.max(0,(t-i)/(g-i))):0,C=Math.round(z*100);return `<div style="margin:4px 0">
2
2
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:2px">
3
- <span style="color:${v};max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${s}</span>
4
- <span style="color:#666;margin-left:8px">${F}%</span>
3
+ <span style="color:${$};max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${s}</span>
4
+ <span style="color:#666;margin-left:8px">${C}%</span>
5
5
  </div>
6
6
  <div style="height:3px;background:#2a2a2a;border-radius:2px;position:relative;overflow:hidden">
7
- <div style="position:absolute;left:${i*100}%;width:${(b-i)*100}%;height:100%;background:${v}33;border-radius:2px"></div>
8
- <div style="position:absolute;left:${i*100}%;width:${(b-i)*A*100}%;height:100%;background:${v};border-radius:2px;transition:width 0.05s linear"></div>
7
+ <div style="position:absolute;left:${i*100}%;width:${(g-i)*100}%;height:100%;background:${$}33;border-radius:2px"></div>
8
+ <div style="position:absolute;left:${i*100}%;width:${(g-i)*z*100}%;height:100%;background:${$};border-radius:2px;transition:width 0.05s linear"></div>
9
9
  </div>
10
- </div>`}).join("");g.innerHTML=`
10
+ </div>`}).join("");w.innerHTML=`
11
11
  <div style="color:#555;margin-bottom:8px;font-size:10px;text-transform:uppercase;letter-spacing:0.12em;border-bottom:1px solid rgba(255,255,255,0.06);padding-bottom:6px">
12
12
  scrollDrawTimeline \xB7 ${u}
13
13
  </div>
@@ -20,4 +20,4 @@
20
20
  <div style="height:2px;background:#2a2a2a;border-radius:1px;overflow:hidden">
21
21
  <div style="height:100%;background:#fff;border-radius:1px;width:${t*100}%;transition:width 0.05s linear"></div>
22
22
  </div>
23
- </div>`;}function j(){return h==="x"?window.scrollX:window.scrollY}function re(){return h==="x"?window.innerWidth:window.innerHeight}function B(){let t=p.getBoundingClientRect(),u=j(),l=h==="x"?t.left:t.top,s=h==="x"?t.width:t.height,i=K({top:l,height:s},u,re(),ee,te);O=i.tStart,N=i.tEnd;}function V(t){p.style.setProperty("--scroll-draw-progress",String(t)),L.forEach(({elements:u,lengths:l,from:s,to:i,easeFn:b,fade:C})=>{let v=i-s,A=v>0?Math.min(1,Math.max(0,(t-s)/v)):0,F=b(A);u.forEach((U,oe)=>{U.style.strokeDashoffset=`${l[oe]*(1-F)}`,C&&(U.style.opacity=String(F));});}),ne(t);}function W(){M=-1,S=false,L.forEach(({elements:t,lengths:u,fade:l})=>{t.forEach((s,i)=>{s.style.strokeDashoffset=`${u[i]}`,l&&(s.style.opacity="0");});}),p.style.setProperty("--scroll-draw-progress","0");}function P(){if(!$||x)return;let t=J(j(),O,N,y);d&&(M=Math.max(M,t),t=M),E=t,V(t),t>=1&&!S?(S=true,c?.(),I>0&&d&&(k=setTimeout(()=>{I!==1/0&&I--,W();},T))):t<1&&!d&&(S=false),w=requestAnimationFrame(P);}B();let H=new IntersectionObserver(t=>{t.forEach(u=>{$=u.isIntersecting,$&&!x?w=requestAnimationFrame(P):cancelAnimationFrame(w);});},{threshold:0});H.observe(p);let z;function D(){clearTimeout(z),z=setTimeout(()=>{L.forEach(({elements:t,lengths:u})=>{t.forEach((l,s)=>{u[s]=q(l),l.style.strokeDasharray=`${u[s]}`;});}),B();},150);}return window.addEventListener("resize",D),window.addEventListener("orientationchange",D),{destroy(){cancelAnimationFrame(w),clearTimeout(z),clearTimeout(k),H.disconnect(),window.removeEventListener("resize",D),window.removeEventListener("orientationchange",D),g&&(g.remove(),g=null);},replay(){I=f==="infinite"?1/0:f??0,clearTimeout(k),W(),x=false;},pause(){x=true,cancelAnimationFrame(w);},resume(){x&&(x=false,$&&(w=requestAnimationFrame(P)));},seek(t){E=Math.min(1,Math.max(0,t)),M=E,x=true,cancelAnimationFrame(w),V(E);},getProgress(){return E}}}exports.scrollDrawTimeline=ce;
23
+ </div>`;}function X(){return x==="x"?window.scrollX:window.scrollY}function le(){return x==="x"?window.innerWidth:window.innerHeight}function _(){let t=p.getBoundingClientRect(),u=X(),l=x==="x"?t.left:t.top,s=x==="x"?t.width:t.height,i=te({top:l,height:s},u,le(),se,ae);H=i.tStart,U=i.tEnd;}function J(t){p.style.setProperty("--scroll-draw-progress",String(t)),q.forEach(({elements:u,lengths:l,from:s,to:i,easeFn:g,fade:j})=>{let $=i-s,z=$>0?Math.min(1,Math.max(0,(t-s)/$)):0,C=g(z);u.forEach((Q,ce)=>{Q.style.strokeDashoffset=`${l[ce]*(1-C)}`,j&&(Q.style.opacity=String(C));});}),ue(t);}function k(){D=-1,I=0,S=false,q.forEach(({elements:t,lengths:u,fade:l})=>{t.forEach((s,i)=>{s.style.strokeDashoffset=`${u[i]}`,l&&(s.style.opacity="0");});}),p.style.setProperty("--scroll-draw-progress","0");}function O(){if(!F||y)return;let t;h?t=Math.min(1,(performance.now()-G)/re):(t=ee(X(),H,U,M),(d||L>0)&&(D=Math.max(D,t),t=D)),I=t,J(t),t>=1&&!S?(S=true,c?.(),L>0&&!h&&!f?f=setTimeout(()=>{f=void 0,T!==1/0&&T--,k(),h=true,G=performance.now();},E):A>0&&d&&!h&&!f&&(f=setTimeout(()=>{f=void 0,A!==1/0&&A--,k();},E))):!h&&t<1&&!d&&(S=false),h&&t>=1&&!f&&(S=false,T>0?f=setTimeout(()=>{f=void 0,T!==1/0&&T--,k(),G=performance.now();},E):h=false),v=requestAnimationFrame(O);}_();let K=new IntersectionObserver(t=>{t.forEach(u=>{F=u.isIntersecting,F&&!y?v=requestAnimationFrame(O):cancelAnimationFrame(v);});},{threshold:0});K.observe(p);let N;function P(){clearTimeout(N),N=setTimeout(()=>{q.forEach(({elements:t,lengths:u})=>{t.forEach((l,s)=>{u[s]=W(l),l.style.strokeDasharray=`${u[s]}`;});}),_();},150);}return window.addEventListener("resize",P),window.addEventListener("orientationchange",P),{destroy(){cancelAnimationFrame(v),clearTimeout(N),clearTimeout(f),K.disconnect(),window.removeEventListener("resize",P),window.removeEventListener("orientationchange",P),w&&(w.remove(),w=null);},replay(){A=b==="infinite"?1/0:b??0,T=L,h=false,clearTimeout(f),f=void 0,k(),y=false;},pause(){y=true,cancelAnimationFrame(v);},resume(){y&&(y=false,F&&(v=requestAnimationFrame(O)));},seek(t){I=Math.min(1,Math.max(0,t)),D=I,y=true,cancelAnimationFrame(v),J(I);},getProgress(){return I}}}exports.scrollDrawTimeline=ge;
@@ -50,6 +50,17 @@ interface ScrollDrawTimelineOptions {
50
50
  repeat?: number | 'infinite';
51
51
  /** Milliseconds to wait before each repeat. Default 0. */
52
52
  repeatDelay?: number;
53
+ /**
54
+ * After the scroll-driven animation completes, automatically replay the full
55
+ * timeline as a time-driven loop — no further scroll input needed. Use `true`
56
+ * to loop infinitely or a number to loop N additional times.
57
+ *
58
+ * Each iteration plays over `loopDuration` milliseconds, then waits
59
+ * `repeatDelay` before the next iteration begins.
60
+ */
61
+ loop?: boolean | number;
62
+ /** Duration of each time-driven loop iteration in milliseconds. Default 1500. */
63
+ loopDuration?: number;
53
64
  /**
54
65
  * Show a developer overlay panel visualising each track's window and live
55
66
  * fill progress. Injected into document.body as a fixed HUD, removed on destroy().
@@ -50,6 +50,17 @@ interface ScrollDrawTimelineOptions {
50
50
  repeat?: number | 'infinite';
51
51
  /** Milliseconds to wait before each repeat. Default 0. */
52
52
  repeatDelay?: number;
53
+ /**
54
+ * After the scroll-driven animation completes, automatically replay the full
55
+ * timeline as a time-driven loop — no further scroll input needed. Use `true`
56
+ * to loop infinitely or a number to loop N additional times.
57
+ *
58
+ * Each iteration plays over `loopDuration` milliseconds, then waits
59
+ * `repeatDelay` before the next iteration begins.
60
+ */
61
+ loop?: boolean | number;
62
+ /** Duration of each time-driven loop iteration in milliseconds. Default 1500. */
63
+ loopDuration?: number;
53
64
  /**
54
65
  * Show a developer overlay panel visualising each track's window and live
55
66
  * fill progress. Injected into document.body as a fixed HUD, removed on destroy().
@@ -1,13 +1,13 @@
1
- function ie({bounces:e=3,decay:n=.5}={}){let r=Math.max(1,Math.round(e)),o=Math.max(.01,Math.min(.99,n)),p=Math.sqrt(o),m=0,y=[];for(let a=0;a<r;a++){let c=Math.pow(p,a);y.push(c),m+=c;}let d=[0],h=0;for(let a=0;a<r;a++)h+=y[a]/m,d.push(h);return a=>{if(a<=0)return 0;if(a>=1)return 1;for(let c=0;c<r;c++)if(a<=d[c+1]){let f=(a-d[c])/(d[c+1]-d[c]);if(c===0)return f*(2-f);let T=1-Math.pow(o,c);return T+(1-T)*(2*f-1)*(2*f-1)}return 1}}function se({amplitude:e=1,period:n=.4}={}){let r=Math.max(1,e),o=Math.max(.1,n),p=r<=1?o/4:o/(2*Math.PI)*Math.asin(1/r);return m=>m<=0?0:m>=1?1:r*Math.pow(2,-10*m)*Math.sin((m-p)*(2*Math.PI)/o)+1}var R={linear:e=>e,"ease-in":e=>e*e,"ease-out":e=>e*(2-e),"ease-in-out":e=>e<.5?2*e*e:-1+(4-2*e)*e,spring:e=>1-Math.cos(e*Math.PI*2.5)*Math.pow(1-e,2.2),bounce:ie(),elastic:se()};function G(e="top bottom"){let n=e.trim();if(/^\d+(\.\d+)?%$/.test(n))return {element:"top",viewport:n};let[r="top",o="bottom"]=n.split(/\s+/).filter(Boolean);return {element:r,viewport:o}}function X(e,n,r,o){switch(o){case "top":return e+r;case "center":return e+r+n/2;case "bottom":return e+r+n;default:return e+r}}function _(e,n){if(/^\d+(\.\d+)?%$/.test(e))return n*(parseFloat(e)/100);switch(e){case "top":return 0;case "center":return n/2;case "bottom":return n;default:return n}}function q(e){let n=e.tagName.toLowerCase();if(n==="rect"){let r=parseFloat(e.getAttribute("width")??"0"),o=parseFloat(e.getAttribute("height")??"0");return 2*(r+o)}if(n==="circle"){let r=parseFloat(e.getAttribute("r")??"0");return 2*Math.PI*r}return e.getTotalLength()}function ae(e,n,r){return Math.min(r,Math.max(n,e))}function J(e,n,r,o){return r===n?0:ae((e-n)/(r-n)*o,0,1)}function K(e,n,r,o,p){let m=X(e.top,e.height,n,o.element)-_(o.viewport,r),y=X(e.top,e.height,n,p.element)-_(p.viewport,r);return {tStart:m,tEnd:y}}var Q=["#ff90e8","#ffc900","#5865F2","#22c55e","#f59e0b","#ef4444","#aaa","#60a5fa"];function ce(e,n){let r={destroy:()=>{},replay:()=>{},pause:()=>{},resume:()=>{},seek:()=>{},getProgress:()=>0};if(typeof window>"u")return r;let o=typeof e=="string"?document.querySelector(e):e;if(!o)return console.warn("[svg-scroll-draw/timeline] Container not found:",e),r;let p=o,{trigger:m={},speed:y=1,once:d=false,axis:h="y",tracks:a,onComplete:c,repeat:f,repeatDelay:T=0,debug:Z=false,label:Y}=n,ee=G(m.start??"top bottom"),te=G(m.end??"bottom top"),I=f==="infinite"?1/0:f??0,k,L=a.map(t=>{let u=typeof t.easing=="function"?t.easing:R[t.easing??"linear"]??R.linear,l=Array.from(p.querySelectorAll(t.selector)),s=l.map(i=>q(i));return l.forEach((i,b)=>{i.style.strokeDasharray=`${s[b]}`,i.style.strokeDashoffset=`${s[b]}`,t.fade&&(i.style.opacity="0");}),{...t,elements:l,lengths:s,easeFn:u}}),O=0,N=0,$=false,x=false,w=0,S=false,M=-1,E=0,g=null;Z&&(g=document.createElement("div"),Object.assign(g.style,{position:"fixed",bottom:"16px",left:"16px",zIndex:"9999",background:"rgba(0,0,0,0.88)",backdropFilter:"blur(8px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"10px",padding:"10px 14px",fontFamily:"monospace",fontSize:"11px",color:"#fff",minWidth:"240px",pointerEvents:"none",lineHeight:"1.4"}),document.body.appendChild(g));function ne(t){if(!g)return;let u=Y??(typeof e=="string"?e:"timeline"),l=a.map(({selector:s,from:i,to:b},C)=>{let v=Q[C%Q.length],A=b>i?Math.min(1,Math.max(0,(t-i)/(b-i))):0,F=Math.round(A*100);return `<div style="margin:4px 0">
1
+ function pe({bounces:e=3,decay:n=.5}={}){let r=Math.max(1,Math.round(e)),o=Math.max(.01,Math.min(.99,n)),p=Math.sqrt(o),m=0,M=[];for(let a=0;a<r;a++){let c=Math.pow(p,a);M.push(c),m+=c;}let d=[0],x=0;for(let a=0;a<r;a++)x+=M[a]/m,d.push(x);return a=>{if(a<=0)return 0;if(a>=1)return 1;for(let c=0;c<r;c++)if(a<=d[c+1]){let b=(a-d[c])/(d[c+1]-d[c]);if(c===0)return b*(2-b);let E=1-Math.pow(o,c);return E+(1-E)*(2*b-1)*(2*b-1)}return 1}}function me({amplitude:e=1,period:n=.4}={}){let r=Math.max(1,e),o=Math.max(.1,n),p=r<=1?o/4:o/(2*Math.PI)*Math.asin(1/r);return m=>m<=0?0:m>=1?1:r*Math.pow(2,-10*m)*Math.sin((m-p)*(2*Math.PI)/o)+1}var B={linear:e=>e,"ease-in":e=>e*e,"ease-out":e=>e*(2-e),"ease-in-out":e=>e<.5?2*e*e:-1+(4-2*e)*e,spring:e=>1-Math.cos(e*Math.PI*2.5)*Math.pow(1-e,2.2),bounce:pe(),elastic:me()};function V(e="top bottom"){let n=e.trim();if(/^\d+(\.\d+)?%$/.test(n))return {element:"top",viewport:n};let[r="top",o="bottom"]=n.split(/\s+/).filter(Boolean);return {element:r,viewport:o}}function Z(e,n,r,o){switch(o){case "top":return e+r;case "center":return e+r+n/2;case "bottom":return e+r+n;default:return e+r}}function Y(e,n){if(/^\d+(\.\d+)?%$/.test(e))return n*(parseFloat(e)/100);switch(e){case "top":return 0;case "center":return n/2;case "bottom":return n;default:return n}}function W(e){let n=e.tagName.toLowerCase();if(n==="rect"){let r=parseFloat(e.getAttribute("width")??"0"),o=parseFloat(e.getAttribute("height")??"0");return 2*(r+o)}if(n==="circle"){let r=parseFloat(e.getAttribute("r")??"0");return 2*Math.PI*r}return e.getTotalLength()}function fe(e,n,r){return Math.min(r,Math.max(n,e))}function ee(e,n,r,o){return r===n?0:fe((e-n)/(r-n)*o,0,1)}function te(e,n,r,o,p){let m=Z(e.top,e.height,n,o.element)-Y(o.viewport,r),M=Z(e.top,e.height,n,p.element)-Y(p.viewport,r);return {tStart:m,tEnd:M}}var ne=["#ff90e8","#ffc900","#5865F2","#22c55e","#f59e0b","#ef4444","#aaa","#60a5fa"];function ge(e,n){let r={destroy:()=>{},replay:()=>{},pause:()=>{},resume:()=>{},seek:()=>{},getProgress:()=>0};if(typeof window>"u")return r;let o=typeof e=="string"?document.querySelector(e):e;if(!o)return console.warn("[svg-scroll-draw/timeline] Container not found:",e),r;let p=o,{trigger:m={},speed:M=1,once:d=false,axis:x="y",tracks:a,onComplete:c,repeat:b,repeatDelay:E=0,loop:R=false,loopDuration:re=1500,debug:oe=false,label:ie}=n,se=V(m.start??"top bottom"),ae=V(m.end??"bottom top"),A=b==="infinite"?1/0:b??0,f,L=R===true?1/0:typeof R=="number"?R:0,h=false,G=0,T=L,q=a.map(t=>{let u=typeof t.easing=="function"?t.easing:B[t.easing??"linear"]??B.linear,l=Array.from(p.querySelectorAll(t.selector)),s=l.map(i=>W(i));return l.forEach((i,g)=>{i.style.strokeDasharray=`${s[g]}`,i.style.strokeDashoffset=`${s[g]}`,t.fade&&(i.style.opacity="0");}),{...t,elements:l,lengths:s,easeFn:u}}),H=0,U=0,F=false,y=false,v=0,S=false,D=-1,I=0,w=null;oe&&(w=document.createElement("div"),Object.assign(w.style,{position:"fixed",bottom:"16px",left:"16px",zIndex:"9999",background:"rgba(0,0,0,0.88)",backdropFilter:"blur(8px)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"10px",padding:"10px 14px",fontFamily:"monospace",fontSize:"11px",color:"#fff",minWidth:"240px",pointerEvents:"none",lineHeight:"1.4"}),document.body.appendChild(w));function ue(t){if(!w)return;let u=ie??(typeof e=="string"?e:"timeline"),l=a.map(({selector:s,from:i,to:g},j)=>{let $=ne[j%ne.length],z=g>i?Math.min(1,Math.max(0,(t-i)/(g-i))):0,C=Math.round(z*100);return `<div style="margin:4px 0">
2
2
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:2px">
3
- <span style="color:${v};max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${s}</span>
4
- <span style="color:#666;margin-left:8px">${F}%</span>
3
+ <span style="color:${$};max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${s}</span>
4
+ <span style="color:#666;margin-left:8px">${C}%</span>
5
5
  </div>
6
6
  <div style="height:3px;background:#2a2a2a;border-radius:2px;position:relative;overflow:hidden">
7
- <div style="position:absolute;left:${i*100}%;width:${(b-i)*100}%;height:100%;background:${v}33;border-radius:2px"></div>
8
- <div style="position:absolute;left:${i*100}%;width:${(b-i)*A*100}%;height:100%;background:${v};border-radius:2px;transition:width 0.05s linear"></div>
7
+ <div style="position:absolute;left:${i*100}%;width:${(g-i)*100}%;height:100%;background:${$}33;border-radius:2px"></div>
8
+ <div style="position:absolute;left:${i*100}%;width:${(g-i)*z*100}%;height:100%;background:${$};border-radius:2px;transition:width 0.05s linear"></div>
9
9
  </div>
10
- </div>`}).join("");g.innerHTML=`
10
+ </div>`}).join("");w.innerHTML=`
11
11
  <div style="color:#555;margin-bottom:8px;font-size:10px;text-transform:uppercase;letter-spacing:0.12em;border-bottom:1px solid rgba(255,255,255,0.06);padding-bottom:6px">
12
12
  scrollDrawTimeline \xB7 ${u}
13
13
  </div>
@@ -20,4 +20,4 @@ function ie({bounces:e=3,decay:n=.5}={}){let r=Math.max(1,Math.round(e)),o=Math.
20
20
  <div style="height:2px;background:#2a2a2a;border-radius:1px;overflow:hidden">
21
21
  <div style="height:100%;background:#fff;border-radius:1px;width:${t*100}%;transition:width 0.05s linear"></div>
22
22
  </div>
23
- </div>`;}function j(){return h==="x"?window.scrollX:window.scrollY}function re(){return h==="x"?window.innerWidth:window.innerHeight}function B(){let t=p.getBoundingClientRect(),u=j(),l=h==="x"?t.left:t.top,s=h==="x"?t.width:t.height,i=K({top:l,height:s},u,re(),ee,te);O=i.tStart,N=i.tEnd;}function V(t){p.style.setProperty("--scroll-draw-progress",String(t)),L.forEach(({elements:u,lengths:l,from:s,to:i,easeFn:b,fade:C})=>{let v=i-s,A=v>0?Math.min(1,Math.max(0,(t-s)/v)):0,F=b(A);u.forEach((U,oe)=>{U.style.strokeDashoffset=`${l[oe]*(1-F)}`,C&&(U.style.opacity=String(F));});}),ne(t);}function W(){M=-1,S=false,L.forEach(({elements:t,lengths:u,fade:l})=>{t.forEach((s,i)=>{s.style.strokeDashoffset=`${u[i]}`,l&&(s.style.opacity="0");});}),p.style.setProperty("--scroll-draw-progress","0");}function P(){if(!$||x)return;let t=J(j(),O,N,y);d&&(M=Math.max(M,t),t=M),E=t,V(t),t>=1&&!S?(S=true,c?.(),I>0&&d&&(k=setTimeout(()=>{I!==1/0&&I--,W();},T))):t<1&&!d&&(S=false),w=requestAnimationFrame(P);}B();let H=new IntersectionObserver(t=>{t.forEach(u=>{$=u.isIntersecting,$&&!x?w=requestAnimationFrame(P):cancelAnimationFrame(w);});},{threshold:0});H.observe(p);let z;function D(){clearTimeout(z),z=setTimeout(()=>{L.forEach(({elements:t,lengths:u})=>{t.forEach((l,s)=>{u[s]=q(l),l.style.strokeDasharray=`${u[s]}`;});}),B();},150);}return window.addEventListener("resize",D),window.addEventListener("orientationchange",D),{destroy(){cancelAnimationFrame(w),clearTimeout(z),clearTimeout(k),H.disconnect(),window.removeEventListener("resize",D),window.removeEventListener("orientationchange",D),g&&(g.remove(),g=null);},replay(){I=f==="infinite"?1/0:f??0,clearTimeout(k),W(),x=false;},pause(){x=true,cancelAnimationFrame(w);},resume(){x&&(x=false,$&&(w=requestAnimationFrame(P)));},seek(t){E=Math.min(1,Math.max(0,t)),M=E,x=true,cancelAnimationFrame(w),V(E);},getProgress(){return E}}}export{ce as scrollDrawTimeline};
23
+ </div>`;}function X(){return x==="x"?window.scrollX:window.scrollY}function le(){return x==="x"?window.innerWidth:window.innerHeight}function _(){let t=p.getBoundingClientRect(),u=X(),l=x==="x"?t.left:t.top,s=x==="x"?t.width:t.height,i=te({top:l,height:s},u,le(),se,ae);H=i.tStart,U=i.tEnd;}function J(t){p.style.setProperty("--scroll-draw-progress",String(t)),q.forEach(({elements:u,lengths:l,from:s,to:i,easeFn:g,fade:j})=>{let $=i-s,z=$>0?Math.min(1,Math.max(0,(t-s)/$)):0,C=g(z);u.forEach((Q,ce)=>{Q.style.strokeDashoffset=`${l[ce]*(1-C)}`,j&&(Q.style.opacity=String(C));});}),ue(t);}function k(){D=-1,I=0,S=false,q.forEach(({elements:t,lengths:u,fade:l})=>{t.forEach((s,i)=>{s.style.strokeDashoffset=`${u[i]}`,l&&(s.style.opacity="0");});}),p.style.setProperty("--scroll-draw-progress","0");}function O(){if(!F||y)return;let t;h?t=Math.min(1,(performance.now()-G)/re):(t=ee(X(),H,U,M),(d||L>0)&&(D=Math.max(D,t),t=D)),I=t,J(t),t>=1&&!S?(S=true,c?.(),L>0&&!h&&!f?f=setTimeout(()=>{f=void 0,T!==1/0&&T--,k(),h=true,G=performance.now();},E):A>0&&d&&!h&&!f&&(f=setTimeout(()=>{f=void 0,A!==1/0&&A--,k();},E))):!h&&t<1&&!d&&(S=false),h&&t>=1&&!f&&(S=false,T>0?f=setTimeout(()=>{f=void 0,T!==1/0&&T--,k(),G=performance.now();},E):h=false),v=requestAnimationFrame(O);}_();let K=new IntersectionObserver(t=>{t.forEach(u=>{F=u.isIntersecting,F&&!y?v=requestAnimationFrame(O):cancelAnimationFrame(v);});},{threshold:0});K.observe(p);let N;function P(){clearTimeout(N),N=setTimeout(()=>{q.forEach(({elements:t,lengths:u})=>{t.forEach((l,s)=>{u[s]=W(l),l.style.strokeDasharray=`${u[s]}`;});}),_();},150);}return window.addEventListener("resize",P),window.addEventListener("orientationchange",P),{destroy(){cancelAnimationFrame(v),clearTimeout(N),clearTimeout(f),K.disconnect(),window.removeEventListener("resize",P),window.removeEventListener("orientationchange",P),w&&(w.remove(),w=null);},replay(){A=b==="infinite"?1/0:b??0,T=L,h=false,clearTimeout(f),f=void 0,k(),y=false;},pause(){y=true,cancelAnimationFrame(v);},resume(){y&&(y=false,F&&(v=requestAnimationFrame(O)));},seek(t){I=Math.min(1,Math.max(0,t)),D=I,y=true,cancelAnimationFrame(v),J(I);},getProgress(){return I}}}export{ge as scrollDrawTimeline};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svg-scroll-draw",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Scroll-driven SVG path drawing animation library — zero dependencies, ~4.4 KB gzipped, works with React, Vue, and vanilla JS",
5
5
  "keywords": [
6
6
  "svg",