627 lines
18 KiB
TypeScript
627 lines
18 KiB
TypeScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import type * as React from 'react';
|
|
import {ScrollView} from '../Components/ScrollView/ScrollView';
|
|
import {View} from '../Components/View/View';
|
|
import {Image} from '../Image/Image';
|
|
import {FlatListComponent, FlatListProps} from '../Lists/FlatList';
|
|
import {
|
|
DefaultSectionT,
|
|
SectionListComponent,
|
|
SectionListProps,
|
|
} from '../Lists/SectionList';
|
|
import {ColorValue} from '../StyleSheet/StyleSheet';
|
|
import {Text} from '../Text/Text';
|
|
import {NativeSyntheticEvent} from '../Types/CoreEventTypes';
|
|
|
|
export namespace Animated {
|
|
type AnimatedValue = Value;
|
|
type AnimatedValueXY = ValueXY;
|
|
|
|
class Animated {
|
|
// Internal class, no public API.
|
|
}
|
|
|
|
class AnimatedNode {
|
|
/**
|
|
* Adds an asynchronous listener to the value so you can observe updates from
|
|
* animations. This is useful because there is no way to
|
|
* synchronously read the value because it might be driven natively.
|
|
*
|
|
* See https://reactnative.dev/docs/animatedvalue.html#addlistener
|
|
*/
|
|
addListener(callback: (value: any) => any): string;
|
|
/**
|
|
* Unregister a listener. The `id` param shall match the identifier
|
|
* previously returned by `addListener()`.
|
|
*
|
|
* See https://reactnative.dev/docs/animatedvalue.html#removelistener
|
|
*/
|
|
removeListener(id: string): void;
|
|
/**
|
|
* Remove all registered listeners.
|
|
*
|
|
* See https://reactnative.dev/docs/animatedvalue.html#removealllisteners
|
|
*/
|
|
removeAllListeners(): void;
|
|
|
|
hasListeners(): boolean;
|
|
}
|
|
|
|
class AnimatedWithChildren extends AnimatedNode {
|
|
// Internal class, no public API.
|
|
}
|
|
|
|
type RgbaValue = {
|
|
readonly r: number;
|
|
readonly g: number;
|
|
readonly b: number;
|
|
readonly a: number;
|
|
};
|
|
|
|
type RgbaAnimatedValue = {
|
|
readonly r: AnimatedValue;
|
|
readonly g: AnimatedValue;
|
|
readonly b: AnimatedValue;
|
|
readonly a: AnimatedValue;
|
|
};
|
|
|
|
type AnimatedConfig = {
|
|
readonly useNativeDriver: boolean;
|
|
};
|
|
|
|
class AnimatedColor extends AnimatedWithChildren {
|
|
r: AnimatedValue;
|
|
g: AnimatedValue;
|
|
b: AnimatedValue;
|
|
a: AnimatedValue;
|
|
|
|
constructor(
|
|
valueIn?: RgbaValue | RgbaAnimatedValue | ColorValue | null,
|
|
config?: AnimatedConfig | null,
|
|
);
|
|
nativeColor: unknown; // Unsure what to do here
|
|
setValue: (value: RgbaValue | ColorValue) => void;
|
|
setOffset: (offset: RgbaValue) => void;
|
|
flattenOffset: () => void;
|
|
extractOffset: () => void;
|
|
addListener: (callback: (value: ColorValue) => unknown) => string;
|
|
removeListener: (id: string) => void;
|
|
removeAllListeners: () => void;
|
|
stopAnimation: (callback: (value: ColorValue) => unknown) => void;
|
|
resetAnimation: (callback: (value: ColorValue) => unknown) => void;
|
|
}
|
|
|
|
class AnimatedInterpolation<
|
|
OutputT extends number | string,
|
|
> extends AnimatedWithChildren {
|
|
interpolate(
|
|
config: InterpolationConfigType,
|
|
): AnimatedInterpolation<OutputT>;
|
|
}
|
|
|
|
type ExtrapolateType = 'extend' | 'identity' | 'clamp';
|
|
|
|
type InterpolationConfigType = {
|
|
inputRange: number[];
|
|
outputRange: number[] | string[];
|
|
easing?: ((input: number) => number) | undefined;
|
|
extrapolate?: ExtrapolateType | undefined;
|
|
extrapolateLeft?: ExtrapolateType | undefined;
|
|
extrapolateRight?: ExtrapolateType | undefined;
|
|
};
|
|
|
|
type ValueListenerCallback = (state: {value: number}) => void;
|
|
|
|
type Animation = {
|
|
start(
|
|
fromValue: number,
|
|
onUpdate: (value: number) => void,
|
|
onEnd: EndCallback | null,
|
|
previousAnimation: Animation | null,
|
|
animatedValue: AnimatedValue,
|
|
): void;
|
|
stop(): void;
|
|
};
|
|
|
|
/**
|
|
* Standard value for driving animations. One `Animated.Value` can drive
|
|
* multiple properties in a synchronized fashion, but can only be driven by one
|
|
* mechanism at a time. Using a new mechanism (e.g. starting a new animation,
|
|
* or calling `setValue`) will stop any previous ones.
|
|
*/
|
|
export class Value extends AnimatedWithChildren {
|
|
constructor(value: number, config?: AnimatedConfig | null);
|
|
|
|
/**
|
|
* Directly set the value. This will stop any animations running on the value
|
|
* and update all the bound properties.
|
|
*/
|
|
setValue(value: number): void;
|
|
|
|
/**
|
|
* Sets an offset that is applied on top of whatever value is set, whether via
|
|
* `setValue`, an animation, or `Animated.event`. Useful for compensating
|
|
* things like the start of a pan gesture.
|
|
*/
|
|
setOffset(offset: number): void;
|
|
|
|
/**
|
|
* Merges the offset value into the base value and resets the offset to zero.
|
|
* The final output of the value is unchanged.
|
|
*/
|
|
flattenOffset(): void;
|
|
|
|
/**
|
|
* Sets the offset value to the base value, and resets the base value to zero.
|
|
* The final output of the value is unchanged.
|
|
*/
|
|
extractOffset(): void;
|
|
|
|
/**
|
|
* Adds an asynchronous listener to the value so you can observe updates from
|
|
* animations. This is useful because there is no way to
|
|
* synchronously read the value because it might be driven natively.
|
|
*/
|
|
addListener(callback: ValueListenerCallback): string;
|
|
|
|
removeListener(id: string): void;
|
|
|
|
removeAllListeners(): void;
|
|
|
|
/**
|
|
* Stops any running animation or tracking. `callback` is invoked with the
|
|
* final value after stopping the animation, which is useful for updating
|
|
* state to match the animation position with layout.
|
|
*/
|
|
stopAnimation(callback?: (value: number) => void): void;
|
|
|
|
/**
|
|
* Stops any animation and resets the value to its original.
|
|
*
|
|
* See https://reactnative.dev/docs/animatedvalue#resetanimation
|
|
*/
|
|
resetAnimation(callback?: (value: number) => void): void;
|
|
|
|
/**
|
|
* Interpolates the value before updating the property, e.g. mapping 0-1 to
|
|
* 0-10.
|
|
*/
|
|
interpolate<OutputT extends number | string>(
|
|
config: InterpolationConfigType,
|
|
): AnimatedInterpolation<OutputT>;
|
|
|
|
/**
|
|
* Typically only used internally, but could be used by a custom Animation
|
|
* class.
|
|
*
|
|
* See https://reactnative.dev/docs/animatedvalue#animate
|
|
*/
|
|
animate(animation: Animation, callback?: EndCallback | null): void;
|
|
}
|
|
|
|
type ValueXYListenerCallback = (value: {x: number; y: number}) => void;
|
|
|
|
/**
|
|
* 2D Value for driving 2D animations, such as pan gestures. Almost identical
|
|
* API to normal `Animated.Value`, but multiplexed. Contains two regular
|
|
* `Animated.Value`s under the hood.
|
|
*/
|
|
export class ValueXY extends AnimatedWithChildren {
|
|
x: AnimatedValue;
|
|
y: AnimatedValue;
|
|
|
|
constructor(
|
|
valueIn?: {x: number | AnimatedValue; y: number | AnimatedValue},
|
|
config?: AnimatedConfig | null,
|
|
);
|
|
|
|
setValue(value: {x: number; y: number}): void;
|
|
|
|
setOffset(offset: {x: number; y: number}): void;
|
|
|
|
flattenOffset(): void;
|
|
|
|
extractOffset(): void;
|
|
|
|
resetAnimation(callback?: (value: {x: number; y: number}) => void): void;
|
|
|
|
stopAnimation(callback?: (value: {x: number; y: number}) => void): void;
|
|
|
|
addListener(callback: ValueXYListenerCallback): string;
|
|
|
|
removeListener(id: string): void;
|
|
|
|
/**
|
|
* Converts `{x, y}` into `{left, top}` for use in style, e.g.
|
|
*
|
|
*```javascript
|
|
* style={this.state.anim.getLayout()}
|
|
*```
|
|
*/
|
|
getLayout(): {[key: string]: AnimatedValue};
|
|
|
|
/**
|
|
* Converts `{x, y}` into a useable translation transform, e.g.
|
|
*
|
|
*```javascript
|
|
* style={{
|
|
* transform: this.state.anim.getTranslateTransform()
|
|
* }}
|
|
*```
|
|
*/
|
|
getTranslateTransform(): [
|
|
{translateX: AnimatedValue},
|
|
{translateY: AnimatedValue},
|
|
];
|
|
}
|
|
|
|
type EndResult = {finished: boolean};
|
|
type EndCallback = (result: EndResult) => void;
|
|
|
|
export interface CompositeAnimation {
|
|
/**
|
|
* Animations are started by calling start() on your animation.
|
|
* start() takes a completion callback that will be called when the
|
|
* animation is done or when the animation is done because stop() was
|
|
* called on it before it could finish.
|
|
*
|
|
* @param callback - Optional function that will be called
|
|
* after the animation finished running normally or when the animation
|
|
* is done because stop() was called on it before it could finish
|
|
*
|
|
* @example
|
|
* Animated.timing({}).start(({ finished }) => {
|
|
* // completion callback
|
|
* });
|
|
*/
|
|
start: (callback?: EndCallback) => void;
|
|
/**
|
|
* Stops any running animation.
|
|
*/
|
|
stop: () => void;
|
|
/**
|
|
* Stops any running animation and resets the value to its original.
|
|
*/
|
|
reset: () => void;
|
|
}
|
|
|
|
interface AnimationConfig {
|
|
isInteraction?: boolean | undefined;
|
|
useNativeDriver: boolean;
|
|
}
|
|
|
|
/**
|
|
* Animates a value from an initial velocity to zero based on a decay
|
|
* coefficient.
|
|
*/
|
|
export function decay(
|
|
value: AnimatedValue | AnimatedValueXY,
|
|
config: DecayAnimationConfig,
|
|
): CompositeAnimation;
|
|
|
|
interface DecayAnimationConfig extends AnimationConfig {
|
|
velocity: number | {x: number; y: number};
|
|
deceleration?: number | undefined;
|
|
}
|
|
|
|
/**
|
|
* Animates a value along a timed easing curve. The `Easing` module has tons
|
|
* of pre-defined curves, or you can use your own function.
|
|
*/
|
|
export const timing: (
|
|
value: AnimatedValue | AnimatedValueXY,
|
|
config: TimingAnimationConfig,
|
|
) => CompositeAnimation;
|
|
|
|
interface TimingAnimationConfig extends AnimationConfig {
|
|
toValue:
|
|
| number
|
|
| AnimatedValue
|
|
| {x: number; y: number}
|
|
| AnimatedValueXY
|
|
| AnimatedInterpolation<number>;
|
|
easing?: ((value: number) => number) | undefined;
|
|
duration?: number | undefined;
|
|
delay?: number | undefined;
|
|
}
|
|
|
|
interface SpringAnimationConfig extends AnimationConfig {
|
|
toValue:
|
|
| number
|
|
| AnimatedValue
|
|
| {x: number; y: number}
|
|
| AnimatedValueXY
|
|
| RgbaValue
|
|
| AnimatedColor
|
|
| AnimatedInterpolation<number>;
|
|
overshootClamping?: boolean | undefined;
|
|
restDisplacementThreshold?: number | undefined;
|
|
restSpeedThreshold?: number | undefined;
|
|
velocity?: number | {x: number; y: number} | undefined;
|
|
bounciness?: number | undefined;
|
|
speed?: number | undefined;
|
|
tension?: number | undefined;
|
|
friction?: number | undefined;
|
|
stiffness?: number | undefined;
|
|
mass?: number | undefined;
|
|
damping?: number | undefined;
|
|
delay?: number | undefined;
|
|
}
|
|
|
|
interface LoopAnimationConfig {
|
|
iterations?: number | undefined; // default -1 for infinite
|
|
/**
|
|
* Defaults to `true`
|
|
*/
|
|
resetBeforeIteration?: boolean | undefined;
|
|
}
|
|
|
|
/**
|
|
* Creates a new Animated value composed from two Animated values added
|
|
* together.
|
|
*/
|
|
export function add<OutputT extends number | string>(
|
|
a: Animated,
|
|
b: Animated,
|
|
): AnimatedAddition<OutputT>;
|
|
|
|
class AnimatedAddition<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Creates a new Animated value composed by subtracting the second Animated
|
|
* value from the first Animated value.
|
|
*/
|
|
export function subtract<OutputT extends number | string>(
|
|
a: Animated,
|
|
b: Animated,
|
|
): AnimatedSubtraction<OutputT>;
|
|
|
|
class AnimatedSubtraction<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Creates a new Animated value composed by dividing the first Animated
|
|
* value by the second Animated value.
|
|
*/
|
|
export function divide<OutputT extends number | string>(
|
|
a: Animated,
|
|
b: Animated,
|
|
): AnimatedDivision<OutputT>;
|
|
|
|
class AnimatedDivision<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Creates a new Animated value composed from two Animated values multiplied
|
|
* together.
|
|
*/
|
|
export function multiply<OutputT extends number | string>(
|
|
a: Animated,
|
|
b: Animated,
|
|
): AnimatedMultiplication<OutputT>;
|
|
|
|
class AnimatedMultiplication<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Creates a new Animated value that is the (non-negative) modulo of the
|
|
* provided Animated value
|
|
*/
|
|
export function modulo<OutputT extends number | string>(
|
|
a: Animated,
|
|
modulus: number,
|
|
): AnimatedModulo<OutputT>;
|
|
|
|
class AnimatedModulo<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Create a new Animated value that is limited between 2 values. It uses the
|
|
* difference between the last value so even if the value is far from the bounds
|
|
* it will start changing when the value starts getting closer again.
|
|
* (`value = clamp(value + diff, min, max)`).
|
|
*
|
|
* This is useful with scroll events, for example, to show the navbar when
|
|
* scrolling up and to hide it when scrolling down.
|
|
*/
|
|
export function diffClamp<OutputT extends number | string>(
|
|
a: Animated,
|
|
min: number,
|
|
max: number,
|
|
): AnimatedDiffClamp<OutputT>;
|
|
|
|
class AnimatedDiffClamp<
|
|
OutputT extends number | string,
|
|
> extends AnimatedInterpolation<OutputT> {}
|
|
|
|
/**
|
|
* Starts an animation after the given delay.
|
|
*/
|
|
export function delay(time: number): CompositeAnimation;
|
|
|
|
/**
|
|
* Starts an array of animations in order, waiting for each to complete
|
|
* before starting the next. If the current running animation is stopped, no
|
|
* following animations will be started.
|
|
*/
|
|
export function sequence(
|
|
animations: Array<CompositeAnimation>,
|
|
): CompositeAnimation;
|
|
|
|
/**
|
|
* Array of animations may run in parallel (overlap), but are started in
|
|
* sequence with successive delays. Nice for doing trailing effects.
|
|
*/
|
|
|
|
export function stagger(
|
|
time: number,
|
|
animations: Array<CompositeAnimation>,
|
|
): CompositeAnimation;
|
|
|
|
/**
|
|
* Loops a given animation continuously, so that each time it reaches the end,
|
|
* it resets and begins again from the start. Can specify number of times to
|
|
* loop using the key 'iterations' in the config. Will loop without blocking
|
|
* the UI thread if the child animation is set to 'useNativeDriver'.
|
|
*/
|
|
|
|
export function loop(
|
|
animation: CompositeAnimation,
|
|
config?: LoopAnimationConfig,
|
|
): CompositeAnimation;
|
|
|
|
/**
|
|
* Spring animation based on Rebound and Origami. Tracks velocity state to
|
|
* create fluid motions as the `toValue` updates, and can be chained together.
|
|
*/
|
|
export function spring(
|
|
value: AnimatedValue | AnimatedValueXY,
|
|
config: SpringAnimationConfig,
|
|
): CompositeAnimation;
|
|
|
|
type ParallelConfig = {
|
|
stopTogether?: boolean | undefined; // If one is stopped, stop all. default: true
|
|
};
|
|
|
|
/**
|
|
* Starts an array of animations all at the same time. By default, if one
|
|
* of the animations is stopped, they will all be stopped. You can override
|
|
* this with the `stopTogether` flag.
|
|
*/
|
|
export function parallel(
|
|
animations: Array<CompositeAnimation>,
|
|
config?: ParallelConfig,
|
|
): CompositeAnimation;
|
|
|
|
type Mapping = {[key: string]: Mapping} | AnimatedValue;
|
|
interface EventConfig<T> {
|
|
listener?: ((event: NativeSyntheticEvent<T>) => void) | undefined;
|
|
useNativeDriver: boolean;
|
|
}
|
|
|
|
/**
|
|
* Takes an array of mappings and extracts values from each arg accordingly,
|
|
* then calls `setValue` on the mapped outputs. e.g.
|
|
*
|
|
*```javascript
|
|
* onScroll={Animated.event(
|
|
* [{nativeEvent: {contentOffset: {x: this._scrollX}}}]
|
|
* {listener}, // Optional async listener
|
|
* )
|
|
* ...
|
|
* onPanResponderMove: Animated.event([
|
|
* null, // raw event arg ignored
|
|
* {dx: this._panX}, // gestureState arg
|
|
* ]),
|
|
*```
|
|
*/
|
|
export function event<T>(
|
|
argMapping: Array<Mapping | null>,
|
|
config?: EventConfig<T>,
|
|
): (...args: any[]) => void;
|
|
|
|
export type ComponentProps<T> = T extends
|
|
| React.ComponentType<infer P>
|
|
| React.Component<infer P>
|
|
? P
|
|
: never;
|
|
|
|
export type LegacyRef<C> = {getNode(): C};
|
|
|
|
type Nullable = undefined | null;
|
|
type Primitive = string | number | boolean | symbol;
|
|
type Builtin = Function | Date | Error | RegExp;
|
|
|
|
interface WithAnimatedArray<P> extends Array<WithAnimatedValue<P>> {}
|
|
type WithAnimatedObject<T> = {
|
|
[K in keyof T]: WithAnimatedValue<T[K]>;
|
|
};
|
|
|
|
export type WithAnimatedValue<T> = T extends Builtin | Nullable
|
|
? T
|
|
: T extends Primitive
|
|
? T | Value | AnimatedInterpolation<number | string> // add `Value` and `AnimatedInterpolation` but also preserve original T
|
|
: T extends Array<infer P>
|
|
? WithAnimatedArray<P>
|
|
: T extends {}
|
|
? WithAnimatedObject<T>
|
|
: T; // in case it's something we don't yet know about (for .e.g bigint)
|
|
|
|
type NonAnimatedProps = 'key' | 'ref';
|
|
|
|
type TAugmentRef<T> = T extends React.Ref<infer R>
|
|
? unknown extends R
|
|
? never
|
|
: React.Ref<R | LegacyRef<R>>
|
|
: never;
|
|
|
|
export type AnimatedProps<T> = {
|
|
[key in keyof T]: key extends NonAnimatedProps
|
|
? key extends 'ref'
|
|
? TAugmentRef<T[key]>
|
|
: T[key]
|
|
: WithAnimatedValue<T[key]>;
|
|
};
|
|
|
|
export interface AnimatedComponent<T extends React.ComponentType<any>>
|
|
extends React.FC<AnimatedProps<React.ComponentPropsWithRef<T>>> {}
|
|
|
|
export type AnimatedComponentOptions = {
|
|
collapsable?: boolean | undefined;
|
|
};
|
|
|
|
/**
|
|
* Make any React component Animatable. Used to create `Animated.View`, etc.
|
|
*/
|
|
export function createAnimatedComponent<T extends React.ComponentType<any>>(
|
|
component: T,
|
|
options?: AnimatedComponentOptions,
|
|
): AnimatedComponent<T>;
|
|
|
|
/**
|
|
* Animated variants of the basic native views. Accepts Animated.Value for
|
|
* props and style.
|
|
*/
|
|
export const View: AnimatedComponent<typeof _View>;
|
|
export const Image: AnimatedComponent<typeof _Image>;
|
|
export const Text: AnimatedComponent<typeof _Text>;
|
|
export const ScrollView: AnimatedComponent<typeof _ScrollView>;
|
|
|
|
/**
|
|
* FlatList and SectionList infer generic Type defined under their `data` and `section` props.
|
|
*/
|
|
|
|
export class FlatList<ItemT = any> extends FlatListComponent<
|
|
ItemT,
|
|
AnimatedProps<FlatListProps<ItemT>>
|
|
> {}
|
|
|
|
export class SectionList<
|
|
ItemT = any,
|
|
SectionT = DefaultSectionT,
|
|
> extends SectionListComponent<
|
|
AnimatedProps<SectionListProps<ItemT, SectionT>>
|
|
> {}
|
|
}
|
|
|
|
// We need to alias these views so we can reference them in the Animated
|
|
// namespace where their names are shadowed.
|
|
declare const _View: typeof View;
|
|
declare const _Image: typeof Image;
|
|
declare const _Text: typeof Text;
|
|
declare const _ScrollView: typeof ScrollView;
|