/** * 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; } 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( config: InterpolationConfigType, ): AnimatedInterpolation; /** * 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; 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; 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( a: Animated, b: Animated, ): AnimatedAddition; class AnimatedAddition< OutputT extends number | string, > extends AnimatedInterpolation {} /** * Creates a new Animated value composed by subtracting the second Animated * value from the first Animated value. */ export function subtract( a: Animated, b: Animated, ): AnimatedSubtraction; class AnimatedSubtraction< OutputT extends number | string, > extends AnimatedInterpolation {} /** * Creates a new Animated value composed by dividing the first Animated * value by the second Animated value. */ export function divide( a: Animated, b: Animated, ): AnimatedDivision; class AnimatedDivision< OutputT extends number | string, > extends AnimatedInterpolation {} /** * Creates a new Animated value composed from two Animated values multiplied * together. */ export function multiply( a: Animated, b: Animated, ): AnimatedMultiplication; class AnimatedMultiplication< OutputT extends number | string, > extends AnimatedInterpolation {} /** * Creates a new Animated value that is the (non-negative) modulo of the * provided Animated value */ export function modulo( a: Animated, modulus: number, ): AnimatedModulo; class AnimatedModulo< OutputT extends number | string, > extends AnimatedInterpolation {} /** * 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( a: Animated, min: number, max: number, ): AnimatedDiffClamp; class AnimatedDiffClamp< OutputT extends number | string, > extends AnimatedInterpolation {} /** * 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; /** * 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; /** * 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, config?: ParallelConfig, ): CompositeAnimation; type Mapping = {[key: string]: Mapping} | AnimatedValue; interface EventConfig { listener?: ((event: NativeSyntheticEvent) => 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( argMapping: Array, config?: EventConfig, ): (...args: any[]) => void; export type ComponentProps = T extends | React.ComponentType | React.Component ? P : never; export type LegacyRef = {getNode(): C}; type Nullable = undefined | null; type Primitive = string | number | boolean | symbol; type Builtin = Function | Date | Error | RegExp; interface WithAnimatedArray

extends Array> {} type WithAnimatedObject = { [K in keyof T]: WithAnimatedValue; }; export type WithAnimatedValue = T extends Builtin | Nullable ? T : T extends Primitive ? T | Value | AnimatedInterpolation // add `Value` and `AnimatedInterpolation` but also preserve original T : T extends Array ? WithAnimatedArray

: T extends {} ? WithAnimatedObject : T; // in case it's something we don't yet know about (for .e.g bigint) type NonAnimatedProps = 'key' | 'ref'; type TAugmentRef = T extends React.Ref ? unknown extends R ? never : React.Ref> : never; export type AnimatedProps = { [key in keyof T]: key extends NonAnimatedProps ? key extends 'ref' ? TAugmentRef : T[key] : WithAnimatedValue; }; export interface AnimatedComponent> extends React.FC>> {} export type AnimatedComponentOptions = { collapsable?: boolean | undefined; }; /** * Make any React component Animatable. Used to create `Animated.View`, etc. */ export function createAnimatedComponent>( component: T, options?: AnimatedComponentOptions, ): AnimatedComponent; /** * Animated variants of the basic native views. Accepts Animated.Value for * props and style. */ export const View: AnimatedComponent; export const Image: AnimatedComponent; export const Text: AnimatedComponent; export const ScrollView: AnimatedComponent; /** * FlatList and SectionList infer generic Type defined under their `data` and `section` props. */ export class FlatList extends FlatListComponent< ItemT, AnimatedProps> > {} export class SectionList< ItemT = any, SectionT = DefaultSectionT, > extends SectionListComponent< AnimatedProps> > {} } // 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;