react-native-reanimated 4.3.0 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +12 -5
  2. package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +59 -37
  3. package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +11 -8
  4. package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +11 -3
  5. package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +9 -2
  6. package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +6 -2
  7. package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +8 -2
  8. package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +17 -4
  9. package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +5 -0
  10. package/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +5 -0
  11. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +25 -12
  12. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
  13. package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +12 -5
  14. package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +6 -3
  15. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +4 -6
  16. package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +25 -7
  17. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +38 -0
  18. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +106 -33
  19. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +165 -92
  20. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +12 -34
  21. package/README.md +1 -1
  22. package/android/CMakeLists.txt +4 -1
  23. package/android/build.gradle +2 -0
  24. package/android/generate-stub-pch.gradle.kts +84 -0
  25. package/android/src/main/cpp/ReanimatedPCH.h +46 -0
  26. package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +14 -1
  27. package/android/src/main/java/com/swmansion/reanimated/keyboard/KeyboardAnimationCallback.java +9 -1
  28. package/apple/reanimated/apple/ReanimatedModule.mm +12 -1
  29. package/lib/module/common/constants/platform.js +5 -5
  30. package/lib/module/common/constants/platform.js.map +1 -1
  31. package/lib/module/createAnimatedComponent/AnimatedComponent.js +1 -7
  32. package/lib/module/createAnimatedComponent/AnimatedComponent.js.map +1 -1
  33. package/lib/module/createAnimatedComponent/getViewInfo.js +3 -1
  34. package/lib/module/createAnimatedComponent/getViewInfo.js.map +1 -1
  35. package/lib/module/css/component/AnimatedComponent.js +0 -2
  36. package/lib/module/css/component/AnimatedComponent.js.map +1 -1
  37. package/lib/module/css/native/managers/CSSManager.js +16 -7
  38. package/lib/module/css/native/managers/CSSManager.js.map +1 -1
  39. package/lib/module/css/native/managers/CSSTransitionsManager.js +8 -1
  40. package/lib/module/css/native/managers/CSSTransitionsManager.js.map +1 -1
  41. package/lib/module/css/svg/native/processors/stroke.js +9 -5
  42. package/lib/module/css/svg/native/processors/stroke.js.map +1 -1
  43. package/lib/module/css/utils/props.js +6 -0
  44. package/lib/module/css/utils/props.js.map +1 -1
  45. package/lib/module/hook/useAnimatedRef.js +2 -2
  46. package/lib/module/hook/useAnimatedRef.js.map +1 -1
  47. package/lib/module/mutables.js +5 -1
  48. package/lib/module/mutables.js.map +1 -1
  49. package/lib/module/platform-specific/findHostInstance.js +8 -5
  50. package/lib/module/platform-specific/findHostInstance.js.map +1 -1
  51. package/lib/module/platform-specific/jsVersion.js +1 -1
  52. package/lib/module/updateProps/updateProps.js +3 -2
  53. package/lib/module/updateProps/updateProps.js.map +1 -1
  54. package/lib/module/valueSetter.js +1 -1
  55. package/lib/module/valueSetter.js.map +1 -1
  56. package/lib/typescript/common/constants/platform.d.ts.map +1 -1
  57. package/lib/typescript/createAnimatedComponent/AnimatedComponent.d.ts.map +1 -1
  58. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +0 -1
  59. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
  60. package/lib/typescript/createAnimatedComponent/getViewInfo.d.ts.map +1 -1
  61. package/lib/typescript/css/component/AnimatedComponent.d.ts +0 -1
  62. package/lib/typescript/css/component/AnimatedComponent.d.ts.map +1 -1
  63. package/lib/typescript/css/native/managers/CSSManager.d.ts +7 -0
  64. package/lib/typescript/css/native/managers/CSSManager.d.ts.map +1 -1
  65. package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts +5 -1
  66. package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts.map +1 -1
  67. package/lib/typescript/css/svg/native/processors/stroke.d.ts.map +1 -1
  68. package/lib/typescript/css/utils/props.d.ts.map +1 -1
  69. package/lib/typescript/mutables.d.ts.map +1 -1
  70. package/lib/typescript/platform-specific/findHostInstance.d.ts.map +1 -1
  71. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  72. package/lib/typescript/platform-specific/types.d.ts +1 -0
  73. package/lib/typescript/platform-specific/types.d.ts.map +1 -1
  74. package/lib/typescript/updateProps/updateProps.d.ts.map +1 -1
  75. package/lib/typescript/valueSetter.d.ts.map +1 -1
  76. package/package.json +5 -3
  77. package/src/common/constants/platform.ts +6 -5
  78. package/src/createAnimatedComponent/AnimatedComponent.tsx +1 -7
  79. package/src/createAnimatedComponent/commonTypes.ts +0 -1
  80. package/src/createAnimatedComponent/getViewInfo.ts +3 -1
  81. package/src/css/component/AnimatedComponent.tsx +0 -2
  82. package/src/css/native/managers/CSSManager.ts +33 -12
  83. package/src/css/native/managers/CSSTransitionsManager.ts +9 -2
  84. package/src/css/svg/native/processors/stroke.ts +9 -6
  85. package/src/css/utils/props.ts +7 -0
  86. package/src/hook/useAnimatedRef.ts +2 -2
  87. package/src/mutables.ts +5 -1
  88. package/src/platform-specific/findHostInstance.ts +7 -7
  89. package/src/platform-specific/jsVersion.ts +1 -1
  90. package/src/platform-specific/types.ts +2 -0
  91. package/src/updateProps/updateProps.ts +3 -2
  92. package/src/valueSetter.ts +2 -1
