New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@react-spring/core

Package Overview
Dependencies
Maintainers
1
Versions
134
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@react-spring/core - npm Package Compare versions

Comparing version 9.0.0-canary.808.9.7e75a67 to 9.0.0-canary.808.10.132aadf

src/SpringPhase.ts

112

index.d.ts
import { RefObject, ReactNode } from 'react';
import { Constrain, ObjectFromUnion, FluidValue, ObjectType, OneOrMore, InterpolatorFn, InterpolatorArgs, FluidObserver, Animatable, Merge, UnknownPartial, FluidProps, UnknownProps as UnknownProps$1, Any, Remap, Indexable as Indexable$1, Falsy as Falsy$1, InterpolatorConfig, ExtrapolateType } from '@react-spring/shared';
import { Constrain, ObjectFromUnion, FluidValue, ObjectType, OneOrMore, InterpolatorFn, InterpolatorArgs, FluidObserver, Animatable, Merge, Indexable as Indexable$1, UnknownPartial, FluidProps, UnknownProps as UnknownProps$1, Any, NarrowValues, Remap, Falsy as Falsy$1, InterpolatorConfig, ExtrapolateType } from '@react-spring/shared';
export { Animatable, FrameLoop, Globals, createInterpolator } from '@react-spring/shared';

@@ -321,11 +321,3 @@ import { Indexable, Falsy, NoInfer, OneOrMore as OneOrMore$1 } from '@react-spring/shared/types/common';

/** Default props for a `SpringValue` object */
declare type DefaultProps<T = unknown> = {
[D in (typeof DEFAULT_PROPS)[number]]?: PendingProps<T>[D];
};
/** Pending props for a `SpringValue` object */
declare type PendingProps<T = unknown> = unknown & SpringUpdate<T> & AnimationEvents<T>;
declare type Phase = typeof DISPOSED | typeof CREATED | typeof IDLE | typeof PAUSED | typeof ACTIVE;
/** The spring cannot be animated */
declare const DISPOSED = "DISPOSED";
declare type SpringPhase = typeof DISPOSED | typeof CREATED | typeof IDLE | typeof PAUSED | typeof ACTIVE;
/** The spring has not animated yet */

@@ -335,7 +327,15 @@ declare const CREATED = "CREATED";

declare const IDLE = "IDLE";
/** The spring is animating */
declare const ACTIVE = "ACTIVE";
/** The spring is frozen in time */
declare const PAUSED = "PAUSED";
/** The spring is animating */
declare const ACTIVE = "ACTIVE";
/** An opaque animatable value */
/** The spring cannot be animated */
declare const DISPOSED = "DISPOSED";
/** Default props for a `SpringValue` object */
declare type DefaultProps<T = unknown> = {
[D in typeof DEFAULT_PROPS[number]]?: PendingProps<T>[D];
};
/** Pending props for a `SpringValue` object */
declare type PendingProps<T = unknown> = unknown & SpringUpdate<T> & AnimationEvents<T>;
declare class SpringValue<T = any> extends FrameValue<T> {

@@ -349,3 +349,3 @@ /** The property name used when `to` or `from` is an object. Useful when debugging too. */

/** The lifecycle phase of this spring */
protected _phase: string;
protected _phase: SpringPhase;
/** The state for `runAsync` calls */

@@ -365,3 +365,3 @@ protected _state: RunAsyncState<T>;

/** Check the current phase */
is(phase: Phase): boolean;
is(phase: SpringPhase): boolean;
/** Set the current value, while stopping the current animation */

@@ -510,2 +510,3 @@ set(value: T | FluidValue<T>): this;

}
declare type EventProp<T> = T | Indexable$1<T>;
/**

@@ -521,15 +522,15 @@ * The event props of a `SpringValue` animation.

*/
onAnimate?: OnAnimate<T>;
onAnimate?: EventProp<OnAnimate<T>>;
/**
* Called when an animation moves for the first time
*/
onStart?: OnStart<T>;
onStart?: EventProp<OnStart<T>>;
/**
* Called when all animations come to a stand-still
*/
onRest?: OnRest<T>;
onRest?: EventProp<OnRest<T>>;
/**
* Called when a key/value pair is changed
*/
onChange?: OnChange<T>;
onChange?: EventProp<OnChange<T>>;
};

@@ -539,3 +540,4 @@

