react-native-screens 3.15.0 → 3.16.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 (51) hide show
  1. package/README.md +34 -1
  2. package/RNScreens.podspec +1 -4
  3. package/android/build.gradle +1 -1
  4. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +50 -21
  5. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +22 -21
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +7 -5
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +1 -2
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackViewManager.kt +9 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +3 -6
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -1
  11. package/ios/RNSScreen.h +1 -0
  12. package/ios/RNSScreen.mm +24 -4
  13. package/ios/RNSScreenStack.mm +2 -2
  14. package/ios/RNSScreenStackHeaderConfig.mm +2 -2
  15. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  16. package/lib/commonjs/index.js +4 -1
  17. package/lib/commonjs/index.js.map +1 -1
  18. package/lib/commonjs/index.native.js +36 -30
  19. package/lib/commonjs/index.native.js.map +1 -1
  20. package/lib/commonjs/native-stack/views/NativeStackView.js +3 -1
  21. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  22. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +1 -1
  23. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  24. package/lib/commonjs/reanimated/ReanimatedScreen.js +1 -1
  25. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -1
  26. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  27. package/lib/module/index.js +1 -0
  28. package/lib/module/index.js.map +1 -1
  29. package/lib/module/index.native.js +37 -30
  30. package/lib/module/index.native.js.map +1 -1
  31. package/lib/module/native-stack/views/NativeStackView.js +3 -1
  32. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  33. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +2 -2
  34. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  35. package/lib/module/reanimated/ReanimatedScreen.js +2 -2
  36. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -1
  37. package/lib/typescript/index.d.ts +1 -0
  38. package/lib/typescript/native-stack/types.d.ts +5 -0
  39. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  40. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  41. package/lib/typescript/types.d.ts +5 -0
  42. package/native-stack/README.md +6 -0
  43. package/package.json +1 -1
  44. package/src/fabric/ScreenNativeComponent.js +1 -1
  45. package/src/index.native.tsx +39 -26
  46. package/src/index.tsx +2 -0
  47. package/src/native-stack/types.tsx +5 -0
  48. package/src/native-stack/views/NativeStackView.tsx +2 -0
  49. package/src/reanimated/ReanimatedNativeStackScreen.tsx +2 -2
  50. package/src/reanimated/ReanimatedScreen.tsx +2 -2
  51. package/src/types.tsx +5 -0
package/README.md CHANGED
@@ -18,7 +18,31 @@ To learn about how to use `react-native-screens` with Fabric architecture, head
18
18
 
19
19
  ### iOS
20
20
 
