qarl 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var R=Object.create;var L=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var q=(t,s,e)=>s in t?L(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var N=(t,s)=>()=>(s||t((s={exports:{}}).exports,s),s.exports);var Y=(t,s,e,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of V(s))!G.call(t,r)&&r!==e&&L(t,r,{get:()=>s[r],enumerable:!(i=j(s,r))||i.enumerable});return t};var z=(t,s,e)=>(e=t!=null?R(B(t)):{},Y(s||!t||!t.__esModule?L(e,"default",{value:t,enumerable:!0}):e,t));var y=(t,s,e)=>(q(t,typeof s!="symbol"?s+"":s,e),e);var k=N(($,b)=>{"use strict";var K=Object.prototype.hasOwnProperty,g="~";function T(){}Object.create&&(T.prototype=Object.create(null),new T().__proto__||(g=!1));function H(t,s,e){this.fn=t,this.context=s,this.once=e||!1}function F(t,s,e,i,r){if(typeof e!="function")throw new TypeError("The listener must be a function");var n=new H(e,i||t,r),a=g?g+s:s;return t._events[a]?t._events[a].fn?t._events[a]=[t._events[a],n]:t._events[a].push(n):(t._events[a]=n,t._eventsCount++),t}function D(t,s){--t._eventsCount===0?t._events=new T:delete t._events[s]}function f(){this._events=new T,this._eventsCount=0}f.prototype.eventNames=function(){var s=[],e,i;if(this._eventsCount===0)return s;for(i in e=this._events)K.call(e,i)&&s.push(g?i.slice(1):i);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(e)):s};f.prototype.listeners=function(s){var e=g?g+s:s,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var r=0,n=i.length,a=new Array(n);r<n;r++)a[r]=i[r].fn;return a};f.prototype.listenerCount=function(s){var e=g?g+s:s,i=this._events[e];return i?i.fn?1:i.length:0};f.prototype.emit=function(s,e,i,r,n,a){var p=g?g+s:s;if(!this._events[p])return!1;var o=this._events[p],l=arguments.length,m,h;if(o.fn){switch(o.once&&this.removeListener(s,o.fn,void 0,!0),l){case 1:return o.fn.call(o.context),!0;case 2:return o.fn.call(o.context,e),!0;case 3:return o.fn.call(o.context,e,i),!0;case 4:return o.fn.call(o.context,e,i,r),!0;case 5:return o.fn.call(o.context,e,i,r,n),!0;case 6:return o.fn.call(o.context,e,i,r,n,a),!0}for(h=1,m=new Array(l-1);h<l;h++)m[h-1]=arguments[h];o.fn.apply(o.context,m)}else{var I=o.length,c;for(h=0;h<I;h++)switch(o[h].once&&this.removeListener(s,o[h].fn,void 0,!0),l){case 1:o[h].fn.call(o[h].context);break;case 2:o[h].fn.call(o[h].context,e);break;case 3:o[h].fn.call(o[h].context,e,i);break;case 4:o[h].fn.call(o[h].context,e,i,r);break;default:if(!m)for(c=1,m=new Array(l-1);c<l;c++)m[c-1]=arguments[c];o[h].fn.apply(o[h].context,m)}}return!0};f.prototype.on=function(s,e,i){return F(this,s,e,i,!1)};f.prototype.once=function(s,e,i){return F(this,s,e,i,!0)};f.prototype.removeListener=function(s,e,i,r){var n=g?g+s:s;if(!this._events[n])return this;if(!e)return D(this,n),this;var a=this._events[n];if(a.fn)a.fn===e&&(!r||a.once)&&(!i||a.context===i)&&D(this,n);else{for(var p=0,o=[],l=a.length;p<l;p++)(a[p].fn!==e||r&&!a[p].once||i&&a[p].context!==i)&&o.push(a[p]);o.length?this._events[n]=o.length===1?o[0]:o:D(this,n)}return this};f.prototype.removeAllListeners=function(s){var e;return s?(e=g?g+s:s,this._events[e]&&D(this,e)):(this._events=new T,this._eventsCount=0),this};f.prototype.off=f.prototype.removeListener;f.prototype.addListener=f.prototype.on;f.prefixed=g;f.EventEmitter=f;typeof b<"u"&&(b.exports=f)});var U=z(k(),1);var Q=U.default;var C={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0,autoApplyProcessors:!0};var _={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"};var x=Math.PI*2,v=Math.pow,E={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-t*2),inQuad:t=>v(t,2),outQuad:t=>1-(1-t)*(1-t),inOutQuad:t=>t<.5?2*t*t:-1+(4-2*t)*t,inCubic:t=>v(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*v(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>v(t,4),outQuart:t=>1- --t*v(t,3),inOutQuart:t=>t<.5?8*v(t,4):1-8*--t*t*t*t,inQuint:t=>v(t,5),outQuint:t=>1+--t*v(t,4),inOutQuint:t=>t<.5?16*v(t,5):1+16*--t*t*t*t*t,inSine:t=>1-Math.cos(t*Math.PI/2),outSine:t=>Math.sin(t*Math.PI/2),inOutSine:t=>-(Math.cos(Math.PI*t)-1)/2,inBack:(t,s=1.70158)=>t*t*((s+1)*t-s),outBack:(t,s=1.70158)=>(t-=1)*t*((s+1)*t+s)+1,inOutBack:(t,s=1.70158)=>(t*=2)<1?.5*(t*t*((s*1.525+1)*t-s*1.525)):.5*((t-=2)*t*((s*1.525+1)*t+s*1.525)+2),inExpo:t=>t===0?0:Math.pow(2,10*(t-1)),outExpo:t=>t===1?1:1-Math.pow(2,-10*t),inOutExpo:t=>t===0?0:t===1?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:-s*Math.pow(2,10*(t-1))*Math.sin((t-1-e/x*Math.asin(1/s))*x/e),outElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:s*Math.pow(2,-10*t)*Math.sin((t-e/x*Math.asin(1/s))*x/e)+1,inOutElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:t<.5?-.5*s*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*x/e):.5*s*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*x/e)+1};var O={pingPong:function(t){return t<=.5?this._easing(t*2):1-this._easing((t-.5)*2)},yoyo:function(t){return this._easing(E.yoyo(t))},bounce:function(t){return E.yoyo(this._easing(t))}};var J=0,d=class d extends Q{constructor(e={},i){super();y(this,"_reversedEasing",e=>this.settings.easing(1-e));y(this,"_stepDelay",e=>{this.remainingDelay-=e,this.lastDeltaTime=e,!(this.remainingDelay>0)&&(this.emit(_.BEGIN),this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)});y(this,"_stepTime",(e=0)=>{this.elapsedTime+=e,this.lastDeltaTime=e,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()});this.index=J++,this.overrides=e,this.settings={},this.reset(e),i&&(this.manager=i),this.lastDeltaTime=0}on(...e){return super.on(...e),this}off(...e){return super.off(...e),this}once(...e){return super.once(...e),this}onComplete(...e){return super.on(_.COMPLETE,...e),this}onUpdate(...e){return super.on(_.UPDATE,...e),this}onceComplete(...e){return super.once(_.COMPLETE,...e),this}static _noop(){}static mergeConfigs(e,i){e!==i&&Object.keys(i).forEach(r=>{typeof i[r]=="object"&&i[r]!==null?((!e[r]||typeof e[r]!="object")&&(e[r]={}),d.mergeConfigs(e[r],i[r])):e[r]=i[r]})}static lerp(e,i,r){return e+(i-e)*r}_processState(){this.step=d._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=d._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);let{target:e,time:i,repeat:r,loop:n,reversed:a,delay:p}=this.settings;this.target=e,this.time=Math.max(i,0),this.repeat=r>0?r:n?1/0:0,this.reversed=a,this.remainingDelay=p,this._processEasing()}_processEasing(){let e=typeof this.settings.easing=="string"?E[this.settings.easing]||E.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:e;let i=typeof this.settings.mode=="string"?O[this.settings.mode]:this.settings.mode;this._calculateEasing=i?i.bind(this):this._easing}_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(_.UPDATE,this)}_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(_.COMPLETE))}_repeat(e=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),e&&this.emit(_.REPEAT)}reset(e=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...e},this._processState(),this}applyProcessors(e=this.settings){e.processors.forEach(i=>{d.mergeConfigs(e,i.call(this,e)||{})})}tweak(e={}){return d.mergeConfigs(this.settings,e),this._refreshDynamicProps(),this}seek(e=0,i=!0){return this.elapsedTime=Math.min(Math.max(e,0),this.time),i&&this._update(),this}setProgress(e=0,i=!0){return this.seek(this.time*e,i)}reverse(e=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,e),this._processEasing(),this}play(e=!0){return this.isPlaying?this:(this.settings.autoApplyProcessors&&this._refreshDynamicProps(),e&&this.emit(_.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(_.BEGIN)),this.manager&&this.manager.addToActive(this),this)}playPromise(e=this.promise){return this.play(),this.promise=e||new Promise(i=>{this._resolve=i}),this.promise}stop(e=!0){return this._processState(),e&&this.emit(_.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=d._noop,this.manager&&this.manager.removeFromActive(this),this}replay(e=!1){return this.stop(e),this.play(e),this}get isPlaying(){return this.step!==d._noop}remove(){this.stop(),this.manager.remove(this)}};y(d,"DEFAULTS",C);var u=d;var P=class extends u{_preparePropertySetters(){this.propertySetters=this.properties.map(s=>{let e=s.split("."),i=e.pop();return r=>{let n=this.target;for(let a=0;a<e.length;a++)n=n[e[a]];n[i]=r}})}_generatePath(){let s=this.settings.points,e=Math.max(this.settings.smoothing,1),i=[];this.totalLength=0;function r(n,a,p,o,l){let m=l*l,h=m*l;return n.map((I,c)=>.5*(2*a[c]+(-n[c]+p[c])*l+(2*n[c]-5*a[c]+4*p[c]-o[c])*m+(-n[c]+3*a[c]-3*p[c]+o[c])*h))}for(let n=0;n<s.length-1;n++){let a=s[n===0?n:n-1],p=s[n],o=s[n+1],l=s[n+2<s.length?n+2:n+1];for(let m=0;m<e;m++){let h=r(a,p,o,l,m/e);i.push(h),i.length>1&&(this.totalLength+=this._calculateDistance(i[i.length-2],h))}}return i.push(s[s.length-1]),i}_calculateDistance(s,e){return Math.sqrt(s.reduce((i,r,n)=>i+Math.pow(e[n]-s[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),!this.target||this.path.length===0?this._setTargetProperties=u._noop:(this._tryToSetupProperties(),this._preparePropertySetters())}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){let s=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=s[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(s){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](s[e])}_clamp(s,e,i){return Math.max(e,Math.min(s,i))}_getInterpolatedPosition(){let s=this.path.length-1,e=this.easeValue*s,i=this._clamp(e,0,s),r=i>=s?s-1:Math.floor(i),n=Math.min(r+1,s),a=e-r,p=this.path[r],o=this.path[n];return p.map((l,m)=>u.lerp(l,o[m],a))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}};y(P,"DEFAULTS",{...u.DEFAULTS,properties:null,points:[],smoothing:20});var A=class extends u{_refreshDynamicProps(){super._refreshDynamicProps(),this._processFromTo()}_processFromTo(){this._lerps=[],this.target&&(this._setupStates(),this._createLerps())}_setupStates(){this._from=this.settings.from||this._createState(this.settings.to||{},this.target),this._to=this.settings.to||this._createState(this.settings.from||{},this.target)}_createState(s={},e={},i={}){let r=(n,a,p)=>{for(let o in n)typeof n[o]=="object"?(p[o]={},r(n[o],a[o],p[o])):p[o]=a[o]};return r(s,e,i),i}_createLerpStep(s,e,i,r){if(this.settings.dynamic)return()=>{s[r]=u.lerp(e[r],i[r],this.easeValue)};{let n=e[r],a=i[r]-n;return()=>{s[r]=n+a*this.easeValue}}}_createLerps(s=this.target,e=this._from,i=this._to){for(let r in i)typeof i[r]=="object"?this._createLerps(s[r],e[r],i[r]):this._lerps.push(this._createLerpStep(s,e,i,r))}_update(){super._update();for(let s of this._lerps)s()}from(s={}){return this.tweak({from:s}),this}to(s={}){return this.tweak({to:s}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}};y(A,"DEFAULTS",{...u.DEFAULTS,dynamic:!1,from:null,to:null});function w(t){return t.target?t.creator?t.creator instanceof u?t.creator:(console.error("Invalid creator provided. Using default creator."),u):t.points?P:t.from||t.to?A:u:u}var S=class{constructor(){y(this,"update",s=>{this.activeAnimations.forEach(e=>{e.step(s)})});this.activeAnimations=new Map,this.allAnimations=new Map}create({on:s={},once:e={},...i}){let r=w(i),n=new r(i,this);return Object.keys(s).forEach(a=>{n.on(a,s[a])}),Object.keys(e).forEach(a=>{n.once(a,e[a])}),this.add(n),n}getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:s}={}){s&&(this.activeAnimations.delete(s),this.allAnimations.delete(s))}add(s){this.allAnimations.set(s.index,s)}addToActive(s){this.activeAnimations.set(s.index,s)}removeFromActive(s){this.activeAnimations.delete(s.index)}stopAll(){this.activeAnimations.forEach(s=>{s.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}};var W=new S;var M=class t{constructor(s,e={}){this.callback=s,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(s,e={}){let i=new t(s,e);return i.start(),i}start(){if(this.isRunning)return;this.isRunning=!0;let s=e=>{if(!this.isRunning)return;let i=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(i),this.isRunning&&(this.animationId=requestAnimationFrame(s))};requestAnimationFrame(e=>{this.lastTime=e,s(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}};function X(t,s){let e=new w(t),i=new e(t);return M.start(i.step.bind(i)),s?i.playPromise():i.play()}export{u as Core,P as Curve,C as DEFAULTS,_ as EVENTS,A as FromTo,W as GlobalManager,M as Loop,S as Manager,E as easings,O as modes,X as play};
1
+ var R=Object.create;var L=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var q=(t,s,e)=>s in t?L(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e;var N=(t,s)=>()=>(s||t((s={exports:{}}).exports,s),s.exports);var Y=(t,s,e,i)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of V(s))!G.call(t,r)&&r!==e&&L(t,r,{get:()=>s[r],enumerable:!(i=j(s,r))||i.enumerable});return t};var z=(t,s,e)=>(e=t!=null?R(B(t)):{},Y(s||!t||!t.__esModule?L(e,"default",{value:t,enumerable:!0}):e,t));var y=(t,s,e)=>(q(t,typeof s!="symbol"?s+"":s,e),e);var k=N(($,b)=>{"use strict";var K=Object.prototype.hasOwnProperty,g="~";function T(){}Object.create&&(T.prototype=Object.create(null),new T().__proto__||(g=!1));function H(t,s,e){this.fn=t,this.context=s,this.once=e||!1}function F(t,s,e,i,r){if(typeof e!="function")throw new TypeError("The listener must be a function");var n=new H(e,i||t,r),a=g?g+s:s;return t._events[a]?t._events[a].fn?t._events[a]=[t._events[a],n]:t._events[a].push(n):(t._events[a]=n,t._eventsCount++),t}function D(t,s){--t._eventsCount===0?t._events=new T:delete t._events[s]}function f(){this._events=new T,this._eventsCount=0}f.prototype.eventNames=function(){var s=[],e,i;if(this._eventsCount===0)return s;for(i in e=this._events)K.call(e,i)&&s.push(g?i.slice(1):i);return Object.getOwnPropertySymbols?s.concat(Object.getOwnPropertySymbols(e)):s};f.prototype.listeners=function(s){var e=g?g+s:s,i=this._events[e];if(!i)return[];if(i.fn)return[i.fn];for(var r=0,n=i.length,a=new Array(n);r<n;r++)a[r]=i[r].fn;return a};f.prototype.listenerCount=function(s){var e=g?g+s:s,i=this._events[e];return i?i.fn?1:i.length:0};f.prototype.emit=function(s,e,i,r,n,a){var p=g?g+s:s;if(!this._events[p])return!1;var o=this._events[p],l=arguments.length,m,h;if(o.fn){switch(o.once&&this.removeListener(s,o.fn,void 0,!0),l){case 1:return o.fn.call(o.context),!0;case 2:return o.fn.call(o.context,e),!0;case 3:return o.fn.call(o.context,e,i),!0;case 4:return o.fn.call(o.context,e,i,r),!0;case 5:return o.fn.call(o.context,e,i,r,n),!0;case 6:return o.fn.call(o.context,e,i,r,n,a),!0}for(h=1,m=new Array(l-1);h<l;h++)m[h-1]=arguments[h];o.fn.apply(o.context,m)}else{var I=o.length,c;for(h=0;h<I;h++)switch(o[h].once&&this.removeListener(s,o[h].fn,void 0,!0),l){case 1:o[h].fn.call(o[h].context);break;case 2:o[h].fn.call(o[h].context,e);break;case 3:o[h].fn.call(o[h].context,e,i);break;case 4:o[h].fn.call(o[h].context,e,i,r);break;default:if(!m)for(c=1,m=new Array(l-1);c<l;c++)m[c-1]=arguments[c];o[h].fn.apply(o[h].context,m)}}return!0};f.prototype.on=function(s,e,i){return F(this,s,e,i,!1)};f.prototype.once=function(s,e,i){return F(this,s,e,i,!0)};f.prototype.removeListener=function(s,e,i,r){var n=g?g+s:s;if(!this._events[n])return this;if(!e)return D(this,n),this;var a=this._events[n];if(a.fn)a.fn===e&&(!r||a.once)&&(!i||a.context===i)&&D(this,n);else{for(var p=0,o=[],l=a.length;p<l;p++)(a[p].fn!==e||r&&!a[p].once||i&&a[p].context!==i)&&o.push(a[p]);o.length?this._events[n]=o.length===1?o[0]:o:D(this,n)}return this};f.prototype.removeAllListeners=function(s){var e;return s?(e=g?g+s:s,this._events[e]&&D(this,e)):(this._events=new T,this._eventsCount=0),this};f.prototype.off=f.prototype.removeListener;f.prototype.addListener=f.prototype.on;f.prefixed=g;f.EventEmitter=f;typeof b<"u"&&(b.exports=f)});var U=z(k(),1);var Q=U.default;var C={processors:[],time:0,loop:!1,mode:null,delay:0,repeat:0,target:null,easing:t=>t,reversed:!1,repeatDelay:0,autoApplyProcessors:!1};var _={PLAY:"play",STOP:"stop",BEGIN:"begin",UPDATE:"update",REPEAT:"repeat",COMPLETE:"complete"};var x=Math.PI*2,v=Math.pow,E={reverse:t=>1-t,linear:t=>t,yoyo:t=>1-Math.abs(1-t*2),inQuad:t=>v(t,2),outQuad:t=>1-(1-t)*(1-t),inOutQuad:t=>t<.5?2*t*t:-1+(4-2*t)*t,inCubic:t=>v(t,3),outCubic:t=>--t*t*t+1,inOutCubic:t=>t<.5?4*v(t,3):(t-1)*(2*t-2)*(2*t-2)+1,inQuart:t=>v(t,4),outQuart:t=>1- --t*v(t,3),inOutQuart:t=>t<.5?8*v(t,4):1-8*--t*t*t*t,inQuint:t=>v(t,5),outQuint:t=>1+--t*v(t,4),inOutQuint:t=>t<.5?16*v(t,5):1+16*--t*t*t*t*t,inSine:t=>1-Math.cos(t*Math.PI/2),outSine:t=>Math.sin(t*Math.PI/2),inOutSine:t=>-(Math.cos(Math.PI*t)-1)/2,inBack:(t,s=1.70158)=>t*t*((s+1)*t-s),outBack:(t,s=1.70158)=>(t-=1)*t*((s+1)*t+s)+1,inOutBack:(t,s=1.70158)=>(t*=2)<1?.5*(t*t*((s*1.525+1)*t-s*1.525)):.5*((t-=2)*t*((s*1.525+1)*t+s*1.525)+2),inExpo:t=>t===0?0:Math.pow(2,10*(t-1)),outExpo:t=>t===1?1:1-Math.pow(2,-10*t),inOutExpo:t=>t===0?0:t===1?1:t<.5?.5*Math.pow(2,20*t-10):1-.5*Math.pow(2,-20*t+10),inElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:-s*Math.pow(2,10*(t-1))*Math.sin((t-1-e/x*Math.asin(1/s))*x/e),outElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:s*Math.pow(2,-10*t)*Math.sin((t-e/x*Math.asin(1/s))*x/e)+1,inOutElastic:(t,s=1,e=.5)=>t===0?0:t===1?1:t<.5?-.5*s*Math.pow(2,20*t-10)*Math.sin((20*t-11.125)*x/e):.5*s*Math.pow(2,-20*t+10)*Math.sin((20*t-11.125)*x/e)+1};var O={pingPong:function(t){return t<=.5?this._easing(t*2):1-this._easing((t-.5)*2)},yoyo:function(t){return this._easing(E.yoyo(t))},bounce:function(t){return E.yoyo(this._easing(t))}};var J=0,d=class d extends Q{constructor(e={},i){super();y(this,"_reversedEasing",e=>this.settings.easing(1-e));y(this,"_stepDelay",e=>{this.remainingDelay-=e,this.lastDeltaTime=e,!(this.remainingDelay>0)&&(this.emit(_.BEGIN),this.step=this._stepTime,this.step(Math.abs(this.remainingDelay)),this.remainingDelay=this.settings.delay)});y(this,"_stepTime",(e=0)=>{this.elapsedTime+=e,this.lastDeltaTime=e,this.elapsedTime>=this.time?(this.elapsedTime=this.time,this._update(),this._complete()):this._update()});this.index=J++,this.overrides=e,this.settings={},this.reset(e),i&&(this.manager=i),this.lastDeltaTime=0}on(...e){return super.on(...e),this}off(...e){return super.off(...e),this}once(...e){return super.once(...e),this}onComplete(...e){return super.on(_.COMPLETE,...e),this}onUpdate(...e){return super.on(_.UPDATE,...e),this}onceComplete(...e){return super.once(_.COMPLETE,...e),this}static _noop(){}static mergeConfigs(e,i){e!==i&&Object.keys(i).forEach(r=>{typeof i[r]=="object"&&i[r]!==null?((!e[r]||typeof e[r]!="object")&&(e[r]={}),d.mergeConfigs(e[r],i[r])):e[r]=i[r]})}static lerp(e,i,r){return e+(i-e)*r}_processState(){this.step=d._noop,this.progress=0,this.easeValue=0,this.elapsedTime=0,this.promise=null,this._resolve=d._noop,this._refreshDynamicProps()}_refreshDynamicProps(){this.applyProcessors(this.settings);let{target:e,time:i,repeat:r,loop:n,reversed:a,delay:p}=this.settings;this.target=e,this.time=Math.max(i,0),this.repeat=r>0?r:n?1/0:0,this.reversed=a,this.remainingDelay=p,this._processEasing()}_processEasing(){let e=typeof this.settings.easing=="string"?E[this.settings.easing]||E.linear:this.settings.easing;this._easing=this.reversed?this._reversedEasing:e;let i=typeof this.settings.mode=="string"?O[this.settings.mode]:this.settings.mode;this._calculateEasing=i?i.bind(this):this._easing}_update(){this.progress=this.elapsedTime/this.time,this.easeValue=this._calculateEasing(this.progress),this.emit(_.UPDATE,this)}_complete(){this.repeat-- >0?this._repeat():(this._resolve(),this.stop(!1),this.emit(_.COMPLETE))}_repeat(e=!0){this.remainingDelay=this.settings.repeatDelay,this.elapsedTime=0,this.remainingDelay>0&&(this.step=this._stepDelay),this._update(),e&&this.emit(_.REPEAT)}reset(e=this.constructor.DEFAULTS){return this.settings={...this.constructor.DEFAULTS,...e},this._processState(),this}applyProcessors(e=this.settings){e.processors.forEach(i=>{d.mergeConfigs(e,i.call(this,e)||{})})}tweak(e={}){return d.mergeConfigs(this.settings,e),this._refreshDynamicProps(),this}seek(e=0,i=!0){return this.elapsedTime=Math.min(Math.max(e,0),this.time),i&&this._update(),this}setProgress(e=0,i=!0){return this.seek(this.time*e,i)}reverse(e=!1){return this.reversed=!this.reversed,this.seek(this.time-this.elapsedTime,e),this._processEasing(),this}play(e=!0){return this.isPlaying?this:(this.settings.autoApplyProcessors&&this._refreshDynamicProps(),e&&this.emit(_.PLAY),this.remainingDelay>0?this.step=this._stepDelay:(this.step=this._stepTime,this.emit(_.BEGIN)),this.manager&&this.manager.addToActive(this),this)}playPromise(e=this.promise){return this.play(),this.promise=e||new Promise(i=>{this._resolve=i}),this.promise}stop(e=!0){return this._processState(),e&&this.emit(_.STOP),this.manager&&this.manager.removeFromActive(this),this}pause(){return this.step=d._noop,this.manager&&this.manager.removeFromActive(this),this}replay(e=!1){return this.stop(e),this.play(e),this}get isPlaying(){return this.step!==d._noop}remove(){this.stop(),this.manager.remove(this)}};y(d,"DEFAULTS",C);var u=d;var P=class extends u{_preparePropertySetters(){this.propertySetters=this.properties.map(s=>{let e=s.split("."),i=e.pop();return r=>{let n=this.target;for(let a=0;a<e.length;a++)n=n[e[a]];n[i]=r}})}_generatePath(){let s=this.settings.points,e=Math.max(this.settings.smoothing,1),i=[];this.totalLength=0;function r(n,a,p,o,l){let m=l*l,h=m*l;return n.map((I,c)=>.5*(2*a[c]+(-n[c]+p[c])*l+(2*n[c]-5*a[c]+4*p[c]-o[c])*m+(-n[c]+3*a[c]-3*p[c]+o[c])*h))}for(let n=0;n<s.length-1;n++){let a=s[n===0?n:n-1],p=s[n],o=s[n+1],l=s[n+2<s.length?n+2:n+1];for(let m=0;m<e;m++){let h=r(a,p,o,l,m/e);i.push(h),i.length>1&&(this.totalLength+=this._calculateDistance(i[i.length-2],h))}}return i.push(s[s.length-1]),i}_calculateDistance(s,e){return Math.sqrt(s.reduce((i,r,n)=>i+Math.pow(e[n]-s[n],2),0))}_refreshDynamicProps(){super._refreshDynamicProps(),this.path=this._generatePath(),!this.target||this.path.length===0?this._setTargetProperties=u._noop:(this._tryToSetupProperties(),this._preparePropertySetters())}_tryToSetupProperties(){if(this.settings.properties)this.properties=this.settings.properties;else if(this.path[0].length<=3){let s=[["position.x"],["position.x","position.y"],["position.x","position.y","position.z"]];this.properties=s[this.path[0].length-1]}else this.properties=[]}_setTargetProperties(s){for(let e=0;e<this.propertySetters.length;e++)this.propertySetters[e](s[e])}_clamp(s,e,i){return Math.max(e,Math.min(s,i))}_getInterpolatedPosition(){let s=this.path.length-1,e=this.easeValue*s,i=this._clamp(e,0,s),r=i>=s?s-1:Math.floor(i),n=Math.min(r+1,s),a=e-r,p=this.path[r],o=this.path[n];return p.map((l,m)=>u.lerp(l,o[m],a))}_update(){super._update(),this._setTargetProperties(this._getInterpolatedPosition())}};y(P,"DEFAULTS",{...u.DEFAULTS,properties:null,points:[],smoothing:20});var A=class extends u{_refreshDynamicProps(){super._refreshDynamicProps(),this._processFromTo()}_processFromTo(){this._lerps=[],this.target&&(this._setupStates(),this._createLerps())}_setupStates(){this._from=this.settings.from||this._createState(this.settings.to||{},this.target),this._to=this.settings.to||this._createState(this.settings.from||{},this.target)}_createState(s={},e={},i={}){let r=(n,a,p)=>{for(let o in n)typeof n[o]=="object"?(p[o]={},r(n[o],a[o],p[o])):p[o]=a[o]};return r(s,e,i),i}_createLerpStep(s,e,i,r){if(this.settings.dynamic)return()=>{s[r]=u.lerp(e[r],i[r],this.easeValue)};{let n=e[r],a=i[r]-n;return()=>{s[r]=n+a*this.easeValue}}}_createLerps(s=this.target,e=this._from,i=this._to){for(let r in i)typeof i[r]=="object"?this._createLerps(s[r],e[r],i[r]):this._lerps.push(this._createLerpStep(s,e,i,r))}_update(){super._update();for(let s of this._lerps)s()}from(s={}){return this.tweak({from:s}),this}to(s={}){return this.tweak({to:s}),this}swap(){return this.tweak({from:this.settings.to,to:this.settings.from}),this}};y(A,"DEFAULTS",{...u.DEFAULTS,dynamic:!1,from:null,to:null});function w(t){return t.target?t.creator?t.creator.prototype instanceof u?t.creator:(console.error("Invalid creator provided. Using default creator."),u):t.points?P:t.from||t.to?A:u:u}var S=class{constructor(){y(this,"update",s=>{this.activeAnimations.forEach(e=>{e.step(s)})});this.activeAnimations=new Map,this.allAnimations=new Map}create({on:s={},once:e={},...i}){let r=w(i),n=new r(i,this);return Object.keys(s).forEach(a=>{n.on(a,s[a])}),Object.keys(e).forEach(a=>{n.once(a,e[a])}),this.add(n),n}getActiveAnimations(){return Array.from(this.activeAnimations.values())}getAllAnimations(){return Array.from(this.allAnimations.values())}remove({index:s}={}){s&&(this.activeAnimations.delete(s),this.allAnimations.delete(s))}add(s){this.allAnimations.set(s.index,s)}addToActive(s){this.activeAnimations.set(s.index,s)}removeFromActive(s){this.activeAnimations.delete(s.index)}stopAll(){this.activeAnimations.forEach(s=>{s.stop()})}removeAll(){this.stopAll(),this.activeAnimations.clear(),this.allAnimations.clear()}};var W=new S;var M=class t{constructor(s,e={}){this.callback=s,this.options={maxDeltaTime:100,...e},this.isRunning=!1,this.lastTime=0,this.animationId=null}static start(s,e={}){let i=new t(s,e);return i.start(),i}start(){if(this.isRunning)return;this.isRunning=!0;let s=e=>{if(!this.isRunning)return;let i=Math.min(e-this.lastTime,this.options.maxDeltaTime);this.lastTime=e,this.callback(i),this.isRunning&&(this.animationId=requestAnimationFrame(s))};requestAnimationFrame(e=>{this.lastTime=e,s(e)})}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}get running(){return this.isRunning}};function X(t,s){let e=new w(t),i=new e(t);return M.start(i.step.bind(i)),s?i.playPromise():i.play()}export{u as Core,P as Curve,C as DEFAULTS,_ as EVENTS,A as FromTo,W as GlobalManager,M as Loop,S as Manager,E as easings,O as modes,X as play};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qarl",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "simple animation library",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/types/Core.d.ts CHANGED
@@ -1,48 +1,243 @@
1
1
  import EventEmitter from 'eventemitter3';
