react-native-reanimated 2.11.0 → 2.13.0

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 (50) hide show
  1. package/Common/cpp/NativeModules/NativeReanimatedModule.cpp +1 -0
  2. package/RNReanimated.podspec +7 -4
  3. package/android/.gradle/7.5.1/checksums/checksums.lock +0 -0
  4. package/android/.gradle/7.5.1/checksums/md5-checksums.bin +0 -0
  5. package/android/.gradle/7.5.1/checksums/sha1-checksums.bin +0 -0
  6. package/android/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock +0 -0
  7. package/android/.gradle/7.5.1/executionHistory/executionHistory.bin +0 -0
  8. package/android/.gradle/7.5.1/executionHistory/executionHistory.lock +0 -0
  9. package/android/.gradle/7.5.1/fileHashes/fileHashes.bin +0 -0
  10. package/android/.gradle/7.5.1/fileHashes/fileHashes.lock +0 -0
  11. package/android/.gradle/7.5.1/fileHashes/resourceHashesCache.bin +0 -0
  12. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  13. package/android/.gradle/buildOutputCleanup/cache.properties +1 -1
  14. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  15. package/android/.gradle/file-system.probe +0 -0
  16. package/android/CMakeLists.txt +1 -1
  17. package/android/build.gradle +72 -36
  18. package/android/src/main/java/com/swmansion/reanimated/layoutReanimation/ReanimatedUIManager.java +1 -1
  19. package/android/{rnVersionPatch/62 → src/reactNativeVersionPatch/UIImplementation/64/com/swmansion/reanimated}/layoutReanimation/ReanimatedUIImplementation.java +0 -0
  20. package/android/src/{main/java → reactNativeVersionPatch/UIImplementation/latest}/com/swmansion/reanimated/layoutReanimation/ReanimatedUIImplementation.java +0 -0
  21. package/android/src/reactNativeVersionPatch/messageQueueThread/67/com/swmansion/reanimated/ReanimatedMessageQueueThread.java +12 -0
  22. package/android/src/reactNativeVersionPatch/messageQueueThread/latest/com/swmansion/reanimated/ReanimatedMessageQueueThread.java +12 -0
  23. package/android/{rnVersionPatch/62 → src/reactNativeVersionPatch/nativeHierarchyManager/62/com/swmansion/reanimated}/layoutReanimation/ReanimatedNativeHierarchyManager.java +0 -0
  24. package/android/src/{main/java → reactNativeVersionPatch/nativeHierarchyManager/latest}/com/swmansion/reanimated/layoutReanimation/ReanimatedNativeHierarchyManager.java +0 -0
  25. package/ios/REAModule.mm +21 -2
  26. package/ios/keyboardObserver/REAKeyboardEventObserver.m +1 -1
  27. package/lib/createAnimatedComponent.js +3 -4
  28. package/lib/reanimated2/NativeMethods.js +78 -43
  29. package/lib/reanimated2/globals.d.ts +39 -13
  30. package/lib/reanimated2/hook/useScrollViewOffset.js +2 -1
  31. package/lib/reanimated2/jestUtils.js +14 -7
  32. package/lib/types/reanimated2/NativeMethods.d.ts +2 -2
  33. package/lib/types/reanimated2/frameCallback/FrameCallbackRegistryUI.d.ts +14 -0
  34. package/package.json +6 -5
  35. package/scripts/reanimated_utils.rb +14 -2
  36. package/src/createAnimatedComponent.tsx +2 -3
  37. package/src/reanimated2/NativeMethods.ts +98 -54
  38. package/src/reanimated2/frameCallback/FrameCallbackRegistryUI.ts +1 -1
  39. package/src/reanimated2/globals.d.ts +39 -13
  40. package/src/reanimated2/hook/useScrollViewOffset.ts +4 -3
  41. package/src/reanimated2/jestUtils.ts +14 -6
  42. package/android/rnVersionPatch/63/layoutReanimation/ReanimatedUIImplementation.java +0 -68
  43. package/android/rnVersionPatch/64/layoutReanimation/ReanimatedUIImplementation.java +0 -68
  44. package/android/rnVersionPatch/65/.gitkeep +0 -0
  45. package/android/rnVersionPatch/66/.gitkeep +0 -0
  46. package/android/rnVersionPatch/67/.gitkeep +0 -0
  47. package/android/rnVersionPatch/68/.gitkeep +0 -0
  48. package/android/rnVersionPatch/69/.gitkeep +0 -0
  49. package/android/rnVersionPatch/70/.gitkeep +0 -0
  50. package/android/rnVersionPatch/backup/.gitkeep +0 -0
