Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svelte

Package Overview
Dependencies
Maintainers
3
Versions
819
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svelte - npm Package Compare versions

Comparing version 5.7.1 to 5.8.0

2

package.json

@@ -5,3 +5,3 @@ {

"license": "MIT",
"version": "5.7.1",
"version": "5.8.0",
"type": "module",

@@ -8,0 +8,0 @@ "types": "./types/index.d.ts",

@@ -48,2 +48,23 @@ // Store the references to globals in case someone tries to monkey patch these, causing the below

/**
* TODO replace with Promise.withResolvers once supported widely enough
* @template T
*/
export function deferred() {
/** @type {(value: T) => void} */
var resolve;
/** @type {(reason: any) => void} */
var reject;
/** @type {Promise<T>} */
var promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
// @ts-expect-error
return { promise, resolve, reject };
}
/**
* @template V

@@ -50,0 +71,0 @@ * @param {V} value

@@ -1,7 +0,9 @@

import { Spring } from './public.js';
export interface TickContext<T> {
export interface TickContext {
inv_mass: number;
dt: number;
opts: Spring<T>;
opts: {
stiffness: number;
damping: number;
precision: number;
};
settled: boolean;

@@ -17,4 +19,18 @@ }

export interface SpringUpdateOpts {
/**
* @deprecated Only use this for the spring store; does nothing when set on the Spring class
*/
hard?: any;
/**
* @deprecated Only use this for the spring store; does nothing when set on the Spring class
*/
soft?: string | number | boolean;
/**
* Only use this for the Spring class; does nothing when set on the spring store
*/
instant?: boolean;
/**
* Only use this for the Spring class; does nothing when set on the spring store
*/
preserveMomentum?: number;
}

@@ -21,0 +37,0 @@

@@ -1,7 +0,18 @@

