svg-scroll-draw 2.12.0 → 2.14.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 CHANGED
@@ -32,6 +32,7 @@
32
32
  | `devtools` | `svg-scroll-draw/devtools` | Visual overlay showing every active animation's triggers and progress. Dev-only. |
33
33
  | `AOS` | `svg-scroll-draw/aos` | Drop-in replacement for AOS: same `AOS.init()`, same `data-aos` markup, no `aos.css`. |
34
34
  | `ScrollReveal` | `svg-scroll-draw/scrollreveal` | Drop-in replacement for ScrollReveal.js 4, MIT instead of GPL-3.0. |
35
+ | `Vivus` | `svg-scroll-draw/vivus` | Drop-in replacement for vivus 0.4: same `new Vivus()` API and output. |
35
36
 
36
37
  All APIs return the same instance object: `{ destroy, replay, pause, resume, seek, getProgress }`.
37
38
 
@@ -362,7 +363,7 @@ import { ScrollDraw } from 'svg-scroll-draw/vue';
362
363
  ## AOS drop-in — switch from AOS in one line
363
364
 
364
365
  Already using [AOS](https://github.com/michalsnik/aos)? `svg-scroll-draw/aos` speaks its API and
365
- reads its markup, so the move is an import change. Keep every `data-aos`, `data-aos-offset`,
366
+ reads its markup, so the move is an import change — or one command: `npx svg-scroll-draw migrate`. Keep every `data-aos`, `data-aos-offset`,
366
367
  `data-aos-delay`, `data-aos-anchor-placement` and custom animation; delete `aos.css` — the styles ship
367
368
  inside the module. 3.0 KB gzipped with the styles, against 6.7 KB for AOS 2.3.4 with its stylesheet.
368
369
 
@@ -402,7 +403,8 @@ Differences, on purpose:
402
403
 
403
404
  On [ScrollReveal](https://scrollrevealjs.org)? It is GPL-3.0 (with a paid licence for commercial work)
404
405
  and has not shipped since 4.0.9. `svg-scroll-draw/scrollreveal` is an independent, MIT-licensed
405
- implementation of the same API, so the move is an import change. 4.5 KB gzipped, against 5.6 KB.
406
+ implementation of the same API, so the move is an import change — or one command: `npx svg-scroll-draw migrate`.
407
+ 4.5 KB gzipped, against 5.6 KB.
406
408
 
407
409
  ```diff
408
410
  - import ScrollReveal from 'scrollreveal';
@@ -430,6 +432,36 @@ Differences, on purpose:
430
432
 
431
433
  ---
432
434
 
435
+ ## vivus drop-in — keep your `new Vivus()` code
436
+
437
+ On [vivus](https://github.com/maxwellito/vivus)? It has not shipped since 0.4.6 (April 2021).
438
+ `svg-scroll-draw/vivus` runs the same API, so the move is an import change — or one command:
439
+ `npx svg-scroll-draw migrate`. 3.9 KB gzipped, against 4.1 KB.
440
+
441
+ ```diff
442
+ - import Vivus from 'vivus';
443
+ + import Vivus from 'svg-scroll-draw/vivus';
444
+
445
+ new Vivus('my-svg', { type: 'oneByOne', duration: 200 }, () => console.log('drawn'));
446
+ ```
447
+
448
+ No bundler? `<script src="https://unpkg.com/svg-scroll-draw/dist/cdn/vivus.global.js"></script>`
449
+ defines `window.Vivus`. With CommonJS, `require('svg-scroll-draw/vivus').default` is the class.
450
+
451
+ Every option, every animation type (`delayed`, `sync`, `async`, `nsync`, `oneByOne`, `scenario`,
452
+ `scenario-sync`), the `start` modes, `file` and `<object>` loading, the `data-start` / `data-duration` /
453
+ `data-delay` / `data-async` / `data-ignore` attributes, `Vivus.EASE` and the other timing functions, and
454
+ `play` / `stop` / `reset` / `finish` / `setFrameProgress` / `getStatus` / `destroy` / `recalc` behave as
455
+ in 0.4.6. Shapes become `<path>`s with the same `d` strings, and dashes get the same values: the browser
456
+ suite runs vivus 0.4.6 beside it across nine configurations and requires the SVG markup to match exactly
457
+ at every point of the animation. Like vivus, the clock is the animation frame.
458
+
459
+ One difference, on purpose: under `prefers-reduced-motion: reduce`, `play()` jumps to the end and still
460
+ fires its callbacks. When you want the stroke to follow the scroll instead of a clock, use
461
+ [`scrollDraw`](#scrolldraw--svg-path-drawing-v1-api-unchanged) from the same package.
462
+
463
+ ---
464
+
433
465
  ## Instance API
434
466
 
435
467
  Every function returns the same instance object:
@@ -522,6 +554,7 @@ devtools.highlight('#my-element'); // outline for 2 seconds
522
554
  | `svg-scroll-draw/devtools` | `devtools` (dev-only) |
523
555
  | `svg-scroll-draw/aos` | `AOS` (default), `init`, `refresh`, `refreshHard`, `destroy` |
524
556
  | `svg-scroll-draw/scrollreveal` | `ScrollReveal` (default and named) |
557
+ | `svg-scroll-draw/vivus` | `Vivus` (default and named) |
525
558
 
526
559
  ---
527
560
 
@@ -535,6 +568,7 @@ devtools.highlight('#my-element'); // outline for 2 seconds
535
568
  | `svg-scroll-draw/text` | 2.5 KB |
536
569
  | `svg-scroll-draw/video` | 2.0 KB |
537
570
  | `svg-scroll-draw/scrollreveal` | 4.5 KB |
571
+ | `svg-scroll-draw/vivus` | 3.9 KB |
538
572
  | `svg-scroll-draw/aos` (styles included) | 3.0 KB |
539
573
  | `svg-scroll-draw/snap` | 1.7 KB |
540
574
  | `svg-scroll-draw/devtools` | 1.7 KB (dev only) |
@@ -571,6 +605,19 @@ npx svg-scroll-draw init
571
605
 
572
606
  Scaffolds a ready-to-use starter file for React, Vue, Svelte, Solid, or Vanilla JS.
573
607
 
608
+ ### Switching from AOS, ScrollReveal or vivus
609
+
610
+ ```bash
611
+ npx svg-scroll-draw migrate --dry-run # see what would change
612
+ npx svg-scroll-draw migrate # apply it
613
+ ```
614
+
615
+ Points every `import` / `require` of `aos`, `scrollreveal` and `vivus` at the matching drop-in, swaps CDN
616
+ `<script>` tags for the script-tag builds (dropping any stale `integrity` hash), removes AOS's `aos.css`
617
+ imports, `<link>`s and `@import`s, and swaps the dependency in `package.json`. It rewrites module names,
618
+ URLs and dependency entries only — never the code that uses them — skips `node_modules` and build output,
619
+ and will not write over uncommitted git changes unless you pass `--force`.
620
+
574
621
  ---
575
622
 
576
623
  ## Browser support
@@ -0,0 +1 @@
1
+ "use strict";(()=>{function g(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches}function m(r,...t){}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return!1;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],S="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return`M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var x={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return`M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return`M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function A(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n}let i=x[t.tagName.toLowerCase()](e),s=document.createElementNS(S,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t)}}var c=class c{constructor(t,e,i){this.isReady=!1;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=!1;this.reverseStack=!1;this.selfDestroy=!1;this.ignoreInvisible=!1;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init()}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=!0,this.init()}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=!0;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=!0,this.init())};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:!1,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{})}mapping(){let t=0,e=0,i=0,s=!1,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:!1},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=!0,s=!0}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o)}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case"delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case"oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case"sync":case"async":case"nsync":n.startAt=0,n.duration=this.duration;break;case"scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case"scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration})}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()))}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`}this.trace(),this.mustRecalcScale=null}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else{this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished()}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this)}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i))})}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(!0);e.el.parentNode?.replaceChild(i,e.el),e.el=i}init(){this.frameLength=0,this.currentFrame=0,this.map=[],A(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this)}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null)};this.viewportListener=t,window.addEventListener("scroll",t),t()}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e)})}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return!i.width&&!i.height}return!1}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,w=p;globalThis.Vivus=w;})();
package/dist/cli/init.js CHANGED
@@ -25,8 +25,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli/init.ts
27
27
  var readline = __toESM(require("readline"));
28
- var fs = __toESM(require("fs"));
29
- var path = __toESM(require("path"));
28
+ var fs2 = __toESM(require("fs"));
29
+ var path2 = __toESM(require("path"));
30
30
 
31
31
  // src/cli/generators.ts
32
32
  var SAMPLE_SVG_JSX = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100">
@@ -138,6 +138,254 @@ function needsSelector(framework) {
138
138
  return framework === "vanilla";
139
139
  }
140
140
 
141
+ // src/cli/migrate.ts
142
+ var fs = __toESM(require("fs"));
143
+ var path = __toESM(require("path"));
144
+ var import_node_child_process = require("child_process");
145
+ var LIBS = ["aos", "scrollreveal", "vivus"];
146
+ var LABEL = { aos: "AOS", scrollreveal: "ScrollReveal", vivus: "vivus" };
147
+ var esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
148
+ function rewriteSpecifiers(src, changes) {
149
+ let out = src;
150
+ for (const lib of LIBS) {
151
+ const spec = lib === "aos" ? `aos(?:\\/dist\\/aos(?:\\.js)?)?` : esc(lib);
152
+ const target = `svg-scroll-draw/${lib}`;
153
+ const fromRe = new RegExp(`(\\bfrom\\s*)(['"])${spec}\\2`, "g");
154
+ const dynRe = new RegExp(`(\\bimport\\s*\\(\\s*)(['"])${spec}\\2(\\s*\\))`, "g");
155
+ const reqRe = new RegExp(`(\\brequire\\s*\\(\\s*)(['"])${spec}\\2(\\s*\\))`, "g");
156
+ let n = 0;
157
+ out = out.replace(fromRe, (_m, pre, q) => {
158
+ n++;
159
+ return `${pre}${q}${target}${q}`;
160
+ });
161
+ out = out.replace(dynRe, (_m, pre, q, post) => {
162
+ n++;
163
+ return `${pre}${q}${target}${q}${post}`;
164
+ });
165
+ out = out.replace(reqRe, (_m, pre, q, post) => {
166
+ n++;
167
+ return lib === "aos" ? `${pre}${q}${target}${q}${post}` : `${pre}${q}${target}${q}${post}.default`;
168
+ });
169
+ if (n) changes.push(`${LABEL[lib]}: ${n} import${n === 1 ? "" : "s"} \u2192 ${target}`);
170
+ }
171
+ return out;
172
+ }
173
+ function dropAosCssImports(src, changes) {
174
+ let n = 0;
175
+ const out = src.replace(/^[ \t]*import\s+(['"])aos\/dist\/aos(?:\.min)?\.css\1;?[ \t]*\r?\n?/gm, () => {
176
+ n++;
177
+ return "";
178
+ }).replace(/^[ \t]*require\s*\(\s*(['"])aos\/dist\/aos(?:\.min)?\.css\1\s*\);?[ \t]*\r?\n?/gm, () => {
179
+ n++;
180
+ return "";
181
+ });
182
+ if (n) changes.push(`AOS: removed ${n} aos.css import${n === 1 ? "" : "s"} (the drop-in ships its styles)`);
183
+ return out;
184
+ }
185
+ var SCRIPT_URL = {
186
+ aos: /^(?:https?:)?\/\/(?:unpkg\.com\/aos(?:@[^/]+)?(?:\/dist\/aos(?:\.min)?\.js)?|cdn\.jsdelivr\.net\/npm\/aos(?:@[^/]+)?(?:\/dist\/aos(?:\.min)?\.js)?|cdnjs\.cloudflare\.com\/ajax\/libs\/aos\/[^/]+\/aos(?:\.min)?\.js)$|(?:^|\/)node_modules\/aos\/dist\/aos(?:\.min)?\.js$/,
187
+ scrollreveal: /^(?:https?:)?\/\/(?:unpkg\.com\/scrollreveal(?:@[^/]+)?(?:\/dist\/scrollreveal(?:\.min)?\.js)?|cdn\.jsdelivr\.net\/npm\/scrollreveal(?:@[^/]+)?(?:\/dist\/scrollreveal(?:\.min)?\.js)?|cdnjs\.cloudflare\.com\/ajax\/libs\/scrollReveal\.js\/[^/]+\/scrollreveal(?:\.min)?\.js)$|(?:^|\/)node_modules\/scrollreveal\/dist\/scrollreveal(?:\.min)?\.js$/i,
188
+ vivus: /^(?:https?:)?\/\/(?:unpkg\.com\/vivus(?:@[^/]+)?(?:\/dist\/vivus(?:\.min)?\.js)?|cdn\.jsdelivr\.net\/npm\/vivus(?:@[^/]+)?(?:\/dist\/vivus(?:\.min)?\.js)?|cdnjs\.cloudflare\.com\/ajax\/libs\/vivus\/[^/]+\/vivus(?:\.min)?\.js)$|(?:^|\/)node_modules\/vivus\/dist\/vivus(?:\.min)?\.js$/
189
+ };
190
+ var AOS_CSS_URL = /^(?:https?:)?\/\/(?:unpkg\.com\/aos(?:@[^/]+)?\/dist\/aos\.css|cdn\.jsdelivr\.net\/npm\/aos(?:@[^/]+)?\/dist\/aos\.css|cdnjs\.cloudflare\.com\/ajax\/libs\/aos\/[^/]+\/aos(?:\.min)?\.css)$|(?:^|\/)node_modules\/aos\/dist\/aos\.css$/;
191
+ function rewriteScriptTags(src, version, changes) {
192
+ return src.replace(/<script\b([^>]*)>/gi, (tag, attrs) => {
193
+ const m = /\bsrc\s*=\s*(["'])([^"']+)\1/i.exec(attrs);
194
+ if (!m) return tag;
195
+ const lib = LIBS.find((l) => SCRIPT_URL[l].test(m[2]));
196
+ if (!lib) return tag;
197
+ const url = `https://unpkg.com/svg-scroll-draw@${version}/dist/cdn/${lib}.global.js`;
198
+ const hadIntegrity = /\bintegrity\s*=/i.test(attrs);
199
+ const next = attrs.replace(m[0], `src=${m[1]}${url}${m[1]}`).replace(/\s+integrity\s*=\s*(["'])[^"']*\1/gi, "");
200
+ changes.push(`${LABEL[lib]}: <script> \u2192 ${url}${hadIntegrity ? " (old integrity hash removed)" : ""}`);
201
+ return `<script${next}>`;
202
+ });
203
+ }
204
+ function dropAosCssLinks(src, changes) {
205
+ let n = 0;
206
+ const out = src.replace(/^[ \t]*<link\b[^>]*>[ \t]*\r?\n?/gim, (line) => {
207
+ const m = /\bhref\s*=\s*(["'])([^"']+)\1/i.exec(line);
208
+ if (m && AOS_CSS_URL.test(m[2])) {
209
+ n++;
210
+ return "";
211
+ }
212
+ return line;
213
+ });
214
+ if (n) changes.push(`AOS: removed ${n} aos.css <link> (the drop-in ships its styles)`);
215
+ return out;
216
+ }
217
+ function dropAosCssAtImports(src, changes) {
218
+ let n = 0;
219
+ const out = src.replace(
220
+ /^[ \t]*@import\s+(?:url\(\s*)?(['"]?)~?aos\/dist\/aos(?:\.min)?\.css\1\s*\)?\s*;?[ \t]*\r?\n?/gm,
221
+ () => {
222
+ n++;
223
+ return "";
224
+ }
225
+ );
226
+ if (n) changes.push(`AOS: removed ${n} @import of aos.css (the drop-in ships its styles)`);
227
+ return out;
228
+ }
229
+ var SCRIPT_EXT = /\.(?:[cm]?[jt]sx?|vue|svelte|astro)$/i;
230
+ var HTML_EXT = /\.(?:html?|vue|svelte|astro|php|ejs|hbs|njk|liquid|erb)$/i;
231
+ var CSS_EXT = /\.(?:css|scss|sass|less)$/i;
232
+ function migrateSource(src, filename, version) {
233
+ const changes = [];
234
+ let code = src;
235
+ if (SCRIPT_EXT.test(filename)) {
236
+ code = dropAosCssImports(code, changes);
237
+ code = rewriteSpecifiers(code, changes);
238
+ }
239
+ if (HTML_EXT.test(filename)) {
240
+ code = rewriteScriptTags(code, version, changes);
241
+ code = dropAosCssLinks(code, changes);
242
+ }
243
+ if (CSS_EXT.test(filename) || /\.(?:vue|svelte|astro)$/i.test(filename)) {
244
+ code = dropAosCssAtImports(code, changes);
245
+ }
246
+ return { code, changes };
247
+ }
248
+ function migratePackageJson(text, version) {
249
+ const changes = [];
250
+ let pkg;
251
+ try {
252
+ pkg = JSON.parse(text);
253
+ } catch {
254
+ return { code: text, changes };
255
+ }
256
+ const remove = [...LIBS, "@types/aos"];
257
+ let home = null;
258
+ for (const field of ["dependencies", "devDependencies"]) {
259
+ const deps = pkg[field];
260
+ if (!deps) continue;
261
+ for (const name of remove) {
262
+ if (name in deps) {
263
+ delete deps[name];
264
+ changes.push(`package.json: removed ${name} from ${field}`);
265
+ if (!home && name !== "@types/aos") home = field;
266
+ }
267
+ }
268
+ }
269
+ if (!home) return { code: text, changes };
270
+ const already = ["dependencies", "devDependencies"].some(
271
+ (f) => pkg[f]?.["svg-scroll-draw"]
272
+ );
273
+ if (!already) {
274
+ const deps = pkg[home] ?? (pkg[home] = {});
275
+ deps["svg-scroll-draw"] = `^${version}`;
276
+ pkg[home] = Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b)));
277
+ changes.push(`package.json: added svg-scroll-draw ^${version} to ${home}`);
278
+ }
279
+ const indent = /^\{\r?\n(\t| +)/.exec(text)?.[1] ?? " ";
280
+ return { code: JSON.stringify(pkg, null, indent) + (text.endsWith("\n") ? "\n" : ""), changes };
281
+ }
282
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
283
+ "node_modules",
284
+ ".git",
285
+ "dist",
286
+ "build",
287
+ "out",
288
+ ".next",
289
+ ".nuxt",
290
+ ".output",
291
+ ".svelte-kit",
292
+ ".vercel",
293
+ ".netlify",
294
+ ".turbo",
295
+ ".cache",
296
+ "coverage",
297
+ ".parcel-cache",
298
+ "vendor"
299
+ ]);
300
+ var MAX_BYTES = 2 * 1024 * 1024;
301
+ function* walk(dir) {
302
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
303
+ if (entry.isDirectory()) {
304
+ if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) yield* walk(path.join(dir, entry.name));
305
+ } else if (entry.isFile()) {
306
+ yield path.join(dir, entry.name);
307
+ }
308
+ }
309
+ }
310
+ function installCommand(dir) {
311
+ if (fs.existsSync(path.join(dir, "pnpm-lock.yaml"))) return "pnpm install";
312
+ if (fs.existsSync(path.join(dir, "yarn.lock"))) return "yarn install";
313
+ if (fs.existsSync(path.join(dir, "bun.lockb")) || fs.existsSync(path.join(dir, "bun.lock"))) return "bun install";
314
+ return "npm install";
315
+ }
316
+ function gitDirty(dir) {
317
+ try {
318
+ return (0, import_node_child_process.execSync)("git status --porcelain", { cwd: dir, stdio: ["ignore", "pipe", "ignore"] }).toString().trim() !== "";
319
+ } catch {
320
+ return false;
321
+ }
322
+ }
323
+ var HELP = `
324
+ svg-scroll-draw migrate [dir] [--dry-run] [--force]
325
+
326
+ Moves a project off AOS, ScrollReveal and vivus onto svg-scroll-draw's drop-ins:
327
+ \u2022 imports / requires of 'aos', 'scrollreveal', 'vivus' \u2192 svg-scroll-draw/<lib>
328
+ \u2022 CDN <script> tags \u2192 svg-scroll-draw's script-tag builds
329
+ \u2022 AOS's aos.css imports, <link>s and @imports removed (the drop-in ships its styles)
330
+ \u2022 package.json: the old packages swapped for svg-scroll-draw
331
+
332
+ --dry-run show what would change, write nothing
333
+ --force write even if the git working tree has uncommitted changes
334
+ `;
335
+ function runMigrate(args, version, log = console.log) {
336
+ if (args.includes("--help") || args.includes("-h")) {
337
+ log(HELP);
338
+ return 0;
339
+ }
340
+ const dryRun = args.includes("--dry-run");
341
+ const force = args.includes("--force");
342
+ const dir = path.resolve(args.find((a) => !a.startsWith("-")) ?? ".");
343
+ if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
344
+ log(` \u2717 Not a directory: ${dir}`);
345
+ return 1;
346
+ }
347
+ const edits = [];
348
+ for (const file of walk(dir)) {
349
+ const base = path.basename(file);
350
+ const isPkg = base === "package.json";
351
+ if (!isPkg && !SCRIPT_EXT.test(base) && !HTML_EXT.test(base) && !CSS_EXT.test(base)) continue;
352
+ if (fs.statSync(file).size > MAX_BYTES) continue;
353
+ const text = fs.readFileSync(file, "utf8");
354
+ if (!isPkg && !/aos|scrollreveal|vivus/i.test(text)) continue;
355
+ const result = isPkg ? migratePackageJson(text, version) : migrateSource(text, base, version);
356
+ if (result.changes.length && result.code !== text) edits.push({ file, code: result.code, changes: result.changes });
357
+ }
358
+ log(`
359
+ svg-scroll-draw migrate${dryRun ? " (dry run)" : ""} \u2014 ${dir}
360
+ `);
361
+ if (!edits.length) {
362
+ log(" No AOS, ScrollReveal or vivus usage found. Nothing to do.\n");
363
+ return 0;
364
+ }
365
+ for (const { file, changes } of edits) {
366
+ log(` ${path.relative(dir, file) || path.basename(file)}`);
367
+ for (const c of changes) log(` \u2022 ${c}`);
368
+ }
369
+ if (dryRun) {
370
+ log(`
371
+ ${edits.length} file${edits.length === 1 ? "" : "s"} would change. Run again without --dry-run to apply.
372
+ `);
373
+ return 0;
374
+ }
375
+ if (!force && gitDirty(dir)) {
376
+ log("\n \u2717 The git working tree has uncommitted changes. Commit or stash them first so the");
377
+ log(" migration is a clean diff you can review, or pass --force to write anyway.\n");
378
+ return 1;
379
+ }
380
+ for (const { file, code } of edits) fs.writeFileSync(file, code);
381
+ const touchedPkg = edits.some((e) => path.basename(e.file) === "package.json");
382
+ log(`
383
+ \u2713 Updated ${edits.length} file${edits.length === 1 ? "" : "s"}.`);
384
+ log(` Next: ${touchedPkg ? `run \`${installCommand(dir)}\`, then ` : ""}review the diff (git diff) and try the page.
385
+ `);
386
+ return 0;
387
+ }
388
+
141
389
  // src/cli/init.ts
142
390
  var RESET = "\x1B[0m";
143
391
  var BOLD = "\x1B[1m";
@@ -147,19 +395,19 @@ var GREEN = "\x1B[32m";
147
395
  var CYAN = "\x1B[36m";
148
396
  function ask(rl, question, fallback) {
149
397
  return new Promise(
150
- (resolve) => rl.question(` ${CYAN}?${RESET} ${question} ${DIM}(${fallback})${RESET} `, (ans) => {
151
- resolve(ans.trim() || fallback);
398
+ (resolve2) => rl.question(` ${CYAN}?${RESET} ${question} ${DIM}(${fallback})${RESET} `, (ans) => {
399
+ resolve2(ans.trim() || fallback);
152
400
  })
153
401
  );
154
402
  }
155
403
  function pick(rl, question, options, fallback) {
156
404
  const opts = options.map((o, i) => `${DIM}${i + 1})${RESET} ${o}`).join(" ");
157
405
  return new Promise(
158
- (resolve) => rl.question(` ${CYAN}?${RESET} ${question}
406
+ (resolve2) => rl.question(` ${CYAN}?${RESET} ${question}
159
407
  ${opts}
160
408
  ${DIM}(${fallback})${RESET} `, (ans) => {
161
409
  const idx = parseInt(ans) - 1;
162
- resolve(idx >= 0 && idx < options.length ? options[idx] : fallback);
410
+ resolve2(idx >= 0 && idx < options.length ? options[idx] : fallback);
163
411
  })
164
412
  );
165
413
  }
@@ -179,8 +427,8 @@ async function main() {
179
427
  }
180
428
  const selector = needsSelector(framework) ? await ask(rl, "CSS selector for your SVG container?", "#my-svg") : "#my-svg";
181
429
  const outFile = FILE_NAMES[framework] ?? "scroll-draw.js";
182
- const outPath = path.join(process.cwd(), outFile);
183
- if (fs.existsSync(outPath)) {
430
+ const outPath = path2.join(process.cwd(), outFile);
431
+ if (fs2.existsSync(outPath)) {
184
432
  const overwrite = await ask(rl, `${outFile} already exists. Overwrite?`, "y");
185
433
  if (overwrite.toLowerCase() !== "y") {
186
434
  console.log(`
@@ -190,7 +438,7 @@ async function main() {
190
438
  }
191
439
  }
192
440
  const code = GENERATORS[framework]?.({ selector, easing, preset }) ?? "";
193
- fs.writeFileSync(outPath, code, "utf8");
441
+ fs2.writeFileSync(outPath, code, "utf8");
194
442
  console.log(`
195
443
  ${GREEN}\u2713${RESET} ${BOLD}${outFile}${RESET} created.
196
444
  `);
@@ -208,7 +456,30 @@ async function main() {
208
456
  rl.close();
209
457
  }
210
458
  }
211
- main().catch((e) => {
212
- console.error(e);
213
- process.exit(1);
214
- });
459
+ function ownVersion() {
460
+ try {
461
+ return JSON.parse(fs2.readFileSync(path2.join(__dirname, "..", "..", "package.json"), "utf8")).version;
462
+ } catch {
463
+ return "latest";
464
+ }
465
+ }
466
+ var USAGE = `
467
+ npx svg-scroll-draw init scaffold a starter file
468
+ npx svg-scroll-draw migrate switch a project from AOS, ScrollReveal or vivus (--dry-run to preview)
469
+ `;
470
+ var [command, ...rest] = process.argv.slice(2);
471
+ if (command === "help" || command === "--help" || command === "-h") {
472
+ console.log(USAGE);
473
+ } else if (command === "migrate") {
474
+ process.exitCode = runMigrate(rest, ownVersion());
475
+ } else if (command === void 0 || command === "init") {
476
+ main().catch((e) => {
477
+ console.error(e);
478
+ process.exit(1);
479
+ });
480
+ } else {
481
+ console.error(`
482
+ Unknown command "${command}".
483
+ ${USAGE}`);
484
+ process.exitCode = 1;
485
+ }
@@ -0,0 +1,2 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});function g(){return typeof window>"u"||typeof window.matchMedia!="function"?false:window.matchMedia("(prefers-reduced-motion: reduce)").matches}var w=typeof __SVG_SCROLL_DRAW_DEV__<"u"?__SVG_SCROLL_DRAW_DEV__:typeof process<"u"&&typeof process.env<"u"&&process.env.NODE_ENV!=="production";function m(r,...t){w&&console.warn(`[svg-scroll-draw] ${r}`,...t);}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return false;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],x="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i;}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return `M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var A={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return `M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return `M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function R(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n;}let i=A[t.tagName.toLowerCase()](e),s=document.createElementNS(x,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t);}}var c=class c{constructor(t,e,i){this.isReady=false;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=false;this.reverseStack=false;this.selfDestroy=false;this.ignoreInvisible=false;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init();}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s;}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=true,this.init();}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=true;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=true,this.init());};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:false,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{});}mapping(){let t=0,e=0,i=0,s=false,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:false},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=true,s=true;}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o);}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case "delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case "oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case "sync":case "async":case "nsync":n.startAt=0,n.duration=this.duration;break;case "scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case "scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration;});}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()));}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`;}this.trace(),this.mustRecalcScale=null;}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else {this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished();}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this);}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i));});}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(true);e.el.parentNode?.replaceChild(i,e.el),e.el=i;}init(){this.frameLength=0,this.currentFrame=0,this.map=[],R(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this);}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null);};this.viewportListener=t,window.addEventListener("scroll",t),t();}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e);});}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return !i.width&&!i.height}return false}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,O=p;
2
+ exports.Vivus=p;exports.default=O;
@@ -0,0 +1,100 @@
1
+ type VivusType = 'delayed' | 'sync' | 'async' | 'nsync' | 'oneByOne' | 'scenario' | 'scenario-sync';
2
+ type VivusStart = 'inViewport' | 'manual' | 'autostart';
3
+ type VivusTiming = (x: number) => number;
4
+ type VivusCallback = (instance: Vivus) => void;
5
+ interface VivusOptions {
6
+ type?: VivusType;
7
+ /** Load the SVG from this URL into `element` instead of using markup. */
8
+ file?: string;
9
+ start?: VivusStart;
10
+ /** Animation length in frames. Default 120. */
11
+ duration?: number;
12
+ /** For `delayed`: frames between the first and last path starting. Default duration / 3. */
13
+ delay?: number;
14
+ /** Extra gap in the dash pattern, so the line start never shows early. Default 1. */
15
+ dashGap?: number;
16
+ /** Clone-and-replace each path after every update (an old IE/Edge repaint hack). */
17
+ forceRender?: boolean;
18
+ reverseStack?: boolean;
19
+ selfDestroy?: boolean;
20
+ onReady?: VivusCallback;
21
+ ignoreInvisible?: boolean;
22
+ pathTimingFunction?: VivusTiming;
23
+ animTimingFunction?: VivusTiming;
24
+ }
25
+ interface PathRecord {
26
+ el: SVGPathElement;
27
+ length: number;
28
+ startAt: number;
29
+ duration: number;
30
+ isResizeSensitive: boolean;
31
+ progress?: number;
32
+ }
33
+ declare class Vivus {
34
+ static LINEAR: VivusTiming;
35
+ static EASE: VivusTiming;
36
+ static EASE_OUT: VivusTiming;
37
+ static EASE_IN: VivusTiming;
38
+ static EASE_OUT_BOUNCE: VivusTiming;
39
+ el: Element;
40
+ parentEl: Element;
41
+ isReady: boolean;
42
+ type: VivusType;
43
+ start: VivusStart;
44
+ duration: number;
45
+ delay: number | null;
46
+ dashGap: number;
47
+ forceRender: boolean;
48
+ reverseStack: boolean;
49
+ selfDestroy: boolean;
50
+ ignoreInvisible: boolean;
51
+ onReady?: VivusCallback;
52
+ animTimingFunction: VivusTiming;
53
+ pathTimingFunction: VivusTiming;
54
+ callback: VivusCallback;
55
+ map: PathRecord[];
56
+ frameLength: number;
57
+ currentFrame: number;
58
+ delayUnit: number;
59
+ speed: number;
60
+ handle: number | null;
61
+ private instanceCallback;
62
+ private mustRecalcScale;
63
+ private viewportListener;
64
+ constructor(element: string | Element, options?: VivusOptions, callback?: VivusCallback);
65
+ private setElement;
66
+ private setOptions;
67
+ private setCallback;
68
+ /** Measure every path, set its dashes, and work out when each one draws. */
69
+ mapping(): void;
70
+ /** Re-measure `vector-effect: non-scaling-stroke` paths on the next frame (after a resize). */
71
+ recalc(): void;
72
+ performLineRecalc(): void;
73
+ /** One frame: advance by `speed`, render, and finish at either end. */
74
+ draw(): void;
75
+ private finished;
76
+ /** Render the current frame to every path's dash offset. */
77
+ trace(): void;
78
+ renderPath(index: number): void;
79
+ init(): void;
80
+ private starter;
81
+ /** `'start'`, `'progress'` or `'end'`. */
82
+ getStatus(): 'start' | 'progress' | 'end';
83
+ reset(): this;
84
+ finish(): this;
85
+ /** Jump to a point (0–1) and render it. */
86
+ setFrameProgress(progress: number): this;
87
+ /**
88
+ * Animate at `speed` frames per frame (negative plays backwards). The callback
89
+ * may be given alone, as the first argument.
90
+ */
91
+ play(speed?: number | VivusCallback, callback?: VivusCallback): this;
92
+ stop(): this;
93
+ /** Stop and remove every dash style vivus set. */
94
+ destroy(): void;
95
+ isInvisible(el: Element): boolean;
96
+ /** Whether `el` is in view; with `h` = 1 its whole height must fit above the fold. */
97
+ isInViewport(el: Element, h?: number): boolean;
98
+ }
99
+
100
+ export { Vivus, type VivusCallback, type VivusOptions, type VivusStart, type VivusTiming, type VivusType, Vivus as default };
@@ -0,0 +1,100 @@
1
+ type VivusType = 'delayed' | 'sync' | 'async' | 'nsync' | 'oneByOne' | 'scenario' | 'scenario-sync';
2
+ type VivusStart = 'inViewport' | 'manual' | 'autostart';
3
+ type VivusTiming = (x: number) => number;
4
+ type VivusCallback = (instance: Vivus) => void;
5
+ interface VivusOptions {
6
+ type?: VivusType;
7
+ /** Load the SVG from this URL into `element` instead of using markup. */
8
+ file?: string;
9
+ start?: VivusStart;
10
+ /** Animation length in frames. Default 120. */
11
+ duration?: number;
12
+ /** For `delayed`: frames between the first and last path starting. Default duration / 3. */
13
+ delay?: number;
14
+ /** Extra gap in the dash pattern, so the line start never shows early. Default 1. */
15
+ dashGap?: number;
16
+ /** Clone-and-replace each path after every update (an old IE/Edge repaint hack). */
17
+ forceRender?: boolean;
18
+ reverseStack?: boolean;
19
+ selfDestroy?: boolean;
20
+ onReady?: VivusCallback;
21
+ ignoreInvisible?: boolean;
22
+ pathTimingFunction?: VivusTiming;
23
+ animTimingFunction?: VivusTiming;
24
+ }
25
+ interface PathRecord {
26
+ el: SVGPathElement;
27
+ length: number;
28
+ startAt: number;
29
+ duration: number;
30
+ isResizeSensitive: boolean;
31
+ progress?: number;
32
+ }
33
+ declare class Vivus {
34
+ static LINEAR: VivusTiming;
35
+ static EASE: VivusTiming;
36
+ static EASE_OUT: VivusTiming;
37
+ static EASE_IN: VivusTiming;
38
+ static EASE_OUT_BOUNCE: VivusTiming;
39
+ el: Element;
40
+ parentEl: Element;
41
+ isReady: boolean;
42
+ type: VivusType;
43
+ start: VivusStart;
44
+ duration: number;
45
+ delay: number | null;
46
+ dashGap: number;
47
+ forceRender: boolean;
48
+ reverseStack: boolean;
49
+ selfDestroy: boolean;
50
+ ignoreInvisible: boolean;
51
+ onReady?: VivusCallback;
52
+ animTimingFunction: VivusTiming;
53
+ pathTimingFunction: VivusTiming;
54
+ callback: VivusCallback;
55
+ map: PathRecord[];
56
+ frameLength: number;
57
+ currentFrame: number;
58
+ delayUnit: number;
59
+ speed: number;
60
+ handle: number | null;
61
+ private instanceCallback;
62
+ private mustRecalcScale;
63
+ private viewportListener;
64
+ constructor(element: string | Element, options?: VivusOptions, callback?: VivusCallback);
65
+ private setElement;
66
+ private setOptions;
67
+ private setCallback;
68
+ /** Measure every path, set its dashes, and work out when each one draws. */
69
+ mapping(): void;
70
+ /** Re-measure `vector-effect: non-scaling-stroke` paths on the next frame (after a resize). */
71
+ recalc(): void;
72
+ performLineRecalc(): void;
73
+ /** One frame: advance by `speed`, render, and finish at either end. */
74
+ draw(): void;
75
+ private finished;
76
+ /** Render the current frame to every path's dash offset. */
77
+ trace(): void;
78
+ renderPath(index: number): void;
79
+ init(): void;
80
+ private starter;
81
+ /** `'start'`, `'progress'` or `'end'`. */
82
+ getStatus(): 'start' | 'progress' | 'end';
83
+ reset(): this;
84
+ finish(): this;
85
+ /** Jump to a point (0–1) and render it. */
86
+ setFrameProgress(progress: number): this;
87
+ /**
88
+ * Animate at `speed` frames per frame (negative plays backwards). The callback
89
+ * may be given alone, as the first argument.
90
+ */
91
+ play(speed?: number | VivusCallback, callback?: VivusCallback): this;
92
+ stop(): this;
93
+ /** Stop and remove every dash style vivus set. */
94
+ destroy(): void;
95
+ isInvisible(el: Element): boolean;
96
+ /** Whether `el` is in view; with `h` = 1 its whole height must fit above the fold. */
97
+ isInViewport(el: Element, h?: number): boolean;
98
+ }
99
+
100
+ export { Vivus, type VivusCallback, type VivusOptions, type VivusStart, type VivusTiming, type VivusType, Vivus as default };
@@ -0,0 +1,2 @@
1
+ function g(){return typeof window>"u"||typeof window.matchMedia!="function"?false:window.matchMedia("(prefers-reduced-motion: reduce)").matches}var w=typeof __SVG_SCROLL_DRAW_DEV__<"u"?__SVG_SCROLL_DRAW_DEV__:typeof process<"u"&&typeof process.env<"u"&&process.env.NODE_ENV!=="production";function m(r,...t){w&&console.warn(`[svg-scroll-draw] ${r}`,...t);}var E=["delayed","sync","async","nsync","oneByOne","scenario","scenario-sync"],L=["inViewport","manual","autostart"];function u(r,t){let e=parseInt(r,10);return e>=0?e:t}function V(r){if(typeof window>"u")return false;let t=window,e=i=>typeof t[i]=="function"&&r instanceof t[i];return e("SVGSVGElement")||e("SVGGElement")||r?.constructor===t.SVGElement}var y=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],$=["line","ellipse","circle","polygon","polyline","rect"],x="http://www.w3.org/2000/svg";function v(r){let t=r.points.trim().split(" ");if(r.points.indexOf(",")===-1){let i=[];for(let s=0;s<t.length;s+=2)i.push(`${t[s]},${t[s+1]}`);t=i;}let e=`M${t[0]}`;for(let i=1;i<t.length;i++)t[i].indexOf(",")!==-1&&(e+=`L${t[i]}`);return e}function b(r,t,e,i){let s=parseFloat(e)||0,a=parseFloat(i)||0,n=parseFloat(r)||0,o=parseFloat(t)||0,l=n-s,h=n+s;return `M${l},${o}A${s},${a} 0,1,1 ${h},${o}A${s},${a} 0,1,1 ${l},${o}`}var A={line:r=>`M${r.x1||0},${r.y1||0}L${r.x2||0},${r.y2||0}`,rect(r){let t=parseFloat(r.x)||0,e=parseFloat(r.y)||0,i=parseFloat(r.width)||0,s=parseFloat(r.height)||0;if(r.rx||r.ry){let a=parseInt(r.rx,10)||-1,n=parseInt(r.ry,10)||-1;a=Math.min(Math.max(a<0?n:a,0),i/2),n=Math.min(Math.max(n<0?a:n,0),s/2);let o=`A ${a},${n},0,0,1,`;return `M ${t+a},${e} L ${t+i-a},${e} ${o}${t+i},${e+n} L ${t+i},${e+s-n} ${o}${t+i-a},${e+s} L ${t+a},${e+s} ${o}${t},${e+s-n} L ${t},${e+n} ${o}${t+a},${e}`}return `M${t} ${e} L${t+i} ${e} L${t+i} ${e+s} L${t} ${e+s} Z`},polyline:v,polygon:r=>`${v(r)}Z`,ellipse:r=>b(r.cx,r.cy,r.rx,r.ry),circle:r=>b(r.cx,r.cy,r.r,r.r)};function R(r){for(let t of Array.from(r.querySelectorAll($.join(",")))){let e={};for(let{name:a,value:n}of Array.from(t.attributes)){if(y.indexOf(a)!==-1&&n.indexOf("%")!==-1)throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");e[a]=n;}let i=A[t.tagName.toLowerCase()](e),s=document.createElementNS(x,"path");for(let{name:a,value:n}of Array.from(t.attributes))y.indexOf(a)===-1&&s.setAttribute(a,n);s.setAttribute("d",i),t.parentNode?.replaceChild(s,t);}}var c=class c{constructor(t,e,i){this.isReady=false;this.type="delayed";this.start="inViewport";this.duration=120;this.delay=null;this.dashGap=1;this.forceRender=false;this.reverseStack=false;this.selfDestroy=false;this.ignoreInvisible=false;this.animTimingFunction=c.LINEAR;this.pathTimingFunction=c.LINEAR;this.callback=()=>{};this.map=[];this.frameLength=0;this.currentFrame=0;this.delayUnit=0;this.speed=1;this.handle=null;this.instanceCallback=null;this.mustRecalcScale=null;this.viewportListener=null;this.setElement(t,e),this.setOptions(e),this.setCallback(i),this.isReady&&this.init();}setElement(t,e){if(t===void 0)throw new Error('Vivus [constructor]: "element" parameter is required');let i=t;if(typeof i=="string"){let s=document.getElementById(i);if(!s)throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');i=s;}if(this.parentEl=i,e&&e.file){let s=new XMLHttpRequest;s.addEventListener("load",()=>{let a=document.createElement("div");a.innerHTML=s.responseText;let n=a.querySelector("svg");if(!n)throw new Error(`Vivus [load]: Cannot find the SVG in the loaded file : ${e.file}`);this.el=n,n.setAttribute("width","100%"),n.setAttribute("height","100%"),this.parentEl.appendChild(n),this.isReady=true,this.init();}),s.open("GET",e.file),s.send();return}if(V(i)){this.el=i,this.isReady=true;return}if(i instanceof HTMLObjectElement){let s=i,a=n=>{if(this.isReady)return;let o=s.contentDocument&&s.contentDocument.querySelector("svg");if(!o&&n)throw new Error("Vivus [constructor]: object loaded does not contain any SVG");o&&(s.getAttribute("built-by-vivus")&&(this.parentEl.insertBefore(o,s),this.parentEl.removeChild(s),o.setAttribute("width","100%"),o.setAttribute("height","100%")),this.el=o,this.isReady=true,this.init());};a(),this.isReady||s.addEventListener("load",a);return}throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)')}setOptions(t){if(t!==void 0&&(t===null||t.constructor!==Object))throw new Error('Vivus [constructor]: "options" parameter must be an object');let e=t||{};if(e.type&&E.indexOf(e.type)===-1)throw new Error(`Vivus [constructor]: ${e.type} is not an existing animation \`type\``);if(e.start&&L.indexOf(e.start)===-1)throw new Error(`Vivus [constructor]: ${e.start} is not an existing \`start\` option`);this.type=e.type||"delayed",this.start=e.start||"inViewport";let i=navigator.userAgent,s=i.indexOf("MSIE")!==-1||i.indexOf("Trident/")!==-1||i.indexOf("Edge/")!==-1;if(this.duration=u(e.duration,120),this.delay=u(e.delay,null),this.dashGap=u(e.dashGap,1),this.forceRender=Object.prototype.hasOwnProperty.call(e,"forceRender")?!!e.forceRender:s,this.reverseStack=!!e.reverseStack,this.selfDestroy=!!e.selfDestroy,this.onReady=e.onReady,this.map=[],this.ignoreInvisible=Object.prototype.hasOwnProperty.call(e,"ignoreInvisible")?!!e.ignoreInvisible:false,this.animTimingFunction=e.animTimingFunction||c.LINEAR,this.pathTimingFunction=e.pathTimingFunction||c.LINEAR,this.delay!==null&&this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")}setCallback(t){if(t&&typeof t!="function")throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||(()=>{});}mapping(){let t=0,e=0,i=0,s=false,a=Array.from(this.el.querySelectorAll("path"));a.forEach((n,o)=>{if(this.isInvisible(n))return;let l={el:n,length:0,startAt:0,duration:0,isResizeSensitive:false},h=1;if(n.getAttribute("vector-effect")==="non-scaling-stroke"){let d=n.getBoundingClientRect(),f=n.getBBox();h=Math.max(d.width/f.width,d.height/f.height),l.isResizeSensitive=true,s=true;}if(l.length=Math.ceil(n.getTotalLength()*h),isNaN(l.length)){m("vivus: cannot retrieve a path element length",n);return}this.map.push(l),n.style.strokeDasharray=`${l.length} ${l.length+this.dashGap*2}`,n.style.strokeDashoffset=String(l.length+this.dashGap),l.length+=this.dashGap,e+=l.length,this.renderPath(o);}),s&&m("vivus: this SVG contains non-scaling-strokes. Call instance.recalc() when the SVG is resized."),e=e===0?1:e,this.delay=this.delay===null?this.duration/3:this.delay,this.delayUnit=this.delay/(a.length>1?a.length-1:1),this.reverseStack&&this.map.reverse(),this.map.forEach((n,o)=>{let l=()=>{let h={};for(let{name:d,value:f}of Array.from(n.el.attributes))h[d]=f;return h};switch(this.type){case "delayed":n.startAt=this.delayUnit*o,n.duration=this.duration-this.delay;break;case "oneByOne":n.startAt=i/e*this.duration,n.duration=n.length/e*this.duration;break;case "sync":case "async":case "nsync":n.startAt=0,n.duration=this.duration;break;case "scenario-sync":{let h=l();n.startAt=t+(u(h["data-delay"],this.delayUnit)||0),n.duration=u(h["data-duration"],this.duration),t=h["data-async"]!==void 0?n.startAt:n.startAt+n.duration,this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}case "scenario":{let h=l();n.startAt=u(h["data-start"],this.delayUnit)||0,n.duration=u(h["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,n.startAt+n.duration);break}}i+=n.length,this.frameLength=this.frameLength||this.duration;});}recalc(){this.mustRecalcScale||(this.mustRecalcScale=requestAnimationFrame(()=>this.performLineRecalc()));}performLineRecalc(){for(let t of this.map){if(!t.isResizeSensitive)continue;let e=t.el.getBoundingClientRect(),i=t.el.getBBox(),s=Math.max(e.width/i.width,e.height/i.height);t.length=Math.ceil(t.el.getTotalLength()*s),t.el.style.strokeDasharray=`${t.length} ${t.length+this.dashGap*2}`;}this.trace(),this.mustRecalcScale=null;}draw(){if(this.currentFrame+=this.speed,this.currentFrame<=0)this.stop(),this.reset();else if(this.currentFrame>=this.frameLength)this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy();else {this.trace(),this.handle=requestAnimationFrame(()=>this.draw());return}this.finished();}finished(){if(this.callback(this),this.instanceCallback){let t=this.instanceCallback;this.instanceCallback=null,t(this);}}trace(){let t=this.animTimingFunction(this.currentFrame/this.frameLength)*this.frameLength;this.map.forEach((e,i)=>{let s=this.pathTimingFunction(Math.max(0,Math.min(1,(t-e.startAt)/e.duration)));e.progress!==s&&(e.progress=s,e.el.style.strokeDashoffset=String(Math.floor(e.length*(1-s))),this.renderPath(i));});}renderPath(t){let e=this.forceRender&&this.map&&this.map[t];if(!e)return;let i=e.el.cloneNode(true);e.el.parentNode?.replaceChild(i,e.el),e.el=i;}init(){this.frameLength=0,this.currentFrame=0,this.map=[],R(this.el),this.mapping(),this.starter(),this.onReady&&this.onReady(this);}starter(){if(this.start==="manual")return;if(this.start==="autostart"){this.play();return}let t=()=>{this.isInViewport(this.parentEl,1)&&(this.play(),window.removeEventListener("scroll",t),this.viewportListener=null);};this.viewportListener=t,window.addEventListener("scroll",t),t();}getStatus(){return this.currentFrame===0?"start":this.currentFrame===this.frameLength?"end":"progress"}reset(){return this.setFrameProgress(0)}finish(){return this.setFrameProgress(1)}setFrameProgress(t){let e=Math.min(1,Math.max(0,t));return this.currentFrame=Math.round(this.frameLength*e),this.trace(),this}play(t,e){this.instanceCallback=null;let i=t;if(i&&typeof i=="function")this.instanceCallback=i,i=void 0;else if(i&&typeof i!="number")throw new Error("Vivus [play]: invalid speed");return e&&typeof e=="function"&&!this.instanceCallback&&(this.instanceCallback=e),this.speed=i||1,g()?(this.stop(),this.currentFrame=this.speed<0?0:this.frameLength,this.trace(),this.speed>0&&this.selfDestroy&&this.destroy(),this.finished(),this):(this.handle||this.draw(),this)}stop(){return this.handle&&(cancelAnimationFrame(this.handle),this.handle=null),this}destroy(){this.stop(),this.viewportListener&&(window.removeEventListener("scroll",this.viewportListener),this.viewportListener=null),this.map.forEach((t,e)=>{t.el.style.strokeDashoffset="",t.el.style.strokeDasharray="",this.renderPath(e);});}isInvisible(t){let e=t.getAttribute("data-ignore");if(e!==null)return e!=="false";if(this.ignoreInvisible){let i=t.getBoundingClientRect();return !i.width&&!i.height}return false}isInViewport(t,e=0){let i=window.pageYOffset||document.documentElement.scrollTop,s=i+Math.max(document.documentElement.clientHeight,window.innerHeight),a=t.getBoundingClientRect(),n=i+a.top;return n+a.height*(e||0)<=s&&n+a.height>=i}};c.LINEAR=t=>t,c.EASE=t=>-Math.cos(t*Math.PI)/2+.5,c.EASE_OUT=t=>1-Math.pow(1-t,3),c.EASE_IN=t=>Math.pow(t,3),c.EASE_OUT_BOUNCE=t=>{let e=-Math.cos(t*(.5*Math.PI))+1,i=Math.pow(e,1.5),s=Math.pow(1-t,2),a=-Math.abs(Math.cos(i*(2.5*Math.PI)))+1;return 1-s+a*s};var p=c,O=p;
2
+ export{p as Vivus,O as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svg-scroll-draw",
3
- "version": "2.12.0",
3
+ "version": "2.14.0",
4
4
  "description": "Scroll-driven animation for the web — draw SVG paths, reveal elements, pin sections, scrub video. Zero dependencies, native CSS fast path, works with React, Vue, Svelte, Solid, Angular, Astro and vanilla JS",
5
5
  "keywords": [
6
6
  "svg",
@@ -62,7 +62,11 @@
62
62
  "data-aos",
63
63
  "scrollreveal",
64
64
  "scrollreveal-alternative",
65
- "scroll-reveal-mit"
65
+ "scroll-reveal-mit",
66
+ "vivus",
67
+ "vivus-alternative",
68
+ "svg-line-drawing",
69
+ "line-drawing"
66
70
  ],
67
71
  "homepage": "https://svg-scroll-draw.vercel.app",
68
72
  "repository": {
@@ -151,6 +155,9 @@
151
155
  ],
152
156
  "scrollreveal": [
153
157
  "./dist/scrollreveal/index.d.ts"
158
+ ],
159
+ "vivus": [
160
+ "./dist/vivus/index.d.ts"
154
161
  ]
155
162
  }