2
- import { CoreSettings } from './common';
2
+ import { CoreSettings, EasingFunction } from './common';
3
3
 
4
+ /**
5
+ * Core — base animation class built on EventEmitter3.
6
+ * Manages timing, easing, delays, repeats, and lifecycle events.
7
+ * Extended by FromTo (property interpolation) and Curve (spline animation).
8
+ *
9
+ * @example
10
+ * const anim = new Core({ time: 1000, easing: 'outQuad', loop: true });
11
+ * anim.onUpdate((a) => console.log(a.progress, a.easeValue));
12
+ * anim.play();
13
+ *
14
+ * @example
15
+ * // With promise
16
+ * await anim.playPromise();
17
+ * console.log('animation complete');
18
+ */
4
19
  export class Core extends EventEmitter {
20
+ /** Default settings applied to every new instance. */
5
21
  static DEFAULTS: CoreSettings;
22
+
23
+ /**
24
+ * Linear interpolation between two values.
25
+ * @param a - Start value
26
+ * @param b - End value
27
+ * @param t - Interpolation factor (0..1)
28
+ * @returns Interpolated value
29
+ */
6
30
  static lerp(a: number, b: number, t: number): number;
31
+
32
+ /**
33
+ * Deep-merge `source` into `target`, mutating `target` in place.
34
+ * Nested objects are merged recursively; primitives are overwritten.
35
+ */
7
36
  static mergeConfigs(target: object, source: object): void;
8
37
 
38
+ /** Unique numeric index assigned at construction. */
9
39
  index: number;
40
+
41
+ /** Original overrides passed to the constructor. */
10
42
  overrides: Partial<CoreSettings>;
43
+
44
+ /** Current resolved settings (defaults merged with overrides). */
11
45
  settings: CoreSettings;
46
+
47
+ /** Current animation progress (0..1), before easing. */
12
48
  progress: number;
49
+
50
+ /** Current eased value (0..1 for standard easings, can overshoot for elastic/back). */
13
51
  easeValue: number;
52
+
53
+ /** Elapsed time in milliseconds since animation started. */
14
54
  elapsedTime: number;
55
+
56
+ /** Reference to `settings.target`. */
15
57
  target: any;
58
+
59
+ /** Resolved animation duration in milliseconds (≥ 0). */
16
60
  time: number;
61
+
62
+ /** Remaining repetitions. */
17
63
  repeat: number;
64
+
65
+ /** Whether the animation is currently playing in reverse. */
18
66
  reversed: boolean;
67
+
68
+ /** Remaining delay before next step in milliseconds. */
19
69
  remainingDelay: number;
70
+
71
+ /** Delta time from the most recent `step()` call. */
20
72
  lastDeltaTime: number;
73
+
74
+ /** The Manager this animation belongs to, if any. */
21
75
  manager?: import('./Manager').Manager;
22
76
 
77
+ /**
78
+ * @param overrides - Settings to merge on top of `Core.DEFAULTS`
79
+ * @param manager - Optional Manager instance to auto-register with
80
+ */
23
81
  constructor(overrides?: Partial<CoreSettings>, manager?: import('./Manager').Manager);
24
82
 
83
+ /**
84
+ * Advance the animation by `deltaTime` milliseconds.
85
+ * Called by Manager or Loop each frame.
86
+ * Internally delegates to delay/time step based on current state.
87
+ */
25
88
  step(deltaTime: number): void;
26
89
 
90
+ /**
91
+ * Subscribe to an event. Returns `this` for chaining.
92
+ * @param event - Event name: `'play'` | `'stop'` | `'begin'` | `'update'` | `'repeat'` | `'complete'`
93
+ * @param fn - Callback
94
+ * @param context - Optional `this` context for the callback
95
+ */
27
96
  on(event: string, fn: (...args: any[]) => void, context?: any): this;
97
+
98
+ /**
99
+ * Unsubscribe from an event. Returns `this` for chaining.
100
+ * @param event - Event name
101
+ * @param fn - The exact function reference that was passed to `.on()`
102
+ * @param context - The context that was passed to `.on()`
103
+ */
28
104
  off(event: string, fn: (...args: any[]) => void, context?: any): this;
105
+
106
+ /**
107
+ * Subscribe to an event, auto-removed after first fire. Returns `this` for chaining.
108
+ * @param event - Event name
109
+ * @param fn - Callback
110
+ * @param context - Optional `this` context for the callback
111
+ */
29
112
  once(event: string, fn: (...args: any[]) => void, context?: any): this;
113
+
114
+ /**
115
+ * Shorthand for `.on('complete', fn)`. Returns `this` for chaining.
116
+ *
117
+ * @example
118
+ * animation.onComplete(() => console.log('done')).play();
119
+ */
30
120
  onComplete(fn: (animation: this) => void, context?: any): this;
121
+
122
+ /**
123
+ * Shorthand for `.on('update', fn)`. Returns `this` for chaining.
124
+ *
125
+ * @example
126
+ * animation.onUpdate((a) => {
127
+ * console.log(a.progress, a.easeValue);
128
+ * });
129
+ */
31
130
  onUpdate(fn: (animation: this) => void, context?: any): this;
131
+
132
+ /**
133
+ * Shorthand for `.once('complete', fn)`. Returns `this` for chaining.
134
+ * Callback fires once on the next complete, then is removed.
135
+ */
32
136
  onceComplete(fn: (animation: this) => void, context?: any): this;
33
137
 
138
+ /**
139
+ * Reset the animation to its initial state.
140
+ * Merges `newSettings` (or DEFAULTS) and re-initializes all internal state.
141
+ * @param newSettings - New settings to apply (defaults to `DEFAULTS`)
142
+ * @returns `this` for chaining
143
+ */
34
144
  reset(newSettings?: Partial<CoreSettings>): this;
145
+
146
+ /**
147
+ * Manually apply all processor functions to the current settings.
148
+ * Called automatically if `autoApplyProcessors` is `false`.
149
+ */
35
150
  applyProcessors(settings?: CoreSettings): void;
151
+
152
+ /**
153
+ * Modify settings on a live animation without resetting progress.
154
+ * Deep-merges `newSettings` into current `settings` and refreshes dynamic props.
155
+ *
156
+ * @example
157
+ * animation.tweak({ time: 500, easing: 'inOutCubic' });
158
+ *
159
+ * @returns `this` for chaining
160
+ */
36
161
  tweak(newSettings?: Partial<CoreSettings>): this;
162
+
163
+ /**
164
+ * Jump to a specific time in the animation.
165
+ * @param time - Target time in milliseconds, clamped to [0, this.time]
166
+ * @param callUpdate - Whether to fire the UPDATE event (default: `true`)
167
+ * @returns `this` for chaining
168
+ */
37
169
  seek(time?: number, callUpdate?: boolean): this;
170
+
171
+ /**
172
+ * Jump to a specific progress value.
173
+ * @param progress - Target progress (0..1)
174
+ * @param callUpdate - Whether to fire the UPDATE event (default: `true`)
175
+ * @returns `this` for chaining
176
+ */
38
177
  setProgress(progress?: number, callUpdate?: boolean): this;
178
+
179
+ /**
180
+ * Toggle animation direction. Flips `reversed` and adjusts `elapsedTime`
181
+ * so the animation continues from the mirrored position.
182
+ * @param callUpdate - Whether to fire the UPDATE event (default: `false`)
183
+ * @returns `this` for chaining
184
+ */
39
185
  reverse(callUpdate?: boolean): this;
186
+
187
+ /**
188
+ * Start the animation.
189
+ * If a delay is set, transitions to delay state first (PLAY fires immediately, BEGIN fires after delay).
190
+ * No-op if already playing.
191
+ * @param withEvent - Whether to emit the PLAY event (default: `true`)
192
+ * @returns `this` for chaining
193
+ *
194
+ * @example
195
+ * animation.play();
196
+ */
40
197
  play(withEvent?: boolean): this;
198
+
199
+ /**
200
+ * Start the animation and return a Promise that resolves on complete.
201
+ *
202
+ * @example
203
+ * await animation.playPromise();
204
+ * // animation finished
205
+ *
206
+ * @param promise - Optional existing promise to reuse
207
+ * @returns Promise that resolves when the animation completes
208
+ */
41
209
  playPromise(promise?: Promise<void>): Promise<void>;
210
+
211
+ /**
212
+ * Stop the animation, reset internal state (`progress`, `elapsedTime`, etc.).
213
+ * Removes from Manager's active list.
214
+ * @param withEvent - Whether to emit the STOP event (default: `true`)
215
+ * @returns `this` for chaining
216
+ */
42
217
  stop(withEvent?: boolean): this;
218
+
219
+ /**
220
+ * Pause the animation at its current position.
221
+ * Call `.play()` to resume from the paused point.
222
+ * @returns `this` for chaining
223
+ */
43
224
  pause(): this;
225
+
226
+ /**
227
+ * Stop and immediately play again from the beginning.
228
+ * @param withEvent - Whether to emit STOP/PLAY events (default: `false`)
229
+ * @returns `this` for chaining
230
+ */
44
231
  replay(withEvent?: boolean): this;
232
+
233
+ /**
234
+ * Remove this animation from its Manager (both active and all lists).
235
+ * Calls `.stop()` first.
236
+ */
45
237
  remove(): void;
46
238
 
239
+ /**
240
+ * `true` if the animation is currently advancing (not paused/stopped).
241
+ */
47
242
  get isPlaying(): boolean;
48
243
  }