@@ -20,7 +20,9 @@ export function getViewInfo(element: HostInstance): {
20
20
  viewTag?: number;
21
21
  } {
22
22
  return {
23
- reactViewName: (element?._viewConfig?.uiViewClassName ??
23
+ reactViewName: (element?.__viewConfig?.uiViewClassName ??
24
+ // ReactFabricHostComponent (e.g. react-native-macos) exposes `_viewConfig`.
25
+ element?._viewConfig?.uiViewClassName ??
24
26
  element?.__internalInstanceHandle?.type ??
25
27
  element?.__internalInstanceHandle?.elementType) as string,
26
28
  viewTag: element?.__nativeTag,
@@ -45,7 +45,6 @@ export default class AnimatedComponent<
45
45
  _viewInfo?: ViewInfo;
46
46
  _cssStyle: CSSStyle = {}; // RN style object with Reanimated CSS properties
47
47
  _componentRef: AnimatedComponentRef | HTMLElement | null = null;
48
- _hasAnimatedRef = false;
49
48
  // Used only on web
50
49
  _componentDOMRef: HTMLElement | null = null;
51
50
  _willUnmount: boolean = false;
@@ -136,7 +135,6 @@ export default class AnimatedComponent<
136
135
  // Component can specify ref which should be animated when animated version of the component is created.
137
136
  // Otherwise, we animate the component itself.
138
137
  if (componentRef && componentRef.getAnimatableRef) {
139
- this._hasAnimatedRef = true;
140
138
  return componentRef.getAnimatableRef();
141
139
  }
142
140
  // Case for SVG components on Web
@@ -1,5 +1,9 @@
1
1
  'use strict';
2
- import { getCompoundComponentName, getPropsBuilder } from '../../../common';
2
+ import {
3
+ getCompoundComponentName,
4
+ getPropsBuilder,
5
+ IS_ANDROID,
6
+ } from '../../../common';
3
7
  import type { ShadowNodeWrapper } from '../../../commonTypes';
4
8
  import type { ViewInfo } from '../../../createAnimatedComponent/commonTypes';
5
9
  import type { CSSStyle } from '../../types';
@@ -14,6 +18,13 @@ export default class CSSManager implements ICSSManager {
14
18
  private readonly cssTransitionsManager: CSSTransitionsManager;
15
19
  private readonly viewTag: number;
16
20
  private readonly propsBuilder: ReturnType<typeof getPropsBuilder>;
21
+ /**
22
+ * True if the previous update had CSS transition props attached. On the next
23
+ * update we still need to build `normalizedStyle` only on Android to revert
24
+ * props applied during the transition to correct current values. (fixes
25
+ * https://github.com/software-mansion/react-native-reanimated/issues/9218).
26
+ */
27
+ private hadTransitionLastUpdate = false;
17
28
 
18
29
  constructor(
19
30
  { shadowNodeWrapper, viewTag, reactViewName = 'RCTView' }: ViewInfo,
@@ -40,23 +51,33 @@ export default class CSSManager implements ICSSManager {
40
51
  const [animationProperties, transitionProperties, filteredStyle] =
41
52
  filterCSSAndStyleProperties(style);
42
53
 
43
- const hasAnimationOrTransition =
44
- animationProperties !== null || transitionProperties !== null;
45
- const normalizedStyle = hasAnimationOrTransition
46
- ? this.propsBuilder.build(filteredStyle)
47
- : undefined;
54
+ const hasAnimation = animationProperties !== null;
55
+ const hasTransition = transitionProperties !== null;
48
56
 
49
- // We need to update view style only for animations (e.g. when a property is
50
- // specified only in a subset of keyframes and start/end value comes from style).
51
- if (normalizedStyle && animationProperties) {
52
- setViewStyle(this.viewTag, normalizedStyle);
53
- }
57
+ const normalizedStyle =
58
+ hasAnimation ||
59
+ hasTransition ||
60
+ (IS_ANDROID && this.hadTransitionLastUpdate)
61
+ ? this.propsBuilder.build(filteredStyle)
62
+ : undefined;
54
63
 
55
- this.cssTransitionsManager.update(
64
+ const transitionDetached = this.cssTransitionsManager.update(
56
65
  transitionProperties,
57
66
  normalizedStyle ?? {}
58
67
  );
68
+
69
+ // Record the committed style as the base so animations and (on Android) a
70
+ // detaching transition can revert to it instead of interpolator defaults.
71
+ if (
72
+ normalizedStyle &&
73
+ (hasAnimation || (IS_ANDROID && transitionDetached))
74
+ ) {
75
+ setViewStyle(this.viewTag, normalizedStyle);
76
+ }
77
+
59
78
  this.cssAnimationsManager.update(animationProperties);
79
+
80
+ this.hadTransitionLastUpdate = hasTransition;
60
81
  }
61
82
 
62
83
  unmountCleanup(): void {
@@ -30,10 +30,14 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
30
30
  this.shadowNodeWrapper = shadowNodeWrapper;
31
31
  }
32
32
 
33
+ /**
34
+ * @returns Whether this update detached a running transition (its props were
35
+ * removed, or normalized to an empty config, e.g. when duration is 0).
36
+ */
33
37
  update(
34
38
  transitionProperties: CSSTransitionProperties | null,
35
39
  nextProps: UnknownRecord = {}
36
- ): void {
40
+ ): boolean {
37
41
  const transitionConfig =
38
42
  transitionProperties &&
39
43
  normalizeCSSTransitionProperties(transitionProperties);
@@ -47,8 +51,9 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
47
51
  if (!prevProps || !transitionConfig) {
48
52
  if (this.hasTransition) {
49
53
  this.detach();
54
+ return true;
50
55
  }
51
- return;
56
+ return false;
52
57
  }
53
58
 
54
59
  // Trigger transition for changed properties only
@@ -62,6 +67,8 @@ export default class CSSTransitionsManager implements ICSSTransitionsManager {
62
67
  runCSSTransition(this.shadowNodeWrapper, config);
63
68
  this.hasTransition = true;
64
69
  }
70
+
71
+ return false;
65
72
  }
66
73
 
67
74
  unmountCleanup(): void {
@@ -19,18 +19,21 @@ export const processStrokeDashArray: ValueProcessor<
19
19
  if (isLength(value)) {
20
20
  result = [value];
21
21
  } else if (Array.isArray(value)) {
22
- // We have to repeat the same pattern twice if the number of elements is odd
23
- // "If the number of values is odd, the pattern behaves as if it was duplicated
24
- // to yield an even number of values"
25
- // (https://www.w3.org/TR/fill-stroke-3/#valdef-stroke-dasharray-length-percentage)
26
- result =
27
- value.length % 2 === 0 || value.length < 3 ? value : value.concat(value);
22
+ result = [...value];
28
23
  } else if (value === 'none') {
29
24
  return 'none';
30
25
  } else {
31
26
  throw new ReanimatedError(ERROR_MESSAGES.invalidDashArray(value));
32
27
  }
33
28
 
29
+ // Per the SVG spec an odd-length dash array is repeated to an even length.
30
+ // react-native-svg's extractStroke does this, but animated values bypass it
31
+ // and an odd-length array crashes Android's DashPathEffect, so we repeat here.
32
+ // https://www.w3.org/TR/fill-stroke-3/#valdef-stroke-dasharray-length-percentage
33
+ if (result.length % 2 === 1) {
34
+ result = result.concat(result);
35
+ }
36
+
34
37
  if (__DEV__) {
35
38
  isValidDashArray(result);
36
39
  }
@@ -27,6 +27,13 @@ export function filterCSSAndStyleProperties<S extends AnyRecord>(
27
27
  const filteredStyle: AnyRecord = {};
28
28
 
29
29
  for (const [prop, value] of Object.entries(style)) {
30
+ if (value === undefined) {
31
+ // If the user explicitly sets a property to undefined (e.g. when they want
32
+ // to remove CSS transition or animation), we treat the property as if it was not
33
+ // present in the style object.
34
+ continue;
35
+ }
36
+
30
37
  if (isAnimationProp(prop)) {
31
38
  // TODO - add support for animation shorthand
32
39
  animationProperties[prop] = value;
@@ -37,8 +37,8 @@ function useAnimatedRefBase<TRef extends InstanceOrElement>(
37
37
  wrapperRef.current = getWrapper(ref);
38
38
 
39
39
  // We have to unwrap the tag from the shadow node wrapper.
40
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
- fun.getTag = () => findNodeHandle(ref as any);
40
+ // @ts-expect-error this can't be typed well.
41
+ fun.getTag = () => ref.getScrollableNode?.() || findNodeHandle(ref);
42
42
  fun.current = ref;
43
43
 
44
44
  if (observers.size) {
package/src/mutables.ts CHANGED
@@ -217,8 +217,12 @@ function mutableGuestDecorator<TValue>(
217
217
  set(newValue) {
218
218
  if (globalThis.__RUNTIME_KIND === 1) {
219
219
  checkInvalidWriteDuringRender();
220
+ scheduleOnUI(() => {
221
+ mutable.value = newValue;
222
+ });
223
+ } else {
224
+ mutable.setAsync(newValue);
220
225
  }
221
- mutable.setAsync(newValue);
222
226
  },
223
227
  enumerable: true,
224
228
  configurable: true,
@@ -13,7 +13,9 @@ function findHostInstanceFastPath(maybeNativeRef: HostInstance | undefined) {
13
13
  if (
14
14
  maybeNativeRef.__internalInstanceHandle &&
15
15
  maybeNativeRef.__nativeTag &&
16
- maybeNativeRef._viewConfig
16
+ // ReactFabricHostComponent (e.g. react-native-macos) exposes `_viewConfig`;
17
+ // ReactNativeElement uses `__viewConfig`.
18
+ (maybeNativeRef.__viewConfig || maybeNativeRef._viewConfig)
17
19
  ) {
18
20
  return maybeNativeRef;
19
21
  }
@@ -54,13 +56,11 @@ export function findHostInstance(
54
56
  resolveFindHostInstance_DEPRECATED();
55
57
  /*
56
58
  The Fabric implementation of `findHostInstance_DEPRECATED` requires a React ref as an argument
57
- rather than a native ref. If a component implements the `getAnimatableRef` method, it must use
58
- the ref provided by this method. It is the component's responsibility to ensure that this is
59
- a valid React ref.
59
+ rather than a native ref. Prefer the resolved component ref when available so components can
60
+ forward their ref to the host view that should be animated. Components that expose an animatable
61
+ ref via `getAnimatableRef` already have it resolved into `_componentRef`.
60
62
  */
61
63
  return findHostInstance_DEPRECATED(
62
- (ref as IAnimatedComponentInternalBase)._hasAnimatedRef
63
- ? (ref as IAnimatedComponentInternalBase)._componentRef
64
- : ref
64
+ (ref as IAnimatedComponentInternalBase)._componentRef ?? ref
65
65
  );
66
66
  }
@@ -4,4 +4,4 @@
4
4
  * version used to build the native part of the library in runtime. Remember to
5
5
  * keep this in sync with the version declared in `package.json`
6
6
  */
7
- export const jsVersion = '4.3.0';
7
+ export const jsVersion = '4.3.2';
@@ -3,5 +3,7 @@
3
3
  export type HostInstance = {
4
4
  __internalInstanceHandle?: Record<string, unknown>;
5
5
  __nativeTag?: number;
6
+ __viewConfig?: Record<string, unknown>;
7
+ // Legacy ReactFabricHostComponent key (e.g. react-native-macos).
6
8
  _viewConfig?: Record<string, unknown>;
7
9
  };
@@ -109,7 +109,7 @@ type NativePropsOperation = {
109
109
  function createUpdatePropsManager() {
110
110
  'worklet';
111
111
  const nativeOperations: NativePropsOperation[] = [];
112
- const jsOperations: JSPropsOperation[] = [];
112
+ let jsOperations: JSPropsOperation[] = [];
113
113
 
114
114
  let flushPending = false;
115
115
 
@@ -162,8 +162,9 @@ function createUpdatePropsManager() {
162
162
  nativeOperations.length = 0;
163
163
  }
164
164
  if (jsOperations.length) {
165
+ // Fresh array each flush: scheduleOnRN caches serialized args by identity.
165
166
  scheduleOnRN(updateJSProps, jsOperations);
166
- jsOperations.length = 0;
167
+ jsOperations = [];
167
168
  }
168
169
  flushPending = false;
169
170
  },
@@ -17,7 +17,8 @@ export function valueSetter<Value>(
17
17
  (value !== null &&
18
18
  typeof value === 'object' &&
19
19
  // TODO TYPESCRIPT fix this after fixing AnimationObject type
20
- (value as unknown as AnimationObject).onFrame !== undefined)
20
+ (value as unknown as AnimationObject).onFrame !== undefined &&
21
+ (value as unknown as AnimationObject).onStart !== undefined)
21
22
  ) {
22
23
  const animation: AnimationObject<Value> =
23
24
  typeof value === 'function'