156
163
  },
@@ -390,6 +397,16 @@
390
397
  "default": "./dist/scrollreveal/index.cjs"
391
398
  }
392
399
  },
400
+ "./vivus": {
401
+ "import": {
402
+ "types": "./dist/vivus/index.d.mts",
403
+ "default": "./dist/vivus/index.mjs"
404
+ },
405
+ "require": {
406
+ "types": "./dist/vivus/index.d.ts",
407
+ "default": "./dist/vivus/index.cjs"
408
+ }
409
+ },
393
410
  "./package.json": "./package.json"
394
411
  },
395
412
  "scripts": {
@@ -417,6 +434,7 @@
417
434
  "tsup": "^8.0.0",
418
435
  "typescript": "^5.0.0",
419
436
  "vitest": "^2.0.0",
437
+ "vivus": "^0.4.6",
420
438
  "vue": "^3.5.34"
421
439
  },
422
440
  "sideEffects": [
@@ -424,7 +442,8 @@
424
442
  "./dist/cdn/*",
425
443
  "./src/web-component/*",
426
444
  "./src/cdn.ts",
427
- "./src/scrollreveal/cdn.ts"
445
+ "./src/scrollreveal/cdn.ts",
446
+ "./src/vivus/cdn.ts"
428
447
  ],
429
448
  "engines": {
430
449
  "node": ">=18"