package/types/Curve.d.ts CHANGED
@@ -1,13 +1,61 @@
1
1
  import { Core } from './Core';
2
2
  import { CurveSettings } from './common';
3
3
 
4
+ /**
5
+ * Curve — animates target properties along a Catmull-Rom spline defined by keypoints.
6
+ *
7
+ * Auto-detects property mapping for 1D–3D points (`position.x`, `.y`, `.z`).
8
+ * For higher dimensions or custom paths, provide `properties` explicitly.
9
+ *
10
+ * @example
11
+ * // 3D path — properties auto-detected as position.x/y/z
12
+ * const anim = new Curve({
13
+ * target: mesh,
14
+ * time: 2000,
15
+ * points: [
16
+ * [0, 0, 0],
17
+ * [5, 10, 0],
18
+ * [10, 0, 5],
19
+ * [0, 0, 0],
20
+ * ],
21
+ * easing: 'inOutSine',
22
+ * loop: true,
23
+ * });
24
+ * anim.play();
25
+ *
26
+ * @example
27
+ * // Custom properties — 6D points controlling position + scale
28
+ * const anim = new Curve({
29
+ * target: mesh,
30
+ * time: 3000,
31
+ * properties: ['position.x', 'position.y', 'position.z', 'scale.x', 'scale.y', 'scale.z'],
32
+ * points: [
33
+ * [0, 0, 0, 1, 1, 1],
34
+ * [5, 10, 0, 2, 0.5, 2],
35
+ * [0, 0, 0, 1, 1, 1],
36
+ * ],
37
+ * smoothing: 30,
38
+ * });
39
+ */
4
40
  export class Curve extends Core {
41
+ /** Default settings for Curve, extending Core.DEFAULTS with `points`, `properties`, `smoothing`. */
5
42
  static DEFAULTS: CurveSettings;
6
43
 
44
+ /** Current resolved settings. */
7
45
  settings: CurveSettings;
46
+
47
+ /** Generated spline path — array of interpolated points. */
8
48
  path: number[][];
49
+
50
+ /** Total arc length of the generated path. */
9
51
  totalLength: number;
52
+
53
+ /** Resolved property paths assigned from interpolated values each frame. */
10
54
  properties: string[];
11
55
 
56
+ /**
57
+ * @param overrides - Settings to merge on top of `Curve.DEFAULTS`
58
+ * @param manager - Optional Manager instance to auto-register with
59
+ */
12
60
  constructor(overrides?: Partial<CurveSettings>, manager?: import('./Manager').Manager);
13
61
  }