import { Readable } from '../store/public.js';
import { SpringUpdateOpts, TweenedOptions, Updater } from './private.js';
import { Readable, type Unsubscriber } from '../store/public.js';
import { SpringUpdateOpts, TweenedOptions, Updater, SpringOpts } from './private.js';
// TODO we do declaration merging here in order to not have a breaking change (renaming the Spring interface)
// this means both the Spring class and the Spring interface are merged into one with some things only
// existing on one side. In Svelte 6, remove the type definition and move the jsdoc onto the class in spring.js
export interface Spring<T> extends Readable<T> {
set: (new_value: T, opts?: SpringUpdateOpts) => Promise<void>;
set(new_value: T, opts?: SpringUpdateOpts): Promise<void>;
/**
* @deprecated Only exists on the legacy `spring` store, not the `Spring` class
*/
update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>;
/**
* @deprecated Only exists on the legacy `spring` store, not the `Spring` class
*/
subscribe(fn: (value: T) => void): Unsubscriber;
precision: number;

@@ -12,2 +23,61 @@ damping: number;

/**
* 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.
*
* ```svelte
* <script>
* import { Spring } from 'svelte/motion';
*
* const spring = new Spring(0);
* </script>
*
* <input type="range" bind:value={spring.target} />
* <input type="range" bind:value={spring.current} disabled />
* ```
*/
export class Spring<T> {
constructor(value: T, options?: SpringOpts);
/**
* Create a spring whose value is bound to the return value of `fn`. This must be called
* inside an effect root (for example, during component initialisation).
*
* ```svelte
* <script>
* import { Spring } from 'svelte/motion';
*
* let { number } = $props();
*
* const spring = Spring.of(() => number);
* </script>
* ```
*/
static of<U>(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.
*
* If `options.instant` is `true`, `spring.current` immediately matches `spring.target`.
*
* If `options.preserveMomentum` is provided, the spring will continue on its current trajectory for
* the specified number of milliseconds. This is useful for things like 'fling' gestures.
*/
set(value: T, options?: SpringUpdateOpts): Promise<void>;
damping: number;
precision: number;
stiffness: number;
/**
* The end value of the spring.
* This property only exists on the `Spring` class, not the legacy `spring` store.
*/
target: T;
/**
* The current value of the spring.
* This property only exists on the `Spring` class, not the legacy `spring` store.
*/
get current(): T;
}
export interface Tweened<T> extends Readable<T> {

@@ -18,2 +88,2 @@ set(value: T, opts?: TweenedOptions<T>): Promise<void>;

export * from './index.js';
export { spring, tweened, Tween } from './index.js';
/** @import { Task } from '#client' */
/** @import { SpringOpts, SpringUpdateOpts, TickContext } from './private.js' */
/** @import { Spring } from './public.js' */
/** @import { Spring as SpringStore } from './public.js' */
import { writable } from '../store/shared/index.js';

@@ -8,6 +8,10 @@ import { loop } from '../internal/client/loop.js';

import { is_date } from './utils.js';
import { set, source } from '../internal/client/reactivity/sources.js';
import { render_effect } from '../internal/client/reactivity/effects.js';
import { get } from '../internal/client/runtime.js';
import { deferred, noop } from '../internal/shared/utils.js';
/**
* @template T
* @param {TickContext<T>} ctx
* @param {TickContext} ctx
* @param {T} last_value

@@ -57,6 +61,7 @@ * @param {T} current_value

*
* @deprecated Use [`Spring`](https://svelte.dev/docs/svelte/svelte-motion#Spring) instead
* @template [T=any]
* @param {T} [value]
* @param {SpringOpts} [opts]
* @returns {Spring<T>}
* @returns {SpringStore<T>}
*/

@@ -108,3 +113,3 @@ export function spring(value, opts = {}) {

inv_mass = Math.min(inv_mass + inv_mass_recovery_rate, 1);
/** @type {TickContext<T>} */
/** @type {TickContext} */
const ctx = {

@@ -133,3 +138,4 @@ inv_mass,

}
/** @type {Spring<T>} */
/** @type {SpringStore<T>} */
// @ts-expect-error - class-only properties are missing
const spring = {

@@ -145,1 +151,203 @@ set,

}
/**
* 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.
*
* ```svelte
* <script>
* import { Spring } from 'svelte/motion';
*
* const spring = new Spring(0);
* </script>
*
* <input type="range" bind:value={spring.target} />
* <input type="range" bind:value={spring.current} disabled />
* ```
* @template T
* @since 5.8.0
*/
export class Spring {
#stiffness = source(0.15);
#damping = source(0.8);
#precision = source(0.01);
#current = source(/** @type {T} */ (undefined));
#target = source(/** @type {T} */ (undefined));
#last_value = /** @type {T} */ (undefined);
#last_time = 0;
#inverse_mass = 1;
#momentum = 0;
/** @type {import('../internal/client/types').Task | null} */
#task = null;
/** @type {ReturnType<typeof deferred> | null} */
#deferred = null;
/**
* @param {T} value
* @param {SpringOpts} [options]
*/
constructor(value, options = {}) {
this.#current.v = this.#target.v = 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);
if (typeof options.precision === 'number') this.#precision.v = options.precision;
}
/**
* Create a spring whose value is bound to the return value of `fn`. This must be called
* inside an effect root (for example, during component initialisation).
*
* ```svelte
* <script>
* import { Spring } from 'svelte/motion';
*
* let { number } = $props();
*
* const spring = Spring.of(() => number);
* </script>
* ```
* @template U
* @param {() => U} fn
* @param {SpringOpts} [options]
*/
static of(fn, options) {
const spring = new Spring(fn(), options);
render_effect(() => {
spring.set(fn());
});
return spring;
}
/** @param {T} value */
#update(value) {
set(this.#target, value);
this.#current.v ??= value;
this.#last_value ??= this.#current.v;
if (!this.#task) {
this.#last_time = raf.now();
var inv_mass_recovery_rate = 1000 / (this.#momentum * 60);
this.#task ??= loop((now) => {
this.#inverse_mass = Math.min(this.#inverse_mass + inv_mass_recovery_rate, 1);
/** @type {import('./private').TickContext} */
const ctx = {
inv_mass: this.#inverse_mass,
opts: {
stiffness: this.#stiffness.v,
damping: this.#damping.v,
precision: this.#precision.v
},
settled: true,
dt: ((now - this.#last_time) * 60) / 1000
};
var next = tick_spring(ctx, this.#last_value, this.#current.v, this.#target.v);
this.#last_value = this.#current.v;
this.#last_time = now;
set(this.#current, next);
if (ctx.settled) {
this.#task = null;
}
return !ctx.settled;
});
}
return this.#task.promise;
}
/**
* Sets `spring.target` to `value` and returns a `Promise` that resolves if and when `spring.current` catches up to it.
*
* If `options.instant` is `true`, `spring.current` immediately matches `spring.target`.
*
* If `options.preserveMomentum` is provided, the spring will continue on its current trajectory for
* the specified number of milliseconds. This is useful for things like 'fling' gestures.
*
* @param {T} value
* @param {SpringUpdateOpts} [options]
*/
set(value, options) {
this.#deferred?.reject(new Error('Aborted'));
if (options?.instant || this.#current.v === undefined) {
this.#task?.abort();
this.#task = null;
set(this.#current, set(this.#target, value));
return Promise.resolve();
}
if (options?.preserveMomentum) {
this.#inverse_mass = 0;
this.#momentum = options.preserveMomentum;
}
var d = (this.#deferred = deferred());
d.promise.catch(noop);
this.#update(value).then(() => {
if (d !== this.#deferred) return;
d.resolve(undefined);
});
return d.promise;
}
get current() {
return get(this.#current);
}
get damping() {
return get(this.#damping);
}
set damping(v) {
set(this.#damping, clamp(v, 0, 1));
}
get precision() {
return get(this.#precision);
}
set precision(v) {
set(this.#precision, v);
}
get stiffness() {
return get(this.#stiffness);
}
set stiffness(v) {
set(this.#stiffness, clamp(v, 0, 1));
}
get target() {
return get(this.#target);
}
set target(v) {
this.set(v);
}
}
/**
* @param {number} n
* @param {number} min
* @param {number} max
*/
function clamp(n, min, max) {
return Math.max(min, Math.min(max, n));
}

@@ -9,2 +9,4 @@ /** @import { Task } from '../internal/client/types' */

import { is_date } from './utils.js';
import { set, source } from '../internal/client/reactivity/sources.js';
import { get, render_effect } from 'svelte/internal/client';

@@ -80,2 +82,3 @@ /**

*
* @deprecated Use [`Tween`](https://svelte.dev/docs/svelte/svelte-motion#Tween) instead
* @template T

@@ -157,1 +160,135 @@ * @param {T} [value]

}
/**
* A wrapper for a value that tweens smoothly to its target value. Changes to `tween.target` will cause `tween.current` to
* move towards it over time, taking account of the `delay`, `duration` and `easing` options.
*
* ```svelte
* <script>
* import { Tween } from 'svelte/motion';
*
* const tween = new Tween(0);
* </script>
*
* <input type="range" bind:value={tween.target} />
* <input type="range" bind:value={tween.current} disabled />
* ```
* @template T
* @since 5.8.0
*/
export class Tween {
#current = source(/** @type {T} */ (undefined));
#target = source(/** @type {T} */ (undefined));
/** @type {TweenedOptions<T>} */
#defaults;
/** @type {import('../internal/client/types').Task | null} */
#task = null;
/**
* @param {T} value
* @param {TweenedOptions<T>} options
*/
constructor(value, options = {}) {
this.#current.v = this.#target.v = value;
this.#defaults = options;
}
/**
* Create a tween whose value is bound to the return value of `fn`. This must be called
* inside an effect root (for example, during component initialisation).
*
* ```svelte
* <script>
* import { Tween } from 'svelte/motion';
*
* let { number } = $props();
*
* const tween = Tween.of(() => number);
* </script>
* ```
* @template U
* @param {() => U} fn
* @param {TweenedOptions<U>} [options]
*/
static of(fn, options) {
const tween = new Tween(fn(), options);
render_effect(() => {
tween.set(fn());
});
return tween;
}
/**
* Sets `tween.target` to `value` and returns a `Promise` that resolves if and when `tween.current` catches up to it.
*
* If `options` are provided, they will override the tween's defaults.
* @param {T} value
* @param {TweenedOptions<T>} [options]
* @returns
*/
set(value, options) {
set(this.#target, value);
let previous_value = this.#current.v;
let previous_task = this.#task;
let started = false;
let {
delay = 0,
duration = 400,
easing = linear,
interpolate = get_interpolator
} = { ...this.#defaults, ...options };
const start = raf.now() + delay;
/** @type {(t: number) => T} */
let fn;
this.#task = loop((now) => {
if (now < start) {
return true;
}
if (!started) {
started = true;
fn = interpolate(/** @type {any} */ (previous_value), value);
if (typeof duration === 'function') {
duration = duration(/** @type {any} */ (previous_value), value);
}
previous_task?.abort();
}
const elapsed = now - start;
if (elapsed > /** @type {number} */ (duration)) {
set(this.#current, value);
return false;
}
set(this.#current, fn(easing(elapsed / /** @type {number} */ (duration))));
return true;
});
return this.#task.promise;
}
get current() {
return get(this.#current);
}
get target() {
return get(this.#target);
}
set target(v) {
this.set(v);
}
}

@@ -9,3 +9,3 @@ // generated during release, do not modify

*/
export const VERSION = '5.7.1';
export const VERSION = '5.8.0';
export const PUBLIC_VERSION = '5';

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc