diff --git a/packages/react-native/Libraries/Animated/Animated.d.ts b/packages/animated/Animated.d.ts similarity index 97% rename from packages/react-native/Libraries/Animated/Animated.d.ts rename to packages/animated/Animated.d.ts index aeeb98146da8..4d678cc82517 100644 --- a/packages/react-native/Libraries/Animated/Animated.d.ts +++ b/packages/animated/Animated.d.ts @@ -7,19 +7,21 @@ * @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 { + Image, + Text, + ScrollView, + ColorValue, + View, + FlatListProps, DefaultSectionT, - SectionListComponent, SectionListProps, -} from '../Lists/SectionList'; -import {ColorValue} from '../StyleSheet/StyleSheet'; -import {Text} from '../Text/Text'; -import {NativeSyntheticEvent} from '../Types/CoreEventTypes'; + NativeSyntheticEvent, + SectionListComponent, + FlatListComponent, +} from 'react-native'; + +import type * as React from 'react'; export namespace Animated { type AnimatedValue = Value; diff --git a/packages/react-native/Libraries/Animated/Animated.js b/packages/animated/Animated.js similarity index 100% rename from packages/react-native/Libraries/Animated/Animated.js rename to packages/animated/Animated.js diff --git a/packages/react-native/Libraries/Animated/Animated.js.flow b/packages/animated/Animated.js.flow similarity index 100% rename from packages/react-native/Libraries/Animated/Animated.js.flow rename to packages/animated/Animated.js.flow diff --git a/packages/react-native/Libraries/Animated/AnimatedEvent.js b/packages/animated/AnimatedEvent.js similarity index 96% rename from packages/react-native/Libraries/Animated/AnimatedEvent.js rename to packages/animated/AnimatedEvent.js index 6c22b9ca557b..61bdabde93a3 100644 --- a/packages/react-native/Libraries/Animated/AnimatedEvent.js +++ b/packages/animated/AnimatedEvent.js @@ -10,14 +10,14 @@ 'use strict'; -import type {NativeSyntheticEvent} from '../Types/CoreEventTypes'; import type {PlatformConfig} from './AnimatedPlatformConfig'; +import type {NativeSyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes'; -import NativeAnimatedHelper from '../../src/private/animated/NativeAnimatedHelper'; -import {findNodeHandle} from '../ReactNative/RendererProxy'; import AnimatedValue from './nodes/AnimatedValue'; import AnimatedValueXY from './nodes/AnimatedValueXY'; import invariant from 'invariant'; +import {findNodeHandle} from 'react-native/Libraries/ReactNative/RendererProxy'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; export type Mapping = | {[key: string]: Mapping, ...} diff --git a/packages/react-native/Libraries/Animated/AnimatedExports.js b/packages/animated/AnimatedExports.js similarity index 97% rename from packages/react-native/Libraries/Animated/AnimatedExports.js rename to packages/animated/AnimatedExports.js index a1563b1b6f39..2ed2ce81dbe9 100644 --- a/packages/react-native/Libraries/Animated/AnimatedExports.js +++ b/packages/animated/AnimatedExports.js @@ -16,9 +16,9 @@ import typeof AnimatedSectionList from './components/AnimatedSectionList'; import typeof AnimatedText from './components/AnimatedText'; import typeof AnimatedView from './components/AnimatedView'; -import Platform from '../Utilities/Platform'; import AnimatedImplementation from './AnimatedImplementation'; import AnimatedMock from './AnimatedMock'; +import {Platform} from 'react-native'; const Animated: typeof AnimatedImplementation = Platform.isDisableAnimations ? AnimatedMock diff --git a/packages/react-native/Libraries/Animated/AnimatedExports.js.flow b/packages/animated/AnimatedExports.js.flow similarity index 100% rename from packages/react-native/Libraries/Animated/AnimatedExports.js.flow rename to packages/animated/AnimatedExports.js.flow diff --git a/packages/react-native/Libraries/Animated/AnimatedImplementation.js b/packages/animated/AnimatedImplementation.js similarity index 100% rename from packages/react-native/Libraries/Animated/AnimatedImplementation.js rename to packages/animated/AnimatedImplementation.js diff --git a/packages/animated/AnimatedMock.js b/packages/animated/AnimatedMock.js new file mode 100644 index 000000000000..a31cd00fee58 --- /dev/null +++ b/packages/animated/AnimatedMock.js @@ -0,0 +1,196 @@ +/** + * 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. + * + * @flow + * @format + */ + +'use strict'; + +import type {Numeric as AnimatedNumeric} from './AnimatedImplementation'; +import type {EndResult} from './animations/Animation'; +import type {EndCallback} from './animations/Animation'; +import type {DecayAnimationConfig} from './animations/DecayAnimation'; +import type {SpringAnimationConfig} from './animations/SpringAnimation'; +import type {TimingAnimationConfig} from './animations/TimingAnimation'; + +import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent'; +import AnimatedImplementation from './AnimatedImplementation'; +import createAnimatedComponent from './createAnimatedComponent'; +import AnimatedColor from './nodes/AnimatedColor'; +import AnimatedInterpolation from './nodes/AnimatedInterpolation'; +import AnimatedNode from './nodes/AnimatedNode'; +import AnimatedValue from './nodes/AnimatedValue'; +import AnimatedValueXY from './nodes/AnimatedValueXY'; + +/** + * Animations are a source of flakiness in snapshot testing. This mock replaces + * animation functions from AnimatedImplementation with empty animations for + * predictability in tests. When possible the animation will run immediately + * to the final state. + */ + +// Prevent any callback invocation from recursively triggering another +// callback, which may trigger another animation +let inAnimationCallback = false; +function mockAnimationStart( + start: (callback?: ?EndCallback) => void, +): (callback?: ?EndCallback) => void { + return callback => { + const guardedCallback = + callback == null + ? callback + : (...args: Array) => { + if (inAnimationCallback) { + console.warn( + 'Ignoring recursive animation callback when running mock animations', + ); + return; + } + inAnimationCallback = true; + try { + callback(...args); + } finally { + inAnimationCallback = false; + } + }; + start(guardedCallback); + }; +} + +export type CompositeAnimation = { + start: (callback?: ?EndCallback) => void, + stop: () => void, + reset: () => void, + _startNativeLoop: (iterations?: number) => void, + _isUsingNativeDriver: () => boolean, + ... +}; + +const emptyAnimation = { + start: () => {}, + stop: () => {}, + reset: () => {}, + _startNativeLoop: () => {}, + _isUsingNativeDriver: () => { + return false; + }, +}; + +const mockCompositeAnimation = ( + animations: Array, +): CompositeAnimation => ({ + ...emptyAnimation, + start: mockAnimationStart((callback?: ?EndCallback): void => { + animations.forEach(animation => animation.start()); + callback?.({finished: true}); + }), +}); + +const spring = function ( + value: AnimatedValue | AnimatedValueXY | AnimatedColor, + config: SpringAnimationConfig, +): CompositeAnimation { + const anyValue: any = value; + return { + ...emptyAnimation, + start: mockAnimationStart((callback?: ?EndCallback): void => { + anyValue.setValue(config.toValue); + callback?.({finished: true}); + }), + }; +}; + +const timing = function ( + value: AnimatedValue | AnimatedValueXY | AnimatedColor, + config: TimingAnimationConfig, +): CompositeAnimation { + const anyValue: any = value; + return { + ...emptyAnimation, + start: mockAnimationStart((callback?: ?EndCallback): void => { + anyValue.setValue(config.toValue); + callback?.({finished: true}); + }), + }; +}; + +const decay = function ( + value: AnimatedValue | AnimatedValueXY | AnimatedColor, + config: DecayAnimationConfig, +): CompositeAnimation { + return emptyAnimation; +}; + +const sequence = function ( + animations: Array, +): CompositeAnimation { + return mockCompositeAnimation(animations); +}; + +type ParallelConfig = {stopTogether?: boolean, ...}; +const parallel = function ( + animations: Array, + config?: ?ParallelConfig, +): CompositeAnimation { + return mockCompositeAnimation(animations); +}; + +const delay = function (time: number): CompositeAnimation { + return emptyAnimation; +}; + +const stagger = function ( + time: number, + animations: Array, +): CompositeAnimation { + return mockCompositeAnimation(animations); +}; + +type LoopAnimationConfig = { + iterations: number, + resetBeforeIteration?: boolean, + ... +}; + +const loop = function ( + animation: CompositeAnimation, + // $FlowFixMe[prop-missing] + {iterations = -1}: LoopAnimationConfig = {}, +): CompositeAnimation { + return emptyAnimation; +}; + +export type {AnimatedNumeric as Numeric}; + +const AnimatedMock = { + Value: AnimatedValue, + ValueXY: AnimatedValueXY, + Color: AnimatedColor, + Interpolation: AnimatedInterpolation, + Node: AnimatedNode, + decay, + timing, + spring, + add: AnimatedImplementation.add, + subtract: AnimatedImplementation.subtract, + divide: AnimatedImplementation.divide, + multiply: AnimatedImplementation.multiply, + modulo: AnimatedImplementation.modulo, + diffClamp: AnimatedImplementation.diffClamp, + delay, + sequence, + parallel, + stagger, + loop, + event: AnimatedImplementation.event, + createAnimatedComponent, + attachNativeEvent, + forkEvent: AnimatedImplementation.forkEvent, + unforkEvent: AnimatedImplementation.unforkEvent, + Event: AnimatedEvent, +}; +export default AnimatedMock; diff --git a/packages/react-native/Libraries/Animated/AnimatedPlatformConfig.js b/packages/animated/AnimatedPlatformConfig.js similarity index 100% rename from packages/react-native/Libraries/Animated/AnimatedPlatformConfig.js rename to packages/animated/AnimatedPlatformConfig.js diff --git a/packages/react-native/Libraries/Animated/Easing.d.ts b/packages/animated/Easing.d.ts similarity index 100% rename from packages/react-native/Libraries/Animated/Easing.d.ts rename to packages/animated/Easing.d.ts diff --git a/packages/react-native/Libraries/Animated/Easing.js b/packages/animated/Easing.js similarity index 100% rename from packages/react-native/Libraries/Animated/Easing.js rename to packages/animated/Easing.js diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedAllowlist.js b/packages/animated/NativeAnimatedAllowlist.js similarity index 96% rename from packages/react-native/Libraries/Animated/NativeAnimatedAllowlist.js rename to packages/animated/NativeAnimatedAllowlist.js index ac41c77621e1..359e9ee21924 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedAllowlist.js +++ b/packages/animated/NativeAnimatedAllowlist.js @@ -10,7 +10,7 @@ import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps'; -import * as ReactNativeFeatureFlags from '../../src/private/featureflags/ReactNativeFeatureFlags'; +import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags'; /** * Styles allowed by the native animated implementation. diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedModule.js b/packages/animated/NativeAnimatedModule.js similarity index 57% rename from packages/react-native/Libraries/Animated/NativeAnimatedModule.js rename to packages/animated/NativeAnimatedModule.js index 9b4c3233055b..96711ecd9984 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedModule.js +++ b/packages/animated/NativeAnimatedModule.js @@ -8,6 +8,6 @@ * @format */ -export * from '../../src/private/specs_DEPRECATED/modules/NativeAnimatedModule'; -import NativeAnimatedModule from '../../src/private/specs_DEPRECATED/modules/NativeAnimatedModule'; +export * from 'react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule'; +import NativeAnimatedModule from 'react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule'; export default NativeAnimatedModule; diff --git a/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js b/packages/animated/NativeAnimatedTurboModule.js similarity index 56% rename from packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js rename to packages/animated/NativeAnimatedTurboModule.js index 12c342d2cdf2..ef408e72598c 100644 --- a/packages/react-native/Libraries/Animated/NativeAnimatedTurboModule.js +++ b/packages/animated/NativeAnimatedTurboModule.js @@ -8,6 +8,6 @@ * @format */ -export * from '../../src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule'; -import NativeAnimatedTurboModule from '../../src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule'; +export * from 'react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule'; +import NativeAnimatedTurboModule from 'react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule'; export default NativeAnimatedTurboModule; diff --git a/packages/react-native/Libraries/Animated/SpringConfig.js b/packages/animated/SpringConfig.js similarity index 100% rename from packages/react-native/Libraries/Animated/SpringConfig.js rename to packages/animated/SpringConfig.js diff --git a/packages/react-native/Libraries/Animated/__tests__/Animated-test.js b/packages/animated/__tests__/Animated-test.js similarity index 98% rename from packages/react-native/Libraries/Animated/__tests__/Animated-test.js rename to packages/animated/__tests__/Animated-test.js index 02d425cbd137..2884995fbf48 100644 --- a/packages/react-native/Libraries/Animated/__tests__/Animated-test.js +++ b/packages/animated/__tests__/Animated-test.js @@ -10,10 +10,12 @@ import * as React from 'react'; -const {create, unmount, update} = require('../../../jest/renderer'); -const {PlatformColor} = require('../../StyleSheet/PlatformColorValueTypes'); let Animated = require('../Animated').default; const AnimatedProps = require('../nodes/AnimatedProps').default; +const {create, unmount, update} = require('react-native/jest/renderer'); +const { + PlatformColor, +} = require('react-native/Libraries/StyleSheet/PlatformColorValueTypes'); const TestRenderer = require('react-test-renderer'); // WORKAROUND: `jest.runAllTicks` skips tasks scheduled w/ `queueMicrotask`. @@ -36,7 +38,7 @@ describe('Animated', () => { beforeEach(() => { jest.resetModules(); - ReactNativeFeatureFlags = require('../../../src/private/featureflags/ReactNativeFeatureFlags'); + ReactNativeFeatureFlags = require('react-native/src/private/featureflags/ReactNativeFeatureFlags'); }); mockQueueMicrotask(); @@ -902,14 +904,14 @@ describe('Animated', () => { let InteractionManager; beforeEach(() => { - jest.mock('../../Interaction/InteractionManager'); + jest.mock('react-native/Libraries/Interaction/InteractionManager'); Animated = require('../Animated').default; InteractionManager = - require('../../Interaction/InteractionManager').default; + require('react-native/Libraries/Interaction/InteractionManager').default; }); afterEach(() => { - jest.unmock('../../Interaction/InteractionManager'); + jest.unmock('react-native/Libraries/Interaction/InteractionManager'); }); it('registers an interaction by default', () => { diff --git a/packages/react-native/Libraries/Animated/__tests__/Animated-web-test.js b/packages/animated/__tests__/Animated-web-test.js similarity index 96% rename from packages/react-native/Libraries/Animated/__tests__/Animated-web-test.js rename to packages/animated/__tests__/Animated-web-test.js index 15ebd06c3a62..ae5292be8701 100644 --- a/packages/react-native/Libraries/Animated/__tests__/Animated-web-test.js +++ b/packages/animated/__tests__/Animated-web-test.js @@ -8,11 +8,12 @@ * @oncall react_native */ -const StyleSheet = require('../../StyleSheet/StyleSheet').default; let Animated = require('../Animated').default; let AnimatedProps = require('../nodes/AnimatedProps').default; +const StyleSheet = + require('react-native/Libraries/StyleSheet/StyleSheet').default; -jest.mock('../../Utilities/Platform', () => ({ +jest.mock('react-native/Libraries/Utilities/Platform', () => ({ __esModule: true, default: { OS: 'web', diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedMock-test.js b/packages/animated/__tests__/AnimatedMock-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/AnimatedMock-test.js rename to packages/animated/__tests__/AnimatedMock-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedObject-test.js b/packages/animated/__tests__/AnimatedObject-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/AnimatedObject-test.js rename to packages/animated/__tests__/AnimatedObject-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedProps-test.js b/packages/animated/__tests__/AnimatedProps-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/AnimatedProps-test.js rename to packages/animated/__tests__/AnimatedProps-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedValue-test.js b/packages/animated/__tests__/AnimatedValue-test.js similarity index 98% rename from packages/react-native/Libraries/Animated/__tests__/AnimatedValue-test.js rename to packages/animated/__tests__/AnimatedValue-test.js index b78c893e2c1f..4480745c8c17 100644 --- a/packages/react-native/Libraries/Animated/__tests__/AnimatedValue-test.js +++ b/packages/animated/__tests__/AnimatedValue-test.js @@ -43,7 +43,7 @@ describe('AnimatedValue', () => { })); NativeAnimatedHelper = - require('../../../src/private/animated/NativeAnimatedHelper').default; + require('react-native/src/private/animated/NativeAnimatedHelper').default; AnimatedValue = require('../nodes/AnimatedValue').default; jest.spyOn(NativeAnimatedHelper.API, 'createAnimatedNode'); diff --git a/packages/react-native/Libraries/Animated/__tests__/Easing-test.js b/packages/animated/__tests__/Easing-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/Easing-test.js rename to packages/animated/__tests__/Easing-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js b/packages/animated/__tests__/Interpolation-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/Interpolation-test.js rename to packages/animated/__tests__/Interpolation-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/NativeAnimatedAllowlist-test.js b/packages/animated/__tests__/NativeAnimatedAllowlist-test.js similarity index 94% rename from packages/react-native/Libraries/Animated/__tests__/NativeAnimatedAllowlist-test.js rename to packages/animated/__tests__/NativeAnimatedAllowlist-test.js index 9bdfd3e7b9a4..cd7bafab3dfa 100644 --- a/packages/react-native/Libraries/Animated/__tests__/NativeAnimatedAllowlist-test.js +++ b/packages/animated/__tests__/NativeAnimatedAllowlist-test.js @@ -58,7 +58,7 @@ describe('NativeAnimatedAllowlist', () => { it('checks supported transform props', () => { jest .spyOn( - require('../../../src/private/featureflags/ReactNativeFeatureFlags'), + require('react-native/src/private/featureflags/ReactNativeFeatureFlags'), 'shouldUseAnimatedObjectForTransform', ) .mockReturnValue(false); @@ -73,7 +73,7 @@ describe('NativeAnimatedAllowlist', () => { it('checks supported transform props with object for transform', () => { jest .spyOn( - require('../../../src/private/featureflags/ReactNativeFeatureFlags'), + require('react-native/src/private/featureflags/ReactNativeFeatureFlags'), 'shouldUseAnimatedObjectForTransform', ) .mockReturnValue(true); diff --git a/packages/react-native/Libraries/Animated/__tests__/TimingAnimation-test.js b/packages/animated/__tests__/TimingAnimation-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/TimingAnimation-test.js rename to packages/animated/__tests__/TimingAnimation-test.js diff --git a/packages/react-native/Libraries/Animated/__tests__/bezier-test.js b/packages/animated/__tests__/bezier-test.js similarity index 100% rename from packages/react-native/Libraries/Animated/__tests__/bezier-test.js rename to packages/animated/__tests__/bezier-test.js diff --git a/packages/react-native/Libraries/Animated/animations/Animation.js b/packages/animated/animations/Animation.js similarity index 96% rename from packages/react-native/Libraries/Animated/animations/Animation.js rename to packages/animated/animations/Animation.js index 78242e911d22..186034547f5f 100644 --- a/packages/react-native/Libraries/Animated/animations/Animation.js +++ b/packages/animated/animations/Animation.js @@ -12,9 +12,9 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type AnimatedNode from '../nodes/AnimatedNode'; import type AnimatedValue from '../nodes/AnimatedValue'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags'; import AnimatedProps from '../nodes/AnimatedProps'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; +import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags'; export type EndResult = {finished: boolean, value?: number, ...}; export type EndCallback = (result: EndResult) => void; diff --git a/packages/react-native/Libraries/Animated/animations/DecayAnimation.js b/packages/animated/animations/DecayAnimation.js similarity index 100% rename from packages/react-native/Libraries/Animated/animations/DecayAnimation.js rename to packages/animated/animations/DecayAnimation.js diff --git a/packages/react-native/Libraries/Animated/animations/SpringAnimation.js b/packages/animated/animations/SpringAnimation.js similarity index 100% rename from packages/react-native/Libraries/Animated/animations/SpringAnimation.js rename to packages/animated/animations/SpringAnimation.js diff --git a/packages/react-native/Libraries/Animated/animations/TimingAnimation.js b/packages/animated/animations/TimingAnimation.js similarity index 100% rename from packages/react-native/Libraries/Animated/animations/TimingAnimation.js rename to packages/animated/animations/TimingAnimation.js diff --git a/packages/react-native/Libraries/Animated/bezier.js b/packages/animated/bezier.js similarity index 100% rename from packages/react-native/Libraries/Animated/bezier.js rename to packages/animated/bezier.js diff --git a/packages/react-native/Libraries/Animated/components/AnimatedFlatList.js b/packages/animated/components/AnimatedFlatList.js similarity index 92% rename from packages/react-native/Libraries/Animated/components/AnimatedFlatList.js rename to packages/animated/components/AnimatedFlatList.js index aabdf6a00e8c..560ecd3fc697 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedFlatList.js +++ b/packages/animated/components/AnimatedFlatList.js @@ -10,9 +10,9 @@ import type {AnimatedComponentType} from '../createAnimatedComponent'; -import FlatList from '../../Lists/FlatList'; import createAnimatedComponent from '../createAnimatedComponent'; import * as React from 'react'; +import {FlatList} from 'react-native'; export default (createAnimatedComponent(FlatList): AnimatedComponentType< React.ElementConfig, diff --git a/packages/react-native/Libraries/Animated/components/AnimatedImage.js b/packages/animated/components/AnimatedImage.js similarity index 93% rename from packages/react-native/Libraries/Animated/components/AnimatedImage.js rename to packages/animated/components/AnimatedImage.js index c178480fe73a..74cd47e1cac8 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedImage.js +++ b/packages/animated/components/AnimatedImage.js @@ -10,9 +10,9 @@ import type {AnimatedComponentType} from '../createAnimatedComponent'; -import Image from '../../Image/Image'; import createAnimatedComponent from '../createAnimatedComponent'; import * as React from 'react'; +import {Image} from 'react-native'; export default (createAnimatedComponent( (Image: $FlowFixMe), diff --git a/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js b/packages/animated/components/AnimatedScrollView.js similarity index 88% rename from packages/react-native/Libraries/Animated/components/AnimatedScrollView.js rename to packages/animated/components/AnimatedScrollView.js index c996ca7463d4..67b8fa2f7577 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedScrollView.js +++ b/packages/animated/components/AnimatedScrollView.js @@ -8,20 +8,20 @@ * @format */ -import type {____ViewStyle_Internal} from '../../StyleSheet/StyleSheetTypes'; import type {AnimatedComponentType} from '../createAnimatedComponent'; +import type {____ViewStyle_Internal} from 'react-native/Libraries/StyleSheet/StyleSheetTypes'; -import RefreshControl from '../../Components/RefreshControl/RefreshControl'; -import ScrollView from '../../Components/ScrollView/ScrollView'; -import flattenStyle from '../../StyleSheet/flattenStyle'; -import splitLayoutProps from '../../StyleSheet/splitLayoutProps'; -import StyleSheet from '../../StyleSheet/StyleSheet'; -import Platform from '../../Utilities/Platform'; -import useMergeRefs from '../../Utilities/useMergeRefs'; import createAnimatedComponent from '../createAnimatedComponent'; import useAnimatedProps from '../useAnimatedProps'; import * as React from 'react'; import {useMemo} from 'react'; +import RefreshControl from 'react-native/Libraries/Components/RefreshControl/RefreshControl'; +import ScrollView from 'react-native/Libraries/Components/ScrollView/ScrollView'; +import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle'; +import splitLayoutProps from 'react-native/Libraries/StyleSheet/splitLayoutProps'; +import StyleSheet from 'react-native/Libraries/StyleSheet/StyleSheet'; +import Platform from 'react-native/Libraries/Utilities/Platform'; +import useMergeRefs from 'react-native/Libraries/Utilities/useMergeRefs'; type AnimatedScrollViewProps = React.ElementConfig; type AnimatedScrollViewInstance = React.ElementRef; diff --git a/packages/react-native/Libraries/Animated/components/AnimatedSectionList.js b/packages/animated/components/AnimatedSectionList.js similarity index 83% rename from packages/react-native/Libraries/Animated/components/AnimatedSectionList.js rename to packages/animated/components/AnimatedSectionList.js index 52b98b8dd26f..04289cb51f63 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedSectionList.js +++ b/packages/animated/components/AnimatedSectionList.js @@ -8,12 +8,12 @@ * @format */ -import type {SectionBase} from '../../Lists/SectionList'; import type {AnimatedComponentType} from '../createAnimatedComponent'; +import type {SectionBase} from 'react-native/Libraries/Lists/SectionList'; -import SectionList from '../../Lists/SectionList'; import createAnimatedComponent from '../createAnimatedComponent'; import * as React from 'react'; +import {SectionList} from 'react-native'; export default (createAnimatedComponent(SectionList): AnimatedComponentType< React.ElementConfig, diff --git a/packages/react-native/Libraries/Animated/components/AnimatedText.js b/packages/animated/components/AnimatedText.js similarity index 93% rename from packages/react-native/Libraries/Animated/components/AnimatedText.js rename to packages/animated/components/AnimatedText.js index 02679f1a8013..99b56abc9d31 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedText.js +++ b/packages/animated/components/AnimatedText.js @@ -10,9 +10,9 @@ import type {AnimatedComponentType} from '../createAnimatedComponent'; -import Text from '../../Text/Text'; import createAnimatedComponent from '../createAnimatedComponent'; import * as React from 'react'; +import {Text} from 'react-native'; export default (createAnimatedComponent( (Text: $FlowFixMe), diff --git a/packages/react-native/Libraries/Animated/components/AnimatedView.js b/packages/animated/components/AnimatedView.js similarity index 92% rename from packages/react-native/Libraries/Animated/components/AnimatedView.js rename to packages/animated/components/AnimatedView.js index 5eca94417e67..9d686cca6a8c 100644 --- a/packages/react-native/Libraries/Animated/components/AnimatedView.js +++ b/packages/animated/components/AnimatedView.js @@ -10,9 +10,9 @@ import type {AnimatedComponentType} from '../createAnimatedComponent'; -import View from '../../Components/View/View'; import createAnimatedComponent from '../createAnimatedComponent'; import * as React from 'react'; +import {View} from 'react-native'; export default (createAnimatedComponent(View): AnimatedComponentType< React.ElementConfig, diff --git a/packages/animated/createAnimatedComponent.js b/packages/animated/createAnimatedComponent.js new file mode 100644 index 000000000000..efd284048df2 --- /dev/null +++ b/packages/animated/createAnimatedComponent.js @@ -0,0 +1,149 @@ +/** + * 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. + * + * @flow + * @format + */ + +import type AnimatedAddition from './nodes/AnimatedAddition'; +import type AnimatedDiffClamp from './nodes/AnimatedDiffClamp'; +import type AnimatedDivision from './nodes/AnimatedDivision'; +import type AnimatedInterpolation from './nodes/AnimatedInterpolation'; +import type AnimatedModulo from './nodes/AnimatedModulo'; +import type AnimatedMultiplication from './nodes/AnimatedMultiplication'; +import type AnimatedNode from './nodes/AnimatedNode'; +import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps'; +import type AnimatedSubtraction from './nodes/AnimatedSubtraction'; +import type AnimatedValue from './nodes/AnimatedValue'; + +import * as React from 'react'; +import {useMemo} from 'react'; +import {View} from 'react-native'; +import useMergeRefs from 'react-native/Libraries/Utilities/useMergeRefs'; +import createAnimatedPropsHook from 'react-native/src/private/animated/createAnimatedPropsHook'; +import composeStyles from 'react-native/src/private/styles/composeStyles'; + +type Nullable = void | null; +type Primitive = string | number | boolean | symbol | void; +type Builtin = (...$ReadOnlyArray) => mixed | Date | Error | RegExp; + +export type WithAnimatedValue<+T> = T extends Builtin | Nullable + ? T + : T extends Primitive + ? + | T + | AnimatedNode + | AnimatedAddition + | AnimatedSubtraction + | AnimatedDivision + | AnimatedMultiplication + | AnimatedModulo + | AnimatedDiffClamp + | AnimatedValue + | AnimatedInterpolation + | AnimatedInterpolation + | AnimatedInterpolation + : T extends $ReadOnlyArray + ? $ReadOnlyArray> + : T extends {...} + ? {+[K in keyof T]: WithAnimatedValue} + : T; + +type NonAnimatedProps = + | 'ref' + | 'innerViewRef' + | 'scrollViewRef' + | 'testID' + | 'disabled' + | 'accessibilityLabel'; +type PassThroughProps = $ReadOnly<{ + passthroughAnimatedPropExplicitValues?: React.ElementConfig< + typeof View, + > | null, +}>; + +export type AnimatedProps = { + [K in keyof Props]: K extends NonAnimatedProps + ? Props[K] + : WithAnimatedValue, +} & PassThroughProps; + +export type AnimatedBaseProps = { + [K in keyof Props]: K extends NonAnimatedProps + ? Props[K] + : WithAnimatedValue, +}; + +export type AnimatedComponentType = component( + ref?: React.RefSetter, + ...AnimatedProps +); + +export default function createAnimatedComponent< + TInstance: React.ComponentType, +>( + Component: TInstance, +): AnimatedComponentType< + $ReadOnly>, + React.ElementRef, +> { + return unstable_createAnimatedComponentWithAllowlist(Component, null); +} + +export function unstable_createAnimatedComponentWithAllowlist< + TProps: {...}, + TInstance: React.ComponentType, +>( + Component: TInstance, + allowlist: ?AnimatedPropsAllowlist, +): AnimatedComponentType> { + const useAnimatedProps = createAnimatedPropsHook(allowlist); + + const AnimatedComponent: AnimatedComponentType< + TProps, + React.ElementRef, + > = React.forwardRef, React.ElementRef>( + (props, forwardedRef) => { + const [reducedProps, callbackRef] = useAnimatedProps< + TProps, + React.ElementRef, + >(props); + const ref = useMergeRefs>( + callbackRef, + forwardedRef, + ); + + // Some components require explicit passthrough values for animation + // to work properly. For example, if an animated component is + // transformed and Pressable, onPress will not work after transform + // without these passthrough values. + // $FlowFixMe[prop-missing] + const {passthroughAnimatedPropExplicitValues, style} = reducedProps; + const passthroughStyle = passthroughAnimatedPropExplicitValues?.style; + const mergedStyle = useMemo( + () => composeStyles(style, passthroughStyle), + [passthroughStyle, style], + ); + + // NOTE: It is important that `passthroughAnimatedPropExplicitValues` is + // spread after `reducedProps` but before `style`. + return ( + + ); + }, + ); + + AnimatedComponent.displayName = `Animated(${ + Component.displayName || 'Anonymous' + })`; + + return AnimatedComponent; +} diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js b/packages/animated/nodes/AnimatedAddition.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedAddition.js rename to packages/animated/nodes/AnimatedAddition.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js b/packages/animated/nodes/AnimatedColor.js similarity index 94% rename from packages/react-native/Libraries/Animated/nodes/AnimatedColor.js rename to packages/animated/nodes/AnimatedColor.js index c1481cc21fdd..428391cbf182 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedColor.js +++ b/packages/animated/nodes/AnimatedColor.js @@ -10,17 +10,17 @@ 'use strict'; -import type {ProcessedColorValue} from '../../StyleSheet/processColor'; -import type {ColorValue} from '../../StyleSheet/StyleSheet'; -import type {NativeColorValue} from '../../StyleSheet/StyleSheetTypes'; import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type {AnimatedNodeConfig} from './AnimatedNode'; +import type {ProcessedColorValue} from 'react-native/Libraries/StyleSheet/processColor'; +import type {ColorValue} from 'react-native/Libraries/StyleSheet/StyleSheet'; +import type {NativeColorValue} from 'react-native/Libraries/StyleSheet/StyleSheetTypes'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import normalizeColor from '../../StyleSheet/normalizeColor'; -import {processColorObject} from '../../StyleSheet/PlatformColorValueTypes'; import AnimatedValue, {flushValue} from './AnimatedValue'; import AnimatedWithChildren from './AnimatedWithChildren'; +import normalizeColor from 'react-native/Libraries/StyleSheet/normalizeColor'; +import {processColorObject} from 'react-native/Libraries/StyleSheet/PlatformColorValueTypes'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; export type AnimatedColorConfig = $ReadOnly<{ ...AnimatedNodeConfig, diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js b/packages/animated/nodes/AnimatedDiffClamp.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedDiffClamp.js rename to packages/animated/nodes/AnimatedDiffClamp.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js b/packages/animated/nodes/AnimatedDivision.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedDivision.js rename to packages/animated/nodes/AnimatedDivision.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js b/packages/animated/nodes/AnimatedInterpolation.js similarity index 97% rename from packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js rename to packages/animated/nodes/AnimatedInterpolation.js index 908790bca5b6..ed846be95b2a 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedInterpolation.js +++ b/packages/animated/nodes/AnimatedInterpolation.js @@ -16,13 +16,13 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type AnimatedNode from './AnimatedNode'; import type {AnimatedNodeConfig} from './AnimatedNode'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import {validateInterpolation} from '../../../src/private/animated/NativeAnimatedValidation'; -import normalizeColor from '../../StyleSheet/normalizeColor'; -import processColor from '../../StyleSheet/processColor'; import Easing from '../Easing'; import AnimatedWithChildren from './AnimatedWithChildren'; import invariant from 'invariant'; +import normalizeColor from 'react-native/Libraries/StyleSheet/normalizeColor'; +import processColor from 'react-native/Libraries/StyleSheet/processColor'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; +import {validateInterpolation} from 'react-native/src/private/animated/NativeAnimatedValidation'; type ExtrapolateType = 'extend' | 'identity' | 'clamp'; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js b/packages/animated/nodes/AnimatedModulo.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedModulo.js rename to packages/animated/nodes/AnimatedModulo.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js b/packages/animated/nodes/AnimatedMultiplication.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedMultiplication.js rename to packages/animated/nodes/AnimatedMultiplication.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js b/packages/animated/nodes/AnimatedNode.js similarity index 98% rename from packages/react-native/Libraries/Animated/nodes/AnimatedNode.js rename to packages/animated/nodes/AnimatedNode.js index a851bf40eafb..1cf942e5bd63 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedNode.js +++ b/packages/animated/nodes/AnimatedNode.js @@ -10,8 +10,8 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; import invariant from 'invariant'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; type ValueListenerCallback = (state: {value: number, ...}) => mixed; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedObject.js b/packages/animated/nodes/AnimatedObject.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedObject.js rename to packages/animated/nodes/AnimatedObject.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js b/packages/animated/nodes/AnimatedProps.js similarity index 98% rename from packages/react-native/Libraries/Animated/nodes/AnimatedProps.js rename to packages/animated/nodes/AnimatedProps.js index 62058b26df54..8ee373e0897a 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js +++ b/packages/animated/nodes/AnimatedProps.js @@ -12,13 +12,13 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type {AnimatedNodeConfig} from './AnimatedNode'; import type {AnimatedStyleAllowlist} from './AnimatedStyle'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import {findNodeHandle} from '../../ReactNative/RendererProxy'; import {AnimatedEvent} from '../AnimatedEvent'; import AnimatedNode from './AnimatedNode'; import AnimatedObject from './AnimatedObject'; import AnimatedStyle from './AnimatedStyle'; import invariant from 'invariant'; +import {findNodeHandle} from 'react-native/Libraries/ReactNative/RendererProxy'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; export type AnimatedPropsAllowlist = $ReadOnly<{ style?: ?AnimatedStyleAllowlist, diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js b/packages/animated/nodes/AnimatedStyle.js similarity index 95% rename from packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js rename to packages/animated/nodes/AnimatedStyle.js index 89a2561ac447..040f3df6f0d6 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedStyle.js +++ b/packages/animated/nodes/AnimatedStyle.js @@ -11,14 +11,14 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type {AnimatedNodeConfig} from './AnimatedNode'; -import {validateStyles} from '../../../src/private/animated/NativeAnimatedValidation'; -import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags'; -import flattenStyle from '../../StyleSheet/flattenStyle'; -import Platform from '../../Utilities/Platform'; import AnimatedNode from './AnimatedNode'; import AnimatedObject from './AnimatedObject'; import AnimatedTransform from './AnimatedTransform'; import AnimatedWithChildren from './AnimatedWithChildren'; +import flattenStyle from 'react-native/Libraries/StyleSheet/flattenStyle'; +import Platform from 'react-native/Libraries/Utilities/Platform'; +import {validateStyles} from 'react-native/src/private/animated/NativeAnimatedValidation'; +import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags'; export type AnimatedStyleAllowlist = $ReadOnly<{[string]: true}>; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js b/packages/animated/nodes/AnimatedSubtraction.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedSubtraction.js rename to packages/animated/nodes/AnimatedSubtraction.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js b/packages/animated/nodes/AnimatedTracking.js similarity index 96% rename from packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js rename to packages/animated/nodes/AnimatedTracking.js index 8fabf2cc9fdc..01855f85844f 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedTracking.js +++ b/packages/animated/nodes/AnimatedTracking.js @@ -15,8 +15,8 @@ import type {EndCallback} from '../animations/Animation'; import type {AnimatedNodeConfig} from './AnimatedNode'; import type AnimatedValue from './AnimatedValue'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; import AnimatedNode from './AnimatedNode'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; export default class AnimatedTracking extends AnimatedNode { _value: AnimatedValue; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js b/packages/animated/nodes/AnimatedTransform.js similarity index 96% rename from packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js rename to packages/animated/nodes/AnimatedTransform.js index b0b79b1b0b62..0525747e6f8e 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedTransform.js +++ b/packages/animated/nodes/AnimatedTransform.js @@ -13,10 +13,10 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; import type {AnimatedNodeConfig} from './AnimatedNode'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import {validateTransform} from '../../../src/private/animated/NativeAnimatedValidation'; import AnimatedNode from './AnimatedNode'; import AnimatedWithChildren from './AnimatedWithChildren'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; +import {validateTransform} from 'react-native/src/private/animated/NativeAnimatedValidation'; type Transform = { [string]: diff --git a/packages/animated/nodes/AnimatedValue.js b/packages/animated/nodes/AnimatedValue.js new file mode 100644 index 000000000000..60bb4bbc8c7f --- /dev/null +++ b/packages/animated/nodes/AnimatedValue.js @@ -0,0 +1,375 @@ +/** + * 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. + * + * @flow + * @format + */ + +import type {PlatformConfig} from '../AnimatedPlatformConfig'; +import type Animation from '../animations/Animation'; +import type {EndCallback} from '../animations/Animation'; +import type {InterpolationConfigType} from './AnimatedInterpolation'; +import type AnimatedNode from './AnimatedNode'; +import type {AnimatedNodeConfig} from './AnimatedNode'; +import type AnimatedTracking from './AnimatedTracking'; +import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter'; + +import AnimatedInterpolation from './AnimatedInterpolation'; +import AnimatedWithChildren from './AnimatedWithChildren'; +import InteractionManager from 'react-native/Libraries/Interaction/InteractionManager'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; + +export type AnimatedValueConfig = $ReadOnly<{ + ...AnimatedNodeConfig, + useNativeDriver: boolean, +}>; + +const NativeAnimatedAPI = NativeAnimatedHelper.API; + +/** + * Animated works by building a directed acyclic graph of dependencies + * transparently when you render your Animated components. + * + * new Animated.Value(0) + * .interpolate() .interpolate() new Animated.Value(1) + * opacity translateY scale + * style transform + * View#234 style + * View#123 + * + * A) Top Down phase + * When an Animated.Value is updated, we recursively go down through this + * graph in order to find leaf nodes: the views that we flag as needing + * an update. + * + * B) Bottom Up phase + * When a view is flagged as needing an update, we recursively go back up + * in order to build the new value that it needs. The reason why we need + * this two-phases process is to deal with composite props such as + * transform which can receive values from multiple parents. + */ +export function flushValue(rootNode: AnimatedNode): void { + + const leaves = new Set<{update: () => void, ...}>(); + function findAnimatedStyles(node: AnimatedNode) { + // $FlowFixMe[prop-missing] + if (typeof node.update === 'function') { + leaves.add((node: any)); + } else { + node.__getChildren().forEach(findAnimatedStyles); + } + } + findAnimatedStyles(rootNode); + leaves.forEach(leaf => leaf.update()); +} + +/** + * Some operations are executed only on batch end, which is _mostly_ scheduled when + * Animated component props change. For some of the changes which require immediate execution + * (e.g. setValue), we create a separate batch in case none is scheduled. + */ +function _executeAsAnimatedBatch(id: string, operation: () => void) { + NativeAnimatedAPI.setWaitingForIdentifier(id); + operation(); + NativeAnimatedAPI.unsetWaitingForIdentifier(id); +} + +/** + * 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. + * + * See https://reactnative.dev/docs/animatedvalue + */ +export default class AnimatedValue extends AnimatedWithChildren { + #listenerCount: number; + #updateSubscription: ?EventSubscription; + + _value: number; + _startingValue: number; + _offset: number; + _animation: ?Animation; + _tracking: ?AnimatedTracking; + + constructor(value: number, config?: ?AnimatedValueConfig) { + super(config); + if (typeof value !== 'number') { + throw new Error('AnimatedValue: Attempting to set value to undefined'); + } + + this.#listenerCount = 0; + this.#updateSubscription = null; + + this._startingValue = this._value = value; + this._offset = 0; + this._animation = null; + if (config && config.useNativeDriver) { + this.__makeNative(); + } + } + + __detach() { + if (this.__isNative) { + NativeAnimatedAPI.getValue(this.__getNativeTag(), value => { + this._value = value - this._offset; + }); + } + this.stopAnimation(); + super.__detach(); + } + + __getValue(): number { + return this._value + this._offset; + } + + __makeNative(platformConfig: ?PlatformConfig): void { + super.__makeNative(platformConfig); + if (this.#listenerCount > 0) { + this.#ensureUpdateSubscriptionExists(); + } + } + + addListener(callback: (value: any) => mixed): string { + const id = super.addListener(callback); + this.#listenerCount++; + if (this.__isNative) { + this.#ensureUpdateSubscriptionExists(); + } + return id; + } + + removeListener(id: string): void { + super.removeListener(id); + this.#listenerCount--; + if (this.__isNative && this.#listenerCount === 0) { + this.#updateSubscription?.remove(); + } + } + + removeAllListeners(): void { + super.removeAllListeners(); + this.#listenerCount = 0; + if (this.__isNative) { + this.#updateSubscription?.remove(); + } + } + + #ensureUpdateSubscriptionExists(): void { + if (this.#updateSubscription != null) { + return; + } + const nativeTag = this.__getNativeTag(); + NativeAnimatedAPI.startListeningToAnimatedNodeValue(nativeTag); + const subscription: EventSubscription = + NativeAnimatedHelper.nativeEventEmitter.addListener( + 'onAnimatedValueUpdate', + data => { + if (data.tag === nativeTag) { + this.__onAnimatedValueUpdateReceived(data.value); + } + }, + ); + + this.#updateSubscription = { + remove: () => { + // Only this function assigns to `this.#updateSubscription`. + if (this.#updateSubscription == null) { + return; + } + this.#updateSubscription = null; + subscription.remove(); + NativeAnimatedAPI.stopListeningToAnimatedNodeValue(nativeTag); + }, + }; + } + + /** + * Directly set the value. This will stop any animations running on the value + * and update all the bound properties. + * + * See https://reactnative.dev/docs/animatedvalue#setvalue + */ + setValue(value: number): void { + if (this._animation) { + this._animation.stop(); + this._animation = null; + } + this._updateValue( + value, + !this.__isNative /* don't perform a flush for natively driven values */, + ); + if (this.__isNative) { + _executeAsAnimatedBatch(this.__getNativeTag().toString(), () => + NativeAnimatedAPI.setAnimatedNodeValue(this.__getNativeTag(), value), + ); + } + } + + /** + * 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. + * + * See https://reactnative.dev/docs/animatedvalue#setoffset + */ + setOffset(offset: number): void { + this._offset = offset; + if (this.__isNative) { + NativeAnimatedAPI.setAnimatedNodeOffset(this.__getNativeTag(), offset); + } + } + + /** + * Merges the offset value into the base value and resets the offset to zero. + * The final output of the value is unchanged. + * + * See https://reactnative.dev/docs/animatedvalue#flattenoffset + */ + flattenOffset(): void { + this._value += this._offset; + this._offset = 0; + if (this.__isNative) { + NativeAnimatedAPI.flattenAnimatedNodeOffset(this.__getNativeTag()); + } + } + + /** + * Sets the offset value to the base value, and resets the base value to zero. + * The final output of the value is unchanged. + * + * See https://reactnative.dev/docs/animatedvalue#extractoffset + */ + extractOffset(): void { + this._offset += this._value; + this._value = 0; + if (this.__isNative) { + NativeAnimatedAPI.extractAnimatedNodeOffset(this.__getNativeTag()); + } + } + + /** + * 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. + * + * See https://reactnative.dev/docs/animatedvalue#stopanimation + */ + stopAnimation(callback?: ?(value: number) => void): void { + this.stopTracking(); + this._animation && this._animation.stop(); + this._animation = null; + if (callback) { + if (this.__isNative) { + NativeAnimatedAPI.getValue(this.__getNativeTag(), callback); + } else { + callback(this.__getValue()); + } + } + } + + /** + * Stops any animation and resets the value to its original. + * + * See https://reactnative.dev/docs/animatedvalue#resetanimation + */ + resetAnimation(callback?: ?(value: number) => void): void { + this.stopAnimation(callback); + this._value = this._startingValue; + if (this.__isNative) { + NativeAnimatedAPI.setAnimatedNodeValue( + this.__getNativeTag(), + this._startingValue, + ); + } + } + + __onAnimatedValueUpdateReceived(value: number): void { + this._updateValue(value, false /*flush*/); + } + + /** + * Interpolates the value before updating the property, e.g. mapping 0-1 to + * 0-10. + */ + interpolate( + config: InterpolationConfigType, + ): AnimatedInterpolation { + return new AnimatedInterpolation(this, config); + } + + /** + * 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): void { + let handle = null; + if (animation.__isInteraction) { + handle = InteractionManager.createInteractionHandle(); + } + const previousAnimation = this._animation; + this._animation && this._animation.stop(); + this._animation = animation; + animation.start( + this._value, + value => { + // Natively driven animations will never call into that callback, therefore we can always + // pass flush = true to allow the updated value to propagate to native with setNativeProps + this._updateValue(value, true /* flush */); + }, + result => { + this._animation = null; + if (handle !== null) { + InteractionManager.clearInteractionHandle(handle); + } + callback && callback(result); + }, + previousAnimation, + this, + ); + } + + /** + * Typically only used internally. + */ + stopTracking(): void { + this._tracking && this._tracking.__detach(); + this._tracking = null; + } + + /** + * Typically only used internally. + */ + track(tracking: AnimatedTracking): void { + this.stopTracking(); + this._tracking = tracking; + // Make sure that the tracking animation starts executing + this._tracking && this._tracking.update(); + } + + _updateValue(value: number, flush: boolean): void { + if (value === undefined) { + throw new Error('AnimatedValue: Attempting to set value to undefined'); + } + + this._value = value; + if (flush) { + flushValue(this); + } + this.__callListeners(this.__getValue()); + } + + __getNativeConfig(): Object { + return { + type: 'value', + value: this._value, + offset: this._offset, + debugID: this.__getDebugID(), + }; + } +} diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js b/packages/animated/nodes/AnimatedValueXY.js similarity index 100% rename from packages/react-native/Libraries/Animated/nodes/AnimatedValueXY.js rename to packages/animated/nodes/AnimatedValueXY.js diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedWithChildren.js b/packages/animated/nodes/AnimatedWithChildren.js similarity index 96% rename from packages/react-native/Libraries/Animated/nodes/AnimatedWithChildren.js rename to packages/animated/nodes/AnimatedWithChildren.js index 9d4469e33c44..043ff67732de 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedWithChildren.js +++ b/packages/animated/nodes/AnimatedWithChildren.js @@ -12,8 +12,8 @@ import type {PlatformConfig} from '../AnimatedPlatformConfig'; -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; import AnimatedNode from './AnimatedNode'; +import NativeAnimatedHelper from 'react-native/src/private/animated/NativeAnimatedHelper'; const {connectAnimatedNodes, disconnectAnimatedNodes} = NativeAnimatedHelper.API; diff --git a/packages/animated/package.json b/packages/animated/package.json new file mode 100644 index 000000000000..5bfa9bccb110 --- /dev/null +++ b/packages/animated/package.json @@ -0,0 +1,16 @@ +{ + "name": "@react-native/animated", + "version": "0.80.0", + "description": "Fluid animations for React Native.", + "repository": { + "type": "git", + "url": "git@github.com:facebook/react-native.git", + "directory": "packages/animated" + }, + "license": "MIT", + "peerDependencies": { + "react-native": "*", + "react": "^19.0.0", + "react-test-renderer": "^19.0.0" + } + } \ No newline at end of file diff --git a/packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js b/packages/animated/shouldUseTurboAnimatedModule.js similarity index 85% rename from packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js rename to packages/animated/shouldUseTurboAnimatedModule.js index 0a780617e483..e6188ad47d8f 100644 --- a/packages/react-native/Libraries/Animated/shouldUseTurboAnimatedModule.js +++ b/packages/animated/shouldUseTurboAnimatedModule.js @@ -8,7 +8,7 @@ * @format */ -import Platform from '../Utilities/Platform'; +import Platform from 'react-native/Libraries/Utilities/Platform'; function shouldUseTurboAnimatedModule(): boolean { return Platform.OS === 'ios' && global.RN$Bridgeless === true; diff --git a/packages/react-native/Libraries/Animated/useAnimatedProps.js b/packages/animated/useAnimatedProps.js similarity index 62% rename from packages/react-native/Libraries/Animated/useAnimatedProps.js rename to packages/animated/useAnimatedProps.js index b167716f365a..ffeb062e9362 100644 --- a/packages/react-native/Libraries/Animated/useAnimatedProps.js +++ b/packages/animated/useAnimatedProps.js @@ -8,9 +8,9 @@ * @format */ -import type {AnimatedPropsHook} from '../../src/private/animated/createAnimatedPropsHook'; +import type {AnimatedPropsHook} from 'react-native/src/private/animated/createAnimatedPropsHook'; -import createAnimatedPropsHook from '../../src/private/animated/createAnimatedPropsHook'; +import createAnimatedPropsHook from 'react-native/src/private/animated/createAnimatedPropsHook'; /** * @deprecated diff --git a/packages/react-native/Libraries/Animated/useAnimatedValue.d.ts b/packages/animated/useAnimatedValue.d.ts similarity index 100% rename from packages/react-native/Libraries/Animated/useAnimatedValue.d.ts rename to packages/animated/useAnimatedValue.d.ts diff --git a/packages/react-native/Libraries/Animated/useAnimatedValue.js b/packages/animated/useAnimatedValue.js similarity index 100% rename from packages/react-native/Libraries/Animated/useAnimatedValue.js rename to packages/animated/useAnimatedValue.js diff --git a/packages/eslint-plugin-react-native/utils.js b/packages/eslint-plugin-react-native/utils.js index 241927c53b9b..c36a67e58859 100644 --- a/packages/eslint-plugin-react-native/utils.js +++ b/packages/eslint-plugin-react-native/utils.js @@ -54,7 +54,6 @@ const publicAPIMapping = { 'Libraries/Lists/VirtualizedSectionList': 'VirtualizedSectionList', 'Libraries/ActionSheetIOS/ActionSheetIOS': 'ActionSheetIOS', 'Libraries/Alert/Alert': 'Alert', - 'Libraries/Animated/Animated': 'Animated', 'Libraries/Utilities/Appearance': 'Appearance', 'Libraries/ReactNative/AppRegistry': 'AppRegistry', 'Libraries/AppState/AppState': 'AppState', @@ -64,7 +63,6 @@ const publicAPIMapping = { 'src/private/devsupport/devmenu/DevMenu': 'DevMenu', 'Libraries/Utilities/DevSettings': 'DevSettings', 'Libraries/Utilities/Dimensions': 'Dimensions', - 'Libraries/Animated/Easing': 'Easing', 'Libraries/ReactNative/I18nManager': 'I18nManager', 'Libraries/Interaction/InteractionManager': 'InteractionManager', 'Libraries/Components/Keyboard/Keyboard': 'Keyboard', @@ -86,7 +84,6 @@ const publicAPIMapping = { 'Libraries/Components/ToastAndroid/ToastAndroid': 'ToastAndroid', 'Libraries/TurboModule/TurboModuleRegistry': 'TurboModuleRegistry', 'Libraries/ReactNative/UIManager': 'UIManager', - 'Libraries/Animated/useAnimatedValue': 'useAnimatedValue', 'Libraries/Utilities/useColorScheme': 'useColorScheme', 'Libraries/Utilities/useWindowDimensions': 'useWindowDimensions', 'Libraries/UTFSequence': 'UTFSequence', diff --git a/packages/polyfills/console.js b/packages/polyfills/console.js index 4f0b9cad52e2..949b123e2bc7 100644 --- a/packages/polyfills/console.js +++ b/packages/polyfills/console.js @@ -11,7 +11,7 @@ 'use client'; -/* eslint-disable no-shadow, eqeqeq, curly, no-unused-vars, no-void, no-control-regex */ +/* eslint-disable no-shadow, eqeqeq, no-unused-vars, no-void, no-control-regex */ /** * This pipes all of our console logging functions to native logging so that diff --git a/packages/react-native/Libraries/Animated/AnimatedMock.js b/packages/react-native/Libraries/Animated/AnimatedMock.js index 5613f27358a9..319488b05fff 100644 --- a/packages/react-native/Libraries/Animated/AnimatedMock.js +++ b/packages/react-native/Libraries/Animated/AnimatedMock.js @@ -10,186 +10,8 @@ 'use strict'; -import type {Numeric as AnimatedNumeric} from './AnimatedImplementation'; -import type {EndResult} from './animations/Animation'; -import type {EndCallback} from './animations/Animation'; -import type {DecayAnimationConfig} from './animations/DecayAnimation'; -import type {SpringAnimationConfig} from './animations/SpringAnimation'; -import type {TimingAnimationConfig} from './animations/TimingAnimation'; +import AnimatedMock from '@react-native/animated/AnimatedMock'; -import {AnimatedEvent, attachNativeEvent} from './AnimatedEvent'; -import AnimatedImplementation from './AnimatedImplementation'; -import createAnimatedComponent from './createAnimatedComponent'; -import AnimatedColor from './nodes/AnimatedColor'; -import AnimatedInterpolation from './nodes/AnimatedInterpolation'; -import AnimatedNode from './nodes/AnimatedNode'; -import AnimatedValue from './nodes/AnimatedValue'; -import AnimatedValueXY from './nodes/AnimatedValueXY'; +export type * from '@react-native/animated/AnimatedMock'; -/** - * Animations are a source of flakiness in snapshot testing. This mock replaces - * animation functions from AnimatedImplementation with empty animations for - * predictability in tests. When possible the animation will run immediately - * to the final state. - */ - -// Prevent any callback invocation from recursively triggering another -// callback, which may trigger another animation -let inAnimationCallback = false; -function mockAnimationStart( - start: (callback?: ?EndCallback) => void, -): (callback?: ?EndCallback) => void { - return callback => { - const guardedCallback = - callback == null - ? callback - : (...args: Array) => { - if (inAnimationCallback) { - console.warn( - 'Ignoring recursive animation callback when running mock animations', - ); - return; - } - inAnimationCallback = true; - try { - callback(...args); - } finally { - inAnimationCallback = false; - } - }; - start(guardedCallback); - }; -} - -export type CompositeAnimation = { - start: (callback?: ?EndCallback) => void, - stop: () => void, - reset: () => void, - _startNativeLoop: (iterations?: number) => void, - _isUsingNativeDriver: () => boolean, - ... -}; - -const emptyAnimation = { - start: () => {}, - stop: () => {}, - reset: () => {}, - _startNativeLoop: () => {}, - _isUsingNativeDriver: () => { - return false; - }, -}; - -const mockCompositeAnimation = ( - animations: Array, -): CompositeAnimation => ({ - ...emptyAnimation, - start: mockAnimationStart((callback?: ?EndCallback): void => { - animations.forEach(animation => animation.start()); - callback?.({finished: true}); - }), -}); - -const spring = function ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: SpringAnimationConfig, -): CompositeAnimation { - const anyValue: any = value; - return { - ...emptyAnimation, - start: mockAnimationStart((callback?: ?EndCallback): void => { - anyValue.setValue(config.toValue); - callback?.({finished: true}); - }), - }; -}; - -const timing = function ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: TimingAnimationConfig, -): CompositeAnimation { - const anyValue: any = value; - return { - ...emptyAnimation, - start: mockAnimationStart((callback?: ?EndCallback): void => { - anyValue.setValue(config.toValue); - callback?.({finished: true}); - }), - }; -}; - -const decay = function ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: DecayAnimationConfig, -): CompositeAnimation { - return emptyAnimation; -}; - -const sequence = function ( - animations: Array, -): CompositeAnimation { - return mockCompositeAnimation(animations); -}; - -type ParallelConfig = {stopTogether?: boolean, ...}; -const parallel = function ( - animations: Array, - config?: ?ParallelConfig, -): CompositeAnimation { - return mockCompositeAnimation(animations); -}; - -const delay = function (time: number): CompositeAnimation { - return emptyAnimation; -}; - -const stagger = function ( - time: number, - animations: Array, -): CompositeAnimation { - return mockCompositeAnimation(animations); -}; - -type LoopAnimationConfig = { - iterations: number, - resetBeforeIteration?: boolean, - ... -}; - -const loop = function ( - animation: CompositeAnimation, - // $FlowFixMe[prop-missing] - {iterations = -1}: LoopAnimationConfig = {}, -): CompositeAnimation { - return emptyAnimation; -}; - -export type {AnimatedNumeric as Numeric}; - -export default { - Value: AnimatedValue, - ValueXY: AnimatedValueXY, - Color: AnimatedColor, - Interpolation: AnimatedInterpolation, - Node: AnimatedNode, - decay, - timing, - spring, - add: AnimatedImplementation.add, - subtract: AnimatedImplementation.subtract, - divide: AnimatedImplementation.divide, - multiply: AnimatedImplementation.multiply, - modulo: AnimatedImplementation.modulo, - diffClamp: AnimatedImplementation.diffClamp, - delay, - sequence, - parallel, - stagger, - loop, - event: AnimatedImplementation.event, - createAnimatedComponent, - attachNativeEvent, - forkEvent: AnimatedImplementation.forkEvent, - unforkEvent: AnimatedImplementation.unforkEvent, - Event: AnimatedEvent, -} as typeof AnimatedImplementation; +export default AnimatedMock; diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 183cee96e502..061c786d723e 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -8,142 +8,10 @@ * @format */ -import type AnimatedAddition from './nodes/AnimatedAddition'; -import type AnimatedDiffClamp from './nodes/AnimatedDiffClamp'; -import type AnimatedDivision from './nodes/AnimatedDivision'; -import type AnimatedInterpolation from './nodes/AnimatedInterpolation'; -import type AnimatedModulo from './nodes/AnimatedModulo'; -import type AnimatedMultiplication from './nodes/AnimatedMultiplication'; -import type AnimatedNode from './nodes/AnimatedNode'; -import type {AnimatedPropsAllowlist} from './nodes/AnimatedProps'; -import type AnimatedSubtraction from './nodes/AnimatedSubtraction'; -import type AnimatedValue from './nodes/AnimatedValue'; +'use strict'; -import createAnimatedPropsHook from '../../src/private/animated/createAnimatedPropsHook'; -import composeStyles from '../../src/private/styles/composeStyles'; -import View from '../Components/View/View'; -import useMergeRefs from '../Utilities/useMergeRefs'; -import * as React from 'react'; -import {useMemo} from 'react'; +import createAnimatedComponent from '@react-native/animated/createAnimatedComponent'; -type Nullable = void | null; -type Primitive = string | number | boolean | symbol | void; -type Builtin = (...$ReadOnlyArray) => mixed | Date | Error | RegExp; +export type * from '@react-native/animated/createAnimatedComponent'; -export type WithAnimatedValue<+T> = T extends Builtin | Nullable - ? T - : T extends Primitive - ? - | T - | AnimatedNode - | AnimatedAddition - | AnimatedSubtraction - | AnimatedDivision - | AnimatedMultiplication - | AnimatedModulo - | AnimatedDiffClamp - | AnimatedValue - | AnimatedInterpolation - | AnimatedInterpolation - | AnimatedInterpolation - : T extends $ReadOnlyArray - ? $ReadOnlyArray> - : T extends {...} - ? {+[K in keyof T]: WithAnimatedValue} - : T; - -type NonAnimatedProps = - | 'ref' - | 'innerViewRef' - | 'scrollViewRef' - | 'testID' - | 'disabled' - | 'accessibilityLabel'; -type PassThroughProps = $ReadOnly<{ - passthroughAnimatedPropExplicitValues?: React.ElementConfig< - typeof View, - > | null, -}>; - -export type AnimatedProps = { - [K in keyof Props]: K extends NonAnimatedProps - ? Props[K] - : WithAnimatedValue, -} & PassThroughProps; - -export type AnimatedBaseProps = { - [K in keyof Props]: K extends NonAnimatedProps - ? Props[K] - : WithAnimatedValue, -}; - -export type AnimatedComponentType = component( - ref?: React.RefSetter, - ...AnimatedProps -); - -export default function createAnimatedComponent< - TInstance: React.ComponentType, ->( - Component: TInstance, -): AnimatedComponentType< - $ReadOnly>, - React.ElementRef, -> { - return unstable_createAnimatedComponentWithAllowlist(Component, null); -} - -export function unstable_createAnimatedComponentWithAllowlist< - TProps: {...}, - TInstance: React.ComponentType, ->( - Component: TInstance, - allowlist: ?AnimatedPropsAllowlist, -): AnimatedComponentType> { - const useAnimatedProps = createAnimatedPropsHook(allowlist); - - const AnimatedComponent: AnimatedComponentType< - TProps, - React.ElementRef, - > = React.forwardRef, React.ElementRef>( - (props, forwardedRef) => { - const [reducedProps, callbackRef] = useAnimatedProps< - TProps, - React.ElementRef, - >(props); - const ref = useMergeRefs>( - callbackRef, - forwardedRef, - ); - - // Some components require explicit passthrough values for animation - // to work properly. For example, if an animated component is - // transformed and Pressable, onPress will not work after transform - // without these passthrough values. - // $FlowFixMe[prop-missing] - const {passthroughAnimatedPropExplicitValues, style} = reducedProps; - const passthroughStyle = passthroughAnimatedPropExplicitValues?.style; - const mergedStyle = useMemo( - () => composeStyles(style, passthroughStyle), - [passthroughStyle, style], - ); - - // NOTE: It is important that `passthroughAnimatedPropExplicitValues` is - // spread after `reducedProps` but before `style`. - return ( - - ); - }, - ); - - AnimatedComponent.displayName = `Animated(${ - Component.displayName || 'Anonymous' - })`; - - return AnimatedComponent; -} +export default createAnimatedComponent; diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js index 1727b9f463bc..93c391755db2 100644 --- a/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js +++ b/packages/react-native/Libraries/Animated/nodes/AnimatedValue.js @@ -4,372 +4,12 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow * @format + * @flow */ -import type {EventSubscription} from '../../vendor/emitter/EventEmitter'; -import type {PlatformConfig} from '../AnimatedPlatformConfig'; -import type Animation from '../animations/Animation'; -import type {EndCallback} from '../animations/Animation'; -import type {InterpolationConfigType} from './AnimatedInterpolation'; -import type AnimatedNode from './AnimatedNode'; -import type {AnimatedNodeConfig} from './AnimatedNode'; -import type AnimatedTracking from './AnimatedTracking'; - -import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper'; -import InteractionManager from '../../Interaction/InteractionManager'; -import AnimatedInterpolation from './AnimatedInterpolation'; -import AnimatedWithChildren from './AnimatedWithChildren'; - -export type AnimatedValueConfig = $ReadOnly<{ - ...AnimatedNodeConfig, - useNativeDriver: boolean, -}>; - -const NativeAnimatedAPI = NativeAnimatedHelper.API; - -/** - * Animated works by building a directed acyclic graph of dependencies - * transparently when you render your Animated components. - * - * new Animated.Value(0) - * .interpolate() .interpolate() new Animated.Value(1) - * opacity translateY scale - * style transform - * View#234 style - * View#123 - * - * A) Top Down phase - * When an Animated.Value is updated, we recursively go down through this - * graph in order to find leaf nodes: the views that we flag as needing - * an update. - * - * B) Bottom Up phase - * When a view is flagged as needing an update, we recursively go back up - * in order to build the new value that it needs. The reason why we need - * this two-phases process is to deal with composite props such as - * transform which can receive values from multiple parents. - */ -export function flushValue(rootNode: AnimatedNode): void { - // eslint-disable-next-line func-call-spacing - const leaves = new Set<{update: () => void, ...}>(); - function findAnimatedStyles(node: AnimatedNode) { - // $FlowFixMe[prop-missing] - if (typeof node.update === 'function') { - leaves.add((node: any)); - } else { - node.__getChildren().forEach(findAnimatedStyles); - } - } - findAnimatedStyles(rootNode); - leaves.forEach(leaf => leaf.update()); -} - -/** - * Some operations are executed only on batch end, which is _mostly_ scheduled when - * Animated component props change. For some of the changes which require immediate execution - * (e.g. setValue), we create a separate batch in case none is scheduled. - */ -function _executeAsAnimatedBatch(id: string, operation: () => void) { - NativeAnimatedAPI.setWaitingForIdentifier(id); - operation(); - NativeAnimatedAPI.unsetWaitingForIdentifier(id); -} - -/** - * 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. - * - * See https://reactnative.dev/docs/animatedvalue - */ -export default class AnimatedValue extends AnimatedWithChildren { - #listenerCount: number; - #updateSubscription: ?EventSubscription; - - _value: number; - _startingValue: number; - _offset: number; - _animation: ?Animation; - _tracking: ?AnimatedTracking; - - constructor(value: number, config?: ?AnimatedValueConfig) { - super(config); - if (typeof value !== 'number') { - throw new Error('AnimatedValue: Attempting to set value to undefined'); - } - - this.#listenerCount = 0; - this.#updateSubscription = null; - - this._startingValue = this._value = value; - this._offset = 0; - this._animation = null; - if (config && config.useNativeDriver) { - this.__makeNative(); - } - } - - __detach() { - if (this.__isNative) { - NativeAnimatedAPI.getValue(this.__getNativeTag(), value => { - this._value = value - this._offset; - }); - } - this.stopAnimation(); - super.__detach(); - } - - __getValue(): number { - return this._value + this._offset; - } - - __makeNative(platformConfig: ?PlatformConfig): void { - super.__makeNative(platformConfig); - if (this.#listenerCount > 0) { - this.#ensureUpdateSubscriptionExists(); - } - } - - addListener(callback: (value: any) => mixed): string { - const id = super.addListener(callback); - this.#listenerCount++; - if (this.__isNative) { - this.#ensureUpdateSubscriptionExists(); - } - return id; - } - - removeListener(id: string): void { - super.removeListener(id); - this.#listenerCount--; - if (this.__isNative && this.#listenerCount === 0) { - this.#updateSubscription?.remove(); - } - } - - removeAllListeners(): void { - super.removeAllListeners(); - this.#listenerCount = 0; - if (this.__isNative) { - this.#updateSubscription?.remove(); - } - } - - #ensureUpdateSubscriptionExists(): void { - if (this.#updateSubscription != null) { - return; - } - const nativeTag = this.__getNativeTag(); - NativeAnimatedAPI.startListeningToAnimatedNodeValue(nativeTag); - const subscription: EventSubscription = - NativeAnimatedHelper.nativeEventEmitter.addListener( - 'onAnimatedValueUpdate', - data => { - if (data.tag === nativeTag) { - this.__onAnimatedValueUpdateReceived(data.value); - } - }, - ); - - this.#updateSubscription = { - remove: () => { - // Only this function assigns to `this.#updateSubscription`. - if (this.#updateSubscription == null) { - return; - } - this.#updateSubscription = null; - subscription.remove(); - NativeAnimatedAPI.stopListeningToAnimatedNodeValue(nativeTag); - }, - }; - } - - /** - * Directly set the value. This will stop any animations running on the value - * and update all the bound properties. - * - * See https://reactnative.dev/docs/animatedvalue#setvalue - */ - setValue(value: number): void { - if (this._animation) { - this._animation.stop(); - this._animation = null; - } - this._updateValue( - value, - !this.__isNative /* don't perform a flush for natively driven values */, - ); - if (this.__isNative) { - _executeAsAnimatedBatch(this.__getNativeTag().toString(), () => - NativeAnimatedAPI.setAnimatedNodeValue(this.__getNativeTag(), value), - ); - } - } - - /** - * 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. - * - * See https://reactnative.dev/docs/animatedvalue#setoffset - */ - setOffset(offset: number): void { - this._offset = offset; - if (this.__isNative) { - NativeAnimatedAPI.setAnimatedNodeOffset(this.__getNativeTag(), offset); - } - } - - /** - * Merges the offset value into the base value and resets the offset to zero. - * The final output of the value is unchanged. - * - * See https://reactnative.dev/docs/animatedvalue#flattenoffset - */ - flattenOffset(): void { - this._value += this._offset; - this._offset = 0; - if (this.__isNative) { - NativeAnimatedAPI.flattenAnimatedNodeOffset(this.__getNativeTag()); - } - } - - /** - * Sets the offset value to the base value, and resets the base value to zero. - * The final output of the value is unchanged. - * - * See https://reactnative.dev/docs/animatedvalue#extractoffset - */ - extractOffset(): void { - this._offset += this._value; - this._value = 0; - if (this.__isNative) { - NativeAnimatedAPI.extractAnimatedNodeOffset(this.__getNativeTag()); - } - } - - /** - * 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. - * - * See https://reactnative.dev/docs/animatedvalue#stopanimation - */ - stopAnimation(callback?: ?(value: number) => void): void { - this.stopTracking(); - this._animation && this._animation.stop(); - this._animation = null; - if (callback) { - if (this.__isNative) { - NativeAnimatedAPI.getValue(this.__getNativeTag(), callback); - } else { - callback(this.__getValue()); - } - } - } - - /** - * Stops any animation and resets the value to its original. - * - * See https://reactnative.dev/docs/animatedvalue#resetanimation - */ - resetAnimation(callback?: ?(value: number) => void): void { - this.stopAnimation(callback); - this._value = this._startingValue; - if (this.__isNative) { - NativeAnimatedAPI.setAnimatedNodeValue( - this.__getNativeTag(), - this._startingValue, - ); - } - } - - __onAnimatedValueUpdateReceived(value: number): void { - this._updateValue(value, false /*flush*/); - } - - /** - * Interpolates the value before updating the property, e.g. mapping 0-1 to - * 0-10. - */ - interpolate( - config: InterpolationConfigType, - ): AnimatedInterpolation { - return new AnimatedInterpolation(this, config); - } - - /** - * 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): void { - let handle = null; - if (animation.__isInteraction) { - handle = InteractionManager.createInteractionHandle(); - } - const previousAnimation = this._animation; - this._animation && this._animation.stop(); - this._animation = animation; - animation.start( - this._value, - value => { - // Natively driven animations will never call into that callback, therefore we can always - // pass flush = true to allow the updated value to propagate to native with setNativeProps - this._updateValue(value, true /* flush */); - }, - result => { - this._animation = null; - if (handle !== null) { - InteractionManager.clearInteractionHandle(handle); - } - callback && callback(result); - }, - previousAnimation, - this, - ); - } - - /** - * Typically only used internally. - */ - stopTracking(): void { - this._tracking && this._tracking.__detach(); - this._tracking = null; - } - - /** - * Typically only used internally. - */ - track(tracking: AnimatedTracking): void { - this.stopTracking(); - this._tracking = tracking; - // Make sure that the tracking animation starts executing - this._tracking && this._tracking.update(); - } - - _updateValue(value: number, flush: boolean): void { - if (value === undefined) { - throw new Error('AnimatedValue: Attempting to set value to undefined'); - } +'use strict'; - this._value = value; - if (flush) { - flushValue(this); - } - this.__callListeners(this.__getValue()); - } +import AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; - __getNativeConfig(): Object { - return { - type: 'value', - value: this._value, - offset: this._offset, - debugID: this.__getDebugID(), - }; - } -} +export default AnimatedValue; diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js index c6226de285b8..222c3e8e0c76 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -31,7 +31,6 @@ import { VScrollContentViewNativeComponent, VScrollViewNativeComponent, } from '../../../src/private/components/scrollview/VScrollViewNativeComponents'; -import AnimatedImplementation from '../../Animated/AnimatedImplementation'; import FrameRateLogger from '../../Interaction/FrameRateLogger'; import {findNodeHandle} from '../../ReactNative/RendererProxy'; import UIManager from '../../ReactNative/UIManager'; @@ -48,6 +47,7 @@ import processDecelerationRate from './processDecelerationRate'; import Commands from './ScrollViewCommands'; import ScrollViewContext, {HORIZONTAL, VERTICAL} from './ScrollViewContext'; import ScrollViewStickyHeader from './ScrollViewStickyHeader'; +import AnimatedImplementation from '@react-native/animated/AnimatedImplementation'; import invariant from 'invariant'; import memoize from 'memoize-one'; import nullthrows from 'nullthrows'; diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js b/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js index 89d62dae3c04..fd7878bc8ee5 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js @@ -10,11 +10,11 @@ import type {LayoutChangeEvent} from '../../Types/CoreEventTypes'; -import Animated from '../../Animated/Animated'; import {isPublicInstance as isFabricPublicInstance} from '../../ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstanceUtils'; import StyleSheet from '../../StyleSheet/StyleSheet'; import Platform from '../../Utilities/Platform'; import useMergeRefs from '../../Utilities/useMergeRefs'; +import Animated from '@react-native/animated/Animated'; import * as React from 'react'; import {useCallback, useEffect, useMemo, useRef, useState} from 'react'; diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableBounce.js b/packages/react-native/Libraries/Components/Touchable/TouchableBounce.js index 776076101bf8..9064ea0b6c46 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableBounce.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableBounce.js @@ -11,12 +11,12 @@ import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; import typeof TouchableWithoutFeedback from './TouchableWithoutFeedback'; -import Animated from '../../Animated/Animated'; import Pressability, { type PressabilityConfig, } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; import Platform from '../../Utilities/Platform'; +import Animated from '@react-native/animated/Animated'; import * as React from 'react'; type TouchableBounceProps = $ReadOnly<{ diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js index c965c5ad02f2..3b1016e4d6c6 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js @@ -11,14 +11,14 @@ import type {ViewStyleProp} from '../../StyleSheet/StyleSheet'; import type {TouchableWithoutFeedbackProps} from './TouchableWithoutFeedback'; -import Animated from '../../Animated/Animated'; -import Easing from '../../Animated/Easing'; import Pressability, { type PressabilityConfig, } from '../../Pressability/Pressability'; import {PressabilityDebugView} from '../../Pressability/PressabilityDebug'; import flattenStyle from '../../StyleSheet/flattenStyle'; import Platform from '../../Utilities/Platform'; +import Animated from '@react-native/animated/Animated'; +import Easing from '@react-native/animated/Easing'; import * as React from 'react'; export type TVProps = $ReadOnly<{ diff --git a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js index 6831eb70304c..c7c8d7b91e95 100644 --- a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js +++ b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorSourceMapStatus.js @@ -10,12 +10,12 @@ import type {GestureResponderEvent} from '../../Types/CoreEventTypes'; -import Animated from '../../Animated/Animated'; -import Easing from '../../Animated/Easing'; import StyleSheet from '../../StyleSheet/StyleSheet'; import Text from '../../Text/Text'; import LogBoxButton from './LogBoxButton'; import * as LogBoxStyle from './LogBoxStyle'; +import Animated from '@react-native/animated/Animated'; +import Easing from '@react-native/animated/Easing'; import * as React from 'react'; type Props = $ReadOnly<{ diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts index a2b6d65e028b..ead619cf1158 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -7,7 +7,7 @@ * @format */ -import {Animated} from '../Animated/Animated'; +import {Animated} from '@react-native/animated/Animated'; import {ImageResizeMode} from '../Image/ImageResizeMode'; import {ColorValue} from './StyleSheet'; diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index c7f1dde4ac09..593d24dfee51 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -10,8 +10,6 @@ 'use strict'; -import type {WithAnimatedValue} from '../Animated/createAnimatedComponent'; -import type AnimatedNode from '../Animated/nodes/AnimatedNode'; import type {ImageResizeMode} from './../Image/ImageResizeMode'; import type { ____DangerouslyImpreciseStyle_InternalOverrides, @@ -21,6 +19,8 @@ import type { ____ViewStyle_InternalOverrides, } from './private/_StyleSheetTypesOverrides'; import type {____TransformStyle_Internal} from './private/_TransformStyle'; +import type {WithAnimatedValue} from '@react-native/animated/createAnimatedComponent'; +import type AnimatedNode from '@react-native/animated/nodes/AnimatedNode'; export type {____TransformStyle_Internal}; diff --git a/packages/react-native/Libraries/StyleSheet/flattenStyle.js b/packages/react-native/Libraries/StyleSheet/flattenStyle.js index 3353d039abfa..cb168f792c27 100644 --- a/packages/react-native/Libraries/StyleSheet/flattenStyle.js +++ b/packages/react-native/Libraries/StyleSheet/flattenStyle.js @@ -10,11 +10,11 @@ 'use strict'; -import type AnimatedNode from '../Animated/nodes/AnimatedNode'; import type { ____DangerouslyImpreciseAnimatedStyleProp_Internal, ____FlattenStyleProp_Internal, } from './StyleSheetTypes'; +import type AnimatedNode from '@react-native/animated/nodes/AnimatedNode'; type NonAnimatedNodeObject = TStyleProp extends AnimatedNode ? empty diff --git a/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js b/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js index 74aecb7decd0..ca3a882f6216 100644 --- a/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js +++ b/packages/react-native/Libraries/StyleSheet/private/_TransformStyle.js @@ -8,7 +8,7 @@ * @format */ -import type AnimatedNode from '../../Animated/nodes/AnimatedNode'; +import type AnimatedNode from '@react-native/animated/nodes/AnimatedNode'; export type ____TransformStyle_Internal = $ReadOnly<{ /** diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index d64601d15600..a293902b4c61 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -116,958 +116,20 @@ exports[`public API should not change unintentionally Libraries/Alert/RCTAlertMa " `; -exports[`public API should not change unintentionally Libraries/Animated/Animated.js 1`] = ` -"declare const Animated: AnimatedExports; -declare export default typeof Animated; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/Animated.js.flow 1`] = ` -"export * as default from \\"./AnimatedExports\\"; -export type { CompositeAnimation, Numeric } from \\"./AnimatedImplementation\\"; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/AnimatedEvent.js 1`] = ` -"export type Mapping = - | { [key: string]: Mapping, ... } - | AnimatedValue - | AnimatedValueXY; -export type EventConfig = { - listener?: ?(NativeSyntheticEvent) => mixed, - useNativeDriver: boolean, - platformConfig?: PlatformConfig, -}; -declare export function attachNativeEvent( - viewRef: any, - eventName: string, - argMapping: $ReadOnlyArray, - platformConfig: ?PlatformConfig -): { detach: () => void }; -declare export class AnimatedEvent { - constructor( - argMapping: $ReadOnlyArray, - config: EventConfig - ): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/AnimatedExports.js 1`] = ` -"declare const Animated: typeof AnimatedImplementation; -declare export default { - get FlatList(): AnimatedFlatList, - get Image(): AnimatedImage, - get ScrollView(): AnimatedScrollView, - get SectionList(): AnimatedSectionList, - get Text(): AnimatedText, - get View(): AnimatedView, - ...typeof Animated, -}; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/AnimatedExports.js.flow 1`] = ` -"export { default as FlatList } from \\"./components/AnimatedFlatList\\"; -export { default as Image } from \\"./components/AnimatedImage\\"; -export { default as ScrollView } from \\"./components/AnimatedScrollView\\"; -export { default as SectionList } from \\"./components/AnimatedSectionList\\"; -export { default as Text } from \\"./components/AnimatedText\\"; -export { default as View } from \\"./components/AnimatedView\\"; -export { default as Color } from \\"./nodes/AnimatedColor\\"; -export { AnimatedEvent as Event } from \\"./AnimatedEvent\\"; -export { default as Interpolation } from \\"./nodes/AnimatedInterpolation\\"; -export { default as Node } from \\"./nodes/AnimatedNode\\"; -export { default as Value } from \\"./nodes/AnimatedValue\\"; -export { default as ValueXY } from \\"./nodes/AnimatedValueXY\\"; -export type { default as AnimatedInterpolation } from \\"./nodes/AnimatedInterpolation\\"; -export type { default as AnimatedColor } from \\"./nodes/AnimatedColor\\"; -export type { AnimatedValueConfig as AnimatedConfig } from \\"./nodes/AnimatedValue\\"; -export type { default as AnimatedNode } from \\"./nodes/AnimatedNode\\"; -export type { default as AnimatedAddition } from \\"./nodes/AnimatedAddition\\"; -export type { default as AnimatedDiffClamp } from \\"./nodes/AnimatedDiffClamp\\"; -export type { default as AnimatedDivision } from \\"./nodes/AnimatedDivision\\"; -export type { default as AnimatedModulo } from \\"./nodes/AnimatedModulo\\"; -export type { default as AnimatedMultiplication } from \\"./nodes/AnimatedMultiplication\\"; -export type { default as AnimatedSubtraction } from \\"./nodes/AnimatedSubtraction\\"; -export type { WithAnimatedValue } from \\"./createAnimatedComponent\\"; -export type { AnimatedComponentType as AnimatedComponent } from \\"./createAnimatedComponent\\"; -declare export const add: typeof AnimatedImplementation.add; -declare export const attachNativeEvent: typeof AnimatedImplementation.attachNativeEvent; -declare export const createAnimatedComponent: typeof AnimatedImplementation.createAnimatedComponent; -declare export const decay: typeof AnimatedImplementation.decay; -declare export const delay: typeof AnimatedImplementation.delay; -declare export const diffClamp: typeof AnimatedImplementation.diffClamp; -declare export const divide: typeof AnimatedImplementation.divide; -declare export const event: typeof AnimatedImplementation.event; -declare export const forkEvent: typeof AnimatedImplementation.forkEvent; -declare export const loop: typeof AnimatedImplementation.loop; -declare export const modulo: typeof AnimatedImplementation.modulo; -declare export const multiply: typeof AnimatedImplementation.multiply; -declare export const parallel: typeof AnimatedImplementation.parallel; -declare export const sequence: typeof AnimatedImplementation.sequence; -declare export const spring: typeof AnimatedImplementation.spring; -declare export const stagger: typeof AnimatedImplementation.stagger; -declare export const subtract: typeof AnimatedImplementation.subtract; -declare export const timing: typeof AnimatedImplementation.timing; -declare export const unforkEvent: typeof AnimatedImplementation.unforkEvent; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/AnimatedImplementation.js 1`] = ` -"export type CompositeAnimation = { - start: (callback?: ?EndCallback, isLooping?: boolean) => void, - stop: () => void, - reset: () => void, - ... -}; -declare const add: ( - a: AnimatedNode | number, - b: AnimatedNode | number -) => AnimatedAddition; -declare const subtract: ( - a: AnimatedNode | number, - b: AnimatedNode | number -) => AnimatedSubtraction; -declare const divide: ( - a: AnimatedNode | number, - b: AnimatedNode | number -) => AnimatedDivision; -declare const multiply: ( - a: AnimatedNode | number, - b: AnimatedNode | number -) => AnimatedMultiplication; -declare const modulo: (a: AnimatedNode, modulus: number) => AnimatedModulo; -declare const diffClamp: ( - a: AnimatedNode, - min: number, - max: number -) => AnimatedDiffClamp; -declare const spring: ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: SpringAnimationConfig -) => CompositeAnimation; -declare const timing: ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: TimingAnimationConfig -) => CompositeAnimation; -declare const decay: ( - value: AnimatedValue | AnimatedValueXY | AnimatedColor, - config: DecayAnimationConfig -) => CompositeAnimation; -declare const sequence: ( - animations: Array -) => CompositeAnimation; -type ParallelConfig = { - stopTogether?: boolean, - ... -}; -declare const parallel: ( - animations: Array, - config?: ?ParallelConfig -) => CompositeAnimation; -declare const delay: (time: number) => CompositeAnimation; -declare const stagger: ( - time: number, - animations: Array -) => CompositeAnimation; -type LoopAnimationConfig = { - iterations: number, - resetBeforeIteration?: boolean, - ... -}; -declare const loop: ( - animation: CompositeAnimation, - $$PARAM_1$$?: LoopAnimationConfig -) => CompositeAnimation; -declare function forkEvent( - event: ?AnimatedEvent | ?Function, - listener: Function -): AnimatedEvent | Function; -declare function unforkEvent( - event: ?AnimatedEvent | ?Function, - listener: Function -): void; -declare const event: ( - argMapping: $ReadOnlyArray, - config: EventConfig -) => any; -type AnimatedNumeric = - | AnimatedAddition - | AnimatedDiffClamp - | AnimatedDivision - | AnimatedInterpolation - | AnimatedModulo - | AnimatedMultiplication - | AnimatedSubtraction - | AnimatedValue; -export type { AnimatedNumeric as Numeric }; -declare export default { - Value: typeof AnimatedValue, - ValueXY: typeof AnimatedValueXY, - Color: typeof AnimatedColor, - Interpolation: typeof AnimatedInterpolation, - Node: typeof AnimatedNode, - decay: typeof decay, - timing: typeof timing, - spring: typeof spring, - add: typeof add, - subtract: typeof subtract, - divide: typeof divide, - multiply: typeof multiply, - modulo: typeof modulo, - diffClamp: typeof diffClamp, - delay: typeof delay, - sequence: typeof sequence, - parallel: typeof parallel, - stagger: typeof stagger, - loop: typeof loop, - event: typeof event, - createAnimatedComponent: typeof createAnimatedComponent, - attachNativeEvent: typeof attachNativeEvent, - forkEvent: typeof forkEvent, - unforkEvent: typeof unforkEvent, - Event: typeof AnimatedEvent, -}; -" -`; - exports[`public API should not change unintentionally Libraries/Animated/AnimatedMock.js 1`] = ` -"export type CompositeAnimation = { - start: (callback?: ?EndCallback) => void, - stop: () => void, - reset: () => void, - ... -}; -export type { AnimatedNumeric as Numeric }; -declare export default typeof AnimatedImplementation; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/AnimatedPlatformConfig.js 1`] = ` -"export type PlatformConfig = {}; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/Easing.js 1`] = ` -"export type EasingFunction = (t: number) => number; -declare const EasingStatic: { - step0(n: number): number, - step1(n: number): number, - linear(t: number): number, - ease(t: number): number, - quad(t: number): number, - cubic(t: number): number, - poly(n: number): EasingFunction, - sin(t: number): number, - circle(t: number): number, - exp(t: number): number, - elastic(bounciness?: number): EasingFunction, - back(s?: number): EasingFunction, - bounce(t: number): number, - bezier(x1: number, y1: number, x2: number, y2: number): EasingFunction, - in(easing: EasingFunction): EasingFunction, - out(easing: EasingFunction): EasingFunction, - inOut(easing: EasingFunction): EasingFunction, -}; -export type Easing = typeof EasingStatic; -declare export default typeof EasingStatic; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/NativeAnimatedAllowlist.js 1`] = ` -"declare export default AnimatedPropsAllowlist; -declare export function allowInterpolationParam(param: string): void; -declare export function allowStyleProp(prop: string): void; -declare export function allowTransformProp(prop: string): void; -declare export function isSupportedColorStyleProp(prop: string): boolean; -declare export function isSupportedInterpolationParam(param: string): boolean; -declare export function isSupportedStyleProp(prop: string): boolean; -declare export function isSupportedTransformProp(prop: string): boolean; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/NativeAnimatedModule.js 1`] = ` -"export * from \\"../../src/private/specs_DEPRECATED/modules/NativeAnimatedModule\\"; -declare export default typeof NativeAnimatedModule; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/NativeAnimatedTurboModule.js 1`] = ` -"export * from \\"../../src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule\\"; -declare export default typeof NativeAnimatedTurboModule; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/SpringConfig.js 1`] = ` -"type SpringConfigType = { - stiffness: number, - damping: number, - ... -}; -declare export function fromOrigamiTensionAndFriction( - tension: number, - friction: number -): SpringConfigType; -declare export function fromBouncinessAndSpeed( - bounciness: number, - speed: number -): SpringConfigType; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/animations/Animation.js 1`] = ` -"export type EndResult = { finished: boolean, value?: number, ... }; -export type EndCallback = (result: EndResult) => void; -export type AnimationConfig = $ReadOnly<{ - isInteraction?: boolean, - useNativeDriver: boolean, - platformConfig?: PlatformConfig, - onComplete?: ?EndCallback, - iterations?: number, - isLooping?: boolean, - debugID?: ?string, - ... -}>; -declare export default class Animation { - constructor(config: AnimationConfig): void; - start( - fromValue: number, - onUpdate: (value: number) => void, - onEnd: ?EndCallback, - previousAnimation: ?Animation, - animatedValue: AnimatedValue - ): void; - stop(): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/animations/DecayAnimation.js 1`] = ` -"export type DecayAnimationConfig = $ReadOnly<{ - ...AnimationConfig, - velocity: - | number - | $ReadOnly<{ - x: number, - y: number, - ... - }>, - deceleration?: number, - ... -}>; -export type DecayAnimationConfigSingle = $ReadOnly<{ - ...AnimationConfig, - velocity: number, - deceleration?: number, - ... -}>; -declare export default class DecayAnimation extends Animation { - constructor(config: DecayAnimationConfigSingle): void; - start( - fromValue: number, - onUpdate: (value: number) => void, - onEnd: ?EndCallback, - previousAnimation: ?Animation, - animatedValue: AnimatedValue - ): void; - onUpdate(): void; - stop(): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/animations/SpringAnimation.js 1`] = ` -"export type SpringAnimationConfig = $ReadOnly<{ - ...AnimationConfig, - toValue: - | number - | AnimatedValue - | { - x: number, - y: number, - ... - } - | AnimatedValueXY - | { - r: number, - g: number, - b: number, - a: number, - ... - } - | AnimatedColor - | AnimatedInterpolation, - overshootClamping?: boolean, - restDisplacementThreshold?: number, - restSpeedThreshold?: number, - velocity?: - | number - | $ReadOnly<{ - x: number, - y: number, - ... - }>, - bounciness?: number, - speed?: number, - tension?: number, - friction?: number, - stiffness?: number, - damping?: number, - mass?: number, - delay?: number, - ... -}>; -export type SpringAnimationConfigSingle = $ReadOnly<{ - ...AnimationConfig, - toValue: number, - overshootClamping?: boolean, - restDisplacementThreshold?: number, - restSpeedThreshold?: number, - velocity?: number, - bounciness?: number, - speed?: number, - tension?: number, - friction?: number, - stiffness?: number, - damping?: number, - mass?: number, - delay?: number, - ... -}>; -declare opaque type SpringAnimationInternalState; -declare export default class SpringAnimation extends Animation { - constructor(config: SpringAnimationConfigSingle): void; - start( - fromValue: number, - onUpdate: (value: number) => void, - onEnd: ?EndCallback, - previousAnimation: ?Animation, - animatedValue: AnimatedValue - ): void; - getInternalState(): SpringAnimationInternalState; - onUpdate(): void; - stop(): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/animations/TimingAnimation.js 1`] = ` -"export type TimingAnimationConfig = $ReadOnly<{ - ...AnimationConfig, - toValue: - | number - | AnimatedValue - | $ReadOnly<{ - x: number, - y: number, - ... - }> - | AnimatedValueXY - | RgbaValue - | AnimatedColor - | AnimatedInterpolation, - easing?: (value: number) => number, - duration?: number, - delay?: number, - ... -}>; -export type TimingAnimationConfigSingle = $ReadOnly<{ - ...AnimationConfig, - toValue: number, - easing?: (value: number) => number, - duration?: number, - delay?: number, - ... -}>; -declare export default class TimingAnimation extends Animation { - constructor(config: TimingAnimationConfigSingle): void; - start( - fromValue: number, - onUpdate: (value: number) => void, - onEnd: ?EndCallback, - previousAnimation: ?Animation, - animatedValue: AnimatedValue - ): void; - onUpdate(): void; - stop(): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/bezier.js 1`] = ` -"declare export default function bezier( - mX1: number, - mY1: number, - mX2: number, - mY2: number -): (x: number) => number; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedFlatList.js 1`] = ` -"declare export default AnimatedComponentType< - React.ElementConfig, - FlatList, ->; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedImage.js 1`] = ` -"declare export default AnimatedComponentType< - React.ElementConfig, - React.ElementRef, ->; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedScrollView.js 1`] = ` -"type AnimatedScrollViewProps = React.ElementConfig; -type AnimatedScrollViewInstance = React.ElementRef; -declare const AnimatedScrollView: AnimatedComponentType< - AnimatedScrollViewProps, - AnimatedScrollViewInstance, ->; -declare export default typeof AnimatedScrollView; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedSectionList.js 1`] = ` -"declare export default AnimatedComponentType< - React.ElementConfig, - SectionList>, ->; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedText.js 1`] = ` -"declare export default AnimatedComponentType< - React.ElementConfig, - React.ElementRef, ->; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/components/AnimatedView.js 1`] = ` -"declare export default AnimatedComponentType< - React.ElementConfig, - React.ElementRef, ->; +"export type * from \\"@react-native/animated/AnimatedMock\\"; +declare export default typeof AnimatedMock; " `; exports[`public API should not change unintentionally Libraries/Animated/createAnimatedComponent.js 1`] = ` -"type Nullable = void | null; -type Primitive = string | number | boolean | symbol | void; -type Builtin = (...$ReadOnlyArray) => mixed | Date | Error | RegExp; -export type WithAnimatedValue<+T> = T extends Builtin | Nullable - ? T - : T extends Primitive - ? - | T - | AnimatedNode - | AnimatedAddition - | AnimatedSubtraction - | AnimatedDivision - | AnimatedMultiplication - | AnimatedModulo - | AnimatedDiffClamp - | AnimatedValue - | AnimatedInterpolation - | AnimatedInterpolation - | AnimatedInterpolation - : T extends $ReadOnlyArray - ? $ReadOnlyArray> - : T extends { ... } - ? { +[K in keyof T]: WithAnimatedValue } - : T; -type NonAnimatedProps = - | \\"ref\\" - | \\"innerViewRef\\" - | \\"scrollViewRef\\" - | \\"testID\\" - | \\"disabled\\" - | \\"accessibilityLabel\\"; -type PassThroughProps = $ReadOnly<{ - passthroughAnimatedPropExplicitValues?: React.ElementConfig< - typeof View, - > | null, -}>; -export type AnimatedProps = { - [K in keyof Props]: K extends NonAnimatedProps - ? Props[K] - : WithAnimatedValue, -} & PassThroughProps; -export type AnimatedBaseProps = { - [K in keyof Props]: K extends NonAnimatedProps - ? Props[K] - : WithAnimatedValue, -}; -export type AnimatedComponentType< - Props: { ... }, - +Instance = mixed, -> = component(ref?: React.RefSetter, ...AnimatedProps); -declare export default function createAnimatedComponent< - TInstance: React.ComponentType, ->( - Component: TInstance -): AnimatedComponentType< - $ReadOnly>, - React.ElementRef, ->; -declare export function unstable_createAnimatedComponentWithAllowlist< - TProps: { ... }, - TInstance: React.ComponentType, ->( - Component: TInstance, - allowlist: ?AnimatedPropsAllowlist -): AnimatedComponentType>; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedAddition.js 1`] = ` -"declare export default class AnimatedAddition extends AnimatedWithChildren { - constructor( - a: AnimatedNode | number, - b: AnimatedNode | number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedColor.js 1`] = ` -"export type AnimatedColorConfig = $ReadOnly<{ - ...AnimatedNodeConfig, - useNativeDriver: boolean, -}>; -type ColorListenerCallback = (value: ColorValue) => mixed; -export type RgbaValue = { - +r: number, - +g: number, - +b: number, - +a: number, - ... -}; -type RgbaAnimatedValue = { - +r: AnimatedValue, - +g: AnimatedValue, - +b: AnimatedValue, - +a: AnimatedValue, - ... -}; -export type InputValue = ?(RgbaValue | RgbaAnimatedValue | ColorValue); -declare export default class AnimatedColor extends AnimatedWithChildren { - r: AnimatedValue; - g: AnimatedValue; - b: AnimatedValue; - a: AnimatedValue; - nativeColor: ?NativeColorValue; - constructor(valueIn?: InputValue, config?: ?AnimatedColorConfig): void; - setValue(value: RgbaValue | ColorValue): void; - setOffset(offset: RgbaValue): void; - flattenOffset(): void; - extractOffset(): void; - stopAnimation(callback?: ColorListenerCallback): void; - resetAnimation(callback?: ColorListenerCallback): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedDiffClamp.js 1`] = ` -"declare export default class AnimatedDiffClamp extends AnimatedWithChildren { - constructor( - a: AnimatedNode, - min: number, - max: number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedDivision.js 1`] = ` -"declare export default class AnimatedDivision extends AnimatedWithChildren { - constructor( - a: AnimatedNode | number, - b: AnimatedNode | number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedInterpolation.js 1`] = ` -"type ExtrapolateType = \\"extend\\" | \\"identity\\" | \\"clamp\\"; -export type InterpolationConfigType = $ReadOnly<{ - ...AnimatedNodeConfig, - inputRange: $ReadOnlyArray, - outputRange: $ReadOnlyArray, - easing?: (input: number) => number, - extrapolate?: ExtrapolateType, - extrapolateLeft?: ExtrapolateType, - extrapolateRight?: ExtrapolateType, -}>; -declare export default class AnimatedInterpolation - extends AnimatedWithChildren -{ - constructor( - parent: AnimatedNode, - config: InterpolationConfigType - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedModulo.js 1`] = ` -"declare export default class AnimatedModulo extends AnimatedWithChildren { - constructor( - a: AnimatedNode, - modulus: number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedMultiplication.js 1`] = ` -"declare export default class AnimatedMultiplication - extends AnimatedWithChildren -{ - constructor( - a: AnimatedNode | number, - b: AnimatedNode | number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedNode.js 1`] = ` -"export type AnimatedNodeConfig = $ReadOnly<{ - debugID?: string, -}>; -declare export default class AnimatedNode { - constructor( - config?: ?$ReadOnly<{ - ...AnimatedNodeConfig, - ... - }> - ): void; - addListener(callback: (value: any) => mixed): string; - removeListener(id: string): void; - removeAllListeners(): void; - hasListeners(): boolean; - toJSON(): mixed; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedObject.js 1`] = ` -"declare export function isPlainObject( - value: mixed -): value is $ReadOnly<{ [string]: mixed }>; -declare export default class AnimatedObject extends AnimatedWithChildren { - static from(value: mixed): ?AnimatedObject; - constructor( - nodes: $ReadOnlyArray, - value: mixed, - config?: ?AnimatedNodeConfig - ): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedProps.js 1`] = ` -"export type AnimatedPropsAllowlist = $ReadOnly<{ - style?: ?AnimatedStyleAllowlist, - [string]: true, -}>; -type TargetViewInstance = React.ElementRef; -declare export default class AnimatedProps extends AnimatedNode { - constructor( - inputProps: { [string]: mixed }, - callback: () => void, - allowlist?: ?AnimatedPropsAllowlist, - config?: ?AnimatedNodeConfig - ): void; - update(): void; - setNativeView(instance: TargetViewInstance): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedStyle.js 1`] = ` -"export type AnimatedStyleAllowlist = $ReadOnly<{ [string]: true }>; -declare export default class AnimatedStyle extends AnimatedWithChildren { - static from( - inputStyle: any, - allowlist: ?AnimatedStyleAllowlist - ): ?AnimatedStyle; - constructor( - nodeKeys: $ReadOnlyArray, - nodes: $ReadOnlyArray, - style: { [string]: mixed }, - inputStyle: any, - config?: ?AnimatedNodeConfig - ): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedSubtraction.js 1`] = ` -"declare export default class AnimatedSubtraction extends AnimatedWithChildren { - constructor( - a: AnimatedNode | number, - b: AnimatedNode | number, - config?: ?AnimatedNodeConfig - ): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedTracking.js 1`] = ` -"declare export default class AnimatedTracking extends AnimatedNode { - constructor( - value: AnimatedValue, - parent: AnimatedNode, - animationClass: any, - animationConfig: Object, - callback?: ?EndCallback, - config?: ?AnimatedNodeConfig - ): void; - update(): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedTransform.js 1`] = ` -"type Transform = { - [string]: - | number - | string - | T - | $ReadOnlyArray - | { [string]: number | string | T }, -}; -declare export default class AnimatedTransform extends AnimatedWithChildren { - static from(transforms: $ReadOnlyArray>): ?AnimatedTransform; - constructor( - nodes: $ReadOnlyArray, - transforms: $ReadOnlyArray>, - config?: ?AnimatedNodeConfig - ): void; -} +"export type * from \\"@react-native/animated/createAnimatedComponent\\"; +declare export default typeof createAnimatedComponent; " `; exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedValue.js 1`] = ` -"export type AnimatedValueConfig = $ReadOnly<{ - ...AnimatedNodeConfig, - useNativeDriver: boolean, -}>; -declare export function flushValue(rootNode: AnimatedNode): void; -declare export default class AnimatedValue extends AnimatedWithChildren { - constructor(value: number, config?: ?AnimatedValueConfig): void; - addListener(callback: (value: any) => mixed): string; - removeListener(id: string): void; - removeAllListeners(): void; - setValue(value: number): void; - setOffset(offset: number): void; - flattenOffset(): void; - extractOffset(): void; - stopAnimation(callback?: ?(value: number) => void): void; - resetAnimation(callback?: ?(value: number) => void): void; - interpolate( - config: InterpolationConfigType - ): AnimatedInterpolation; - animate(animation: Animation, callback: ?EndCallback): void; - stopTracking(): void; - track(tracking: AnimatedTracking): void; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedValueXY.js 1`] = ` -"export type AnimatedValueXYConfig = $ReadOnly<{ - ...AnimatedNodeConfig, - useNativeDriver: boolean, -}>; -type ValueXYListenerCallback = (value: { x: number, y: number, ... }) => mixed; -declare export default class AnimatedValueXY extends AnimatedWithChildren { - x: AnimatedValue; - y: AnimatedValue; - constructor( - valueIn?: ?{ - +x: number | AnimatedValue, - +y: number | AnimatedValue, - ... - }, - config?: ?AnimatedValueXYConfig - ): void; - 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; - removeAllListeners(): void; - getLayout(): { [key: string]: AnimatedValue, ... }; - getTranslateTransform(): Array< - { translateX: AnimatedValue } | { translateY: AnimatedValue }, - >; -} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/nodes/AnimatedWithChildren.js 1`] = ` -"declare export default class AnimatedWithChildren extends AnimatedNode {} -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/shouldUseTurboAnimatedModule.js 1`] = ` -"declare function shouldUseTurboAnimatedModule(): boolean; -declare export default typeof shouldUseTurboAnimatedModule; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/useAnimatedProps.js 1`] = ` -"declare export default AnimatedPropsHook; -" -`; - -exports[`public API should not change unintentionally Libraries/Animated/useAnimatedValue.js 1`] = ` -"declare export default function useAnimatedValue( - initialValue: number, - config?: ?Animated.AnimatedConfig -): Animated.Value; +"declare export default typeof AnimatedValue; " `; @@ -9096,7 +8158,7 @@ export type { AlertOptions, } from \\"./Libraries/Alert/Alert\\"; export { default as Alert } from \\"./Libraries/Alert/Alert\\"; -export { default as Animated } from \\"./Libraries/Animated/Animated\\"; +export { default as Animated } from \\"@react-native/animated/Animated\\"; export * as Appearance from \\"./Libraries/Utilities/Appearance\\"; export type { TaskProvider, @@ -9134,8 +8196,8 @@ export type { export { default as Dimensions } from \\"./Libraries/Utilities/Dimensions\\"; export type { DynamicColorIOSTuple } from \\"./Libraries/StyleSheet/PlatformColorValueTypesIOS\\"; export { DynamicColorIOS } from \\"./Libraries/StyleSheet/PlatformColorValueTypesIOS\\"; -export type { EasingFunction } from \\"./Libraries/Animated/Easing\\"; -export { default as Easing } from \\"./Libraries/Animated/Easing\\"; +export type { EasingFunction } from \\"@react-native/animated/Easing\\"; +export { default as Easing } from \\"@react-native/animated/Easing\\"; export { findNodeHandle } from \\"./Libraries/ReactNative/RendererProxy\\"; export { default as I18nManager } from \\"./Libraries/ReactNative/I18nManager\\"; export type { @@ -9243,7 +8305,7 @@ export { default as ToastAndroid } from \\"./Libraries/Components/ToastAndroid/T export * as TurboModuleRegistry from \\"./Libraries/TurboModule/TurboModuleRegistry\\"; export { default as UIManager } from \\"./Libraries/ReactNative/UIManager\\"; export { unstable_batchedUpdates } from \\"./Libraries/ReactNative/RendererProxy\\"; -export { default as useAnimatedValue } from \\"./Libraries/Animated/useAnimatedValue\\"; +export { default as useAnimatedValue } from \\"@react-native/animated/useAnimatedValue\\"; export { default as useColorScheme } from \\"./Libraries/Utilities/useColorScheme\\"; export { default as useWindowDimensions } from \\"./Libraries/Utilities/useWindowDimensions\\"; export { default as UTFSequence } from \\"./Libraries/UTFSequence\\"; diff --git a/packages/react-native/index.js b/packages/react-native/index.js index 1668f74754e6..cce03abf158b 100644 --- a/packages/react-native/index.js +++ b/packages/react-native/index.js @@ -147,7 +147,7 @@ module.exports = { // Include any types exported in the Animated module together with its default export, so // you can references types such as Animated.Numeric get Animated() { - return require('./Libraries/Animated/Animated').default; + return require('@react-native/animated/Animated').default; }, get Appearance() { return require('./Libraries/Utilities/Appearance'); @@ -196,7 +196,7 @@ module.exports = { .DynamicColorIOS; }, get Easing() { - return require('./Libraries/Animated/Easing').default; + return require('@react-native/animated/Easing').default; }, get findNodeHandle() { return require('./Libraries/ReactNative/RendererProxy').findNodeHandle; @@ -302,7 +302,7 @@ module.exports = { .unstable_batchedUpdates; }, get useAnimatedValue() { - return require('./Libraries/Animated/useAnimatedValue').default; + return require('@react-native/animated/useAnimatedValue').default; }, get useColorScheme() { return require('./Libraries/Utilities/useColorScheme').default; diff --git a/packages/react-native/index.js.flow b/packages/react-native/index.js.flow index b719e1d92221..a60983e2fb12 100644 --- a/packages/react-native/index.js.flow +++ b/packages/react-native/index.js.flow @@ -212,7 +212,7 @@ export type { } from './Libraries/Alert/Alert'; export {default as Alert} from './Libraries/Alert/Alert'; -export {default as Animated} from './Libraries/Animated/Animated'; +export {default as Animated} from '@react-native/animated/Animated'; export * as Appearance from './Libraries/Utilities/Appearance'; @@ -262,8 +262,8 @@ export {default as Dimensions} from './Libraries/Utilities/Dimensions'; export type {DynamicColorIOSTuple} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; export {DynamicColorIOS} from './Libraries/StyleSheet/PlatformColorValueTypesIOS'; -export type {EasingFunction} from './Libraries/Animated/Easing'; -export {default as Easing} from './Libraries/Animated/Easing'; +export type {EasingFunction} from '@react-native/animated/Easing'; +export {default as Easing} from '@react-native/animated/Easing'; export {findNodeHandle} from './Libraries/ReactNative/RendererProxy'; @@ -395,7 +395,7 @@ export {default as ToastAndroid} from './Libraries/Components/ToastAndroid/Toast export * as TurboModuleRegistry from './Libraries/TurboModule/TurboModuleRegistry'; export {default as UIManager} from './Libraries/ReactNative/UIManager'; export {unstable_batchedUpdates} from './Libraries/ReactNative/RendererProxy'; -export {default as useAnimatedValue} from './Libraries/Animated/useAnimatedValue'; +export {default as useAnimatedValue} from '@react-native/animated/useAnimatedValue'; export {default as useColorScheme} from './Libraries/Utilities/useColorScheme'; export {default as useWindowDimensions} from './Libraries/Utilities/useWindowDimensions'; export {default as UTFSequence} from './Libraries/UTFSequence'; diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 6955cfac4850..e3963bb4745f 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -126,6 +126,7 @@ "@react-native/js-polyfills": "0.80.0-main", "@react-native/normalize-colors": "0.80.0-main", "@react-native/virtualized-lists": "0.80.0-main", + "@react-native/animated": "*", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", diff --git a/packages/react-native/src/private/animated/NativeAnimatedHelper.js b/packages/react-native/src/private/animated/NativeAnimatedHelper.js index 24e4be916bc5..78aa0da4a125 100644 --- a/packages/react-native/src/private/animated/NativeAnimatedHelper.js +++ b/packages/react-native/src/private/animated/NativeAnimatedHelper.js @@ -8,23 +8,23 @@ * @format */ -import type {EventConfig} from '../../../Libraries/Animated/AnimatedEvent'; +import type {EventSubscription} from '../../../Libraries/vendor/emitter/EventEmitter'; +import type {EventConfig} from '@react-native/animated/AnimatedEvent'; import type { AnimationConfig, EndCallback, -} from '../../../Libraries/Animated/animations/Animation'; +} from '@react-native/animated/animations/Animation'; import type { AnimatedNodeConfig, EventMapping, -} from '../../../Libraries/Animated/NativeAnimatedModule'; -import type {EventSubscription} from '../../../Libraries/vendor/emitter/EventEmitter'; +} from '@react-native/animated/NativeAnimatedModule'; -import NativeAnimatedNonTurboModule from '../../../Libraries/Animated/NativeAnimatedModule'; -import NativeAnimatedTurboModule from '../../../Libraries/Animated/NativeAnimatedTurboModule'; import NativeEventEmitter from '../../../Libraries/EventEmitter/NativeEventEmitter'; import RCTDeviceEventEmitter from '../../../Libraries/EventEmitter/RCTDeviceEventEmitter'; import Platform from '../../../Libraries/Utilities/Platform'; import * as ReactNativeFeatureFlags from '../featureflags/ReactNativeFeatureFlags'; +import NativeAnimatedNonTurboModule from '@react-native/animated/NativeAnimatedModule'; +import NativeAnimatedTurboModule from '@react-native/animated/NativeAnimatedTurboModule'; import invariant from 'invariant'; import nullthrows from 'nullthrows'; diff --git a/packages/react-native/src/private/animated/NativeAnimatedValidation.js b/packages/react-native/src/private/animated/NativeAnimatedValidation.js index 7bff92a42ed4..0d87428e0191 100644 --- a/packages/react-native/src/private/animated/NativeAnimatedValidation.js +++ b/packages/react-native/src/private/animated/NativeAnimatedValidation.js @@ -8,13 +8,13 @@ * @format */ -import type {InterpolationConfigType} from '../../../Libraries/Animated/nodes/AnimatedInterpolation'; +import type {InterpolationConfigType} from '@react-native/animated/nodes/AnimatedInterpolation'; import { isSupportedInterpolationParam, isSupportedStyleProp, isSupportedTransformProp, -} from '../../../Libraries/Animated/NativeAnimatedAllowlist'; +} from '@react-native/animated/NativeAnimatedAllowlist'; export function validateInterpolation( config: InterpolationConfigType, diff --git a/packages/react-native/src/private/animated/__tests__/AnimatedNative-test.js b/packages/react-native/src/private/animated/__tests__/AnimatedNative-test.js index 442c4a8fca5c..fa0de3b63d17 100644 --- a/packages/react-native/src/private/animated/__tests__/AnimatedNative-test.js +++ b/packages/react-native/src/private/animated/__tests__/AnimatedNative-test.js @@ -18,7 +18,7 @@ describe('Native Animated', () => { function importModules() { return { get Animated() { - return require('../../../../Libraries/Animated/Animated').default; + return require('@react-native/animated/Animated').default; }, get NativeAnimatedHelper() { return require('../NativeAnimatedHelper').default; diff --git a/packages/react-native/src/private/animated/__tests__/createAnimatedPropsHook-test.js b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsHook-test.js index 2b6f4e711770..307b493169e8 100644 --- a/packages/react-native/src/private/animated/__tests__/createAnimatedPropsHook-test.js +++ b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsHook-test.js @@ -24,8 +24,7 @@ describe('useAnimatedProps', () => { return { // $FlowIgnore[unsafe-getters-setters] get AnimatedEvent() { - return require('../../../../Libraries/Animated/AnimatedEvent') - .AnimatedEvent; + return require('@react-native/animated/AnimatedEvent').AnimatedEvent; }, // $FlowIgnore[unsafe-getters-setters] get createAnimatedPropsHook() { diff --git a/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js index 51f71851e176..b86b43745b79 100644 --- a/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js +++ b/packages/react-native/src/private/animated/__tests__/createAnimatedPropsMemoHook-test.js @@ -9,12 +9,12 @@ * @oncall react_native */ -import {AnimatedEvent} from '../../../../Libraries/Animated/AnimatedEvent'; -import AnimatedValue from '../../../../Libraries/Animated/nodes/AnimatedValue'; import { areCompositeKeysEqual, createCompositeKeyForProps, } from '../createAnimatedPropsMemoHook'; +import {AnimatedEvent} from '@react-native/animated/AnimatedEvent'; +import AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; describe('createCompositeKeyForProps', () => { describe('with allowlist', () => { diff --git a/packages/react-native/src/private/animated/createAnimatedPropsHook.js b/packages/react-native/src/private/animated/createAnimatedPropsHook.js index 3bad752daf57..438dab50aa18 100644 --- a/packages/react-native/src/private/animated/createAnimatedPropsHook.js +++ b/packages/react-native/src/private/animated/createAnimatedPropsHook.js @@ -8,17 +8,17 @@ * @format */ -import type {AnimatedPropsAllowlist} from '../../../Libraries/Animated/nodes/AnimatedProps'; import type {EventSubscription} from '../../../Libraries/EventEmitter/NativeEventEmitter'; +import type {AnimatedPropsAllowlist} from '@react-native/animated/nodes/AnimatedProps'; -import AnimatedNode from '../../../Libraries/Animated/nodes/AnimatedNode'; -import AnimatedProps from '../../../Libraries/Animated/nodes/AnimatedProps'; -import AnimatedValue from '../../../Libraries/Animated/nodes/AnimatedValue'; import {isPublicInstance as isFabricPublicInstance} from '../../../Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstanceUtils'; import useRefEffect from '../../../Libraries/Utilities/useRefEffect'; import * as ReactNativeFeatureFlags from '../featureflags/ReactNativeFeatureFlags'; import {createAnimatedPropsMemoHook} from './createAnimatedPropsMemoHook'; import NativeAnimatedHelper from './NativeAnimatedHelper'; +import AnimatedNode from '@react-native/animated/nodes/AnimatedNode'; +import AnimatedProps from '@react-native/animated/nodes/AnimatedProps'; +import AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; import { useCallback, useEffect, diff --git a/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js b/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js index 4887e712d3f1..40bd0be4ab57 100644 --- a/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js +++ b/packages/react-native/src/private/animated/createAnimatedPropsMemoHook.js @@ -9,15 +9,15 @@ * @oncall react_native */ -import type AnimatedProps from '../../../Libraries/Animated/nodes/AnimatedProps'; -import type {AnimatedPropsAllowlist} from '../../../Libraries/Animated/nodes/AnimatedProps'; -import type {AnimatedStyleAllowlist} from '../../../Libraries/Animated/nodes/AnimatedStyle'; +import type AnimatedProps from '@react-native/animated/nodes/AnimatedProps'; +import type {AnimatedPropsAllowlist} from '@react-native/animated/nodes/AnimatedProps'; +import type {AnimatedStyleAllowlist} from '@react-native/animated/nodes/AnimatedStyle'; -import {AnimatedEvent} from '../../../Libraries/Animated/AnimatedEvent'; -import AnimatedNode from '../../../Libraries/Animated/nodes/AnimatedNode'; -import {isPlainObject} from '../../../Libraries/Animated/nodes/AnimatedObject'; import flattenStyle from '../../../Libraries/StyleSheet/flattenStyle'; import * as ReactNativeFeatureFlags from '../featureflags/ReactNativeFeatureFlags'; +import {AnimatedEvent} from '@react-native/animated/AnimatedEvent'; +import AnimatedNode from '@react-native/animated/nodes/AnimatedNode'; +import {isPlainObject} from '@react-native/animated/nodes/AnimatedObject'; import nullthrows from 'nullthrows'; import {useInsertionEffect, useMemo, useRef, useState} from 'react'; diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js index b7746551e61f..6b47d29ac2ee 100644 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js +++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js @@ -10,8 +10,8 @@ import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; -import shouldUseTurboAnimatedModule from '../../../../Libraries/Animated/shouldUseTurboAnimatedModule'; import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; +import shouldUseTurboAnimatedModule from '@react-native/animated/shouldUseTurboAnimatedModule'; type EndResult = {finished: boolean, value?: number, ...}; type EndCallback = (result: EndResult) => void; diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js index 7f584685eb17..60e4d316653c 100644 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js +++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js @@ -10,8 +10,8 @@ import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; -import shouldUseTurboAnimatedModule from '../../../../Libraries/Animated/shouldUseTurboAnimatedModule'; import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; +import shouldUseTurboAnimatedModule from '@react-native/animated/shouldUseTurboAnimatedModule'; type EndResult = {finished: boolean, value?: number, ...}; type EndCallback = (result: EndResult) => void; diff --git a/packages/react-native/src/types/bom.js.flow b/packages/react-native/src/types/bom.js.flow index dac3ad0df6de..3fed47d64255 100644 --- a/packages/react-native/src/types/bom.js.flow +++ b/packages/react-native/src/types/bom.js.flow @@ -109,13 +109,13 @@ declare class WebSocket extends EventTarget { bufferedAmount: number; close(code?: number, reason?: string): void; static CLOSED: 3; - // eslint-disable-next-line ft-flow/no-dupe-keys + CLOSED: 3; static CLOSING: 2; - // eslint-disable-next-line ft-flow/no-dupe-keys + CLOSING: 2; static CONNECTING: 0; - // eslint-disable-next-line ft-flow/no-dupe-keys + CONNECTING: 0; constructor(url: string, protocols?: string | Array): void; extensions: string; @@ -124,7 +124,7 @@ declare class WebSocket extends EventTarget { onmessage: (ev: MessageEvent) => mixed; onopen: (ev: $FlowFixMe) => mixed; static OPEN: 1; - // eslint-disable-next-line ft-flow/no-dupe-keys + OPEN: 1; protocol: string; readyState: number; @@ -138,15 +138,15 @@ declare class WebSocket extends EventTarget { declare class XMLHttpRequest extends EventTarget { abort(): void; static DONE: number; - // eslint-disable-next-line ft-flow/no-dupe-keys + DONE: number; getAllResponseHeaders(): string; getResponseHeader(header: string): string; static HEADERS_RECEIVED: number; - // eslint-disable-next-line ft-flow/no-dupe-keys + HEADERS_RECEIVED: number; static LOADING: number; - // eslint-disable-next-line ft-flow/no-dupe-keys + LOADING: number; msCaching: string; msCachingEnabled(): boolean; @@ -166,7 +166,7 @@ declare class XMLHttpRequest extends EventTarget { password?: string, ): void; static OPENED: number; - // eslint-disable-next-line ft-flow/no-dupe-keys + OPENED: number; overrideMimeType(mime: string): void; readyState: number; @@ -183,7 +183,7 @@ declare class XMLHttpRequest extends EventTarget { statusText: string; timeout: number; static UNSENT: number; - // eslint-disable-next-line ft-flow/no-dupe-keys + UNSENT: number; upload: XMLHttpRequestEventTarget; diff --git a/packages/rn-tester/js/examples/Animated/CombineExample.js b/packages/rn-tester/js/examples/Animated/CombineExample.js index 90117168024a..b785b42e5c3f 100644 --- a/packages/rn-tester/js/examples/Animated/CombineExample.js +++ b/packages/rn-tester/js/examples/Animated/CombineExample.js @@ -9,7 +9,7 @@ */ import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; -import type {Numeric} from 'react-native/Libraries/Animated/AnimatedImplementation'; +import type {Numeric} from '@react-native/animated/AnimatedImplementation'; import RNTesterButton from '../../components/RNTesterButton'; import * as React from 'react'; diff --git a/packages/rn-tester/js/examples/Animated/ComposingExample.js b/packages/rn-tester/js/examples/Animated/ComposingExample.js index f894035bff1f..a74347ae3492 100644 --- a/packages/rn-tester/js/examples/Animated/ComposingExample.js +++ b/packages/rn-tester/js/examples/Animated/ComposingExample.js @@ -9,8 +9,8 @@ */ import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; -import type {CompositeAnimation} from 'react-native/Libraries/Animated/AnimatedMock'; -import type AnimatedValue from 'react-native/Libraries/Animated/nodes/AnimatedValue'; +import type {CompositeAnimation} from '@react-native/animated/AnimatedMock'; +import type AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; import RNTConfigurationBlock from '../../components/RNTConfigurationBlock'; import RNTesterButton from '../../components/RNTesterButton'; diff --git a/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js b/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js index c7725c1e8bb8..e4d9b86c333f 100644 --- a/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js +++ b/packages/rn-tester/js/examples/NativeAnimation/NativeAnimationsExample.js @@ -10,7 +10,7 @@ 'use strict'; -import type AnimatedValue from 'react-native/Libraries/Animated/nodes/AnimatedValue'; +import type AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; import RNTesterSettingSwitchRow from '../../components/RNTesterSettingSwitchRow'; import RNTesterText from '../../components/RNTesterText'; diff --git a/packages/rn-tester/js/examples/ScrollView/ScrollViewAnimatedExample.js b/packages/rn-tester/js/examples/ScrollView/ScrollViewAnimatedExample.js index b24e29e3f3dd..656f21e3b0ed 100644 --- a/packages/rn-tester/js/examples/ScrollView/ScrollViewAnimatedExample.js +++ b/packages/rn-tester/js/examples/ScrollView/ScrollViewAnimatedExample.js @@ -10,7 +10,7 @@ 'use strict'; -import type AnimatedValue from 'react-native/Libraries/Animated/nodes/AnimatedValue'; +import type AnimatedValue from '@react-native/animated/nodes/AnimatedValue'; const React = require('react'); const ReactNative = require('react-native'); diff --git a/packages/rn-tester/metro.config.js b/packages/rn-tester/metro.config.js index 04a0f5639923..33b3c82d7b3b 100644 --- a/packages/rn-tester/metro.config.js +++ b/packages/rn-tester/metro.config.js @@ -32,6 +32,7 @@ const config = { path.resolve(__dirname, '../react-native-test-library'), path.resolve(__dirname, '../virtualized-lists'), path.resolve(__dirname, '../react-native-popup-menu-android'), + path.resolve(__dirname, '../animated'), ], resolver: { blockList: [/..\/react-native\/sdks\/hermes/],