package/types/FromTo.d.ts CHANGED
@@ -1,14 +1,87 @@
1
1
  import { Core } from './Core';
2
2
  import { FromToSettings } from './common';
3
3
 
4
+ /**
5
+ * FromTo — animates target properties by interpolating between `from` and `to` values.
6
+ * Automatically detects numeric properties (including nested objects) and creates lerps.
7
+ *
8
+ * If only `from` is provided, current target values are used as `to` (and vice versa).
9
+ *
10
+ * @example
11
+ * const anim = new FromTo({
12
+ * target: mesh.position,
13
+ * from: { x: 0, y: 0 },
14
+ * to: { x: 100, y: 200 },
15
+ * time: 1000,
16
+ * easing: 'outQuad',
17
+ * });
18
+ * anim.play();
19
+ *
20
+ * @example
21
+ * // Nested properties
22
+ * const anim = new FromTo({
23
+ * target: mesh,
24
+ * from: { position: { x: 0 }, scale: { x: 1 } },
25
+ * to: { position: { x: 10 }, scale: { x: 2 } },
26
+ * time: 500,
27
+ * });
28
+ *
29
+ * @example
30
+ * // Dynamic mode — from/to are re-read each frame
31
+ * const anim = new FromTo({
32
+ * target: obj,
33
+ * from: startValues,
34
+ * to: endValues,
35
+ * dynamic: true,
36
+ * time: 1000,
37
+ * });
38
+ * // Changing startValues/endValues during animation takes effect immediately
39
+ */
4
40
  export class FromTo extends Core {
41
+ /** Default settings for FromTo, extending Core.DEFAULTS with `from`, `to`, `dynamic`. */
5
42
  static DEFAULTS: FromToSettings;
6
43
 
44
+ /** Current resolved settings. */
7
45
  settings: FromToSettings;
8
46
 
47
+ /**
48
+ * @param overrides - Settings to merge on top of `FromTo.DEFAULTS`
49
+ * @param manager - Optional Manager instance to auto-register with
50
+ */
9
51
  constructor(overrides?: Partial<FromToSettings>, manager?: import('./Manager').Manager);
10
52
 
53
+ /**
54
+ * Update `from` values on a live animation.
55
+ * Calls `.tweak()` internally and rebuilds interpolation.
56
+ *
57
+ * @example
58
+ * animation.from({ x: 50 }).play();
59
+ *
60
+ * @param from - New starting values
61
+ * @returns `this` for chaining
62
+ */
11
63
  from(from?: Record<string, any>): this;
64
+
65
+ /**
66
+ * Update `to` values on a live animation.
67
+ * Calls `.tweak()` internally and rebuilds interpolation.
68
+ *
69
+ * @example
70
+ * animation.to({ x: 200 }).play();
71
+ *
72
+ * @param to - New ending values
73
+ * @returns `this` for chaining
74
+ */
12
75
  to(to?: Record<string, any>): this;
76
+
77
+ /**
78
+ * Swap `from` and `to` values, effectively reversing the interpolation direction.
79
+ * Unlike `.reverse()`, this swaps the actual values rather than inverting the easing.
80
+ *
81
+ * @example
82
+ * animation.swap().replay();
83
+ *
84
+ * @returns `this` for chaining
85
+ */
13
86
  swap(): this;
14
87
  }
