diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js b/packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js
index ae7e2f61ca8423..990d086faf8600 100644
--- a/packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js
+++ b/packages/react-native/Libraries/Animated/__tests__/AnimatedBackend-itest.js
@@ -17,6 +17,7 @@ import ensureInstance from '../../../src/private/__tests__/utilities/ensureInsta
import * as Fantom from '@react-native/fantom';
import {createRef} from 'react';
import {Animated, useAnimatedValue} from 'react-native';
+import {allowStyleProp} from 'react-native/Libraries/Animated/NativeAnimatedAllowlist';
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
test('animated opacity', () => {
@@ -73,3 +74,56 @@ test('animated opacity', () => {
,
);
});
+
+test('animate layout props', () => {
+ const viewRef = createRef();
+ allowStyleProp('height');
+
+ let _animatedHeight;
+ let _heightAnimation;
+
+ function MyApp() {
+ const animatedHeight = useAnimatedValue(0);
+ _animatedHeight = animatedHeight;
+ return (
+
+ );
+ }
+
+ const root = Fantom.createRoot();
+
+ Fantom.runTask(() => {
+ root.render();
+ });
+
+ const viewElement = ensureInstance(viewRef.current, ReactNativeElement);
+
+ Fantom.runTask(() => {
+ _heightAnimation = Animated.timing(_animatedHeight, {
+ toValue: 100,
+ duration: 10,
+ useNativeDriver: true,
+ }).start();
+ });
+
+ Fantom.unstable_produceFramesForDuration(10);
+
+ // TODO: this shouldn't be neccessary since animation should be stopped after duration
+ Fantom.runTask(() => {
+ _heightAnimation?.stop();
+ });
+
+ // TODO: getFabricUpdateProps is not working with the cloneMutliple method
+ // expect(Fantom.unstable_getFabricUpdateProps(viewElement).height).toBe(100);
+ expect(root.getRenderedOutput({props: ['height']}).toJSX()).toEqual(
+ ,
+ );
+});
diff --git a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
index af89f0d9ba21a1..6ecc3ccb76c77e 100644
--- a/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
+++ b/packages/react-native/Libraries/Animated/nodes/AnimatedProps.js
@@ -14,6 +14,7 @@ import type {AnimatedStyleAllowlist} from './AnimatedStyle';
import NativeAnimatedHelper from '../../../src/private/animated/NativeAnimatedHelper';
import {findNodeHandle} from '../../ReactNative/RendererProxy';
+import {getNodeFromPublicInstance} from '../../ReactPrivate/ReactNativePrivateInterface';
import flattenStyle from '../../StyleSheet/flattenStyle';
import {AnimatedEvent} from '../AnimatedEvent';
import AnimatedNode from './AnimatedNode';
@@ -249,6 +250,9 @@ export default class AnimatedProps extends AnimatedNode {
if (this._target != null) {
this.#connectAnimatedView(this._target);
}
+ if (this._target != null) {
+ this.#connectShadowNode(this._target);
+ }
}
}
@@ -259,6 +263,9 @@ export default class AnimatedProps extends AnimatedNode {
this._target = {instance, connectedViewTag: null};
if (this.__isNative) {
this.#connectAnimatedView(this._target);
+ if (this._target) {
+ this.#connectShadowNode(this._target);
+ }
}
}
@@ -279,6 +286,19 @@ export default class AnimatedProps extends AnimatedNode {
target.connectedViewTag = viewTag;
}
+ #connectShadowNode(target: TargetView): void {
+ invariant(this.__isNative, 'Expected node to be marked as "native"');
+ // $FlowExpectedError[incompatible-type] - target.instance may be an HTMLElement but we need ReactNativeElement for Fabric
+ const shadowNode = getNodeFromPublicInstance(target.instance);
+ if (shadowNode == null) {
+ return;
+ }
+ NativeAnimatedHelper.API.connectAnimatedNodeToShadowNodeFamily(
+ this.__getNativeTag(),
+ shadowNode,
+ );
+ }
+
#disconnectAnimatedView(target: TargetView): void {
invariant(this.__isNative, 'Expected node to be marked as "native"');
const viewTag = target.connectedViewTag;
diff --git a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm
index a168bddff83abb..7429b1b92eac48 100644
--- a/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm
+++ b/packages/react-native/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm
@@ -165,6 +165,8 @@ - (void)setSurfacePresenter:(id)surfacePresenter
}];
}
+RCT_EXPORT_METHOD(connectAnimatedNodeToShadowNodeFamily : (double)nodeTag shadowNode : (NSDictionary *)shadowNode) {}
+
RCT_EXPORT_METHOD(disconnectAnimatedNodeFromView : (double)nodeTag viewTag : (double)viewTag)
{
[self queueOperationBlock:^(RCTNativeAnimatedNodesManager *nodesManager) {
diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api
index c39a442b5f7d19..2fb63f4ae4b221 100644
--- a/packages/react-native/ReactAndroid/api/ReactAndroid.api
+++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api
@@ -457,6 +457,7 @@ public final class com/facebook/react/animated/NativeAnimatedModule : com/facebo
public fun (Lcom/facebook/react/bridge/ReactApplicationContext;)V
public fun addAnimatedEventToView (DLjava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V
public fun addListener (Ljava/lang/String;)V
+ public fun connectAnimatedNodeToShadowNodeFamily (DLcom/facebook/react/bridge/ReadableMap;)V
public fun connectAnimatedNodeToView (DD)V
public fun connectAnimatedNodes (DD)V
public fun createAnimatedNode (DLcom/facebook/react/bridge/ReadableMap;)V
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt
index 6c5a505c9218e2..ca4a4babb3f4b8 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.kt
@@ -1117,4 +1117,6 @@ public class NativeAnimatedModule(reactContext: ReactApplicationContext) :
public const val ANIMATED_MODULE_DEBUG: Boolean = false
}
+
+ override fun connectAnimatedNodeToShadowNodeFamily(p0: Double, p1: ReadableMap) {}
}
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.cpp b/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.cpp
index 8a8b8edc79d285..f3bd8fae4dab02 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.cpp
@@ -160,6 +160,20 @@ void AnimatedModule::connectAnimatedNodeToView(
ConnectAnimatedNodeToViewOp{.nodeTag = nodeTag, .viewTag = viewTag});
}
+void AnimatedModule::connectAnimatedNodeToShadowNodeFamily(
+ jsi::Runtime& rt,
+ Tag nodeTag,
+ jsi::Object shadowNodeObj) {
+ const auto& nativeState = shadowNodeObj.getNativeState(rt);
+ const auto& shadowNode =
+ std::dynamic_pointer_cast(nativeState)->shadowNode;
+
+ operations_.emplace_back(
+ ConnectAnimatedNodeToShadowNodeFamilyOp{
+ .nodeTag = nodeTag,
+ .shadowNodeFamily = shadowNode->getFamilyShared()});
+}
+
void AnimatedModule::disconnectAnimatedNodeFromView(
jsi::Runtime& /*rt*/,
Tag nodeTag,
@@ -282,6 +296,11 @@ void AnimatedModule::executeOperation(
DisconnectAnimatedNodeFromViewOp>) {
nodesManager->disconnectAnimatedNodeFromView(
op.nodeTag, op.viewTag);
+ } else if constexpr (std::is_same_v<
+ T,
+ ConnectAnimatedNodeToShadowNodeFamilyOp>) {
+ nodesManager->connectAnimatedNodeToShadowNodeFamily(
+ op.nodeTag, op.shadowNodeFamily);
} else if constexpr (std::is_same_v) {
nodesManager->restoreDefaultValues(op.nodeTag);
} else if constexpr (std::is_same_v) {
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.h b/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.h
index a54254e6a6b7c6..858cd95e1b4695 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.h
+++ b/packages/react-native/ReactCommon/react/renderer/animated/AnimatedModule.h
@@ -87,6 +87,11 @@ class AnimatedModule : public NativeAnimatedModuleCxxSpec, publi
Tag viewTag{};
};
+ struct ConnectAnimatedNodeToShadowNodeFamilyOp {
+ Tag nodeTag{};
+ std::shared_ptr shadowNodeFamily{};
+ };
+
struct DisconnectAnimatedNodeFromViewOp {
Tag nodeTag{};
Tag viewTag{};
@@ -124,6 +129,7 @@ class AnimatedModule : public NativeAnimatedModuleCxxSpec, publi
SetAnimatedNodeOffsetOp,
SetAnimatedNodeValueOp,
ConnectAnimatedNodeToViewOp,
+ ConnectAnimatedNodeToShadowNodeFamilyOp,
DisconnectAnimatedNodeFromViewOp,
RestoreDefaultValuesOp,
FlattenAnimatedNodeOffsetOp,
@@ -176,6 +182,8 @@ class AnimatedModule : public NativeAnimatedModuleCxxSpec, publi
void connectAnimatedNodeToView(jsi::Runtime &rt, Tag nodeTag, Tag viewTag);
+ void connectAnimatedNodeToShadowNodeFamily(jsi::Runtime &rt, Tag nodeTag, jsi::Object shadowNode);
+
void disconnectAnimatedNodeFromView(jsi::Runtime &rt, Tag nodeTag, Tag viewTag);
void restoreDefaultValues(jsi::Runtime &rt, Tag nodeTag);
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp
index 50482192a50a2c..76978232e99f8c 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.cpp
@@ -238,6 +238,20 @@ void NativeAnimatedNodesManager::connectAnimatedNodeToView(
}
}
+void NativeAnimatedNodesManager::connectAnimatedNodeToShadowNodeFamily(
+ Tag propsNodeTag,
+ std::shared_ptr family) noexcept {
+ react_native_assert(propsNodeTag);
+ auto node = getAnimatedNode(propsNodeTag);
+ if (node != nullptr) {
+ node->connectToFamily(family);
+ updatedNodeTags_.insert(node->tag());
+ } else {
+ LOG(WARNING)
+ << "Cannot ConnectAnimatedNodeToShadowNodeFamily, animated node has to be props type";
+ }
+}
+
void NativeAnimatedNodesManager::disconnectAnimatedNodeFromView(
Tag propsNodeTag,
Tag viewTag) noexcept {
@@ -889,10 +903,14 @@ void NativeAnimatedNodesManager::schedulePropsCommit(
Tag viewTag,
const folly::dynamic& props,
bool layoutStyleUpdated,
- bool forceFabricCommit) noexcept {
+ bool forceFabricCommit,
+ std::shared_ptr family) noexcept {
if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
if (layoutStyleUpdated) {
mergeObjects(updateViewProps_[viewTag], props);
+ if (family) {
+ tagToShadowNodeFamily_[viewTag] = std::move(family);
+ }
} else {
mergeObjects(updateViewPropsDirect_[viewTag], props);
}
@@ -1003,7 +1021,31 @@ AnimationMutations NativeAnimatedNodesManager::pullAnimationMutations() {
AnimationMutation{tag, nullptr, propsBuilder.get()});
containsChange = true;
}
- updateViewPropsDirect_.clear();
+ for (auto& [tag, props] : updateViewProps_) {
+ auto familyIt = tagToShadowNodeFamily_.find(tag);
+ if (familyIt != tagToShadowNodeFamily_.end()) {
+ if (props.find("width") != props.items().end()) {
+ propsBuilder.setWidth(
+ yoga::Style::SizeLength::points(props["width"].asDouble()));
+ }
+ if (props.find("height") != props.items().end()) {
+ propsBuilder.setHeight(
+ yoga::Style::SizeLength::points(props["height"].asDouble()));
+ }
+ // propsBuilder.storeDynamic(props);
+ mutations.push_back(
+ AnimationMutation{
+ .tag = tag,
+ .family = familyIt->second.get(),
+ .props = propsBuilder.get()});
+ }
+ containsChange = true;
+ }
+ if (containsChange) {
+ updateViewPropsDirect_.clear();
+ updateViewProps_.clear();
+ tagToShadowNodeFamily_.clear();
+ }
}
if (!containsChange) {
@@ -1023,7 +1065,8 @@ AnimationMutations NativeAnimatedNodesManager::pullAnimationMutations() {
}
}
- // Step 2: update all nodes that are connected to the finished animations.
+ // Step 2: update all nodes that are connected to the finished
+ // animations.
updateNodes(finishedAnimationValueNodes);
isEventAnimationInProgress_ = false;
@@ -1034,6 +1077,17 @@ AnimationMutations NativeAnimatedNodesManager::pullAnimationMutations() {
mutations.push_back(
AnimationMutation{tag, nullptr, propsBuilder.get()});
}
+ for (auto& [tag, props] : updateViewProps_) {
+ auto familyIt = tagToShadowNodeFamily_.find(tag);
+ if (familyIt != tagToShadowNodeFamily_.end()) {
+ propsBuilder.storeDynamic(props);
+ mutations.push_back(
+ AnimationMutation{
+ .tag = tag,
+ .family = familyIt->second.get(),
+ .props = propsBuilder.get()});
+ }
+ }
}
} else {
// There is no active animation. Stop the render callback.
@@ -1113,7 +1167,8 @@ void NativeAnimatedNodesManager::onRender() {
}
}
- // Step 2: update all nodes that are connected to the finished animations.
+ // Step 2: update all nodes that are connected to the finished
+ // animations.
updateNodes(finishedAnimationValueNodes);
isEventAnimationInProgress_ = false;
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h
index 965f29489fdfc8..2ea9695e66e933 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h
+++ b/packages/react-native/ReactCommon/react/renderer/animated/NativeAnimatedNodesManager.h
@@ -21,6 +21,7 @@
#include
#endif
#include
+#include
#include
#include
#include
@@ -95,6 +96,8 @@ class NativeAnimatedNodesManager {
void connectAnimatedNodeToView(Tag propsNodeTag, Tag viewTag) noexcept;
+ void connectAnimatedNodeToShadowNodeFamily(Tag propsNodeTag, std::shared_ptr family) noexcept;
+
void disconnectAnimatedNodes(Tag parentTag, Tag childTag) noexcept;
void disconnectAnimatedNodeFromView(Tag propsNodeTag, Tag viewTag) noexcept;
@@ -144,7 +147,8 @@ class NativeAnimatedNodesManager {
Tag viewTag,
const folly::dynamic &props,
bool layoutStyleUpdated,
- bool forceFabricCommit) noexcept;
+ bool forceFabricCommit,
+ std::shared_ptr family = nullptr) noexcept;
/**
* Commits all pending animated property updates to their respective views.
@@ -251,6 +255,7 @@ class NativeAnimatedNodesManager {
std::unordered_map updateViewProps_{};
std::unordered_map updateViewPropsDirect_{};
+ std::unordered_map> tagToShadowNodeFamily_{};
/*
* Sometimes a view is not longer connected to a PropsAnimatedNode, but
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.cpp b/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.cpp
index 8303b74741b898..b343197f55d3f0 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.cpp
@@ -58,6 +58,11 @@ void PropsAnimatedNode::connectToView(Tag viewTag) {
connectedViewTag_ = viewTag;
}
+void PropsAnimatedNode::connectToFamily(
+ std::shared_ptr& family) {
+ viewShadowNodeFamily_ = family;
+}
+
void PropsAnimatedNode::disconnectFromView(Tag viewTag) {
react_native_assert(
connectedViewTag_ == viewTag &&
@@ -144,7 +149,11 @@ void PropsAnimatedNode::update(bool forceFabricCommit) {
layoutStyleUpdated_ = isLayoutStyleUpdated(getConfig()["props"], *manager_);
manager_->schedulePropsCommit(
- connectedViewTag_, props_, layoutStyleUpdated_, forceFabricCommit);
+ connectedViewTag_,
+ props_,
+ layoutStyleUpdated_,
+ forceFabricCommit,
+ viewShadowNodeFamily_.lock());
}
} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.h b/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.h
index 9d654a33b8e11c..5182785b98dc58 100644
--- a/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.h
+++ b/packages/react-native/ReactCommon/react/renderer/animated/nodes/PropsAnimatedNode.h
@@ -14,6 +14,7 @@
#include "AnimatedNode.h"
#include
+#include
#include
namespace facebook::react {
@@ -21,6 +22,7 @@ class PropsAnimatedNode final : public AnimatedNode {
public:
PropsAnimatedNode(Tag tag, const folly::dynamic &config, NativeAnimatedNodesManager &manager);
void connectToView(Tag viewTag);
+ void connectToFamily(std::shared_ptr &family);
void disconnectFromView(Tag viewTag);
void restoreDefaultValues();
@@ -45,5 +47,6 @@ class PropsAnimatedNode final : public AnimatedNode {
bool layoutStyleUpdated_{false};
Tag connectedViewTag_{animated::undefinedAnimatedNodeIdentifier};
+ std::weak_ptr viewShadowNodeFamily_{};
};
} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimatedProps.h b/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimatedProps.h
index d65411a812c6d7..25e69ba6fd0051 100644
--- a/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimatedProps.h
+++ b/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimatedProps.h
@@ -37,4 +37,33 @@ struct AnimatedProps {
std::vector> props;
std::unique_ptr rawProps;
};
+
+inline void cloneProp(BaseViewProps &viewProps, std::unique_ptr &animatedProp)
+{
+ switch (animatedProp->propName) {
+ case OPACITY:
+ viewProps.opacity = get(animatedProp);
+ break;
+
+ case WIDTH:
+ viewProps.yogaStyle.setDimension(yoga::Dimension::Width, get(animatedProp));
+ break;
+
+ case HEIGHT:
+ viewProps.yogaStyle.setDimension(yoga::Dimension::Height, get(animatedProp));
+ break;
+
+ case BORDER_RADII:
+ viewProps.borderRadii = get(animatedProp);
+ break;
+
+ case FLEX:
+ viewProps.yogaStyle.setFlex(get(animatedProp));
+ break;
+
+ case TRANSFORM:
+ viewProps.transform = get(animatedProp);
+ break;
+ }
+}
} // namespace facebook::react
diff --git a/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp b/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp
index 6b49decc8cf2be..24fcd3996cc8d5 100644
--- a/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp
@@ -41,34 +41,7 @@ static inline Props::Shared cloneProps(
auto viewProps = std::const_pointer_cast(
std::static_pointer_cast(newProps));
for (auto& animatedProp : animatedProps.props) {
- switch (animatedProp->propName) {
- case OPACITY:
- viewProps->opacity = get(animatedProp);
- break;
-
- case WIDTH:
- viewProps->yogaStyle.setDimension(
- yoga::Dimension::Width, get(animatedProp));
- break;
-
- case HEIGHT:
- viewProps->yogaStyle.setDimension(
- yoga::Dimension::Height,
- get(animatedProp));
- break;
-
- case BORDER_RADII:
- viewProps->borderRadii = get(animatedProp);
- break;
-
- case FLEX:
- viewProps->yogaStyle.setFlex(get(animatedProp));
- break;
-
- case TRANSFORM:
- viewProps->transform = get(animatedProp);
- break;
- }
+ cloneProp(*viewProps, animatedProp);
}
return newProps;
}
diff --git a/packages/react-native/src/private/animated/NativeAnimatedHelper.js b/packages/react-native/src/private/animated/NativeAnimatedHelper.js
index 5cde2ceef75da7..fb3027e621d917 100644
--- a/packages/react-native/src/private/animated/NativeAnimatedHelper.js
+++ b/packages/react-native/src/private/animated/NativeAnimatedHelper.js
@@ -27,6 +27,7 @@ import Platform from '../../../Libraries/Utilities/Platform';
import * as ReactNativeFeatureFlags from '../featureflags/ReactNativeFeatureFlags';
import invariant from 'invariant';
import nullthrows from 'nullthrows';
+import type {Node} from '../../../Libraries/Renderer/shims/ReactNativeTypes';
// TODO T69437152 @petetheheat - Delete this fork when Fabric ships to 100%.
const NativeAnimatedModule: typeof NativeAnimatedTurboModule =
@@ -83,6 +84,7 @@ function createNativeOperations(): $NonMaybeType {
'removeAnimatedEventFromView', // 19
'addListener', // 20
'removeListener', // 21
+ 'connectAnimatedNodeToShadowNodeFamily', // 22
];
const nativeOperations: {
[$Values]: (...$ReadOnlyArray) => void,
@@ -312,6 +314,16 @@ const API = {
NativeOperations.connectAnimatedNodeToView(nodeTag, viewTag);
},
+ connectAnimatedNodeToShadowNodeFamily(
+ nodeTag: number,
+ shadowNode: Node,
+ ): void {
+ NativeOperations.connectAnimatedNodeToShadowNodeFamily?.(
+ nodeTag,
+ shadowNode,
+ );
+ },
+
disconnectAnimatedNodeFromView(nodeTag: number, viewTag: number): void {
NativeOperations.disconnectAnimatedNodeFromView(nodeTag, viewTag);
},
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 91f64cdcdc3929..f71e7f9dcf5c13 100644
--- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js
+++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedModule.js
@@ -49,6 +49,10 @@ export interface Spec extends TurboModule {
+flattenAnimatedNodeOffset: (nodeTag: number) => void;
+extractAnimatedNodeOffset: (nodeTag: number) => void;
+connectAnimatedNodeToView: (nodeTag: number, viewTag: number) => void;
+ +connectAnimatedNodeToShadowNodeFamily?: (
+ nodeTag: number,
+ shadowNode: Object,
+ ) => void;
+disconnectAnimatedNodeFromView: (nodeTag: number, viewTag: number) => void;
+restoreDefaultValues: (nodeTag: number) => void;
+dropAnimatedNode: (tag: number) => 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 5a20ac1539de67..f67647c5a06c88 100644
--- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js
+++ b/packages/react-native/src/private/specs_DEPRECATED/modules/NativeAnimatedTurboModule.js
@@ -49,6 +49,10 @@ export interface Spec extends TurboModule {
+flattenAnimatedNodeOffset: (nodeTag: number) => void;
+extractAnimatedNodeOffset: (nodeTag: number) => void;
+connectAnimatedNodeToView: (nodeTag: number, viewTag: number) => void;
+ +connectAnimatedNodeToShadowNodeFamily?: (
+ nodeTag: number,
+ shadowNode: Object,
+ ) => void;
+disconnectAnimatedNodeFromView: (nodeTag: number, viewTag: number) => void;
+restoreDefaultValues: (nodeTag: number) => void;
+dropAnimatedNode: (tag: number) => void;