21
- Installation on iOS should be completely handled with auto-linking, if you have ensured pods are installed after adding this module, no other actions should be necessary.
21
+ On iOS obtaining current device orientation [requires asking the system to generate orientation notifications](https://developer.apple.com/documentation/uikit/uidevice/1620053-orientation?language=objc). Our library uses them to enforce correct interface orientation when navigating between screens.
22
+ To make sure that there are no issues with screen orientation you should put following code in your `AppDelegate.m`:
23
+
24
+ ```objective-c
25
+ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
26
+ {
27
+ ...
28
+ #if !TARGET_OS_TV
29
+ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
30
+ #endif // !TARGET_OS_TV
31
+ ...
32
+ return YES:
33
+ }
34
+
35
+ - (void)applicationWillTerminate:(UIApplication *)application
36
+ {
37
+ #if !TARGET_OS_TV
38
+ [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
39
+ #endif // !TARGET_OS_TV
40
+ }
41
+ ```
42
+
43
+ You can see example of these changes being introduced in our [example applications](https://github.com/software-mansion/react-native-screens/blob/main/TestsExample/ios/TestsExample/AppDelegate.mm).
44
+
45
+ Other aspects of installation should be completely handled with auto-linking, just ensure you installed pods after adding this module.
22
46
 
23
47
  ### Android
24
48
 
@@ -71,9 +95,18 @@ Screens are already integrated with the React Native's most popular navigation l
71
95
 
72
96
  | version | react-native version |
73
97
  | ------- | -------------------- |
98
+ | 3.14.0+ | 0.64.0+ |
74
99
  | 3.0.0+ | 0.62.0+ |
75
100
  | 2.0.0+ | 0.60.0+ |
76
101
 
102
+ ### Support for Fabric
103
+ [Fabric](https://reactnative.dev/architecture/fabric-renderer) is React Native's new rendering system. As of [version `3.14.0`](https://github.com/software-mansion/react-native-screens/releases/tag/3.14.0) of this project, Fabric is supported only for react-native 0.69+. Support for `0.68.x` has been dropped.
104
+
105
+ | version | react-native version |
106
+ | ------- | -------------------- |
107
+ | 3.14.0+ | 0.69.0+ |
108
+
109
+
77
110
  ## Usage with [react-navigation](https://github.com/react-navigation/react-navigation)
78
111
 
79
112
  Screens support is built into [react-navigation](https://github.com/react-navigation/react-navigation) starting from version [2.14.0](https://github.com/react-navigation/react-navigation/releases/tag/2.14.0) for all the different navigator types (stack, tab, drawer, etc).
package/RNScreens.podspec CHANGED
@@ -4,9 +4,6 @@ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
4
 
5
5
  fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
6
6
 
7
- # folly_version must match the version used in React Native
8
- # See folly_version in react-native/React/FBReactNativeSpec/FBReactNativeSpec.podspec
9
- folly_version = '2021.06.28.00-v2'
10
7
  folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
11
8
 
12
9
  Pod::Spec.new do |s|
@@ -36,7 +33,7 @@ Pod::Spec.new do |s|
36
33
  s.dependency "React"
37
34
  s.dependency "React-RCTFabric"
38
35
  s.dependency "React-Codegen"
39
- s.dependency "RCT-Folly", folly_version
36
+ s.dependency "RCT-Folly"
40
37
  s.dependency "RCTRequired"
41
38
  s.dependency "RCTTypeSafety"
42
39
  s.dependency "ReactCommon/turbomodule/core"
@@ -50,7 +50,7 @@ android {
50
50
  }
51
51
 
52
52
  defaultConfig {
53
- minSdkVersion safeExtGet('minSdkVersion', 16)
53
+ minSdkVersion safeExtGet('minSdkVersion', 21)
54
54
  targetSdkVersion safeExtGet('targetSdkVersion', 22)
55
55
  versionCode 1
56
56
  versionName "1.0"
@@ -135,6 +135,41 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
135
135
  performUpdatesNow()
136
136
  }
137
137
 
138
+ private fun findFragmentManagerForReactRootView(rootView: ReactRootView): FragmentManager {
139
+ var context = rootView.context
140
+
141
+ // ReactRootView is expected to be initialized with the main React Activity as a context but
142
+ // in case of Expo the activity is wrapped in ContextWrapper and we need to unwrap it
143
+ while (context !is FragmentActivity && context is ContextWrapper) {
144
+ context = context.baseContext
145
+ }
146
+
147
+ check(context is FragmentActivity) {
148
+ "In order to use RNScreens components your app's activity need to extend ReactActivity"
149
+ }
150
+
151
+ // In case React Native is loaded on a Fragment (not directly in activity) we need to find
152
+ // fragment manager whose fragment's view is ReactRootView. As of now, we detect such case by
153
+ // checking whether any fragments are attached to activity which hosts ReactRootView.
154
+ // See: https://github.com/software-mansion/react-native-screens/issues/1506 on why the cases
155
+ // must be treated separately.
156
+ return if (context.supportFragmentManager.fragments.isEmpty()) {
157
+ // We are in standard React Native application w/o custom native navigation based on fragments.
158
+ context.supportFragmentManager
159
+ } else {
160
+ // We are in some custom setup & we want to use the closest fragment manager in hierarchy.
161
+ // `findFragment` method throws IllegalStateException when it fails to resolve appropriate
162
+ // fragment. It might happen when e.g. React Native is loaded directly in Activity
163
+ // but some custom fragments are still used. Such use case seems highly unlikely
164
+ // so, as for now we let application crash.
165
+ try {
166
+ FragmentManager.findFragment<Fragment>(rootView).childFragmentManager
167
+ } catch (ex: IllegalStateException) {
168
+ throw IllegalStateException("Failed to find fragment for React Root View")
169
+ }
170
+ }
171
+ }
172
+
138
173
  private fun setupFragmentManager() {
139
174
  var parent: ViewParent = this
140
175
  // We traverse view hierarchy up until we find screen parent or a root view
@@ -146,28 +181,22 @@ open class ScreenContainer<T : ScreenFragment>(context: Context?) : ViewGroup(co
146
181
  // If parent is of type Screen it means we are inside a nested fragment structure.
147
182
  // Otherwise we expect to connect directly with root view and get root fragment manager
148
183
  if (parent is Screen) {
149
- val screenFragment = parent.fragment
150
- check(screenFragment != null) { "Parent Screen does not have its Fragment attached" }
151
- mParentScreenFragment = screenFragment
152
- screenFragment.registerChildScreenContainer(this)
153
- setFragmentManager(screenFragment.childFragmentManager)
154
- return
155
- }
156
-
157
- // we expect top level view to be of type ReactRootView, this isn't really necessary but in
158
- // order to find root view we test if parent is null. This could potentially happen also when
159
- // the view is detached from the hierarchy and that test would not correctly indicate the root
160
- // view. So in order to make sure we indeed reached the root we test if it is of a correct type.
161
- // This allows us to provide a more descriptive error message for the aforementioned case.
162
- check(parent is ReactRootView) { "ScreenContainer is not attached under ReactRootView" }
163
- // ReactRootView is expected to be initialized with the main React Activity as a context but
164
- // in case of Expo the activity is wrapped in ContextWrapper and we need to unwrap it
165
- var context = parent.context
166
- while (context !is FragmentActivity && context is ContextWrapper) {
167
- context = context.baseContext
184
+ checkNotNull(
185
+ parent.fragment?.let { screenFragment ->
186
+ mParentScreenFragment = screenFragment
187
+ screenFragment.registerChildScreenContainer(this)
188
+ setFragmentManager(screenFragment.childFragmentManager)
189
+ }
190
+ ) { "Parent Screen does not have its Fragment attached" }
191
+ } else {
192
+ // we expect top level view to be of type ReactRootView, this isn't really necessary but in
193
+ // order to find root view we test if parent is null. This could potentially happen also when
194
+ // the view is detached from the hierarchy and that test would not correctly indicate the root
195
+ // view. So in order to make sure we indeed reached the root we test if it is of a correct type.
196
+ // This allows us to provide a more descriptive error message for the aforementioned case.
197
+ check(parent is ReactRootView) { "ScreenContainer is not attached under ReactRootView" }
198
+ setFragmentManager(findFragmentManagerForReactRootView(parent))
168
199
  }
169
- check(context is FragmentActivity) { "In order to use RNScreens components your app's activity need to extend ReactActivity" }
170
- setFragmentManager(context.supportFragmentManager)
171
200
  }
172
201
 
173
202
  protected fun createTransaction(): FragmentTransaction {
@@ -12,8 +12,9 @@ import android.widget.FrameLayout
12
12
  import androidx.fragment.app.Fragment
13
13
  import com.facebook.react.bridge.ReactContext
14
14
  import com.facebook.react.bridge.UiThreadUtil
15
- import com.facebook.react.uimanager.UIManagerModule
15
+ import com.facebook.react.uimanager.UIManagerHelper
16
16
  import com.facebook.react.uimanager.events.Event
17
+ import com.facebook.react.uimanager.events.EventDispatcher
17
18
  import com.swmansion.rnscreens.events.HeaderBackButtonClickedEvent
18
19
  import com.swmansion.rnscreens.events.ScreenAppearEvent
19
20
  import com.swmansion.rnscreens.events.ScreenDisappearEvent
@@ -204,10 +205,10 @@ open class ScreenFragment : Fragment {
204
205
  ScreenLifecycleEvent.WillDisappear -> ScreenWillDisappearEvent(it.id)
205
206
  ScreenLifecycleEvent.Disappear -> ScreenDisappearEvent(it.id)
206
207
  }
207
- (it.context as ReactContext)
208
- .getNativeModule(UIManagerModule::class.java)
209
- ?.eventDispatcher
210
- ?.dispatchEvent(lifecycleEvent)
208
+ val screenContext = screen.context as ReactContext
209
+ val eventDispatcher: EventDispatcher? =
210
+ UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
211
+ eventDispatcher?.dispatchEvent(lifecycleEvent)
211
212
  fragment.dispatchEventInChildContainers(event)
212
213
  }
213
214
  }
@@ -224,10 +225,10 @@ open class ScreenFragment : Fragment {
224
225
  }
225
226
 
226
227
  fun dispatchHeaderBackButtonClickedEvent() {
227
- (screen.context as ReactContext)
228
- .getNativeModule(UIManagerModule::class.java)
229
- ?.eventDispatcher
230
- ?.dispatchEvent(HeaderBackButtonClickedEvent(screen.id))
228
+ val screenContext = screen.context as ReactContext
229
+ val eventDispatcher: EventDispatcher? =
230
+ UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
231
+ eventDispatcher?.dispatchEvent(HeaderBackButtonClickedEvent(screen.id))
231
232
  }
232
233
 
233
234
  fun dispatchTransitionProgress(alpha: Float, closing: Boolean) {
@@ -242,14 +243,14 @@ open class ScreenFragment : Fragment {
242
243
  val coalescingKey = (if (mProgress == 0.0f) 1 else if (mProgress == 1.0f) 2 else 3).toShort()
243
244
  val container: ScreenContainer<*>? = screen.container
244
245
  val goingForward = if (container is ScreenStack) container.goingForward else false
245
- (screen.context as ReactContext)
246
- .getNativeModule(UIManagerModule::class.java)
247
- ?.eventDispatcher
248
- ?.dispatchEvent(
249
- ScreenTransitionProgressEvent(
250
- screen.id, mProgress, closing, goingForward, coalescingKey
251
- )
246
+ val screenContext = screen.context as ReactContext
247
+ val eventDispatcher: EventDispatcher? =
248
+ UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
249
+ eventDispatcher?.dispatchEvent(
250
+ ScreenTransitionProgressEvent(
251
+ screen.id, mProgress, closing, goingForward, coalescingKey
252
252
  )
253
+ )
253
254
  }
254
255
  }
255
256
  }
@@ -302,11 +303,11 @@ open class ScreenFragment : Fragment {
302
303
  val container = screen.container
303
304
  if (container == null || !container.hasScreen(this)) {
304
305
  // we only send dismissed even when the screen has been removed from its container
305
- if (screen.context is ReactContext) {
306
- (screen.context as ReactContext)
307
- .getNativeModule(UIManagerModule::class.java)
308
- ?.eventDispatcher
309
- ?.dispatchEvent(ScreenDismissedEvent(screen.id))
306
+ val screenContext = screen.context
307
+ if (screenContext is ReactContext) {
308
+ val eventDispatcher: EventDispatcher? =
309
+ UIManagerHelper.getEventDispatcherForReactTag(screenContext, screen.id)
310
+ eventDispatcher?.dispatchEvent(ScreenDismissedEvent(screen.id))
310
311
  }
311
312
  }
312
313
  mChildScreenContainers.clear()
@@ -4,7 +4,8 @@ import android.content.Context
4
4
  import android.graphics.Canvas
5
5
  import android.view.View
6
6
  import com.facebook.react.bridge.ReactContext
7
- import com.facebook.react.uimanager.UIManagerModule
7
+ import com.facebook.react.uimanager.UIManagerHelper
8
+ import com.facebook.react.uimanager.events.EventDispatcher
8
9
  import com.swmansion.rnscreens.Screen.StackAnimation
9
10
  import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
10
11
  import java.util.Collections
@@ -67,10 +68,11 @@ class ScreenStack(context: Context?) : ScreenContainer<ScreenStackFragment>(cont
67
68
  }
68
69
 
69
70
  private fun dispatchOnFinishTransitioning() {
70
- (context as ReactContext)
71
- .getNativeModule(UIManagerModule::class.java)
72
- ?.eventDispatcher
73
- ?.dispatchEvent(StackFinishTransitioningEvent(id))
71
+ val eventDispatcher: EventDispatcher? =
72
+ UIManagerHelper.getEventDispatcherForReactTag((context as ReactContext), id)
73
+ eventDispatcher?.dispatchEvent(
74
+ StackFinishTransitioningEvent(id)
75
+ )
74
76
  }
75
77
 
76
78
  override fun removeScreenAt(index: Int) {
@@ -130,7 +130,6 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
130
130
  return null
131
131
  }
132
132
 
133
- @SuppressLint("ObsoleteSdkInt") // to be removed when support for < 0.64 is dropped
134
133
  fun onUpdate() {
135
134
  val stack = screenStack
136
135
  val isTop = stack == null || stack.topScreen == parent
@@ -138,7 +137,7 @@ class ScreenStackHeaderConfig(context: Context) : ViewGroup(context) {
138
137
  return
139
138
  }
140
139
  val activity = screenFragment?.activity as AppCompatActivity? ?: return
141
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && mDirection != null) {
140
+ if (mDirection != null) {
142
141
  if (mDirection == "rtl") {
143
142
  toolbar.layoutDirection = LAYOUT_DIRECTION_RTL
144
143
  } else if (mDirection == "ltr") {
@@ -3,6 +3,7 @@ package com.swmansion.rnscreens
3
3
  import android.view.View
4
4
  import android.view.ViewGroup
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.common.MapBuilder
6
7
  import com.facebook.react.module.annotations.ReactModule
7
8
  import com.facebook.react.uimanager.LayoutShadowNode
8
9
  import com.facebook.react.uimanager.ThemedReactContext
@@ -10,6 +11,7 @@ import com.facebook.react.uimanager.ViewGroupManager
10
11
  import com.facebook.react.uimanager.ViewManagerDelegate
11
12
  import com.facebook.react.viewmanagers.RNSScreenStackManagerDelegate
12
13
  import com.facebook.react.viewmanagers.RNSScreenStackManagerInterface
14
+ import com.swmansion.rnscreens.events.StackFinishTransitioningEvent
13
15
 
14
16
  @ReactModule(name = ScreenStackViewManager.REACT_CLASS)
15
17
  class ScreenStackViewManager : ViewGroupManager<ScreenStack>(), RNSScreenStackManagerInterface<ScreenStack> {
@@ -81,6 +83,13 @@ class ScreenStackViewManager : ViewGroupManager<ScreenStack>(), RNSScreenStackMa
81
83
  return mDelegate
82
84
  }
83
85
 
86
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
87
+ return MapBuilder.of(
88
+ StackFinishTransitioningEvent.EVENT_NAME,
89
+ MapBuilder.of("registrationName", "onFinishTransitioning"),
90
+ )
91
+ }
92
+
84
93
  companion object {
85
94
  const val REACT_CLASS = "RNSScreenStack"
86
95
  }
@@ -162,7 +162,7 @@ class ScreenViewManager : ViewGroupManager<Screen>(), RNSScreenManagerInterface<
162
162
  override fun setSwipeDirection(view: Screen?, value: String?) = Unit
163
163
 
164
164
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
165
- val map: MutableMap<String, Any> = MapBuilder.of(
165
+ return MapBuilder.of(
166
166
  ScreenDismissedEvent.EVENT_NAME,
167
167
  MapBuilder.of("registrationName", "onDismissed"),
168
168
  ScreenWillAppearEvent.EVENT_NAME,
@@ -173,14 +173,11 @@ class ScreenViewManager : ViewGroupManager<Screen>(), RNSScreenManagerInterface<
173
173
  MapBuilder.of("registrationName", "onWillDisappear"),
174
174
  ScreenDisappearEvent.EVENT_NAME,
175
175
  MapBuilder.of("registrationName", "onDisappear"),
176
- StackFinishTransitioningEvent.EVENT_NAME,
177
- MapBuilder.of("registrationName", "onFinishTransitioning"),
176
+ HeaderBackButtonClickedEvent.EVENT_NAME,
177
+ MapBuilder.of("registrationName", "onHeaderBackButtonClicked"),
178
178
  ScreenTransitionProgressEvent.EVENT_NAME,
179
179
  MapBuilder.of("registrationName", "onTransitionProgress")
180
180
  )
181
- // there is no `MapBuilder.of` with more than 7 items
182
- map[HeaderBackButtonClickedEvent.EVENT_NAME] = MapBuilder.of("registrationName", "onHeaderBackButtonClicked")
183
- return map
184
181
  }
185
182
 
186
183
  protected override fun getDelegate(): ViewManagerDelegate<Screen> {
@@ -48,7 +48,7 @@ object ScreenWindowTraits {
48
48
 
49
49
  @SuppressLint("ObsoleteSdkInt") // to be removed when support for < 0.64 is dropped
50
50
  internal fun setColor(screen: Screen, activity: Activity?, context: ReactContext?) {
51
- if (activity == null || context == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
51
+ if (activity == null || context == null) {
52
52
  return
53
53
  }
54
54
  if (mDefaultStatusBarColor == null) {
package/ios/RNSScreen.h CHANGED
@@ -103,6 +103,7 @@ NS_ASSUME_NONNULL_BEGIN
103
103
  #endif
104
104
 
105
105
  - (void)notifyTransitionProgress:(double)progress closing:(BOOL)closing goingForward:(BOOL)goingForward;
106
+ - (BOOL)isModal;
106
107
 
107
108
  @end
108
109
 
package/ios/RNSScreen.mm CHANGED
@@ -508,6 +508,11 @@
508
508
  }
509
509
  }
510
510
 
511
+ - (BOOL)isModal
512
+ {
513
+ return self.stackPresentation != RNSScreenStackPresentationPush;
514
+ }
515
+
511
516
  #pragma mark - Fabric specific
512
517
  #ifdef RN_FABRIC_ENABLED
513
518
 
@@ -545,6 +550,17 @@
545
550
  _dismissed = NO;
546
551
  _state.reset();
547
552
  _touchHandler = nil;
553
+
554
+ // We set this prop to default value here to workaround view-recycling.
555
+ // Let's assume the view has had _stackPresentation == <some modal stack presentation> set
556
+ // before below line was executed. Then, when instantiated again (with the same modal presentation)
557
+ // updateProps:oldProps: method would be called and setter for stack presentation would not be called.
558
+ // This is crucial as in that setter we register `self.controller` as a delegate
559
+ // (UIAdaptivePresentationControllerDelegate) to presentation controller and this leads to buggy modal behaviour as we
560
+ // rely on UIAdaptivePresentationControllerDelegate callbacks. Restoring the default value and then comparing against
561
+ // it in updateProps:oldProps: allows for setter to be called, however if there was some additional logic to execute
562
+ // when stackPresentation is set to "push" the setter would not be triggered.
563
+ _stackPresentation = RNSScreenStackPresentationPush;
548
564
  }
549
565
 
550
566
  - (void)updateProps:(facebook::react::Props::Shared const &)props
@@ -598,9 +614,12 @@
598
614
  }
599
615
  #endif
600
616
 
601
- if (newScreenProps.stackPresentation != oldScreenProps.stackPresentation) {
602
- [self
603
- setStackPresentation:[RNSConvert RNSScreenStackPresentationFromCppEquivalent:newScreenProps.stackPresentation]];
617
+ // Notice that we compare against _stackPresentation, not oldScreenProps.stackPresentation.
618
+ // See comment in prepareForRecycle method for explanation.
619
+ RNSScreenStackPresentation newStackPresentation =
620
+ [RNSConvert RNSScreenStackPresentationFromCppEquivalent:newScreenProps.stackPresentation];
621
+ if (newStackPresentation != _stackPresentation) {
622
+ [self setStackPresentation:newStackPresentation];
604
623
  }
605
624
 
606
625
  if (newScreenProps.stackAnimation != oldScreenProps.stackAnimation) {
@@ -739,7 +758,8 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
739
758
  - (void)viewWillDisappear:(BOOL)animated
740
759
  {
741
760
  [super viewWillDisappear:animated];
742
- if (!self.transitionCoordinator.isInteractive) {
761
+ // self.navigationController might be null when we are dismissing a modal
762
+ if (!self.transitionCoordinator.isInteractive && self.navigationController != nil) {
743
763
  // user might have long pressed ios 14 back button item,
744
764
  // so he can go back more than one screen and we need to dismiss more screens in JS stack then.
745
765
  // We check it by calculating the difference between the index of currently displayed screen
@@ -823,7 +823,7 @@
823
823
  RNSScreenView *topScreen = _reactSubviews.lastObject;
824
824
 
825
825
  if (![topScreen isKindOfClass:[RNSScreenView class]] || !topScreen.gestureEnabled ||
826
- _controller.viewControllers.count < 2) {
826
+ _controller.viewControllers.count < 2 || [topScreen isModal]) {
827
827
  return NO;
828
828
  }
829
829
 
@@ -969,7 +969,7 @@
969
969
  - (void)mountingTransactionWillMount:(facebook::react::MountingTransaction const &)transaction
970
970
  withSurfaceTelemetry:(facebook::react::SurfaceTelemetry const &)surfaceTelemetry
971
971
  {
972
- for (auto mutation : transaction.getMutations()) {
972
+ for (auto &mutation : transaction.getMutations()) {
973
973
  if (mutation.type == facebook::react::ShadowViewMutation::Type::Remove &&
974
974
  mutation.parentShadowView.componentName != nil &&
975
975
  strcmp(mutation.parentShadowView.componentName, "RNSScreenStack") == 0) {
@@ -118,7 +118,7 @@
118
118
  }
119
119
 
120
120
  // we want updates sent to the VC below modal too since it is also visible
121
- BOOL isPresentingVC = vc.presentedViewController == nextVC;
121
+ BOOL isPresentingVC = nextVC != nil && vc.presentedViewController == nextVC;
122
122
 
123
123
  BOOL isInFullScreenModal = nav == nil && _screenView.stackPresentation == RNSScreenStackPresentationFullScreenModal;
124
124
  // if nav is nil, it means we can be in a fullScreen modal, so there is no nextVC, but we still want to update
@@ -580,7 +580,7 @@
580
580
  }
581
581
  case RNSScreenStackHeaderSubviewTypeBackButton: {
582
582
  #ifdef RN_FABRIC_ENABLED
583
- RCTLogWarn(@"Back button subivew is not yet Fabric compatible in react-native-screens");
583
+ RCTLogWarn(@"Back button subview is not yet Fabric compatible in react-native-screens");
584
584
  #endif
585
585
  break;
586
586
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["ScreenNativeComponent.js"],"names":["interfaceOnly"],"mappings":";;;;;;;AAKA;;;;AALA;AACA;AACA;AACA;;AACA;eA0FgB,qCAAoC,WAApC,EAAiD;AAC/DA,EAAAA,aAAa,EAAE;AADgD,CAAjD,C","sourcesContent":["/**\n * @flow strict-local\n * @format\n */\n/* eslint-disable */\nimport codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';\nimport type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes';\nimport type { HostComponent } from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';\nimport type { ColorValue } from 'react-native/Libraries/StyleSheet/StyleSheet';\nimport type {\n BubblingEventHandler,\n WithDefault,\n Int32,\n} from 'react-native/Libraries/Types/CodegenTypes';\n\ntype ScreenEvent = $ReadOnly<{||}>;\n\ntype ScreenDismissedEvent = $ReadOnly<{|\n dismissCount: Int32,\n|}>;\n\ntype TransitionProgressEvent = $ReadOnly<{|\n progress: Double,\n closing: Int32,\n goingForward: Int32,\n|}>;\n\ntype GestureResponseDistanceType = $ReadOnly<{|\n start: Float,\n end: Float,\n top: Float,\n bottom: Float,\n|}>;\n\ntype StackPresentation =\n | 'push'\n | 'modal'\n | 'transparentModal'\n | 'fullScreenModal'\n | 'formSheet'\n | 'containedModal'\n | 'containedTransparentModal';\n\ntype StackAnimation =\n | 'default'\n | 'flip'\n | 'simple_push'\n | 'none'\n | 'fade'\n | 'slide_from_right'\n | 'slide_from_left'\n | 'slide_from_bottom'\n | 'fade_from_bottom';\n\ntype SwipeDirection = 'vertical' | 'horizontal';\n\ntype ReplaceAnimation = 'pop' | 'push';\n\nexport type NativeProps = $ReadOnly<{|\n ...ViewProps,\n onAppear?: ?BubblingEventHandler<ScreenEvent>,\n onDisappear?: ?BubblingEventHandler<ScreenEvent>,\n onDismissed?: ?BubblingEventHandler<ScreenDismissedEvent>,\n onNativeDismissCancelled?: ?BubblingEventHandler<ScreenDismissedEvent>,\n onWillAppear?: ?BubblingEventHandler<ScreenEvent>,\n onWillDisappear?: ?BubblingEventHandler<ScreenEvent>,\n onTransitionProgress?: ?BubblingEventHandler<TransitionProgressEvent>,\n customAnimationOnSwipe?: boolean,\n fullScreenSwipeEnabled?: boolean,\n homeIndicatorHidden?: boolean,\n preventNativeDismiss?: boolean,\n gestureEnabled?: WithDefault<boolean, true>,\n statusBarColor?: ColorValue,\n statusBarHidden?: boolean,\n screenOrientation?: string,\n statusBarAnimation?: string,\n statusBarStyle?: string,\n statusBarTranslucent?: boolean,\n gestureResponseDistance?: GestureResponseDistanceType,\n stackPresentation?: WithDefault<StackPresentation, 'push'>,\n stackAnimation?: WithDefault<StackAnimation, 'default'>,\n transitionDuration?: WithDefault<Int32, 350>,\n replaceAnimation?: WithDefault<ReplaceAnimation, 'pop'>,\n swipeDirection?: WithDefault<SwipeDirection, 'horizontal'>,\n hideKeyboardOnSwipe?: boolean,\n activityState?: WithDefault<Float, -1.0>,\n // TODO: implement these props on iOS\n navigationBarColor?: ColorValue,\n navigationBarHidden?: boolean,\n nativeBackButtonDismissalEnabled?: boolean,\n|}>;\n\ntype ComponentType = HostComponent<NativeProps>;\n\nexport default (codegenNativeComponent<NativeProps>('RNSScreen', {\n interfaceOnly: true,\n}): ComponentType);\n"]}
1
+ {"version":3,"sources":["ScreenNativeComponent.js"],"names":["interfaceOnly"],"mappings":";;;;;;;AAKA;;;;AALA;AACA;AACA;AACA;;AACA;eA0FgB,qCAAoC,WAApC,EAAiD;AAC/DA,EAAAA,aAAa,EAAE;AADgD,CAAjD,C","sourcesContent":["/**\n * @flow strict-local\n * @format\n */\n/* eslint-disable */\nimport codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';\nimport type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes';\nimport type { HostComponent } from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';\nimport type { ColorValue } from 'react-native/Libraries/StyleSheet/StyleSheet';\nimport type {\n BubblingEventHandler,\n WithDefault,\n Int32,\n} from 'react-native/Libraries/Types/CodegenTypes';\n\ntype ScreenEvent = $ReadOnly<{||}>;\n\ntype ScreenDismissedEvent = $ReadOnly<{|\n dismissCount: Int32,\n|}>;\n\ntype TransitionProgressEvent = $ReadOnly<{|\n progress: Double,\n closing: Int32,\n goingForward: Int32,\n|}>;\n\ntype GestureResponseDistanceType = $ReadOnly<{|\n start: Float,\n end: Float,\n top: Float,\n bottom: Float,\n|}>;\n\ntype StackPresentation =\n | 'push'\n | 'modal'\n | 'transparentModal'\n | 'fullScreenModal'\n | 'formSheet'\n | 'containedModal'\n | 'containedTransparentModal';\n\ntype StackAnimation =\n | 'default'\n | 'flip'\n | 'simple_push'\n | 'none'\n | 'fade'\n | 'slide_from_right'\n | 'slide_from_left'\n | 'slide_from_bottom'\n | 'fade_from_bottom';\n\ntype SwipeDirection = 'vertical' | 'horizontal';\n\ntype ReplaceAnimation = 'pop' | 'push';\n\nexport type NativeProps = $ReadOnly<{|\n ...ViewProps,\n onAppear?: ?BubblingEventHandler<ScreenEvent>,\n onDisappear?: ?BubblingEventHandler<ScreenEvent>,\n onDismissed?: ?BubblingEventHandler<ScreenDismissedEvent>,\n onNativeDismissCancelled?: ?BubblingEventHandler<ScreenDismissedEvent>,\n onWillAppear?: ?BubblingEventHandler<ScreenEvent>,\n onWillDisappear?: ?BubblingEventHandler<ScreenEvent>,\n onTransitionProgress?: ?BubblingEventHandler<TransitionProgressEvent>,\n customAnimationOnSwipe?: boolean,\n fullScreenSwipeEnabled?: boolean,\n homeIndicatorHidden?: boolean,\n preventNativeDismiss?: boolean,\n gestureEnabled?: WithDefault<boolean, true>,\n statusBarColor?: ColorValue,\n statusBarHidden?: boolean,\n screenOrientation?: string,\n statusBarAnimation?: string,\n statusBarStyle?: string,\n statusBarTranslucent?: boolean,\n gestureResponseDistance?: GestureResponseDistanceType,\n stackPresentation?: WithDefault<StackPresentation, 'push'>,\n stackAnimation?: WithDefault<StackAnimation, 'default'>,\n transitionDuration?: WithDefault<Int32, 350>,\n replaceAnimation?: WithDefault<ReplaceAnimation, 'pop'>,\n swipeDirection?: WithDefault<SwipeDirection, 'horizontal'>,\n hideKeyboardOnSwipe?: boolean,\n activityState?: WithDefault<Float, -1.0>,\n navigationBarColor?: ColorValue,\n navigationBarHidden?: boolean,\n nativeBackButtonDismissalEnabled?: boolean,\n onHeaderBackButtonClicked?: ?BubblingEventHandler<ScreenEvent>,\n|}>;\n\ntype ComponentType = HostComponent<NativeProps>;\n\nexport default (codegenNativeComponent<NativeProps>('RNSScreen', {\n interfaceOnly: true,\n}): ComponentType);\n"]}
@@ -9,6 +9,7 @@ var _exportNames = {
9
9
  enableFreeze: true,
10
10
  NativeScreen: true,
11
11
  Screen: true,
12
+ InnerScreen: true,
12
13
  ScreenContext: true,
13
14
  ScreenContainer: true,
14
15
  NativeScreenContainer: true,
@@ -49,7 +50,7 @@ Object.defineProperty(exports, "executeNativeBackPress", {
49
50
  return _utils.executeNativeBackPress;
50
51
  }
51
52
  });
52
- exports.shouldUseActivityState = exports.ScreenStackHeaderSubview = exports.SearchBar = exports.ScreenStackHeaderConfig = exports.ScreenStackHeaderSearchBarView = exports.ScreenStackHeaderCenterView = exports.ScreenStackHeaderLeftView = exports.ScreenStackHeaderRightView = exports.ScreenStackHeaderBackButtonImage = exports.FullWindowOverlay = exports.ScreenStack = exports.NativeScreenNavigationContainer = exports.NativeScreenContainer = exports.ScreenContainer = exports.ScreenContext = exports.Screen = exports.NativeScreen = void 0;
53
+ exports.shouldUseActivityState = exports.ScreenStackHeaderSubview = exports.SearchBar = exports.ScreenStackHeaderConfig = exports.ScreenStackHeaderSearchBarView = exports.ScreenStackHeaderCenterView = exports.ScreenStackHeaderLeftView = exports.ScreenStackHeaderRightView = exports.ScreenStackHeaderBackButtonImage = exports.FullWindowOverlay = exports.ScreenStack = exports.NativeScreenNavigationContainer = exports.NativeScreenContainer = exports.ScreenContainer = exports.ScreenContext = exports.InnerScreen = exports.Screen = exports.NativeScreen = void 0;
53
54
 
54
55
  var _react = _interopRequireDefault(require("react"));
55
56
 
@@ -126,6 +127,8 @@ exports.NativeScreen = NativeScreen;
126
127
  const Screen = _reactNative.Animated.createAnimatedComponent(NativeScreen);
127
128
 
128
129
  exports.Screen = Screen;
130
+ const InnerScreen = _reactNative.View;
131
+ exports.InnerScreen = InnerScreen;
129
132
 
130
133
  const ScreenContext = /*#__PURE__*/_react.default.createContext(Screen);
131
134
 
@@ -1 +1 @@
1
- {"version":3,"sources":["index.tsx"],"names":["ENABLE_SCREENS","enableScreens","shouldEnableScreens","screensEnabled","enableFreeze","shouldEnableReactFreeze","NativeScreen","React","Component","render","active","activityState","style","enabled","rest","props","undefined","display","Screen","Animated","createAnimatedComponent","ScreenContext","createContext","ScreenContainer","View","NativeScreenContainer","NativeScreenNavigationContainer","ScreenStack","FullWindowOverlay","ScreenStackHeaderBackButtonImage","ScreenStackHeaderRightView","ScreenStackHeaderLeftView","ScreenStackHeaderCenterView","ScreenStackHeaderSearchBarView","ScreenStackHeaderConfig","SearchBar","ScreenStackHeaderSubview","shouldUseActivityState"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AAUA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AACA;;;;;;AAKA,IAAIA,cAAc,GAAG,IAArB;;AAEO,SAASC,aAAT,CAAuBC,mBAAmB,GAAG,IAA7C,EAAyD;AAC9DF,EAAAA,cAAc,GAAGE,mBAAjB;AACD;;AAEM,SAASC,cAAT,GAAmC;AACxC,SAAOH,cAAP;AACD,C,CAED;AACA;;;AACO,SAASI,YAAT,CAAsBC,uBAAuB,GAAG,IAAhD,EAA4D,CACjE;AACD;;AAEM,MAAMC,YAAN,SAA2BC,eAAMC,SAAjC,CAAwD;AAC7DC,EAAAA,MAAM,GAAgB;AACpB,QAAI;AACFC,MAAAA,MADE;AAEFC,MAAAA,aAFE;AAGFC,MAAAA,KAHE;AAIFC,MAAAA,OAAO,GAAGb,cAJR;AAKF,SAAGc;AALD,QAMA,KAAKC,KANT;;AAQA,QAAIF,OAAJ,EAAa;AACX,UAAIH,MAAM,KAAKM,SAAX,IAAwBL,aAAa,KAAKK,SAA9C,EAAyD;AACvDL,QAAAA,aAAa,GAAGD,MAAM,KAAK,CAAX,GAAe,CAAf,GAAmB,CAAnC,CADuD,CACjB;AACvC;;AACD,0BACE,6BAAC,iBAAD,CACE;AADF;AAEE,QAAA,MAAM,EAAEC,aAAa,KAAK,CAF5B;AAGE,QAAA,KAAK,EAAE,CAACC,KAAD,EAAQ;AAAEK,UAAAA,OAAO,EAAEN,aAAa,KAAK,CAAlB,GAAsB,MAAtB,GAA+B;AAA1C,SAAR;AAHT,SAIMG,IAJN,EADF;AAQD;;AAED,wBAAO,6BAAC,iBAAD,EAAUA,IAAV,CAAP;AACD;;AAzB4D;;;;AA4BxD,MAAMI,MAAM,GAAGC,sBAASC,uBAAT,CAAiCd,YAAjC,CAAf;;;;AAEA,MAAMe,aAAa,gBAAGd,eAAMe,aAAN,CAAoBJ,MAApB,CAAtB;;;AAEA,MAAMK,eAA0D,GAAGC,iBAAnE;;AAEA,MAAMC,qBAAgE,GAAGD,iBAAzE;;AAEA,MAAME,+BAA0E,GAAGF,iBAAnF;;AAEA,MAAMG,WAAkD,GAAGH,iBAA3D;;AAEA,MAAMI,iBAAiB,GAAGJ,iBAA1B;;;AAEA,MAAMK,gCAAgC,GAC3Cd,KAD8C,iBAG9C,6BAAC,iBAAD,qBACE,6BAAC,kBAAD;AAAO,EAAA,UAAU,EAAC,QAAlB;AAA2B,EAAA,YAAY,EAAE;AAAzC,GAAgDA,KAAhD,EADF,CAHK;;;;AAQA,MAAMe,0BAA0B,GACrCf,KADwC,iBAExB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMgB,yBAAyB,GACpChB,KADuC,iBAEvB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMiB,2BAA2B,GACtCjB,KADyC,iBAEzB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMkB,8BAA8B,GACzClB,KAD4C,iBAE5B,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;AAIA,MAAMmB,uBAA0E,GAAGV,iBAAnF,C,CAEP;;;AACO,MAAMW,SAA8C,GAAGX,iBAAvD;;AAEA,MAAMY,wBAEX,GAAGZ,iBAFE;;AAIA,MAAMa,sBAAsB,GAAG,IAA/B","sourcesContent":["import React from 'react';\nimport { Animated, View, ViewProps, ImageProps, Image } from 'react-native';\nimport {\n ScreenProps,\n ScreenContainerProps,\n ScreenStackProps,\n ScreenStackHeaderConfigProps,\n HeaderSubviewTypes,\n SearchBarProps,\n} from './types';\n\nexport * from './types';\nexport { default as useTransitionProgress } from './useTransitionProgress';\nexport {\n isSearchBarAvailableForCurrentPlatform,\n executeNativeBackPress,\n} from './utils';\n\nlet ENABLE_SCREENS = true;\n\nexport function enableScreens(shouldEnableScreens = true): void {\n ENABLE_SCREENS = shouldEnableScreens;\n}\n\nexport function screensEnabled(): boolean {\n return ENABLE_SCREENS;\n}\n\n// @ts-ignore function stub, freezing logic is located in index.native.tsx\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function enableFreeze(shouldEnableReactFreeze = true): void {\n // noop\n}\n\nexport class NativeScreen extends React.Component<ScreenProps> {\n render(): JSX.Element {\n let {\n active,\n activityState,\n style,\n enabled = ENABLE_SCREENS,\n ...rest\n } = this.props;\n\n if (enabled) {\n if (active !== undefined && activityState === undefined) {\n activityState = active !== 0 ? 2 : 0; // change taken from index.native.tsx\n }\n return (\n <View\n // @ts-expect-error: hidden exists on web, but not in React Native\n hidden={activityState === 0}\n style={[style, { display: activityState !== 0 ? 'flex' : 'none' }]}\n {...rest}\n />\n );\n }\n\n return <View {...rest} />;\n }\n}\n\nexport const Screen = Animated.createAnimatedComponent(NativeScreen);\n\nexport const ScreenContext = React.createContext(Screen);\n\nexport const ScreenContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const NativeScreenContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const NativeScreenNavigationContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const ScreenStack: React.ComponentType<ScreenStackProps> = View;\n\nexport const FullWindowOverlay = View;\n\nexport const ScreenStackHeaderBackButtonImage = (\n props: ImageProps\n): JSX.Element => (\n <View>\n <Image resizeMode=\"center\" fadeDuration={0} {...props} />\n </View>\n);\n\nexport const ScreenStackHeaderRightView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderLeftView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderCenterView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderSearchBarView = (\n props: React.PropsWithChildren<SearchBarProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderConfig: React.ComponentType<ScreenStackHeaderConfigProps> = View;\n\n// @ts-expect-error: search bar props have no common props with View\nexport const SearchBar: React.ComponentType<SearchBarProps> = View;\n\nexport const ScreenStackHeaderSubview: React.ComponentType<React.PropsWithChildren<\n ViewProps & { type?: HeaderSubviewTypes }\n>> = View;\n\nexport const shouldUseActivityState = true;\n"]}
1
+ {"version":3,"sources":["index.tsx"],"names":["ENABLE_SCREENS","enableScreens","shouldEnableScreens","screensEnabled","enableFreeze","shouldEnableReactFreeze","NativeScreen","React","Component","render","active","activityState","style","enabled","rest","props","undefined","display","Screen","Animated","createAnimatedComponent","InnerScreen","View","ScreenContext","createContext","ScreenContainer","NativeScreenContainer","NativeScreenNavigationContainer","ScreenStack","FullWindowOverlay","ScreenStackHeaderBackButtonImage","ScreenStackHeaderRightView","ScreenStackHeaderLeftView","ScreenStackHeaderCenterView","ScreenStackHeaderSearchBarView","ScreenStackHeaderConfig","SearchBar","ScreenStackHeaderSubview","shouldUseActivityState"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;AACA;;AAUA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AACA;;AACA;;;;;;AAKA,IAAIA,cAAc,GAAG,IAArB;;AAEO,SAASC,aAAT,CAAuBC,mBAAmB,GAAG,IAA7C,EAAyD;AAC9DF,EAAAA,cAAc,GAAGE,mBAAjB;AACD;;AAEM,SAASC,cAAT,GAAmC;AACxC,SAAOH,cAAP;AACD,C,CAED;AACA;;;AACO,SAASI,YAAT,CAAsBC,uBAAuB,GAAG,IAAhD,EAA4D,CACjE;AACD;;AAEM,MAAMC,YAAN,SAA2BC,eAAMC,SAAjC,CAAwD;AAC7DC,EAAAA,MAAM,GAAgB;AACpB,QAAI;AACFC,MAAAA,MADE;AAEFC,MAAAA,aAFE;AAGFC,MAAAA,KAHE;AAIFC,MAAAA,OAAO,GAAGb,cAJR;AAKF,SAAGc;AALD,QAMA,KAAKC,KANT;;AAQA,QAAIF,OAAJ,EAAa;AACX,UAAIH,MAAM,KAAKM,SAAX,IAAwBL,aAAa,KAAKK,SAA9C,EAAyD;AACvDL,QAAAA,aAAa,GAAGD,MAAM,KAAK,CAAX,GAAe,CAAf,GAAmB,CAAnC,CADuD,CACjB;AACvC;;AACD,0BACE,6BAAC,iBAAD,CACE;AADF;AAEE,QAAA,MAAM,EAAEC,aAAa,KAAK,CAF5B;AAGE,QAAA,KAAK,EAAE,CAACC,KAAD,EAAQ;AAAEK,UAAAA,OAAO,EAAEN,aAAa,KAAK,CAAlB,GAAsB,MAAtB,GAA+B;AAA1C,SAAR;AAHT,SAIMG,IAJN,EADF;AAQD;;AAED,wBAAO,6BAAC,iBAAD,EAAUA,IAAV,CAAP;AACD;;AAzB4D;;;;AA4BxD,MAAMI,MAAM,GAAGC,sBAASC,uBAAT,CAAiCd,YAAjC,CAAf;;;AAEA,MAAMe,WAAW,GAAGC,iBAApB;;;AAEA,MAAMC,aAAa,gBAAGhB,eAAMiB,aAAN,CAAoBN,MAApB,CAAtB;;;AAEA,MAAMO,eAA0D,GAAGH,iBAAnE;;AAEA,MAAMI,qBAAgE,GAAGJ,iBAAzE;;AAEA,MAAMK,+BAA0E,GAAGL,iBAAnF;;AAEA,MAAMM,WAAkD,GAAGN,iBAA3D;;AAEA,MAAMO,iBAAiB,GAAGP,iBAA1B;;;AAEA,MAAMQ,gCAAgC,GAC3Cf,KAD8C,iBAG9C,6BAAC,iBAAD,qBACE,6BAAC,kBAAD;AAAO,EAAA,UAAU,EAAC,QAAlB;AAA2B,EAAA,YAAY,EAAE;AAAzC,GAAgDA,KAAhD,EADF,CAHK;;;;AAQA,MAAMgB,0BAA0B,GACrChB,KADwC,iBAExB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMiB,yBAAyB,GACpCjB,KADuC,iBAEvB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMkB,2BAA2B,GACtClB,KADyC,iBAEzB,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;;AAIA,MAAMmB,8BAA8B,GACzCnB,KAD4C,iBAE5B,6BAAC,iBAAD,EAAUA,KAAV,CAFX;;;AAIA,MAAMoB,uBAA0E,GAAGb,iBAAnF,C,CAEP;;;AACO,MAAMc,SAA8C,GAAGd,iBAAvD;;AAEA,MAAMe,wBAEX,GAAGf,iBAFE;;AAIA,MAAMgB,sBAAsB,GAAG,IAA/B","sourcesContent":["import React from 'react';\nimport { Animated, View, ViewProps, ImageProps, Image } from 'react-native';\nimport {\n ScreenProps,\n ScreenContainerProps,\n ScreenStackProps,\n ScreenStackHeaderConfigProps,\n HeaderSubviewTypes,\n SearchBarProps,\n} from './types';\n\nexport * from './types';\nexport { default as useTransitionProgress } from './useTransitionProgress';\nexport {\n isSearchBarAvailableForCurrentPlatform,\n executeNativeBackPress,\n} from './utils';\n\nlet ENABLE_SCREENS = true;\n\nexport function enableScreens(shouldEnableScreens = true): void {\n ENABLE_SCREENS = shouldEnableScreens;\n}\n\nexport function screensEnabled(): boolean {\n return ENABLE_SCREENS;\n}\n\n// @ts-ignore function stub, freezing logic is located in index.native.tsx\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function enableFreeze(shouldEnableReactFreeze = true): void {\n // noop\n}\n\nexport class NativeScreen extends React.Component<ScreenProps> {\n render(): JSX.Element {\n let {\n active,\n activityState,\n style,\n enabled = ENABLE_SCREENS,\n ...rest\n } = this.props;\n\n if (enabled) {\n if (active !== undefined && activityState === undefined) {\n activityState = active !== 0 ? 2 : 0; // change taken from index.native.tsx\n }\n return (\n <View\n // @ts-expect-error: hidden exists on web, but not in React Native\n hidden={activityState === 0}\n style={[style, { display: activityState !== 0 ? 'flex' : 'none' }]}\n {...rest}\n />\n );\n }\n\n return <View {...rest} />;\n }\n}\n\nexport const Screen = Animated.createAnimatedComponent(NativeScreen);\n\nexport const InnerScreen = View;\n\nexport const ScreenContext = React.createContext(Screen);\n\nexport const ScreenContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const NativeScreenContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const NativeScreenNavigationContainer: React.ComponentType<ScreenContainerProps> = View;\n\nexport const ScreenStack: React.ComponentType<ScreenStackProps> = View;\n\nexport const FullWindowOverlay = View;\n\nexport const ScreenStackHeaderBackButtonImage = (\n props: ImageProps\n): JSX.Element => (\n <View>\n <Image resizeMode=\"center\" fadeDuration={0} {...props} />\n </View>\n);\n\nexport const ScreenStackHeaderRightView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderLeftView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderCenterView = (\n props: React.PropsWithChildren<ViewProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderSearchBarView = (\n props: React.PropsWithChildren<SearchBarProps>\n): JSX.Element => <View {...props} />;\n\nexport const ScreenStackHeaderConfig: React.ComponentType<ScreenStackHeaderConfigProps> = View;\n\n// @ts-expect-error: search bar props have no common props with View\nexport const SearchBar: React.ComponentType<SearchBarProps> = View;\n\nexport const ScreenStackHeaderSubview: React.ComponentType<React.PropsWithChildren<\n ViewProps & { type?: HeaderSubviewTypes }\n>> = View;\n\nexport const shouldUseActivityState = true;\n"]}