package/types/Loop.d.ts CHANGED
@@ -1,18 +1,65 @@
1
1
  import { LoopOptions } from './common';
2
2
 
3
+ /**
4
+ * Loop — requestAnimationFrame wrapper with delta-time capping.
5
+ * Calls the provided callback every frame with `dt` in milliseconds.
6
+ *
7
+ * @example
8
+ * // Static shorthand — create and start in one call
9
+ * const loop = Loop.start((dt) => {
10
+ * manager.update(dt);
11
+ * });
12
+ *
13
+ * // Stop later
14
+ * loop.stop();
15
+ *
16
+ * @example
17
+ * // Manual lifecycle
18
+ * const loop = new Loop((dt) => console.log(dt), { maxDeltaTime: 50 });
19
+ * loop.start();
20
+ * // ...
21
+ * loop.stop();
22
+ */
3
23
  export class Loop {
24
+ /** The callback invoked each frame with `dt` (capped by `maxDeltaTime`). */
4
25
  callback: (dt: number) => void;
26
+
27
+ /** Resolved options with defaults applied. */
5
28
  options: Required<LoopOptions>;
29
+
30
+ /** Whether the loop is currently running. */
6
31
  isRunning: boolean;
32
+
33
+ /** Timestamp of the previous frame (from `requestAnimationFrame`). */
7
34
  lastTime: number;
35
+
36
+ /** Current `requestAnimationFrame` handle, or `null` if stopped. */
8
37
  animationId: number | null;
9
38
 
39
+ /**
40
+ * @param callback - Function called every frame with delta time in ms
41
+ * @param options - Loop options
42
+ */
10
43
  constructor(callback: (dt: number) => void, options?: LoopOptions);
11
44
 
45
+ /**
46
+ * Create a Loop and immediately start it.
47
+ *
48
+ * @example
49
+ * const loop = Loop.start(manager.update);
50
+ *
51
+ * @param callback - Function called every frame with delta time in ms
52
+ * @param options - Loop options
53
+ * @returns The running Loop instance
54
+ */
12
55
  static start(callback: (dt: number) => void, options?: LoopOptions): Loop;
13
56
 
57
+ /** Start the loop. No-op if already running. */
14
58
  start(): void;
59
+
60
+ /** Stop the loop and cancel the next animation frame. */
15
61
  stop(): void;
16
62
 
63
+ /** Alias for `isRunning`. */
17
64
  get running(): boolean;
18
65
  }
