{"version":3,"file":"additween.mjs","sources":["../src/PlainObjectReducer.ts","../node_modules/@babel/runtime/helpers/esm/createClass.js","../node_modules/@babel/runtime/helpers/esm/defineProperty.js","../src/AdditiveTweening.ts","../node_modules/@babel/runtime/helpers/esm/classCallCheck.js","../src/getCurrentTime.ts"],"sourcesContent":["export interface IStateReducer<T extends Record<string, number>> {\n    clone: (state: T) => T;\n    reduce: (targetState: T, toState: T, fromState: T, pos: number) => T;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const PlainObjectReducer: IStateReducer<any> = {\n    clone: function (obj) {\n        const target: Record<string, number> = {};\n        for (const key in obj) {\n            target[key] = obj[key];\n        }\n        return target;\n    },\n\n    reduce: function (targetState, toState, fromState, pos) {\n        for (const key in targetState) {\n            targetState[key] -= (toState[key] - fromState[key]) * pos;\n        }\n        return targetState;\n    },\n};\n","function _defineProperties(target, props) {\n  for (var i = 0; i < props.length; i++) {\n    var descriptor = props[i];\n    descriptor.enumerable = descriptor.enumerable || false;\n    descriptor.configurable = true;\n    if (\"value\" in descriptor) descriptor.writable = true;\n    Object.defineProperty(target, descriptor.key, descriptor);\n  }\n}\n\nexport default function _createClass(Constructor, protoProps, staticProps) {\n  if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n  if (staticProps) _defineProperties(Constructor, staticProps);\n  return Constructor;\n}","export default function _defineProperty(obj, key, value) {\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true\n    });\n  } else {\n    obj[key] = value;\n  }\n\n  return obj;\n}","import { getCurrentTime } from \"./getCurrentTime\";\nimport { PlainObjectReducer } from \"./PlainObjectReducer\";\nimport type { IStateReducer } from \"./PlainObjectReducer\";\n\nfunction noop() {}\n\nfunction identity(t: number): number {\n    return t;\n}\n\nexport type EasingFunction = (t: number) => number;\n\ntype TAnimationStackEntry<T> = {\n    duration: number;\n    end: number;\n    fromState: T;\n    toState: T;\n    easing: EasingFunction;\n};\n\nexport type TAdditiveTweeningOptions<T extends Record<string, number>> = {\n    onRender: (state: T) => void;\n    onFinish?: (finalState: T) => void;\n    onCancel?: () => void;\n    stateReducer?: IStateReducer<T>;\n};\n\nexport class AdditiveTweening<T extends Record<string, number>> {\n    tween: (\n        fromState: T,\n        toState: T,\n        duration: number,\n        easing?: EasingFunction\n    ) => void;\n\n    isTweening: () => boolean;\n\n    finish: () => void;\n\n    cancel: () => void;\n\n    constructor(options: TAdditiveTweeningOptions<T>) {\n        let frame = 0,\n            lastTargetState: T | null = null,\n            currentState = null,\n            animationStack: Array<TAnimationStackEntry<T>> = [];\n\n        const onRender = options.onRender || noop;\n        const stateReducer: IStateReducer<T> =\n            options.stateReducer || PlainObjectReducer;\n        const onFinish = options.onFinish || noop;\n        const onCancel = options.onCancel || noop;\n\n        function filterOutdatedTargetsFromStack(time: number) {\n            const filteredStack = [];\n            for (let i = animationStack.length - 1; i >= 0; i--) {\n                if (animationStack[i].end > time) {\n                    filteredStack.push(animationStack[i]);\n                }\n            }\n\n            animationStack = filteredStack;\n        }\n\n        function getCurrentState(time: number) {\n            let animation, remain;\n\n            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n            let target = stateReducer.clone(lastTargetState!);\n\n            for (let i = animationStack.length - 1; i >= 0; i--) {\n                animation = animationStack[i];\n                if (animation.end < time) {\n                    continue;\n                }\n                remain = (animation.end - time) / animation.duration;\n                target = stateReducer.reduce(\n                    target,\n                    animation.toState,\n                    animation.fromState,\n                    animation.easing(remain)\n                );\n            }\n\n            return target;\n        }\n\n        function hasActiveAnimation(time: number): boolean {\n            for (let i = animationStack.length - 1; i >= 0; i--) {\n                const animation = animationStack[i];\n                if (animation.end >= time) {\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        const animationStep = () => {\n            if (lastTargetState === null) {\n                return;\n            }\n\n            const time = this.now();\n\n            currentState = getCurrentState(time);\n\n            onRender(currentState);\n\n            if (hasActiveAnimation(time)) {\n                frame = this.scheduleAnimationFrame(animationStep);\n            } else {\n                this.finish();\n            }\n        };\n\n        /**\n         * Returns true if any tweening is in process\n         * @returns {boolean}\n         */\n        this.isTweening = function () {\n            return !!lastTargetState;\n        };\n\n        /**\n         * Immediately sets tweening to its final state.\n         */\n        this.finish = function () {\n            if (lastTargetState !== null) {\n                onFinish(lastTargetState);\n\n                lastTargetState = null;\n                currentState = null;\n            }\n        };\n\n        /**\n         * Cancels all active tweening processes\n         */\n        this.cancel = function () {\n            if (lastTargetState !== null) {\n                if (window.cancelAnimationFrame) {\n                    window.cancelAnimationFrame(frame);\n                    frame = 0;\n                }\n                onCancel();\n\n                lastTargetState = null;\n                currentState = null;\n            }\n        };\n\n        /**\n         * Starts new tweening process\n         * @param fromState\n         * @param toState\n         * @param {Number} duration   Duration in ms\n         * @param {Function} easing    An easing function. It should take a number from [0,1] range and return a number from [0,1] range.\n         */\n        this.tween = function (fromState, toState, duration, easing) {\n            const time = this.now();\n\n            const animation = {\n                duration: duration,\n                end: time + duration,\n                fromState:\n                    lastTargetState === null ? fromState : lastTargetState,\n                toState: toState,\n                easing: easing || identity,\n            };\n\n            filterOutdatedTargetsFromStack(time);\n\n            animationStack.push(animation);\n\n            lastTargetState = toState;\n\n            frame = this.scheduleAnimationFrame(animationStep);\n        };\n    }\n\n    scheduleAnimationFrame(cb: () => void): number {\n        return window.requestAnimationFrame(cb);\n    }\n\n    now(): number {\n        return getCurrentTime();\n    }\n}\n","export default function _classCallCheck(instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n}","export function getCurrentTime(): number {\n    if (window.performance && window.performance.now) {\n        return window.performance.now();\n    }\n\n    if (Date.now) {\n        return Date.now();\n    }\n\n    return new Date().getTime();\n}\n"],"names":["PlainObjectReducer","clone","obj","target","key","reduce","targetState","toState","fromState","pos","_defineProperties","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","_defineProperty","value","noop","identity","t","AdditiveTweening","options","instance","Constructor","TypeError","frame","lastTargetState","currentState","animationStack","onRender","stateReducer","onFinish","onCancel","animationStep","time","_this","now","animation","remain","end","duration","easing","getCurrentState","hasActiveAnimation","finish","scheduleAnimationFrame","isTweening","cancel","window","cancelAnimationFrame","tween","this","filteredStack","push","filterOutdatedTargetsFromStack","protoProps","staticProps","cb","requestAnimationFrame","performance","Date","getTime","prototype"],"mappings":"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"}