@@ -3,6 +3,7 @@
3
3
  #include <memory>
4
4
  #include <thread>
5
5
  #include <unordered_map>
6
+ #include <utility>
6
7
 
7
8
  #include "EventHandlerRegistry.h"
8
9
  #include "FeaturesConfig.h"
@@ -4,6 +4,7 @@ require_relative './scripts/reanimated_utils'
4
4
  reanimated_package_json = JSON.parse(File.read(File.join(__dir__, "package.json")))
5
5
  config = find_config()
6
6
  assert_no_multiple_instances(config)
7
+ assert_no_reanimated2_with_new_architecture(reanimated_package_json)
7
8
 
8
9
  folly_prefix = config[:react_native_minor_version] >= 64 ? 'RCT-' : ''
9
10
  folly_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32 -DREACT_NATIVE_MINOR_VERSION=' + config[:react_native_minor_version].to_s
@@ -34,14 +35,16 @@ Pod::Spec.new do |s|
34
35
  "Common/cpp/hidden_headers/**"
35
36
  ]
36
37
 
37
- s.pod_target_xcconfig = {
38
+ s.pod_target_xcconfig = {
38
39
  "USE_HEADERMAP" => "YES",
39
- "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/#{folly_prefix}Folly\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Headers/Private/React-Core\" "
40
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/#{folly_prefix}Folly\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/Headers/Private/React-Core\" ",
41
+ "FRAMEWORK_SEARCH_PATHS" => "\"${PODS_CONFIGURATION_BUILD_DIR}/React-hermes\"",
40
42
  }
41
43
  s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags
42
44
  s.xcconfig = {
43
- "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/glog\" \"$(PODS_ROOT)/#{folly_prefix}Folly\" \"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-hermes\" \"${PODS_ROOT}/Headers/Public/hermes-engine\" \"#{config[:react_native_common_dir]}\"",
44
- "OTHER_CFLAGS" => "$(inherited)" + " " + folly_flags }
45
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/boost-for-react-native\" \"$(PODS_ROOT)/glog\" \"$(PODS_ROOT)/#{folly_prefix}Folly\" \"$(PODS_ROOT)/RCT-Folly\" \"${PODS_ROOT}/Headers/Public/React-hermes\" \"${PODS_ROOT}/Headers/Public/hermes-engine\" \"$(PODS_ROOT)/#{config[:react_native_common_dir]}\"",
46
+ "OTHER_CFLAGS" => "$(inherited)" + " " + folly_flags
47
+ }
45
48
 
46
49
  s.requires_arc = true
47
50
 
@@ -1,2 +1,2 @@
1
- #Thu Oct 13 15:02:41 UTC 2022
1
+ #Fri Nov 11 10:24:13 UTC 2022
2
2
  gradle.version=7.5.1
Binary file
@@ -318,4 +318,4 @@ endif()
318
318
  set (ignoreMe "${CLIENT_SIDE_BUILD}")
319
319
  set (ignoreMe "${JS_RUNTIME_DIR}")
320
320
  set (ignoreMe "${PLAYGROUND_APP_NAME}")
321
- set (ignoreMe "${HERMES_ENABLE_DEBUGGER}")
321
+ set (ignoreMe "${REANIMATED_PACKAGE_BUILD}")
@@ -1,6 +1,7 @@
1
1
  import com.android.Version
2
2
  import org.apache.tools.ant.filters.ReplaceTokens
3
-
3
+ import org.apache.tools.ant.taskdefs.condition.Os
4
+ import groovy.json.JsonSlurper
4
5
  import java.nio.file.Paths
5
6
 