@@ -1,20 +1,121 @@
1
1
  import { Core } from './Core';
2
2
  import { ManagerCreateConfig } from './common';
3
3
 
4
+ /**
5
+ * Manager — creates, stores, and batch-updates animations.
6
+ * Animations created via `.create()` are automatically registered in the Manager.
7
+ * Call `.update(dt)` each frame (typically from a Loop) to advance all active animations.
8
+ *
9
+ * @example
10
+ * const manager = new Manager();
11
+ *
12
+ * const anim = manager.create({
13
+ * target: mesh.position,
14
+ * from: { x: 0 },
15
+ * to: { x: 100 },
16
+ * time: 1000,
17
+ * on: { complete: () => console.log('done') },
18
+ * });
19
+ *
20
+ * anim.play();
21
+ * Loop.start(manager.update);
22
+ */
4
23
  export class Manager {
24
+ /** Map of currently playing animations (index → animation). */
5
25
  activeAnimations: Map<number, Core>;
26
+
27
+ /** Map of all registered animations, active or not (index → animation). */
6
28
  allAnimations: Map<number, Core>;
7
29
 
30
+ /**
31
+ * Create a new animation, auto-detecting the type (Core, FromTo, or Curve).
32
+ * The animation is registered in the Manager but not started — call `.play()`.
33
+ *
34
+ * Type detection:
35
+ * - `config.points` → Curve
36
+ * - `config.from` or `config.to` → FromTo
37
+ * - otherwise → Core
38
+ * - `config.creator` → custom class (must extend Core)
39
+ *
40
+ * Event binding shortcuts:
41
+ * - `config.on` — persistent listeners (`.on()`)
42
+ * - `config.once` — one-time listeners (`.once()`)
43
+ *
44
+ * @example
45
+ * const anim = manager.create({
46
+ * target: obj,
47
+ * to: { x: 10 },
48
+ * time: 500,
49
+ * easing: 'outQuad',
50
+ * on: { update: (a) => render(a.target) },
51
+ * });
52
+ * anim.play();
53
+ */
8
54
  create(config: ManagerCreateConfig): Core;
55
+
56
+ /**
57
+ * Advance all active animations by `dt` milliseconds.
58
+ * Bound to the instance — safe to pass directly to `Loop.start()`.
59
+ *
60
+ * @example
61
+ * Loop.start(manager.update);
62
+ */
9
63
  update(dt: number): void;
64
+
65
+ /**
66
+ * Get a snapshot array of all currently playing animations.
67
+ */
10
68
  getActiveAnimations(): Core[];
69
+
70
+ /**
71
+ * Get a snapshot array of all registered animations (active + inactive).
72
+ */
11
73
  getAllAnimations(): Core[];
74
+
75
+ /**
76
+ * Remove an animation from both active and all lists by its index.
77
+ * @param animation - Object with an `index` property
78
+ */
12
79
  remove(animation: { index?: number }): void;
80
+
81
+ /**
82
+ * Register an animation in the `allAnimations` map.
83
+ * Called automatically by `.create()`.
84
+ */
13
85
  add(animation: Core): void;
86
+
87
+ /**
88
+ * Move an animation to the active list (it will receive `.update()` calls).
89
+ * Called automatically by `animation.play()` when a Manager is attached.
90
+ */
14
91
  addToActive(animation: Core): void;
92
+
93
+ /**
94
+ * Remove an animation from the active list (stops receiving updates).
95
+ * Called automatically by `animation.stop()` / `.pause()`.
96
+ */
15
97
  removeFromActive(animation: Core): void;
98
+
99
+ /**
100
+ * Stop all active animations (calls `.stop()` on each).
101
+ */
16
102
  stopAll(): void;
103
+
104
+ /**
105
+ * Stop all animations and clear both active and all lists.
106
+ */
17
107
  removeAll(): void;
18
108
  }
19
109
 
110
+ /**
111
+ * Pre-created global Manager singleton.
112
+ * Convenient when you don't need multiple independent animation groups.
113
+ *
114
+ * @example
115
+ * import { GlobalManager, Loop } from 'qarl';
116
+ *
117
+ * const anim = GlobalManager.create({ target: obj, to: { x: 10 }, time: 500 });
118
+ * anim.play();
119
+ * Loop.start(GlobalManager.update);
120
+ */
20
121
  export const GlobalManager: Manager;
package/types/common.d.ts CHANGED
@@ -1,53 +1,261 @@
1
1
  import { Core } from './Core';
2
2
 
