pull/14862/merge
José Pablo Ramírez Vargas 3 months ago committed by GitHub
commit 010dd2974e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -20,6 +20,18 @@ export interface Spring<T> extends Readable<T> {
stiffness: number;
}
/**
* Defines the primitive data types that Spring and Tween objects can calculate on.
*/
export type MotionPrimitive = number | Date;
/**
* Defines the type of objects Spring and Tween objects can work on.
*/
export interface MotionRecord {
[x: string]: MotionPrimitive | MotionRecord | (MotionPrimitive | MotionRecord)[];
}
/**
* A wrapper for a value that behaves in a spring-like fashion. Changes to `spring.target` will cause `spring.current` to
* move towards it over time, taking account of the `spring.stiffness` and `spring.damping` parameters.
@ -36,7 +48,7 @@ export interface Spring<T> extends Readable<T> {
* ```
* @since 5.8.0
*/
export class Spring<T> {
export class Spring<T extends MotionRecord[string]> {
constructor(value: T, options?: SpringOpts);
/**
@ -53,7 +65,7 @@ export class Spring<T> {
* </script>
* ```
*/
static of<U>(fn: () => U, options?: SpringOpts): Spring<U>;
static of<U extends MotionRecord[string]>(fn: () => U, options?: SpringOpts): Spring<U>;
/**
* Sets `spring.target` to `value` and returns a `Promise` that resolves if and when `spring.current` catches up to it.

@ -1,6 +1,6 @@
/** @import { Task } from '#client' */
/** @import { SpringOpts, SpringUpdateOpts, TickContext } from './private.js' */
/** @import { Spring as SpringStore } from './public.js' */
/** @import { MotionRecord, Spring as SpringStore } from './public.js' */
import { writable } from '../store/shared/index.js';
import { loop } from '../internal/client/loop.js';
import { raf } from '../internal/client/timing.js';
@ -58,7 +58,7 @@ function tick_spring(ctx, last_value, current_value, target_value) {
* The spring function in Svelte creates a store whose value is animated, with a motion that simulates the behavior of a spring. This means when the value changes, instead of transitioning at a steady rate, it "bounces" like a spring would, depending on the physics parameters provided. This adds a level of realism to the transitions and can enhance the user experience.
*
* @deprecated Use [`Spring`](https://svelte.dev/docs/svelte/svelte-motion#Spring) instead
* @template [T=any]
* @template {MotionRecord[string]} [T=any]
* @param {T} [value]
* @param {SpringOpts} [opts]
* @returns {SpringStore<T>}
@ -164,7 +164,7 @@ export function spring(value, opts = {}) {
* <input type="range" bind:value={spring.target} />
* <input type="range" bind:value={spring.current} disabled />
* ```
* @template T
* @template {MotionRecord[string]} T
* @since 5.8.0
*/
export class Spring {
@ -172,9 +172,10 @@ export class Spring {
#damping = source(0.8);
#precision = source(0.01);
#current = source(/** @type {T} */ (undefined));
#target = source(/** @type {T} */ (undefined));
#current;
#target;
// @ts-expect-error Undefined doesn't satisfy the constraint of T.
#last_value = /** @type {T} */ (undefined);
#last_time = 0;
@ -192,7 +193,8 @@ export class Spring {
* @param {SpringOpts} [options]
*/
constructor(value, options = {}) {
this.#current.v = this.#target.v = value;
this.#current = source(value);
this.#target = source(value);
if (typeof options.stiffness === 'number') this.#stiffness.v = clamp(options.stiffness, 0, 1);
if (typeof options.damping === 'number') this.#damping.v = clamp(options.damping, 0, 1);
@ -212,7 +214,7 @@ export class Spring {
* const spring = Spring.of(() => number);
* </script>
* ```
* @template U
* @template {MotionRecord[string]} U
* @param {() => U} fn
* @param {SpringOpts} [options]
*/

@ -1,5 +1,5 @@
/** @import { Task } from '../internal/client/types' */
/** @import { Tweened } from './public' */
/** @import { MotionRecord, Tweened } from './public' */
/** @import { TweenedOptions } from './private' */
import { writable } from '../store/shared/index.js';
import { raf } from '../internal/client/timing.js';
@ -171,11 +171,15 @@ export function tweened(value, defaults = {}) {
* <input type="range" bind:value={tween.target} />
* <input type="range" bind:value={tween.current} disabled />
* ```
* @template T
*
* Refer to the `MotionRecord` type to understand all possible value types that Tween can handle.
* @template {MotionRecord[string]} T
* @since 5.8.0
*/
export class Tween {
// @ts-expect-error Undefined doesn't satisfy the constraint of T.
#current = source(/** @type {T} */ (undefined));
// @ts-expect-error Undefined doesn't satisfy the constraint of T.
#target = source(/** @type {T} */ (undefined));
/** @type {TweenedOptions<T>} */
@ -206,7 +210,9 @@ export class Tween {
* const tween = Tween.of(() => number);
* </script>
* ```
* @template U
*
* Refer to the `MotionRecord` type to understand all possible value types that Tween can handle.
* @template {MotionRecord[string]} U
* @param {() => U} fn
* @param {TweenedOptions<U>} [options]
*/

Loading…
Cancel
Save