6
7
  /**
@@ -43,12 +44,10 @@ def safeExtGet(prop, fallback) {
43
44
  }
44
45
 
45
46
  def safeAppExtGet(prop, fallback) {
46
- def appProject = null
47
- try {
48
- appProject = project(":app")
49
- } catch(Exception e) {
47
+ if (findProject(':app') == null) {
50
48
  return fallback
51
49
  }
50
+ def appProject = project(':app')
52
51
  appProject?.ext?.has(prop) ? appProject.ext.get(prop) : fallback
53
52
  }
54
53
 
@@ -150,7 +149,7 @@ def findReanimatedInstancesForPath(String path) {
150
149
  }.files
151
150
  }
152
151
 
153
- def assertNoMultipleInstances() {
152
+ def checkNoMultipleInstances() {
154
153
  // Assert there are no multiple installations of Reanimated
155
154
  Set<File> files
156
155
  if (projectDir.path.contains(rootDir.parent)) {
@@ -167,9 +166,9 @@ def assertNoMultipleInstances() {
167
166
  String parsedLocation = files.stream().map({
168
167
  File file -> "- " + file.toString().replace("/package.json", "")
169
168
  }).collect().join("\n")
170
- String exceptionMessage = "\nMultiple versions of Reanimated were detected. Only one " +
171
- "instance of react-native-reanimated can be installed in a project. You need to " +
172
- "resolve the conflict manually. Check out the documentation: " +
169
+ String exceptionMessage = "\n[react-native-reanimated] Multiple versions of Reanimated " +
170
+ "were detected. Only one instance of react-native-reanimated can be installed in a " +
171
+ "project. You need to resolve the conflict manually. Check out the documentation: " +
173
172
  "https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/" +
174
173
  "troubleshooting#multiple-versions-of-reanimated-were-detected \n\nConflict " +
175
174
  "between: \n" + parsedLocation + "\n";
@@ -177,6 +176,21 @@ def assertNoMultipleInstances() {
177
176
  }
178
177
  }
179
178
 
179
+ def getReanimatedVersion() {
180
+ def inputFile = file(projectDir.path + '/../package.json')
181
+ def json = new JsonSlurper().parseText(inputFile.text)
182
+ String reanimatedVersion = json.version
183
+ def (major, minor, patch) = reanimatedVersion.tokenize('.')
184
+ return major.toInteger()
185
+ }
186
+
187
+ def toPlatformFileString(String path) {
188
+ if (Os.isFamily(Os.FAMILY_WINDOWS)) {
189
+ path = path.replace(File.separatorChar, '/' as char)
190
+ }
191
+ return path
192
+ }
193
+
180
194
  boolean CLIENT_SIDE_BUILD = resolveClientSideBuild()
181
195
  if (CLIENT_SIDE_BUILD) {
182
196
  configurations.maybeCreate("default")
@@ -195,6 +209,7 @@ def REACT_NATIVE_VERSION = reactProperties.getProperty("VERSION_NAME")
195
209
  def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
196
210
  def FBJNI_VERSION = "0.3.0"
197
211
  def REANIMATED_PACKAGE_BUILD = System.getenv("REANIMATED_PACKAGE_BUILD")
212
+ def REANIMATED_MAJOR_VERSION = getReanimatedVersion()
198
213
 
199
214
  // We download various C++ open-source dependencies into downloads.
200
215
  // We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk.
@@ -440,7 +455,7 @@ android {
440
455
  "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
441
456
  "-DANDROID_TOOLCHAIN=clang",
442
457
  "-DBOOST_VERSION=${BOOST_VERSION}",
443
- "-DREACT_NATIVE_DIR=${reactNativeRootDir.path}",
458
+ "-DREACT_NATIVE_DIR=${toPlatformFileString(reactNativeRootDir.path)}",
444
459
  "-DJS_RUNTIME=${JS_RUNTIME}",
445
460
  "-DJS_RUNTIME_DIR=${jsRuntimeDir}",
446
461
  "-DCLIENT_SIDE_BUILD=${CLIENT_SIDE_BUILD}",
@@ -525,27 +540,57 @@ android {
525
540
  sourceSets.main {
526
541
  java {
527
542
  if (isNewArchitectureEnabled()) {
528
- srcDirs += [
529
- "src/fabric/java",
530
- ]
543
+ srcDirs += "src/fabric/java"
531
544
  } else {
532
- srcDirs += [
533
- "src/paper/java",
534
- ]
545
+ srcDirs += "src/paper/java"
546
+ }
547
+
548
+ // messageQueueThread
549
+ if (REANIMATED_MAJOR_VERSION > 2) {
550
+ if (REACT_NATIVE_MINOR_VERSION <= 67) {
551
+ srcDirs += "src/reactNativeVersionPatch/messageQueueThread/67"
552
+ } else {
553
+ srcDirs += "src/reactNativeVersionPatch/messageQueueThread/latest"
554
+ }
555
+ }
556
+
557
+ // UIImplementation
558
+ if (REACT_NATIVE_MINOR_VERSION <= 64) {
559
+ srcDirs += "src/reactNativeVersionPatch/UIImplementation/64"
560
+ } else {
561
+ srcDirs += "src/reactNativeVersionPatch/UIImplementation/latest"
562
+ }
563
+
564
+ // nativeHierarchyManager
565
+ if (REACT_NATIVE_MINOR_VERSION <= 62) {
566
+ srcDirs += "src/reactNativeVersionPatch/nativeHierarchyManager/62"
567
+ } else {
568
+ srcDirs += "src/reactNativeVersionPatch/nativeHierarchyManager/latest"
535
569
  }
536
570
  }
537
571
  }
538
572
  }
539
573
 
540
- def assertionTask = task assertNoMultipleInstancesTask {
574
+ def assertNoMultipleInstances = task assertNoMultipleInstancesTask {
541
575
  onlyIf { shouldAssertNoMultipleInstances() && CLIENT_SIDE_BUILD }
542
576
  doFirst {
543
- assertNoMultipleInstances()
577
+ checkNoMultipleInstances()
578
+ }
579
+ }
580
+
581
+ def assertNoReanimated2WithNewArchitecture = task assertNoReanimated2WithNewArchitectureTask {
582
+ onlyIf { isNewArchitectureEnabled() && REANIMATED_MAJOR_VERSION == 2 }
583
+ doFirst {
584
+ throw new Exception(
585
+ "\n[react-native-reanimated] Reanimated 2.x does not support Fabric. " +
586
+ "Please upgrade to 3.x to use Reanimated with the New Architecture. " +
587
+ "For details, see https://blog.swmansion.com/announcing-reanimated-3-16167428c5f7"
588
+ )
544
589
  }
545
590
  }
546
591
 
547
592
  tasks.preBuild {
548
- dependsOn assertionTask
593
+ dependsOn assertNoMultipleInstances, assertNoReanimated2WithNewArchitecture
549
594
  }
550
595
 
551
596
  task cleanCmakeCache() {
@@ -560,21 +605,7 @@ task printVersions {
560
605
  println "Gradle: ${project.gradle.gradleVersion}"
561
606
  }
562
607
 
563
- task Log {
564
- println("building Reanimated2")
565
- }
566
-
567
- task applyJavaPatches(type: Copy) {
568
- def patchDirectory = file("${projectDir}/rnVersionPatch/${REACT_NATIVE_MINOR_VERSION}")
569
- if (patchDirectory.exists()) {
570
- from ("${patchDirectory}") {
571
- include "**/*.java"
572
- }
573
- into ("${projectDir}/src/main/java/com/swmansion/reanimated")
574
- }
575
- }
576
-
577
- task createNativeDepsDirectories(dependsOn: applyJavaPatches) {
608
+ task createNativeDepsDirectories() {
578
609
  downloadsDir.mkdirs()
579
610
  thirdPartyNdkDir.mkdirs()
580
611
  }
@@ -967,8 +998,13 @@ task prepareThirdPartyNdkHeaders(dependsOn:[
967
998
  ) {}
968
999
 
969
1000
  def nativeBuildDependsOn(dependsOnTask) {
970
- def buildTasks = tasks.findAll({ task ->
971
- !task.name.contains("Clean") && (task.name.contains("externalNative") || task.name.contains("CMake")) })
1001
+ def buildTasks = tasks.findAll({ task -> (
1002
+ !task.name.contains("Clean")
1003
+ && (task.name.contains("externalNative")
1004
+ || task.name.contains("CMake")
1005
+ || task.name.contains("generateJsonModel")
1006
+ )
1007
+ ) })
972
1008
  buildTasks.forEach { task -> task.dependsOn(dependsOnTask) }
973
1009
  }
974
1010
 
@@ -20,7 +20,7 @@ class ReaUiImplementationProvider extends UIImplementationProvider {
20
20
  ViewManagerRegistry viewManagerRegistry,
21
21
  EventDispatcher eventDispatcher,
22
22
  int minTimeLeftInFrameForNonBatchedOperationMs) {
23
- return new ReanimatedUIImplementation(
23
+ return new com.facebook.react.uimanager.ReanimatedUIImplementation(
24
24
  reactContext,
25
25
  viewManagerRegistry,
26
26
  eventDispatcher,
@@ -0,0 +1,12 @@
1
+ package com.swmansion.reanimated;
2
+
3
+ import com.facebook.proguard.annotations.DoNotStrip;
4
+ import com.swmansion.reanimated.ReanimatedMessageQueueThreadBase;
5
+
6
+ @DoNotStrip
7
+ public class ReanimatedMessageQueueThread extends ReanimatedMessageQueueThreadBase {
8
+ @Override
9
+ public void runOnQueue(Runnable runnable) {
10
+ messageQueueThread.runOnQueue(runnable);
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ package com.swmansion.reanimated;
2
+
3
+ import com.facebook.proguard.annotations.DoNotStrip;
4
+ import com.swmansion.reanimated.ReanimatedMessageQueueThreadBase;
5
+
6
+ @DoNotStrip
7
+ public class ReanimatedMessageQueueThread extends ReanimatedMessageQueueThreadBase {
8
+ @Override
9
+ public boolean runOnQueue(Runnable runnable) {
10
+ return messageQueueThread.runOnQueue(runnable);
11
+ }
12
+ }
package/ios/REAModule.mm CHANGED
@@ -2,8 +2,7 @@
2
2
  #import <RNReanimated/REAModule.h>
3
3
  #import <RNReanimated/REANodesManager.h>
4
4
  #import <RNReanimated/REATransitionManager.h>
5
-
6
- #import "SingleInstanceChecker.h"
5
+ #import <RNReanimated/SingleInstanceChecker.h>
7
6
 
8
7
  using namespace reanimated;
9
8
 
@@ -15,14 +14,17 @@ typedef void (^AnimatedOperation)(REANodesManager *nodesManager);
15
14
  #ifdef DEBUG
16
15
  SingleInstanceChecker<REAModule> singleInstanceChecker_;
17
16
  #endif
17
+ bool hasListeners;
18
18
  }
19
19
 
20
20
  RCT_EXPORT_MODULE(ReanimatedModule);
21
21
 
22
+ #ifdef RCT_NEW_ARCH_ENABLED
22
23
  + (BOOL)requiresMainQueueSetup
23
24
  {
24
25
  return YES;
25
26
  }
27
+ #endif // RCT_NEW_ARCH_ENABLED
26
28
 
27
29
  - (void)invalidate
28
30
  {
@@ -193,4 +195,21 @@ RCT_EXPORT_METHOD(triggerRender)
193
195
  [_nodesManager dispatchEvent:event];
194
196
  }
195
197
 
198
+ - (void)startObserving
199
+ {
200
+ hasListeners = YES;
201
+ }
202
+
203
+ - (void)stopObserving
204
+ {
205
+ hasListeners = NO;
206
+ }
207
+
208
+ - (void)sendEventWithName:(NSString *)eventName body:(id)body
209
+ {
210
+ if (hasListeners) {
211
+ [super sendEventWithName:eventName body:body];
212
+ }
213
+ }
214
+
196
215
  @end
@@ -1,5 +1,5 @@
1
- #import "REAKeyboardEventObserver.h"
2
1
  #import <Foundation/Foundation.h>
2
+ #import <RNReanimated/REAKeyboardEventObserver.h>
3
3
  #import <React/RCTDefines.h>
4
4
  #import <React/RCTUIManager.h>
5
5
 
@@ -119,11 +119,10 @@ export default function createAnimatedComponent(Component, options) {
119
119
  setLocalRef: (ref) => {
120
120
  // TODO update config
121
121
  const tag = findNodeHandle(ref);
122
- if ((this.props.layout || this.props.entering || this.props.exiting) &&
122
+ if (!shouldBeUseWeb() &&
123
+ (this.props.layout || this.props.entering || this.props.exiting) &&
123
124
  tag != null) {
124
- if (!shouldBeUseWeb()) {
125
- enableLayoutAnimations(true, false);
126
- }
125
+ enableLayoutAnimations(true, false);
127
126
  let layout = this.props.layout ? this.props.layout : DefaultLayout;
128
127
  let entering = this.props.entering
129
128
  ? this.props.entering
@@ -1,53 +1,88 @@
1
1
  import { findNodeHandle } from 'react-native';
2
- import { shouldBeUseWeb } from './PlatformChecker';
2
+ import { isChromeDebugger, isWeb, shouldBeUseWeb } from './PlatformChecker';
3
3
  export function getTag(view) {
4
4
  return findNodeHandle(view);
5
5
  }
6
6
  const isNative = !shouldBeUseWeb();
7
- export function measure(animatedRef) {
8
- 'worklet';
9
- if (!isNative) {
10
- console.warn('[Reanimated] measure() cannot be used on web or Chrome Debugger');
11
- return null;
12
- }
13
- if (!_WORKLET) {
14
- console.warn('[Reanimated] measure() was called from the main JS context. Measure is ' +
15
- 'only available in the UI runtime. This may also happen if measure() ' +
16
- 'was called by a worklet in the useAnimatedStyle hook, because useAnimatedStyle ' +
17
- 'calls the given worklet on the JS runtime during render. If you want to ' +
18
- 'prevent this warning then wrap the call with `if (_WORKLET)`. Then it will ' +
19
- 'only be called on the UI runtime after the render has been completed.');
20
- return null;
21
- }
22
- const viewTag = animatedRef();
23
- if (viewTag === -1) {
24
- console.warn(`[Reanimated] The view with tag ${viewTag} is not a valid argument for measure(). This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`);
25
- return null;
26
- }
27
- const measured = _measure(viewTag);
28
- if (measured === null) {
29
- console.warn(`[Reanimated] The view with tag ${viewTag} has some undefined, not-yet-computed or meaningless value of \`LayoutMetrics\` type. This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`);
30
- return null;
31
- }
32
- else if (measured.x === -1234567) {
33
- console.warn(`[Reanimated] The view with tag ${viewTag} returned an invalid measurement response`);
34
- return null;
35
- }
36
- else if (isNaN(measured.x)) {
37
- console.warn(`[Reanimated] The view with tag ${viewTag} gets view-flattened on Android. To disable view-flattening, set \`collapsable={false}\` on this component.`);
7
+ export let measure;
8
+ if (isWeb()) {
9
+ measure = (animatedRef) => {
10
+ const element = animatedRef(); // TODO: fix typing of animated refs on web
11
+ const viewportOffset = element.getBoundingClientRect();
12
+ return {
13
+ width: element.offsetWidth,
14
+ height: element.offsetHeight,
15
+ x: element.offsetLeft,
16
+ y: element.offsetTop,
17
+ pageX: viewportOffset.left,
18
+ pageY: viewportOffset.top,
19
+ };
20
+ };
21
+ }
22
+ else if (isChromeDebugger()) {
23
+ measure = (_animatedRef) => {
24
+ console.warn('[Reanimated] measure() cannot be used with Chrome Debugger.');
38
25
  return null;
39
- }
40
- else {
41
- return measured;
42
- }
26
+ };
43
27
  }
44
- export function scrollTo(animatedRef, x, y, animated) {
45
- 'worklet';
46
- if (!_WORKLET || !isNative) {
47
- return;
48
- }
49
- const viewTag = animatedRef();
50
- _scrollTo(viewTag, x, y, animated);
28
+ else {
29
+ measure = (animatedRef) => {
30
+ 'worklet';
31
+ if (!_WORKLET) {
32
+ console.warn('[Reanimated] measure() was called from the main JS context. Measure is ' +
33
+ 'only available in the UI runtime. This may also happen if measure() ' +
34
+ 'was called by a worklet in the useAnimatedStyle hook, because useAnimatedStyle ' +
35
+ 'calls the given worklet on the JS runtime during render. If you want to ' +
36
+ 'prevent this warning then wrap the call with `if (_WORKLET)`. Then it will ' +
37
+ 'only be called on the UI runtime after the render has been completed.');
38
+ return null;
39
+ }
40
+ const viewTag = animatedRef();
41
+ if (viewTag === -1) {
42
+ console.warn(`[Reanimated] The view with tag ${viewTag} is not a valid argument for measure(). This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`);
43
+ return null;
44
+ }
45
+ const measured = _measure(viewTag);
46
+ if (measured === null) {
47
+ console.warn(`[Reanimated] The view with tag ${viewTag} has some undefined, not-yet-computed or meaningless value of \`LayoutMetrics\` type. This may be because the view is not currently rendered, which may not be a bug (e.g. an off-screen FlatList item).`);
48
+ return null;
49
+ }
50
+ else if (measured.x === -1234567) {
51
+ console.warn(`[Reanimated] The view with tag ${viewTag} returned an invalid measurement response.`);
52
+ return null;
53
+ }
54
+ else if (isNaN(measured.x)) {
55
+ console.warn(`[Reanimated] The view with tag ${viewTag} gets view-flattened on Android. To disable view-flattening, set \`collapsable={false}\` on this component.`);
56
+ return null;
57
+ }
58
+ else {
59
+ return measured;
60
+ }
61
+ };
62
+ }
63
+ export let scrollTo;
64
+ if (isWeb()) {
65
+ scrollTo = (animatedRef, x, y, animated) => {
66
+ 'worklet';
67
+ const element = animatedRef();
68
+ // @ts-ignore same call as in react-native-web
69
+ element.scrollTo({ x, y, animated });
70
+ };
71
+ }
72
+ else if (isNative) {
73
+ scrollTo = (animatedRef, x, y, animated) => {
74
+ 'worklet';
75
+ if (!_WORKLET) {
76
+ return;
77
+ }
78
+ const viewTag = animatedRef();
79
+ _scrollTo(viewTag, x, y, animated);
80
+ };
81
+ }
82
+ else {
83
+ scrollTo = (_animatedRef, _x, _y) => {
84
+ // no-op
85
+ };
51
86
  }
52
87
  export function setGestureState(handlerTag, newState) {
53
88
  'worklet';
@@ -1,13 +1,19 @@
1
- import { AnimatedStyle, StyleProps } from './commonTypes';
2
- import { ReanimatedConsole } from './core';
3
- import FrameCallbackRegistryUI from './frameCallback/FrameCallbackRegistryUI';
4
- import { MeasuredDimensions } from './NativeMethods';
5
- import { NativeReanimated } from './NativeReanimated/NativeReanimated';
1
+ import type {
2
+ AnimatedStyle,
3
+ StyleProps,
4
+ MeasuredDimensions,
5
+ } from './commonTypes';
6
+ import type { ReanimatedConsole } from './core';
7
+ import type { NativeReanimated } from './NativeReanimated/NativeReanimated';
8
+ import type { FrameCallbackRegistryUI } from './frameCallback/FrameCallbackRegistryUI';
9
+
6
10
  declare global {
7
11
  const _WORKLET: boolean;
8
- const _frameTimestamp: number;
12
+ const _frameTimestamp: number | null;
9
13
  const _eventTimestamp: number;
14
+ const __reanimatedModuleProxy: NativeReanimated;
10
15
  const _setGlobalConsole: (console?: ReanimatedConsole) => void;
16
+ const _log: (s: string) => void;
11
17
  const _getCurrentTime: () => number;
12
18
  const _stopObservingProgress: (tag: number, flag: boolean) => void;
13
19
  const _startObservingProgress: (
@@ -20,7 +26,7 @@ declare global {
20
26
  name: string,
21
27
  updates: StyleProps | AnimatedStyle
22
28
  ) => void;
23
- const _measure: (viewTag: number) => MeasuredDimensions | null;
29
+ const _measure: (viewTag: number) => MeasuredDimensions;
24
30
  const _scrollTo: (
25
31
  viewTag: number,
26
32
  x: number,
@@ -28,20 +34,40 @@ declare global {
28
34
  animated: boolean
29
35
  ) => void;
30
36
  const _chronoNow: () => number;
37
+ const performance: { now: () => number };
38
+ const LayoutAnimationRepository: {
39
+ configs: Record<string, unknown>;
40
+ registerConfig(tag: number, config: Record<string, unknown>): void;
41
+ removeConfig(tag: number): void;
42
+ startAnimationForTag(tag: number, type: string, yogaValues: unknown): void;
43
+ };
31
44
  const ReanimatedDataMock: {
32
45
  now: () => number;
33
46
  };
34
47
  const _frameCallbackRegistry: FrameCallbackRegistryUI;
35
48
  namespace NodeJS {
36
49
  interface Global {
37
- _setGlobalConsole: (console?: ReanimatedConsole) => void;
38
- _log: (s: string) => void;
39
- _setGestureState: () => void;
40
50
  _WORKLET: boolean;
41
- __reanimatedModuleProxy: NativeReanimated;
51
+ _IS_FABRIC: boolean;
42
52
  _frameTimestamp: number | null;
43
- _measure: () => MeasuredDimensions | null;
44
- _scrollTo: () => void;
53
+ _eventTimestamp: number;
54
+ __reanimatedModuleProxy: NativeReanimated;
55
+ _setGlobalConsole: (console?: ReanimatedConsole) => void;
56
+ _log: (s: string) => void;
57
+ _getCurrentTime: () => number;
58
+ _stopObservingProgress: (tag: number, flag: boolean) => void;
59
+ _startObservingProgress: (
60
+ tag: number,
61
+ flag: { value: boolean; _value: boolean }
62
+ ) => void;
63
+ _setGestureState: (handlerTag: number, newState: number) => void;
64
+ _measure: (viewTag: number) => MeasuredDimensions;
65
+ _scrollTo: (
66
+ viewTag: number,
67
+ x: number,
68
+ y: number,
69
+ animated: boolean
70
+ ) => void;
45
71
  _chronoNow: () => number;
46
72
  performance: { now: () => number };
47
73
  LayoutAnimationRepository: {
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import { findNodeHandle } from 'react-native';
3
- import { useEvent, useSharedValue } from '.';
3
+ import { useEvent } from './utils';
4
+ import { useSharedValue } from './useSharedValue';
4
5
  const subscribeForEvents = [
5
6
  'onScroll',
6
7
  'onScrollBeginDrag',
@@ -145,14 +145,21 @@ export const advanceAnimationByFrame = (count) => {
145
145
  jest.advanceTimersByTime(frameTime);
146
146
  };
147
147
  export const setUpTests = (userConfig = {}) => {
148
- let expect;
149
- try {
150
- expect = require('expect');
151
- }
152
- catch (_) {
153
- // for Jest in version 28+
154
- const { expect: expectModule } = require('@jest/globals');
148
+ let expect = global.expect;
149
+ if (expect === undefined) {
150
+ const expectModule = require('expect');
155
151
  expect = expectModule;
152
+ // Starting from Jest 28, "expect" package uses named exports instead of default export.
153
+ // So, requiring "expect" package doesn't give direct access to "expect" function anymore.
154
+ // It gives access to the module object instead.
155
+ // We use this info to detect if the project uses Jest 28 or higher.
156
+ if (typeof expect === 'object') {
157
+ const jestGlobals = require('@jest/globals');
158
+ expect = jestGlobals.expect;
159
+ }
160
+ if (expect === undefined || expect.extend === undefined) {
161
+ expect = expectModule.default;
162
+ }
156
163
  }
157
164
  require('setimmediate');
158
165
  frameTime = Math.round(1000 / config.fps);