3
+ /**
4
+ * Easing function that maps progress `t` (0..1) to an output value.
5
+ * Can accept additional parameters for parametric easings (e.g. `inBack(t, overshoot)`).
6
+ *
7
+ * @example
8
+ * const customEasing: EasingFunction = (t) => t * t;
9
+ *
10
+ * @example
11
+ * const parametric: EasingFunction = (t, strength = 1.5) => t * strength;
12
+ */
3
13
  export type EasingFunction = (t: number, ...args: number[]) => number;
4
14
 
15
+ /**
16
+ * Mode function that wraps an easing to create composite effects (ping-pong, yoyo, etc.).
17
+ * Called with `this` bound to the Core instance, giving access to `this._easing`.
18
+ *
19
+ * @example
20
+ * const customMode: ModeFunction = function(t) {
21
+ * return t <= 0.5
22
+ * ? this._easing(t * 2)
23
+ * : 1 - this._easing((t - 0.5) * 2);
24
+ * };
25
+ */
5
26
  export type ModeFunction = (this: Core, t: number) => number;
6
27
 
28
+ /**
29
+ * Processor function — middleware that can modify animation settings before each play.
30
+ * Called with `this` bound to the Core instance.
31
+ * Return a partial settings object to merge, or void to modify `settings` in place.
32
+ *
33
+ * @example
34
+ * const randomDelay: ProcessorFunction = function(settings) {
35
+ * return { delay: Math.random() * 1000 };
36
+ * };
37
+ */
7
38
  export type ProcessorFunction = (this: Core, settings: CoreSettings) => Partial<CoreSettings> | void;
8
39
 
40
+ /**
41
+ * Base configuration for all animations.
42
+ */
9
43
  export interface CoreSettings {
44
+ /**
45
+ * Array of processor functions applied before each play.
46
+ * Processors can dynamically modify settings (e.g. randomize delay, compute values).
47
+ * @default []
48
+ */
10
49
  processors: ProcessorFunction[];
50
+
51
+ /**
52
+ * Duration of the animation in milliseconds.
53
+ * @default 0
54
+ */
11
55
  time: number;
56
+
57
+ /**
58
+ * If `true`, the animation repeats indefinitely.
59
+ * Overrides `repeat` — sets it to `Infinity`.
60
+ * @default false
61
+ */
12
62
  loop: boolean;
13
- mode: string | ModeFunction | null;
63
+
64
+ /**
65
+ * Animation mode that wraps the easing function.
66
+ * Pass a built-in name (`'pingPong'`, `'yoyo'`, `'bounce'`) or a custom `ModeFunction`.
67
+ * @default null
68
+ */
69
+ mode: ModeName | ModeFunction | null;
70
+
71
+ /**
72
+ * Delay before the animation starts, in milliseconds.
73
+ * The `BEGIN` event fires after the delay; `PLAY` fires immediately.
74
+ * @default 0
75
+ */
14
76
  delay: number;
77
+
78
+ /**
79
+ * Number of times to repeat after the first play.
80
+ * `0` = play once, `1` = play twice, etc. Ignored if `loop` is `true`.
81
+ * @default 0
82
+ */
15
83
  repeat: number;
84
+
85
+ /**
86
+ * The object whose properties will be animated.
87
+ * For FromTo/Curve — the object receiving interpolated values.
88
+ * For bare Core — available via `this.target` in event handlers.
89
+ * @default null
90
+ */
16
91
  target: any;
17
- easing: string | EasingFunction;
92
+
93
+ /**
94
+ * Easing function or a built-in easing name.
95
+ * Controls the animation curve (acceleration/deceleration).
96
+ *
97
+ * Built-in names: `'linear'`, `'inQuad'`, `'outQuad'`, `'inOutQuad'`,
98
+ * `'inCubic'`, `'outCubic'`, `'inOutCubic'`, `'inElastic'`, `'outElastic'`, etc.
99
+ *
100
+ * @default (t) => t // linear
101
+ */
102
+ easing: EasingName | EasingFunction;
103
+
104
+ /**
105
+ * If `true`, the easing is applied in reverse direction.
106
+ * @default false
107
+ */
18
108
  reversed: boolean;
109
+
110
+ /**
111
+ * Delay between repetitions in milliseconds.
112
+ * Only relevant when `repeat > 0` or `loop` is `true`.
113
+ * @default 0
114
+ */
19
115
  repeatDelay: number;
116
+
117
+ /**
118
+ * If `true`, processors are re-applied automatically before each `play()`.
119
+ * If `false`, processors are only applied on `reset()`.
120
+ * @default true
121
+ */
20
122
  autoApplyProcessors: boolean;
21
123
  }
22
124
 
125
+ /**
126
+ * Configuration for FromTo animations.
127
+ * Extends CoreSettings with `from`/`to` value objects.
128
+ */
23
129
  export interface FromToSettings extends CoreSettings {
130
+ /**
131
+ * If `true`, `from` and `to` are re-read each frame, allowing external changes.
132
+ * If `false`, deltas are precomputed once for better performance.
133
+ * @default false
134
+ */
24
135
  dynamic: boolean;
136
+
137
+ /**
138
+ * Starting values. Shape must mirror the `target` object's structure.
139
+ * If omitted, current values of `target` matching `to` keys are used.
140
+ *
141
+ * @example
142
+ * { position: { x: 0, y: 0 }, scale: { x: 1 } }
143
+ * @default null
144
+ */
25
145
  from: Record<string, any> | null;
146
+
147
+ /**
148
+ * Ending values. Shape must mirror the `target` object's structure.
149
+ * If omitted, current values of `target` matching `from` keys are used.
150
+ *
151
+ * @example
152
+ * { position: { x: 100, y: 200 }, scale: { x: 2 } }
153
+ * @default null
154
+ */
26
155
  to: Record<string, any> | null;
27
156
  }
28
157
 
158
+ /**
159
+ * Configuration for Curve (Catmull-Rom spline) animations.
160
+ * Extends CoreSettings with keypoint arrays.
161
+ */
29
162
  export interface CurveSettings extends CoreSettings {
163
+ /**
164
+ * Property paths on `target` to assign interpolated values.
165
+ * Each string is a dot-separated path (e.g. `'position.x'`).
166
+ * If omitted and points have 1–3 dimensions, defaults to `position.x`, `.y`, `.z`.
167
+ *
168
+ * @example
169
+ * ['position.x', 'position.y', 'rotation.z']
170
+ * @default null
171
+ */
30
172
  properties: string[] | null;
173
+
174
+ /**
175
+ * Array of keypoints for the spline. Each point is a number array
176
+ * whose length must match `properties.length`.
177
+ *
178
+ * @example
179
+ * [[0, 0, 0], [5, 10, 0], [10, 0, 0]]
180
+ * @default []
181
+ */
31
182
  points: number[][];
183
+
184
+ /**
185
+ * Number of interpolation steps between each pair of keypoints.
186
+ * Higher values produce smoother curves at the cost of memory.
187
+ * @default 20
188
+ */
32
189
  smoothing: number;
33
190
  }
34
191
 
192
+ /**
193
+ * Options for the animation loop.
194
+ */
35
195
  export interface LoopOptions {
196
+ /**
197
+ * Maximum allowed delta time per frame in milliseconds.
198
+ * Prevents large jumps when the tab is backgrounded.
199
+ * @default 100
200
+ */
36
201
  maxDeltaTime?: number;
37
202
  }
38
203
 
204
+ /**
205
+ * Configuration for `Manager.create()`.
206
+ * Combines CoreSettings with FromTo/Curve fields and event binding shortcuts.
207
+ * The correct animation type (Core, FromTo, or Curve) is auto-detected.
208
+ */
39
209
  export interface ManagerCreateConfig extends Partial<CoreSettings> {
210
+ /**
211
+ * Event listeners attached via `.on()` (persistent).
212
+ *
213
+ * @example
214
+ * { update: (anim) => console.log(anim.progress) }
215
+ */
40
216
  on?: Record<string, (...args: any[]) => void>;
217
+
218
+ /**
219
+ * Event listeners attached via `.once()` (fire once, then removed).
220
+ *
221
+ * @example
222
+ * { complete: () => console.log('done') }
223
+ */
41
224
  once?: Record<string, (...args: any[]) => void>;
225
+
226
+ /** Starting values (triggers FromTo animation). */
42
227
  from?: Record<string, any>;
228
+
229
+ /** Ending values (triggers FromTo animation). */
43
230
  to?: Record<string, any>;
231
+
232
+ /** Keypoints (triggers Curve animation). */
44
233
  points?: number[][];
234
+
235
+ /** Property paths for Curve animation. */
45
236
  properties?: string[];
237
+
238
+ /** Smoothing for Curve animation. */
46
239
  smoothing?: number;
240
+
241
+ /** Dynamic mode for FromTo animation. */
47
242
  dynamic?: boolean;
243
+
244
+ /**
245
+ * Custom animation class to use instead of auto-detection.
246
+ * Must be a subclass of Core (e.g. a custom controller).
247
+ */
48
248
  creator?: typeof Core;
49
249
  }