declare type OnFrame<State extends Indexable> = (frame: UnknownPartial<State>) => void;
declare type ControllerProps<State extends Indexable = Indexable> = {
/** All event props supported by the `Controller` class */
interface EventProps<State extends Indexable> {
/**

@@ -545,7 +547,30 @@ * Called on every frame when animations are active

onFrame?: OnFrame<State>;
} & SpringUpdate<State> & AnimationEvents<unknown> & UnknownPartial<FluidProps<State>>;
/**
* Called when the # of animating values exceeds 0
*
* Also accepts an object for per-key events
*/
onStart?: (() => void) | Indexable<OnStart>;
/**
* Called when the # of animating values hits 0
*
* Also accepts an object for per-key events
*/
onRest?: OnRest<State> | Indexable<OnRest>;
/**
* Called whenever an animation is updated
*
* Also accepts an object for per-key events
*/
onAnimate?: OnAnimate | Indexable<OnAnimate>;
/**
* Called for every change to a key/value pair
*
* Also accepts an object for per-key events
*/
onChange?: OnChange | Indexable<OnChange>;
}
declare type ControllerProps<State extends Indexable = Indexable> = unknown & EventProps<State> & SpringUpdate<State> & UnknownPartial<FluidProps<State>>;
/** The props that are cached by `Controller` objects */
interface CachedProps<State extends Indexable> extends RunAsyncState<State> {
onFrame?: OnFrame<State>;
}
declare type CachedProps<State extends Indexable> = RunAsyncState<State> & NarrowValues<EventProps<State>, Function>;
/** An update that hasn't been applied yet */

@@ -555,18 +580,20 @@ declare type PendingProps$1<State extends Indexable> = ControllerProps<State> & {

};
/** Default props for the `Controller` class */
declare type DefaultProps$1<State extends Indexable> = {
onFrame?: OnFrame<State>;
};
declare class Controller<State extends Indexable = UnknownProps$1> implements FrameValue.Observer {
readonly id: number;
/** The values that changed in the last animation frame */
frame: UnknownPartial<State>;
/** Fallback values for undefined props */
defaultProps: DefaultProps$1<State>;
/** The queue of pending props */
queue: PendingProps$1<State>[];
/** The current controller-only props (eg: `onFrame` and async state) */
/** Fallback values for undefined props */
defaultProps: EventProps<State>;
/** The combined phase of our spring values */
protected _phase: SpringPhase;
/** The values currently being animated */
protected _active: Set<FrameValue<any>>;
/** The animated state that changed in the last animation frame */
protected _frame: UnknownPartial<State>;
/** Event handlers and async state are stored here */
protected _state: CachedProps<State>;
/** The spring values that manage their animations */
protected _springs: Indexable<SpringValue>;
/** The promise for the current set of animations */
protected _promise?: AsyncResult<State>;
constructor(props?: ControllerProps<State>);

@@ -589,3 +616,8 @@ /** Equals true when no springs are animating */

*/
start(queue?: OneOrMore<ControllerProps<State>>): Promise<{
start(queue?: OneOrMore<ControllerProps<State>>): Promise<Readonly<{
value: State;
spring?: SpringValue<State> | undefined;
finished?: boolean | undefined;
cancelled?: boolean | undefined;
}> | {
value: any;

@@ -605,7 +637,7 @@ finished: boolean;

/** Prepare an update with the given props. */
protected _update(propsArg: ControllerProps<State>): PendingProps$1<State>;
protected _prepareUpdate(propsArg: ControllerProps<State>): PendingProps$1<State>;
/** @internal Called at the end of every animation frame */
protected _onFrame(): void;
/** @internal */
onParentChange(event: FrameValue.Event): void;
/** @internal Called at the end of every animation frame */
protected _onFrame(): void;
}

@@ -803,3 +835,3 @@

declare type Phase$1 = number & {
declare type Phase = number & {
__type: 'TransitionPhase';

@@ -843,3 +875,3 @@ };

ctrl: Controller;
phase: Phase$1;
phase: Phase;
/** Destroy no later than this date */

@@ -959,2 +991,2 @@ expiresBy?: number;

export { AnimationResult, AsyncResult, AsyncUpdate, AsyncUpdateFn, Controller, ControllerProps, DefaultProps, ForwardProps, FrameValue, Interpolated, Interpolation, Interpolator, ItemKeys, OnFrame, PendingProps, Phase$1 as Phase, ReservedProps, Spring, SpringConfig, SpringHandle, SpringStopFn, SpringUpdate, SpringUpdateFn, SpringValue, SpringValues, SpringsUpdateFn, Trail, Transition, TransitionFn, TransitionHandle, TransitionPhase, TransitionState, UseSpringProps, UseSpringsProps, UseTransitionProps, config, interpolate, isFrameValue, to, update, useChain, useSpring, useSprings, useTrail, useTransition };
export { AnimationResult, AsyncResult, AsyncUpdate, AsyncUpdateFn, Controller, ControllerProps, DefaultProps, EventProps, ForwardProps, FrameValue, Interpolated, Interpolation, Interpolator, ItemKeys, OnFrame, PendingProps, Phase, ReservedProps, Spring, SpringConfig, SpringHandle, SpringStopFn, SpringUpdate, SpringUpdateFn, SpringValue, SpringValues, SpringsUpdateFn, Trail, Transition, TransitionFn, TransitionHandle, TransitionPhase, TransitionState, UseSpringProps, UseSpringsProps, UseTransitionProps, config, interpolate, isFrameValue, to, update, useChain, useSpring, useSprings, useTrail, useTransition };

@@ -1,6 +0,7 @@

import { useIsomorphicLayoutEffect, each, is, toArray, FluidValue, getFluidConfig, isAnimatedString, isEqual, noop, usePrev, useOnce, useForceUpdate, createInterpolator, Globals } from '@react-spring/shared';
import { useLayoutEffect } from 'react-layout-effect';
import { each, is, isAnimatedString, toArray, getFluidConfig, FluidValue, isEqual, noop, usePrev, useOnce, useForceUpdate, createInterpolator, Globals } from '@react-spring/shared';
export { FrameLoop, Globals, createInterpolator } from '@react-spring/shared';
import React, { useMemo as useMemo$1, useImperativeHandle, useRef } from 'react';
import _extends from '@babel/runtime/helpers/esm/extends';
import { to as to$1, frameLoop, batchedUpdates, createStringInterpolator, now, skipAnimation } from '@react-spring/shared/globals';
import { createStringInterpolator, to as to$1, frameLoop, batchedUpdates, now, skipAnimation } from '@react-spring/shared/globals';
import { useMemoOne } from 'use-memo-one';

@@ -17,3 +18,3 @@ import { getAnimated, AnimatedValue, getPayload, setAnimated, AnimatedString, AnimatedArray } from '@react-spring/animated';

function useChain(refs, timeSteps, timeFrame = 1000) {
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
if (timeSteps) {

@@ -128,2 +129,10 @@ let prevDelay = 0;

function computeGoal(value) {
const config = getFluidConfig(value);
return config ? computeGoal(config.get()) : is.arr(value) ? value.map(computeGoal) : isAnimatedString(value) ? createStringInterpolator({
range: [0, 1],
output: [value, value]
})(1) : value;
}
/**

@@ -241,3 +250,3 @@ * Start an async chain or an async script.

if (props.onRest) {
if (is.fun(props.onRest)) {
props.onRest(result);

@@ -301,2 +310,17 @@ }

/** The spring has not animated yet */
const CREATED = 'CREATED';
/** The spring has animated before */
const IDLE = 'IDLE';
/** The spring is animating */
const ACTIVE = 'ACTIVE';
/** The spring is frozen in time */
const PAUSED = 'PAUSED';
/** The spring cannot be animated */
const DISPOSED = 'DISPOSED';
// The `mass` prop defaults to 1

@@ -654,19 +678,2 @@ const config = {

/** The spring cannot be animated */
const DISPOSED = 'DISPOSED';
/** The spring has not animated yet */
const CREATED = 'CREATED';
/** The spring has animated before */
const IDLE = 'IDLE';
/** The spring is frozen in time */
const PAUSED = 'PAUSED';
/** The spring is animating */
const ACTIVE = 'ACTIVE';
/** An opaque animatable value */
class SpringValue extends FrameValue {

@@ -1106,17 +1113,13 @@ constructor(arg1, arg2) {

const defaultProps = this._defaultProps;
const timestamps = this._timestamps;
/** Get the value of a prop, or its default value */
const get = prop => !is.und(props[prop]) ? props[prop] : defaultProps[prop];
/**
* Delayed `_update` calls perform diffing on certain props
* to know if they were updated during the delay. In that case,
* the prop is ignored, but other props may still apply.
*/
const onAnimate = get('onAnimate');
if (onAnimate) {
onAnimate(props, this);
} // Cast from a partial type.
const anim = this.animation;
const timestamps = this._timestamps;
/** Return true if our prop can be used. This only affects delayed props. */
const diff = prop => {

@@ -1132,6 +1135,16 @@ if (timestamp >= (timestamps[prop] || 0)) {

const {
key,
animation: anim
} = this;
const {
to: prevTo,
from: prevFrom
} = anim; // The "reverse" prop only affects one update.
} = anim;
const onAnimate = coerceEventProp(get('onAnimate'), key);
if (onAnimate) {
onAnimate(props, this);
} // The "reverse" prop only affects one update.
if (props.reverse) [to, from] = [from, to];

@@ -1176,3 +1189,3 @@

if (!anim.config || props.config) {
const config = _extends({}, callProp(defaultProps.config, this.key), callProp(props.config, this.key)); // The "config" prop either overwrites or merges into the existing config.
const config = _extends({}, callProp(defaultProps.config, key), callProp(props.config, key)); // The "config" prop either overwrites or merges into the existing config.

@@ -1192,3 +1205,3 @@

let started = !!toConfig || (changed || reset) && !isEqual(value, to); // Animations with an explicit "velocity" are always started.
let started = !!toConfig || !!getFluidConfig(prevTo) || (changed || reset) && !isEqual(value, to); // Animations with an explicit "velocity" are always started.

@@ -1229,4 +1242,4 @@ if (!started && (config.decay || !is.und(to))) {

anim.onStart = get('onStart');
anim.onChange = get('onChange'); // Update the default props.
anim.onStart = coerceEventProp(get('onStart'), key);
anim.onChange = coerceEventProp(get('onChange'), key); // Update the default props.

@@ -1253,3 +1266,3 @@ if (props.default) {

anim.immediate = // Sometimes the value is not animatable.
!(toConfig || is.num(goal) || is.arr(goal)) || !!matchProp(get('immediate'), this.key); // Avoid calling this before "immediate" is set
!(toConfig || is.num(goal) || is.arr(goal)) || !!matchProp(get('immediate'), key); // Avoid calling this before "immediate" is set

@@ -1259,3 +1272,3 @@ this._reset();

const onRestQueue = anim.onRest || [];
const onRest = props.onRest || reset && onRestQueue[0] || defaultProps.onRest; // The "onRest" prop is always first in the queue.
const onRest = coerceEventProp(props.onRest || reset && onRestQueue[0] || defaultProps.onRest, key); // The "onRest" prop is always first in the queue.

@@ -1287,21 +1300,23 @@ anim.onRest = [onRest || noop, resolve]; // Resolve the promises of unfinished animations.

const anim = this.animation;
if (value === anim.to) return;
let config = getFluidConfig(anim.to);
if (config) {
config.removeChild(this);
}
if (value !== anim.to) {
let config = getFluidConfig(anim.to);
anim.to = value;
let priority = 0;
if (config) {
config.removeChild(this);
}
if (config = getFluidConfig(value)) {
config.addChild(this);
anim.to = value;
let priority = 0;
if (isFrameValue(value)) {
priority = (value.priority || 0) + 1;
if (config = getFluidConfig(value)) {
config.addChild(this);
if (isFrameValue(value)) {
priority = (value.priority || 0) + 1;
}
}
this.priority = priority;
}
this.priority = priority;
}

@@ -1439,13 +1454,11 @@ /** Set the current value and our `node` if necessary. The `_onChange` method is *not* called. */

return !!dest && is.und(src.decay) == is.und(dest.decay) && is.und(src.duration) == is.und(dest.duration) && is.und(src.frequency) == is.und(dest.frequency);
} // Compute the goal value, converting "red" to "rgba(255, 0, 0, 1)" in the process
}
/** Coerce an event prop to an event handler */
function computeGoal(value) {
const config = getFluidConfig(value);
return config ? computeGoal(config.get()) : is.arr(value) ? value.map(computeGoal) : isAnimatedString(value) ? createStringInterpolator({
range: [0, 1],
output: [value, value]
})(1) : value;
function coerceEventProp(prop, key) {
return is.fun(prop) ? prop : key && prop ? prop[key] : undefined;
}
const EVENT_NAMES = ['onFrame', 'onStart', 'onRest', 'onChange', 'onAnimate'];
let nextId$1 = 1;

@@ -1456,13 +1469,19 @@ let lastAsyncId = 0;

this.id = nextId$1++;
/** The values that changed in the last animation frame */
/** The queue of pending props */
this.frame = {};
this.queue = [];
/** Fallback values for undefined props */
this.defaultProps = {};
/** The queue of pending props */
/** The combined phase of our spring values */
this.queue = [];
/** The current controller-only props (eg: `onFrame` and async state) */
this._phase = CREATED;
/** The values currently being animated */
this._active = new Set();
/** The animated state that changed in the last animation frame */
this._frame = {};
/** Event handlers and async state are stored here */
this._state = {};

@@ -1483,3 +1502,3 @@ /** The spring values that manage their animations */

get idle() {
return !this._state.promise && Object.values(this._springs).every(s => s.idle);
return !this._promise;
}

@@ -1500,3 +1519,3 @@ /** Get all existing `SpringValue` objects. This clones the internal store. */

update(props) {
if (props) this.queue.push(this._update(props));
if (props) this.queue.push(this._prepareUpdate(props));
return this;

@@ -1513,5 +1532,5 @@ }

async start(queue) {
start(queue) {
if (queue) {
queue = toArray(queue).map(props => this._update(props));
queue = toArray(queue).map(props => this._prepareUpdate(props));
} else {

@@ -1526,3 +1545,2 @@ queue = this.queue;

to,
onFrame,
keys

@@ -1534,8 +1552,13 @@ } = props;

props.to = undefined;
}
} // Send updates to every affected key.
each(keys, key => {
const promise = this._springs[key].start(props);
promises.push(promise);
}); // Schedule controller-only props.
const state = this._state;
promises.push( // Send updates to every affected key.
...keys.map(key => this._springs[key].start(props)), // Schedule controller-only props.
scheduleProps(++lastAsyncId, {
promises.push(scheduleProps(++lastAsyncId, {
props,

@@ -1545,8 +1568,13 @@ state,

if (!props.cancel) {
// Never reuse "onFrame" from a previous update.
state.onFrame = onFrame || this.defaultProps.onFrame;
each(EVENT_NAMES, key => {
const value = props[key] || this.defaultProps[key];
if (onFrame && props.default) {
this.defaultProps.onFrame = onFrame;
}
if (value && props.default) {
this.defaultProps[key] = value;
}
if (is.fun(value)) {
this._state[key] = value;
}
});
} // Start, replace, or cancel the async animation.

@@ -1567,7 +1595,6 @@

});
const results = await Promise.all(promises);
return {
return this._promise = Promise.all(promises).then(results => ({
value: this._get(),
finished: results.every(result => result.finished)
};
}));
}

@@ -1631,5 +1658,5 @@ /** Stop one animation, some animations, or all animations */

_update(propsArg) {
_prepareUpdate(propsArg) {
const props = interpolateTo(propsArg);
const keys = props.keys = extractKeys(props, this._springs);
props.keys = extractKeys(props, this._springs);
let {

@@ -1646,3 +1673,3 @@ from,

if (from || to) {
this._setSprings(keys, from, to);
this._setSprings(props.keys, from, to);
}

@@ -1652,19 +1679,41 @@

}
/** @internal */
/** @internal Called at the end of every animation frame */
onParentChange(event) {
if (this._state.onFrame && event.type == 'change') {
this.frame[event.parent.key] = event.value;
frameLoop.onFrame(this._onFrame);
_onFrame() {
const {
onFrame,
onStart,
onRest
} = this._state;
const isActive = this._active.size > 0;
if (isActive !== (this._phase == ACTIVE)) {
this._phase = isActive ? ACTIVE : IDLE;
if (isActive) {
callProp(onStart);
} else {
if (onRest) this._promise.then(onRest);
this._promise = undefined;
}
}
if (onFrame) {
onFrame(this._frame);
this._frame = {};
}
}
/** @internal Called at the end of every animation frame */
/** @internal */
_onFrame() {
if (Object.keys(this.frame).length) {
this._state.onFrame(this.frame);
onParentChange(event) {
if (event.type == 'change') {
if (this._state.onFrame) {
this._frame[event.parent.key] = event.value;
}
this.frame = {};
this._active[event.idle ? 'delete' : 'add'](event.parent);
frameLoop.onFrame(this._onFrame);
}

@@ -1766,3 +1815,3 @@ }

useImperativeHandle(ref, () => api);
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
each(updates, (update, i) => ctrls[i].update(update));

@@ -1785,4 +1834,4 @@

const isFn = is.fun(props);
const [[values], update, stop] = useSprings(1, isFn ? props : [props], deps);
return isFn || arguments.length == 3 ? [values, update, stop] : values;
const [[values], update, stop] = useSprings(1, isFn ? props : [props], isFn ? deps || [] : deps);
return isFn || arguments.length == 2 ? [values, update, stop] : values;
}

@@ -1802,3 +1851,3 @@

}, deps);
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
const reverse = is.obj(propsArg) && propsArg.reverse;

@@ -1867,3 +1916,3 @@

const prevTransitions = usedTransitions.current;
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
usedTransitions.current = transitions;

@@ -2036,3 +2085,3 @@ }); // Destroy all transitions on dismount.

useImperativeHandle(ref, () => api);
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
each(changes, ({

@@ -2039,0 +2088,0 @@ phase,

{
"name": "@react-spring/core",
"version": "9.0.0-canary.808.9.7e75a67",
"version": "9.0.0-canary.808.10.132aadf",
"description": "Cross-platform animation engine for React",

@@ -34,4 +34,5 @@ "keywords": [

"@babel/runtime": "^7.3.1",
"@react-spring/animated": "9.0.0-canary.808.9.7e75a67",
"@react-spring/shared": "9.0.0-canary.808.9.7e75a67",
"@react-spring/animated": "9.0.0-canary.808.10.132aadf",
"@react-spring/shared": "9.0.0-canary.808.10.132aadf",
"react-layout-effect": "^1.0.1",
"use-memo-one": "^1.1.0"

@@ -38,0 +39,0 @@ },

@@ -9,2 +9,3 @@ import {

FluidProps,
NarrowValues,
} from '@react-spring/shared'

@@ -14,9 +15,18 @@ import * as G from '@react-spring/shared/globals'

import { SpringUpdate, SpringValues } from './types/spring'
import { AnimationEvents } from './types/animated'
import { OnAnimate, OnRest, OnStart, OnChange } from './types/animated'
import { Indexable, Falsy } from './types/common'
import { runAsync, scheduleProps, RunAsyncState, AsyncResult } from './runAsync'
import { interpolateTo } from './helpers'
import { SpringPhase, CREATED, ACTIVE, IDLE } from './SpringPhase'
import { interpolateTo, callProp } from './helpers'
import { SpringValue } from './SpringValue'
import { FrameValue } from './FrameValue'
const EVENT_NAMES = [
'onFrame',
'onStart',
'onRest',
'onChange',
'onAnimate',
] as const
/** A callback that receives the changed values for each frame. */

@@ -27,3 +37,4 @@ export type OnFrame<State extends Indexable> = (

export type ControllerProps<State extends Indexable = Indexable> = {
/** All event props supported by the `Controller` class */
export interface EventProps<State extends Indexable> {
/**

@@ -33,10 +44,36 @@ * Called on every frame when animations are active

onFrame?: OnFrame<State>
} & SpringUpdate<State> &
AnimationEvents<unknown> &
/**
* Called when the # of animating values exceeds 0
*
* Also accepts an object for per-key events
*/
onStart?: (() => void) | Indexable<OnStart>
/**
* Called when the # of animating values hits 0
*
* Also accepts an object for per-key events
*/
onRest?: OnRest<State> | Indexable<OnRest>
/**
* Called whenever an animation is updated
*
* Also accepts an object for per-key events
*/
onAnimate?: OnAnimate | Indexable<OnAnimate>
/**
* Called for every change to a key/value pair
*
* Also accepts an object for per-key events
*/
onChange?: OnChange | Indexable<OnChange>
}
export type ControllerProps<State extends Indexable = Indexable> = unknown &
EventProps<State> &
SpringUpdate<State> &
UnknownPartial<FluidProps<State>>
/** The props that are cached by `Controller` objects */
interface CachedProps<State extends Indexable> extends RunAsyncState<State> {
onFrame?: OnFrame<State>
}
type CachedProps<State extends Indexable> = RunAsyncState<State> &
NarrowValues<EventProps<State>, Function>

@@ -48,7 +85,2 @@ /** An update that hasn't been applied yet */

/** Default props for the `Controller` class */
type DefaultProps<State extends Indexable> = {
onFrame?: OnFrame<State>
}
let nextId = 1

@@ -61,12 +93,18 @@ let lastAsyncId = 0

/** The values that changed in the last animation frame */
frame: UnknownPartial<State> = {}
/** The queue of pending props */
queue: PendingProps<State>[] = []
/** Fallback values for undefined props */
defaultProps: DefaultProps<State> = {}
defaultProps: EventProps<State> = {}
/** The queue of pending props */
queue: PendingProps<State>[] = []
/** The combined phase of our spring values */
protected _phase: SpringPhase = CREATED
/** The current controller-only props (eg: `onFrame` and async state) */
/** The values currently being animated */
protected _active = new Set<FrameValue>()
/** The animated state that changed in the last animation frame */
protected _frame: UnknownPartial<State> = {}
/** Event handlers and async state are stored here */
protected _state: CachedProps<State> = {}

@@ -77,2 +115,5 @@

/** The promise for the current set of animations */
protected _promise?: AsyncResult<State>
constructor(props?: ControllerProps<State>) {

@@ -88,5 +129,3 @@ this._onFrame = this._onFrame.bind(this)

get idle() {
return (
!this._state.promise && Object.values(this._springs).every(s => s.idle)
)
return !this._promise
}

@@ -108,3 +147,3 @@

update(props: ControllerProps<State> | Falsy) {
if (props) this.queue.push(this._update(props))
if (props) this.queue.push(this._prepareUpdate(props))
return this

@@ -120,5 +159,5 @@ }

*/
async start(queue?: OneOrMore<ControllerProps<State>>) {
start(queue?: OneOrMore<ControllerProps<State>>) {
if (queue) {
queue = toArray<any>(queue).map(props => this._update(props))
queue = toArray<any>(queue).map(props => this._prepareUpdate(props))
} else {

@@ -131,3 +170,4 @@ queue = this.queue

each(queue as PendingProps<State>[], props => {
const { to, onFrame, keys } = props
const { to, keys } = props
const asyncTo = (is.arr(to) || is.fun(to)) && to

@@ -137,7 +177,12 @@ if (asyncTo) {

}
// Send updates to every affected key.
each(keys, key => {
const promise = this._springs[key].start(props as any)
promises.push(promise)
})
// Schedule controller-only props.
const state = this._state
promises.push(
// Send updates to every affected key.
...keys.map(key => this._springs[key].start(props as any)),
// Schedule controller-only props.
scheduleProps(++lastAsyncId, {

@@ -148,7 +193,11 @@ props,

if (!props.cancel) {
// Never reuse "onFrame" from a previous update.
state.onFrame = onFrame || this.defaultProps.onFrame
if (onFrame && props.default) {
this.defaultProps.onFrame = onFrame
}
each(EVENT_NAMES, key => {
const value: any = props[key] || this.defaultProps[key]
if (value && props.default) {
this.defaultProps[key] = value
}
if (is.fun(value)) {
this._state[key] = value
}
})
}

@@ -180,7 +229,6 @@

const results = await Promise.all(promises)
return {
return (this._promise = Promise.all(promises).then(results => ({
value: this._get(),
finished: results.every(result => result.finished),
}
})))
}

@@ -234,5 +282,5 @@

/** Prepare an update with the given props. */
protected _update(propsArg: ControllerProps<State>) {
protected _prepareUpdate(propsArg: ControllerProps<State>) {
const props: PendingProps<State> = interpolateTo(propsArg) as any
const keys = (props.keys = extractKeys(props, this._springs))
props.keys = extractKeys(props, this._springs)

@@ -248,3 +296,3 @@ let { from, to } = props as any

if (from || to) {
this._setSprings(keys, from, to)
this._setSprings(props.keys, from, to)
}

@@ -255,17 +303,33 @@

/** @internal Called at the end of every animation frame */
protected _onFrame() {
const { onFrame, onStart, onRest } = this._state
const isActive = this._active.size > 0
if (isActive !== (this._phase == ACTIVE)) {
this._phase = isActive ? ACTIVE : IDLE
if (isActive) {
callProp(onStart)
} else {
if (onRest) this._promise!.then(onRest)
this._promise = undefined
}
}
if (onFrame) {
onFrame(this._frame)
this._frame = {}
}
}
/** @internal */
onParentChange(event: FrameValue.Event) {
if (this._state.onFrame && event.type == 'change') {
this.frame[event.parent.key as keyof State] = event.value
if (event.type == 'change') {
if (this._state.onFrame) {
this._frame[event.parent.key as keyof State] = event.value
}
this._active[event.idle ? 'delete' : 'add'](event.parent)
G.frameLoop.onFrame(this._onFrame)
}
}
/** @internal Called at the end of every animation frame */
protected _onFrame() {
if (Object.keys(this.frame).length) {
this._state.onFrame!(this.frame)
this.frame = {}
}
}
}

@@ -272,0 +336,0 @@

@@ -1,5 +0,17 @@

import { is, Merge, each, AnyFn, toArray, OneOrMore } from '@react-spring/shared'
import { ReservedProps, ForwardProps } from './types/common'
import { useMemoOne } from 'use-memo-one'
import {
is,
each,
toArray,
getFluidConfig,
isAnimatedString,
AnyFn,
Merge,
OneOrMore,
FluidValue,
} from '@react-spring/shared'
import * as G from '@react-spring/shared/globals'
import { ReservedProps, ForwardProps } from './types/common'
declare const process:

@@ -121,1 +133,16 @@ | { env: { [key: string]: string | undefined } }

}
// Compute the goal value, converting "red" to "rgba(255, 0, 0, 1)" in the process
export function computeGoal<T>(value: T | FluidValue<T>): T {
const config = getFluidConfig(value)
return config
? computeGoal(config.get())
: is.arr(value)
? value.map(computeGoal)
: isAnimatedString(value)
? (G.createStringInterpolator({
range: [0, 1],
output: [value, value] as any,
})(1) as any)
: value
}

@@ -40,3 +40,3 @@ import { is, each, Merge } from '@react-spring/shared'

export type DefaultProps = {
[D in (typeof DEFAULT_PROPS)[number]]?: RunAsyncProps[D]
[D in typeof DEFAULT_PROPS[number]]?: RunAsyncProps[D]
}

@@ -163,3 +163,3 @@

}
if (props.onRest) {
if (is.fun(props.onRest)) {
props.onRest(result as any)

@@ -166,0 +166,0 @@ }

@@ -31,2 +31,3 @@ import {

AnimationEvents,
EventProp,
} from './types/animated'

@@ -40,8 +41,16 @@ import {

} from './runAsync'
import { callProp, DEFAULT_PROPS, matchProp } from './helpers'
import { callProp, computeGoal, DEFAULT_PROPS, matchProp } from './helpers'
import { FrameValue, isFrameValue } from './FrameValue'
import {
SpringPhase,
CREATED,
IDLE,
ACTIVE,
PAUSED,
DISPOSED,
} from './SpringPhase'
/** Default props for a `SpringValue` object */
export type DefaultProps<T = unknown> = {
[D in (typeof DEFAULT_PROPS)[number]]?: PendingProps<T>[D]
[D in typeof DEFAULT_PROPS[number]]?: PendingProps<T>[D]
}

@@ -54,39 +63,26 @@

// TODO: use "const enum" when Babel supports it
type Phase =
| typeof DISPOSED
| typeof CREATED
| typeof IDLE
| typeof PAUSED
| typeof ACTIVE
/** The spring cannot be animated */
const DISPOSED = 'DISPOSED'
/** The spring has not animated yet */
const CREATED = 'CREATED'
/** The spring has animated before */
const IDLE = 'IDLE'
/** The spring is frozen in time */
const PAUSED = 'PAUSED'
/** The spring is animating */
const ACTIVE = 'ACTIVE'
declare const console: { warn: Function }
/** An opaque animatable value */
export class SpringValue<T = any> extends FrameValue<T> {
/** The property name used when `to` or `from` is an object. Useful when debugging too. */
key?: string
/** The animation state */
animation = new Animation()
/** The queue of pending props */
queue?: PendingProps<T>[]
/** The lifecycle phase of this spring */
protected _phase = CREATED
protected _phase: SpringPhase = CREATED
/** The state for `runAsync` calls */
protected _state: RunAsyncState<T> = {}
/** The last time each prop changed */
protected _timestamps: Indexable<number> = {}
/** Some props have customizable default values */
protected _defaultProps = {} as PendingProps<T>
/** Cancel any update from before this timestamp */

@@ -272,3 +268,3 @@ protected _lastAsyncId = 0

/** Check the current phase */
is(phase: Phase) {
is(phase: SpringPhase) {
return this._phase == phase

@@ -517,2 +513,3 @@ }

const defaultProps = this._defaultProps
const timestamps = this._timestamps

@@ -523,13 +520,7 @@ /** Get the value of a prop, or its default value */

const onAnimate = get('onAnimate')
if (onAnimate) {
onAnimate(props as any, this)
}
// Cast from a partial type.
const anim = this.animation
const timestamps = this._timestamps
/** Return true if our prop can be used. This only affects delayed props. */
/**
* Delayed `_update` calls perform diffing on certain props
* to know if they were updated during the delay. In that case,
* the prop is ignored, but other props may still apply.
*/
const diff = (prop: string) => {

@@ -543,4 +534,10 @@ if (timestamp >= (timestamps[prop] || 0)) {

const { key, animation: anim } = this
const { to: prevTo, from: prevFrom } = anim
const onAnimate = coerceEventProp(get('onAnimate'), key)
if (onAnimate) {
onAnimate(props as any, this)
}
// The "reverse" prop only affects one update.

@@ -586,4 +583,4 @@ if (props.reverse) [to, from] = [from, to]

const config = {
...callProp(defaultProps.config, this.key!),
...callProp(props.config, this.key!),
...callProp(defaultProps.config, key!),
...callProp(props.config, key!),
}

@@ -600,3 +597,6 @@ // The "config" prop either overwrites or merges into the existing config.

/** When true, animation is imminent (assuming no interruptions). */
let started = !!toConfig || ((changed || reset) && !isEqual(value, to))
let started =
!!toConfig ||
!!getFluidConfig(prevTo) ||
((changed || reset) && !isEqual(value, to))

@@ -635,4 +635,3 @@ // Animations with an explicit "velocity" are always started.

reset ||
(this.is(CREATED) &&
(!is.und(anim.from) && !isEqual(anim.from, prevFrom)))
(this.is(CREATED) && !is.und(anim.from) && !isEqual(anim.from, prevFrom))
) {

@@ -643,4 +642,4 @@ node.setValue((value = from as T))

// Event props are replaced on every update.
anim.onStart = get('onStart')
anim.onChange = get('onChange')
anim.onStart = coerceEventProp(get('onStart'), key)
anim.onChange = coerceEventProp(get('onChange'), key)

@@ -670,3 +669,3 @@ // Update the default props.

!(toConfig || is.num(goal) || is.arr(goal)) ||
!!matchProp(get('immediate'), this.key)
!!matchProp(get('immediate'), key)

@@ -677,4 +676,6 @@ // Avoid calling this before "immediate" is set

const onRestQueue = anim.onRest || []
const onRest =
props.onRest || (reset && onRestQueue[0]) || defaultProps.onRest
const onRest = coerceEventProp(
props.onRest || (reset && onRestQueue[0]) || defaultProps.onRest,
key
)

@@ -705,19 +706,19 @@ // The "onRest" prop is always first in the queue.

const anim = this.animation
if (value === anim.to) return
if (value !== anim.to) {
let config = getFluidConfig(anim.to)
if (config) {
config.removeChild(this)
}
let config = getFluidConfig(anim.to)
if (config) {
config.removeChild(this)
}
anim.to = value
anim.to = value
let priority = 0
if ((config = getFluidConfig(value))) {
config.addChild(this)
if (isFrameValue(value)) {
priority = (value.priority || 0) + 1
let priority = 0
if ((config = getFluidConfig(value))) {
config.addChild(this)
if (isFrameValue(value)) {
priority = (value.priority || 0) + 1
}
}
this.priority = priority
}
this.priority = priority
}

@@ -855,15 +856,8 @@

// Compute the goal value, converting "red" to "rgba(255, 0, 0, 1)" in the process
function computeGoal<T>(value: T | FluidValue<T>): T {
const config = getFluidConfig(value)
return config
? computeGoal(config.get())
: is.arr(value)
? value.map(computeGoal)
: isAnimatedString(value)
? (G.createStringInterpolator({
range: [0, 1],
output: [value, value] as any,
})(1) as any)
: value
/** Coerce an event prop to an event handler */
function coerceEventProp<T extends Function>(
prop: EventProp<T> | undefined,
key: string | undefined
) {
return is.fun(prop) ? prop : key && prop ? prop[key] : undefined
}

@@ -1,2 +0,2 @@

import { Animatable, FluidValue } from '@react-spring/shared'
import { Animatable, FluidValue, Indexable } from '@react-spring/shared'

@@ -75,2 +75,4 @@ import { MatchProp } from '../helpers'

export type EventProp<T> = T | Indexable<T>
/**

@@ -86,15 +88,15 @@ * The event props of a `SpringValue` animation.

*/
onAnimate?: OnAnimate<T>
onAnimate?: EventProp<OnAnimate<T>>
/**
* Called when an animation moves for the first time
*/
onStart?: OnStart<T>
onStart?: EventProp<OnStart<T>>
/**
* Called when all animations come to a stand-still
*/
onRest?: OnRest<T>
onRest?: EventProp<OnRest<T>>
/**
* Called when a key/value pair is changed
*/
onChange?: OnChange<T>
onChange?: EventProp<OnChange<T>>
}

@@ -101,0 +103,0 @@

@@ -1,2 +0,3 @@

import { each, useIsomorphicLayoutEffect } from '@react-spring/shared'
import { useLayoutEffect } from 'react-layout-effect'
import { each } from '@react-spring/shared'

@@ -8,3 +9,3 @@ /** API

export function useChain(refs, timeSteps, timeFrame = 1000) {
useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
if (timeSteps) {

@@ -11,0 +12,0 @@ let prevDelay = 0

@@ -66,4 +66,8 @@ import { RefObject } from 'react'

const isFn = is.fun(props)
const [[values], update, stop] = useSprings(1, isFn ? props : [props], deps)
return isFn || arguments.length == 3 ? [values, update, stop] : values
const [[values], update, stop] = useSprings(
1,
isFn ? props : [props],
isFn ? deps || [] : deps
)
return isFn || arguments.length == 2 ? [values, update, stop] : values
}
import { useMemo, RefObject, useImperativeHandle } from 'react'
import {
is,
each,
usePrev,
useOnce,
useIsomorphicLayoutEffect,
UnknownProps,
Merge,
} from '@react-spring/shared'
import { useLayoutEffect } from 'react-layout-effect'
import { is, each, usePrev, useOnce, UnknownProps, Merge } from '@react-spring/shared'

@@ -147,3 +140,3 @@ import {

useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
each(updates, (update, i) => ctrls[i].update(update))

@@ -150,0 +143,0 @@ if (!ref) {

@@ -1,2 +0,3 @@

import { is, useIsomorphicLayoutEffect, UnknownProps } from '@react-spring/shared'
import { useLayoutEffect } from 'react-layout-effect'
import { is, UnknownProps } from '@react-spring/shared'

@@ -46,3 +47,3 @@ import { PickAnimated, Valid } from './types/common'

useIsomorphicLayoutEffect(() => {
useLayoutEffect(() => {
const reverse = is.obj(propsArg) && propsArg.reverse

@@ -49,0 +50,0 @@ for (let i = 0; i < ctrls.length; i++) {

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

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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