diff --git a/src/runtime/motion/tweened.js b/src/runtime/motion/tweened.js index 7375d16a96..b7654ffdba 100644 --- a/src/runtime/motion/tweened.js +++ b/src/runtime/motion/tweened.js @@ -4,110 +4,110 @@ import { linear } from '../easing'; import { is_date } from './utils'; /** @returns {(t: any) => any} */ function get_interpolator(a, b) { - if (a === b || a !== a) - return () => a; - const type = typeof a; - if (type !== typeof b || Array.isArray(a) !== Array.isArray(b)) { - throw new Error('Cannot interpolate values of different type'); - } - if (Array.isArray(a)) { - const arr = b.map((bi, i) => { - return get_interpolator(a[i], bi); - }); - return (t) => arr.map((fn) => fn(t)); - } - if (type === 'object') { - if (!a || !b) - throw new Error('Object cannot be null'); - if (is_date(a) && is_date(b)) { - a = a.getTime(); - b = b.getTime(); - const delta = b - a; - return (t) => new Date(a + t * delta); - } - const keys = Object.keys(b); - const interpolators = {}; - keys.forEach((key) => { - interpolators[key] = get_interpolator(a[key], b[key]); - }); - return (t) => { - const result = {}; - keys.forEach((key) => { - result[key] = interpolators[key](t); - }); - return result; - }; - } - if (type === 'number') { - const delta = b - a; - return (t) => a + t * delta; - } - throw new Error(`Cannot interpolate ${type} values`); + if (a === b || a !== a) return () => a; + const type = typeof a; + if (type !== typeof b || Array.isArray(a) !== Array.isArray(b)) { + throw new Error('Cannot interpolate values of different type'); + } + if (Array.isArray(a)) { + const arr = b.map((bi, i) => { + return get_interpolator(a[i], bi); + }); + return (t) => arr.map((fn) => fn(t)); + } + if (type === 'object') { + if (!a || !b) throw new Error('Object cannot be null'); + if (is_date(a) && is_date(b)) { + a = a.getTime(); + b = b.getTime(); + const delta = b - a; + return (t) => new Date(a + t * delta); + } + const keys = Object.keys(b); + const interpolators = {}; + keys.forEach((key) => { + interpolators[key] = get_interpolator(a[key], b[key]); + }); + return (t) => { + const result = {}; + keys.forEach((key) => { + result[key] = interpolators[key](t); + }); + return result; + }; + } + if (type === 'number') { + const delta = b - a; + return (t) => a + t * delta; + } + throw new Error(`Cannot interpolate ${type} values`); } /** @param {T} value * @param {Options} defaults * @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/tweened.ts-to-jsdoc").Tweened} */ export function tweened(value, defaults = {}) { - const store = writable(value); - /** @type {Task} */ - let task; - let target_value = value; - /** @param {T} new_value - * @param {Options} opts - * @returns {any} - */ - function set(new_value, opts) { - if (value == null) { - store.set((value = new_value)); - return Promise.resolve(); - } - target_value = new_value; - let previous_task = task; - let started = false; - let { delay = 0, duration = 400, easing = linear, interpolate = get_interpolator } = assign(assign({}, defaults), opts); - if (duration === 0) { - if (previous_task) { - previous_task.abort(); - previous_task = null; - } - store.set((value = target_value)); - return Promise.resolve(); - } - const start = now() + delay; - let fn; - task = loop((now) => { - if (now < start) - return true; - if (!started) { - fn = interpolate(value, new_value); - if (typeof duration === 'function') - duration = duration(value, new_value); - started = true; - } - if (previous_task) { - previous_task.abort(); - previous_task = null; - } - const elapsed = now - start; - if (elapsed > duration) { - store.set((value = new_value)); - return false; - } - // @ts-ignore - store.set((value = fn(easing(elapsed / duration)))); - return true; - }); - return task.promise; - } - return { - set, - update: (fn, opts) => set(fn(target_value, value), opts), - subscribe: store.subscribe - }; + const store = writable(value); + /** @type {Task} */ + let task; + let target_value = value; + /** @param {T} new_value + * @param {Options} opts + * @returns {any} + */ + function set(new_value, opts) { + if (value == null) { + store.set((value = new_value)); + return Promise.resolve(); + } + target_value = new_value; + let previous_task = task; + let started = false; + let { + delay = 0, + duration = 400, + easing = linear, + interpolate = get_interpolator + } = assign(assign({}, defaults), opts); + if (duration === 0) { + if (previous_task) { + previous_task.abort(); + previous_task = null; + } + store.set((value = target_value)); + return Promise.resolve(); + } + const start = now() + delay; + let fn; + task = loop((now) => { + if (now < start) return true; + if (!started) { + fn = interpolate(value, new_value); + if (typeof duration === 'function') duration = duration(value, new_value); + started = true; + } + if (previous_task) { + previous_task.abort(); + previous_task = null; + } + const elapsed = now - start; + if (elapsed > duration) { + store.set((value = new_value)); + return false; + } + // @ts-ignore + store.set((value = fn(easing(elapsed / duration)))); + return true; + }); + return task.promise; + } + return { + set, + update: (fn, opts) => set(fn(target_value, value), opts), + subscribe: store.subscribe + }; } - /** * @typedef {(target_value: T, value: T) => T} Updater * @template T @@ -117,6 +117,6 @@ export function tweened(value, defaults = {}) { * @property {number} [delay] * @property {number|((from:T,to:T)=>number)} [duration] * @property {(t:number)=>number} [easing] - * @property {(a:T,b:T)=>(t:number)=>T} [interpolate] + * @property {(a:T,b:T)=>(t:number)=>T} [interpolate] */ -/** @typedef {Object} Tweened */ \ No newline at end of file +/** @typedef {Object} Tweened */