50
250
 
251
+ /**
252
+ * Built-in easing function names.
253
+ *
254
+ * Families: Quad, Cubic, Quart, Quint, Sine, Back, Expo, Elastic.
255
+ * Each family has `in`, `out`, and `inOut` variants.
256
+ *
257
+ * Special: `'linear'` (no easing), `'reverse'` (1 − t), `'yoyo'` (triangle wave).
258
+ */
51
259
  export type EasingName =
52
260
  | 'linear' | 'reverse' | 'yoyo'
53
261
  | 'inQuad' | 'outQuad' | 'inOutQuad'
@@ -59,13 +267,29 @@ export type EasingName =
59
267
  | 'inExpo' | 'outExpo' | 'inOutExpo'
60
268
  | 'inElastic' | 'outElastic' | 'inOutElastic';
61
269
 
270
+ /**
271
+ * Built-in animation mode names.
272
+ *
273
+ * - `'pingPong'` — forward then backward using the easing.
274
+ * - `'yoyo'` — easing applied to a triangle wave.
275
+ * - `'bounce'` — triangle wave applied after easing.
276
+ */
62
277
  export type ModeName = 'pingPong' | 'yoyo' | 'bounce';
63
278
 
279
+ /**
280
+ * Event name constants used with `.on()` / `.once()` / `.emit()`.
281
+ */
64
282
  export interface EventTypes {
283
+ /** Fires when `.play()` is called (before delay). */
65
284
  PLAY: 'play';
285
+ /** Fires when `.stop()` is called. */
66
286
  STOP: 'stop';
287
+ /** Fires when the animation actually begins (after delay). */
67
288
  BEGIN: 'begin';
289
+ /** Fires every frame with updated `progress` and `easeValue`. */
68
290
  UPDATE: 'update';
291
+ /** Fires on each repetition. */
69
292
  REPEAT: 'repeat';
293
+ /** Fires when all repetitions are done. */
70
294
  COMPLETE: 'complete';
71
295
  }
@@ -1,3 +1,22 @@
1
1
  import { CoreSettings } from './common';
2
2
 
3
+ /**
4
+ * Default animation settings applied to every Core instance.
5
+ *
6
+ * ```
7
+ * {
8
+ * processors: [],
9
+ * time: 0,
10
+ * loop: false,
11
+ * mode: null,
12
+ * delay: 0,
13
+ * repeat: 0,
14
+ * target: null,
15
+ * easing: (t) => t, // linear
16
+ * reversed: false,
17
+ * repeatDelay: 0,
18
+ * autoApplyProcessors: false,
19
+ * }
20
+ * ```
21
+ */
3
22
  export const DEFAULTS: CoreSettings;
@@ -1,3 +1,35 @@
1
1
  import { EasingFunction, EasingName } from './common';
2
2
 
3
+ /**
4
+ * Built-in easing functions.
5
+ * Each function maps progress `t` (0..1) to an eased output.
6
+ *
7
+ * | Family | In | Out | InOut |
8
+ * |----------|-------------|--------------|----------------|
9
+ * | Quad | `inQuad` | `outQuad` | `inOutQuad` |
10
+ * | Cubic | `inCubic` | `outCubic` | `inOutCubic` |
11
+ * | Quart | `inQuart` | `outQuart` | `inOutQuart` |
12
+ * | Quint | `inQuint` | `outQuint` | `inOutQuint` |
13
+ * | Sine | `inSine` | `outSine` | `inOutSine` |
14
+ * | Back | `inBack` | `outBack` | `inOutBack` |
15
+ * | Expo | `inExpo` | `outExpo` | `inOutExpo` |
16
+ * | Elastic | `inElastic` | `outElastic` | `inOutElastic` |
17
+ *
18
+ * Special:
19
+ * - `linear` — no easing (`t → t`)
20
+ * - `reverse` — inverted (`t → 1 − t`)
21
+ * - `yoyo` — triangle wave (`0 → 1 → 0`)
22
+ *
23
+ * @example
24
+ * import { easings } from 'qarl';
25
+ *
26
+ * // Use as a function directly
27
+ * const value = easings.outElastic(0.5);
28
+ *
29
+ * // Pass by name in config
30
+ * { easing: 'outElastic' }
31
+ *
32
+ * // Or pass the function reference
33
+ * { easing: easings.outElastic }
34
+ */
3
35
  export const easings: Record<EasingName, EasingFunction>;
package/types/events.d.ts CHANGED
@@ -1,3 +1,22 @@
1
1
  import { EventTypes } from './common';
2
2
 
3
+ /**
4
+ * Animation lifecycle event name constants.
5
+ *
6
+ * | Constant | Value | When it fires |
7
+ * |------------|--------------|----------------------------------------------|
8
+ * | `PLAY` | `'play'` | `.play()` called (before delay) |
9
+ * | `STOP` | `'stop'` | `.stop()` called |
10
+ * | `BEGIN` | `'begin'` | Animation actually starts (after delay) |
11
+ * | `UPDATE` | `'update'` | Every frame, after progress/easing computed |
12
+ * | `REPEAT` | `'repeat'` | Each repetition starts |
13
+ * | `COMPLETE` | `'complete'` | All repetitions finished |
14
+ *
15
+ * @example
16
+ * import { EVENTS } from 'qarl';
17
+ *
18
+ * animation.on(EVENTS.UPDATE, (anim) => {
19
+ * console.log(anim.progress);
20
+ * });
21
+ */
3
22
  export const EVENTS: EventTypes;
package/types/index.d.ts CHANGED
@@ -1,3 +1,30 @@
1
+ /**
2
+ * qarl — simple animation library.
3
+ *
4
+ * Core concepts:
5
+ * - **Core** — base animation class (timing, easing, events)
6
+ * - **FromTo** — interpolates object properties between `from` and `to` values
7
+ * - **Curve** — animates along a Catmull-Rom spline
8
+ * - **Manager** — groups and batch-updates animations
9
+ * - **Loop** — requestAnimationFrame wrapper with delta-time capping
10
+ * - **play()** — quick-start: creates animation + Loop in one call
11
+ *
12
+ * @example
13
+ * import { GlobalManager, Loop } from 'qarl';
14
+ *
15
+ * const anim = GlobalManager.create({
16
+ * target: mesh.position,
17
+ * to: { x: 10, y: 5 },
18
+ * time: 1000,
19
+ * easing: 'outQuad',
20
+ * });
21
+ *
22
+ * anim.play();
23
+ * Loop.start(GlobalManager.update);
24
+ *
25
+ * @packageDocumentation
26
+ */
27
+
1
28
  export { Core } from './Core';
2
29
  export { Curve } from './Curve';
3
30
  export { FromTo } from './FromTo';
package/types/modes.d.ts CHANGED
@@ -1,3 +1,20 @@
1
1
  import { ModeFunction, ModeName } from './common';
2
2
 
3
+ /**
4
+ * Built-in animation modes.
5
+ * Modes wrap the easing function to create composite effects.
6
+ *
7
+ * - `pingPong` — forward then backward: `easing(t*2)` for first half, `1 - easing((t-0.5)*2)` for second.
8
+ * - `yoyo` — easing applied to a triangle wave: `easing(1 - |1 - t*2|)`.
9
+ * - `bounce` — triangle wave applied after easing: `1 - |1 - easing(t)*2|`.
10
+ *
11
+ * @example
12
+ * import { modes } from 'qarl';
13
+ *
14
+ * // Pass by name
15
+ * { mode: 'pingPong', easing: 'outQuad' }
16
+ *
17
+ * // Or pass the function reference
18
+ * { mode: modes.pingPong, easing: 'outQuad' }
19
+ */
3
20
  export const modes: Record<ModeName, ModeFunction>;
package/types/play.d.ts CHANGED
@@ -1,5 +1,29 @@
1
1
  import { Core } from './Core';
2
2
  import { CoreSettings, FromToSettings, CurveSettings } from './common';
3
3
 
4
+ /**
5
+ * Quick-start function — creates an animation, starts a Loop, and plays it.
6
+ * Auto-detects the animation type (Core, FromTo, or Curve) from the config.
7
+ *
8
+ * @example
9
+ * // Synchronous — returns the animation instance
10
+ * const anim = play({
11
+ * target: mesh.position,
12
+ * to: { x: 10 },
13
+ * time: 1000,
14
+ * });
15
+ *
16
+ * @example
17
+ * // Async — returns a Promise that resolves on complete
18
+ * await play({
19
+ * target: mesh.position,
20
+ * to: { x: 10 },
21
+ * time: 1000,
22
+ * }, true);
23
+ * console.log('animation finished');
24
+ *
25
+ * @param config - Animation settings (type is auto-detected)
26
+ * @param async - If `true`, returns a Promise instead of the animation
27
+ */
4
28
  export function play(config: Partial<CoreSettings | FromToSettings | CurveSettings>, async?: false): Core;
5
29
  export function play(config: Partial<CoreSettings | FromToSettings | CurveSettings>, async: true): Promise<void>;