react-native-screens 4.0.0-beta.12 → 4.0.0-beta.14

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 (197) hide show
  1. package/README.md +3 -1
  2. package/android/CMakeLists.txt +28 -19
  3. package/android/src/main/java/com/swmansion/rnscreens/NativeDismissalObserver.kt +12 -0
  4. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +59 -84
  5. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetBehaviorExt.kt +42 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt +24 -19
  7. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetUtils.kt +8 -0
  8. package/android/src/main/jni/CMakeLists.txt +28 -19
  9. package/ios/RNSConvert.h +13 -4
  10. package/ios/RNSConvert.mm +50 -28
  11. package/ios/RNSEnums.h +46 -0
  12. package/ios/RNSScreenStackHeaderConfig.h +1 -1
  13. package/ios/RNSScreenStackHeaderConfig.mm +30 -25
  14. package/lib/commonjs/components/FullWindowOverlay.js +8 -5
  15. package/lib/commonjs/components/FullWindowOverlay.js.map +1 -1
  16. package/lib/commonjs/components/Screen.js +28 -10
  17. package/lib/commonjs/components/Screen.js.map +1 -1
  18. package/lib/commonjs/components/ScreenContainer.js +3 -5
  19. package/lib/commonjs/components/ScreenContainer.js.map +1 -1
  20. package/lib/commonjs/components/ScreenContainer.web.js +3 -4
  21. package/lib/commonjs/components/ScreenContainer.web.js.map +1 -1
  22. package/lib/commonjs/components/ScreenContentWrapper.js +2 -4
  23. package/lib/commonjs/components/ScreenContentWrapper.js.map +1 -1
  24. package/lib/commonjs/components/ScreenContentWrapper.web.js +1 -2
  25. package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -1
  26. package/lib/commonjs/components/ScreenFooter.js +2 -8
  27. package/lib/commonjs/components/ScreenFooter.js.map +1 -1
  28. package/lib/commonjs/components/ScreenFooter.web.js +1 -2
  29. package/lib/commonjs/components/ScreenFooter.web.js.map +1 -1
  30. package/lib/commonjs/components/ScreenStack.js +2 -2
  31. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  32. package/lib/commonjs/components/ScreenStack.web.js +2 -1
  33. package/lib/commonjs/components/ScreenStack.web.js.map +1 -1
  34. package/lib/commonjs/components/SearchBar.js +5 -5
  35. package/lib/commonjs/components/SearchBar.js.map +1 -1
  36. package/lib/commonjs/components/SearchBar.web.js +3 -4
  37. package/lib/commonjs/components/SearchBar.web.js.map +1 -1
  38. package/lib/commonjs/core.js +0 -3
  39. package/lib/commonjs/core.js.map +1 -1
  40. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  41. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  42. package/lib/commonjs/gesture-handler/GestureDetectorProvider.js +2 -2
  43. package/lib/commonjs/gesture-handler/GestureDetectorProvider.js.map +1 -1
  44. package/lib/commonjs/index.js +14 -78
  45. package/lib/commonjs/index.js.map +1 -1
  46. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +4 -0
  47. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  48. package/lib/commonjs/native-stack/views/FooterComponent.js +2 -2
  49. package/lib/commonjs/native-stack/views/FooterComponent.js.map +1 -1
  50. package/lib/commonjs/native-stack/views/HeaderConfig.js +10 -8
  51. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  52. package/lib/commonjs/native-stack/views/NativeStackView.js +12 -9
  53. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  54. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +2 -2
  55. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  56. package/lib/commonjs/reanimated/ReanimatedScreen.js +2 -2
  57. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -1
  58. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +2 -2
  59. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -1
  60. package/lib/commonjs/utils.js +28 -6
  61. package/lib/commonjs/utils.js.map +1 -1
  62. package/lib/module/components/FullWindowOverlay.js +9 -6
  63. package/lib/module/components/FullWindowOverlay.js.map +1 -1
  64. package/lib/module/components/Screen.js +27 -9
  65. package/lib/module/components/Screen.js.map +1 -1
  66. package/lib/module/components/ScreenContainer.js +2 -4
  67. package/lib/module/components/ScreenContainer.js.map +1 -1
  68. package/lib/module/components/ScreenContainer.web.js +2 -3
  69. package/lib/module/components/ScreenContainer.web.js.map +1 -1
  70. package/lib/module/components/ScreenContentWrapper.js +1 -3
  71. package/lib/module/components/ScreenContentWrapper.js.map +1 -1
  72. package/lib/module/components/ScreenContentWrapper.web.js +0 -1
  73. package/lib/module/components/ScreenContentWrapper.web.js.map +1 -1
  74. package/lib/module/components/ScreenFooter.js +1 -7
  75. package/lib/module/components/ScreenFooter.js.map +1 -1
  76. package/lib/module/components/ScreenFooter.web.js +0 -1
  77. package/lib/module/components/ScreenFooter.web.js.map +1 -1
  78. package/lib/module/components/ScreenStack.js +1 -1
  79. package/lib/module/components/ScreenStack.js.map +1 -1
  80. package/lib/module/components/ScreenStack.web.js +2 -1
  81. package/lib/module/components/ScreenStack.web.js.map +1 -1
  82. package/lib/module/components/SearchBar.js +3 -3
  83. package/lib/module/components/SearchBar.js.map +1 -1
  84. package/lib/module/components/SearchBar.web.js +2 -3
  85. package/lib/module/components/SearchBar.web.js.map +1 -1
  86. package/lib/module/core.js +0 -3
  87. package/lib/module/core.js.map +1 -1
  88. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  89. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  90. package/lib/module/gesture-handler/GestureDetectorProvider.js +1 -1
  91. package/lib/module/gesture-handler/GestureDetectorProvider.js.map +1 -1
  92. package/lib/module/index.js +8 -13
  93. package/lib/module/index.js.map +1 -1
  94. package/lib/module/native-stack/navigators/createNativeStackNavigator.js +4 -0
  95. package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  96. package/lib/module/native-stack/views/FooterComponent.js +1 -1
  97. package/lib/module/native-stack/views/FooterComponent.js.map +1 -1
  98. package/lib/module/native-stack/views/HeaderConfig.js +3 -1
  99. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  100. package/lib/module/native-stack/views/NativeStackView.js +4 -1
  101. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  102. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +1 -2
  103. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  104. package/lib/module/reanimated/ReanimatedScreen.js +1 -2
  105. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -1
  106. package/lib/module/reanimated/ReanimatedScreenProvider.js +1 -1
  107. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -1
  108. package/lib/module/utils.js +26 -5
  109. package/lib/module/utils.js.map +1 -1
  110. package/lib/typescript/components/FullWindowOverlay.d.ts.map +1 -1
  111. package/lib/typescript/components/Screen.d.ts +2 -7
  112. package/lib/typescript/components/Screen.d.ts.map +1 -1
  113. package/lib/typescript/components/Screen.web.d.ts +1 -1
  114. package/lib/typescript/components/Screen.web.d.ts.map +1 -1
  115. package/lib/typescript/components/ScreenContainer.d.ts +1 -3
  116. package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
  117. package/lib/typescript/components/ScreenContainer.web.d.ts +2 -3
  118. package/lib/typescript/components/ScreenContainer.web.d.ts.map +1 -1
  119. package/lib/typescript/components/ScreenContentWrapper.d.ts +0 -1
  120. package/lib/typescript/components/ScreenContentWrapper.d.ts.map +1 -1
  121. package/lib/typescript/components/ScreenContentWrapper.web.d.ts +0 -1
  122. package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -1
  123. package/lib/typescript/components/ScreenFooter.d.ts +0 -4
  124. package/lib/typescript/components/ScreenFooter.d.ts.map +1 -1
  125. package/lib/typescript/components/ScreenFooter.web.d.ts +0 -1
  126. package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -1
  127. package/lib/typescript/components/ScreenStack.d.ts +1 -1
  128. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  129. package/lib/typescript/components/ScreenStack.web.d.ts +2 -1
  130. package/lib/typescript/components/ScreenStack.web.d.ts.map +1 -1
  131. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +1 -1
  132. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  133. package/lib/typescript/components/ScreenStackHeaderConfig.web.d.ts +1 -1
  134. package/lib/typescript/components/ScreenStackHeaderConfig.web.d.ts.map +1 -1
  135. package/lib/typescript/components/SearchBar.d.ts +1 -15
  136. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  137. package/lib/typescript/components/SearchBar.web.d.ts +2 -3
  138. package/lib/typescript/components/SearchBar.web.d.ts.map +1 -1
  139. package/lib/typescript/core.d.ts +0 -1
  140. package/lib/typescript/core.d.ts.map +1 -1
  141. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +7 -1
  142. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  143. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +2 -2
  144. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  145. package/lib/typescript/index.d.ts +8 -12
  146. package/lib/typescript/index.d.ts.map +1 -1
  147. package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts +3 -0
  148. package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts.map +1 -1
  149. package/lib/typescript/native-stack/types.d.ts +49 -1
  150. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  151. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  152. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  153. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  154. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  155. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  156. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts.map +1 -1
  157. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  158. package/lib/typescript/reanimated/ReanimatedScreen.d.ts.map +1 -1
  159. package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts.map +1 -1
  160. package/lib/typescript/types.d.ts +1 -1
  161. package/lib/typescript/types.d.ts.map +1 -1
  162. package/lib/typescript/utils.d.ts +26 -1
  163. package/lib/typescript/utils.d.ts.map +1 -1
  164. package/native-stack/README.md +2 -1
  165. package/native-stack/package.json +4 -4
  166. package/package.json +1 -1
  167. package/src/components/FullWindowOverlay.tsx +10 -2
  168. package/src/components/Screen.tsx +42 -25
  169. package/src/components/Screen.web.tsx +1 -1
  170. package/src/components/ScreenContainer.tsx +4 -11
  171. package/src/components/ScreenContainer.web.tsx +2 -3
  172. package/src/components/ScreenContentWrapper.tsx +2 -5
  173. package/src/components/ScreenContentWrapper.web.tsx +1 -2
  174. package/src/components/ScreenFooter.tsx +2 -8
  175. package/src/components/ScreenFooter.web.tsx +1 -2
  176. package/src/components/ScreenStack.tsx +2 -1
  177. package/src/components/ScreenStack.web.tsx +3 -1
  178. package/src/components/ScreenStackHeaderConfig.tsx +1 -1
  179. package/src/components/ScreenStackHeaderConfig.web.tsx +1 -1
  180. package/src/components/SearchBar.tsx +4 -7
  181. package/src/components/SearchBar.web.tsx +2 -3
  182. package/src/core.ts +0 -3
  183. package/src/fabric/ModalScreenNativeComponent.ts +9 -1
  184. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +2 -1
  185. package/src/gesture-handler/GestureDetectorProvider.tsx +1 -1
  186. package/src/index.tsx +6 -32
  187. package/src/native-stack/navigators/createNativeStackNavigator.tsx +3 -0
  188. package/src/native-stack/types.tsx +50 -6
  189. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
  190. package/src/native-stack/views/FooterComponent.tsx +1 -1
  191. package/src/native-stack/views/HeaderConfig.tsx +7 -5
  192. package/src/native-stack/views/NativeStackView.tsx +5 -8
  193. package/src/reanimated/ReanimatedNativeStackScreen.tsx +2 -2
  194. package/src/reanimated/ReanimatedScreen.tsx +2 -1
  195. package/src/reanimated/ReanimatedScreenProvider.tsx +2 -1
  196. package/src/types.tsx +1 -0
  197. package/src/utils.ts +27 -5
package/README.md CHANGED
@@ -133,6 +133,9 @@ Here's a table with summary of supported `react-native` versions when Fabric is
133
133
 
134
134
  ## Usage with [react-navigation](https://github.com/react-navigation/react-navigation)
135
135
 
136
+ > [!CAUTION]
137
+ > NativeStack has been moved from react-native-screens/native-stack to @react-navigation/native since version v6. With react-native-screens v4 native stack v5 (react-native-screens/native-stack) is deprecated and marked for removal in the upcoming minor release, react-native-screens v4 will support only @react-navigation/native-stack v7.
138
+
136
139
  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).
137
140
 
138
141
  To configure react-navigation to use screens instead of plain RN Views for rendering screen views, simply add this library as a dependency to your project:
@@ -184,7 +187,6 @@ You can also disable the usage of native screens per navigator with [`detachInac
184
187
  To take advantage of the native stack navigator primitive for React Navigation that leverages `UINavigationController` on iOS and `Fragment` on Android, please refer:
185
188
 
186
189
  - for React Navigation >= v6 to the [Native Stack Navigator part of React Navigation documentation](https://reactnavigation.org/docs/native-stack-navigator)
187
- - for React Navigation v5 to the [README in react-native-screens/native-stack](https://github.com/software-mansion/react-native-screens/tree/main/native-stack)
188
190
 
189
191
  ## `FullWindowOverlay`
190
192
 
@@ -41,28 +41,37 @@ find_package(ReactAndroid REQUIRED CONFIG)
41
41
  if(${RNS_NEW_ARCH_ENABLED})
42
42
  find_package(fbjni REQUIRED CONFIG)
43
43
 
44
- target_link_libraries(
45
- rnscreens
44
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
45
+ target_link_libraries(rnscreens
46
+ ReactAndroid::reactnative
46
47
  ReactAndroid::jsi
47
- ReactAndroid::react_nativemodule_core
48
- ReactAndroid::react_utils
49
- ReactAndroid::reactnativejni
50
- ReactAndroid::fabricjni
51
- ReactAndroid::react_debug
52
- ReactAndroid::react_render_core
53
- ReactAndroid::runtimeexecutor
54
- ReactAndroid::react_render_graphics
55
- ReactAndroid::rrc_view
56
- ReactAndroid::yoga
57
- ReactAndroid::rrc_text
58
- ReactAndroid::glog
59
- ReactAndroid::react_render_componentregistry
60
- ReactAndroid::react_render_consistency
61
- ReactAndroid::react_performance_timeline
62
- ReactAndroid::react_render_observers_events
63
48
  fbjni::fbjni
64
49
  android
65
- )
50
+ )
51
+ else()
52
+ target_link_libraries(
53
+ rnscreens
54
+ ReactAndroid::jsi
55
+ ReactAndroid::react_nativemodule_core
56
+ ReactAndroid::react_utils
57
+ ReactAndroid::reactnativejni
58
+ ReactAndroid::fabricjni
59
+ ReactAndroid::react_debug
60
+ ReactAndroid::react_render_core
61
+ ReactAndroid::runtimeexecutor
62
+ ReactAndroid::react_render_graphics
63
+ ReactAndroid::rrc_view
64
+ ReactAndroid::yoga
65
+ ReactAndroid::rrc_text
66
+ ReactAndroid::glog
67
+ ReactAndroid::react_render_componentregistry
68
+ ReactAndroid::react_render_consistency
69
+ ReactAndroid::react_performance_timeline
70
+ ReactAndroid::react_render_observers_events
71
+ fbjni::fbjni
72
+ android
73
+ )
74
+ endif()
66
75
  else()
67
76
  target_link_libraries(rnscreens
68
77
  ReactAndroid::jsi
@@ -0,0 +1,12 @@
1
+ package com.swmansion.rnscreens
2
+
3
+ interface NativeDismissalObserver {
4
+ /**
5
+ * Observed object should call this observer method when it has been natively dismissed,
6
+ * e.g. in the result of user gesture or other interaction.
7
+ *
8
+ * Prominent usage is for the screen with sheet presentation to notify its wrapper that
9
+ * it has been hidden and requires dismissal.
10
+ */
11
+ fun onNativeDismiss(dismissed: ScreenStackFragmentWrapper)
12
+ }
@@ -24,7 +24,6 @@ import androidx.annotation.RequiresApi
24
24
  import androidx.appcompat.widget.Toolbar
25
25
  import androidx.coordinatorlayout.widget.CoordinatorLayout
26
26
  import androidx.core.view.WindowInsetsCompat
27
- import androidx.fragment.app.commit
28
27
  import com.facebook.react.uimanager.PixelUtil
29
28
  import com.facebook.react.uimanager.PointerEvents
30
29
  import com.facebook.react.uimanager.ReactPointerEventsView
@@ -35,8 +34,12 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCa
35
34
  import com.google.android.material.shape.CornerFamily
36
35
  import com.google.android.material.shape.MaterialShapeDrawable
37
36
  import com.google.android.material.shape.ShapeAppearanceModel
38
- import com.swmansion.rnscreens.bottomsheet.DimmingFragment
39
37
  import com.swmansion.rnscreens.bottomsheet.SheetUtils
38
+ import com.swmansion.rnscreens.bottomsheet.isSheetFitToContents
39
+ import com.swmansion.rnscreens.bottomsheet.useSingleDetent
40
+ import com.swmansion.rnscreens.bottomsheet.useThreeDetents
41
+ import com.swmansion.rnscreens.bottomsheet.useTwoDetents
42
+ import com.swmansion.rnscreens.bottomsheet.usesFormSheetPresentation
40
43
  import com.swmansion.rnscreens.ext.recycle
41
44
  import com.swmansion.rnscreens.utils.DeviceUtils
42
45
 
@@ -53,6 +56,7 @@ class KeyboardVisible(
53
56
  class ScreenStackFragment :
54
57
  ScreenFragment,
55
58
  ScreenStackFragmentWrapper {
59
+ public var nativeDismissalObserver: NativeDismissalObserver? = null
56
60
  private var appBarLayout: AppBarLayout? = null
57
61
  private var toolbar: Toolbar? = null
58
62
  private var isToolbarShadowHidden = false
@@ -157,30 +161,22 @@ class ScreenStackFragment :
157
161
  screen.notifySheetDetentChange(
158
162
  SheetUtils.detentIndexFromSheetState(
159
163
  lastStableState,
160
- screen.sheetDetents.count()
161
- ), true
164
+ screen.sheetDetents.count(),
165
+ ),
166
+ true,
162
167
  )
163
168
  } else if (newState == BottomSheetBehavior.STATE_DRAGGING) {
164
169
  screen.notifySheetDetentChange(
165
170
  SheetUtils.detentIndexFromSheetState(
166
171
  lastStableState,
167
- screen.sheetDetents.count()
172
+ screen.sheetDetents.count(),
168
173
  ),
169
174
  false,
170
175
  )
171
176
  }
172
177
 
173
178
  if (newState == BottomSheetBehavior.STATE_HIDDEN) {
174
- // If we are wrapped in DimmingFragment we want it to be removed alongside
175
- // => we use its fragment manager. Otherwise we just remove this fragment.
176
- if (this@ScreenStackFragment.parentFragment is DimmingFragment) {
177
- parentFragmentManager.commit {
178
- setReorderingAllowed(true)
179
- remove(this@ScreenStackFragment)
180
- }
181
- } else {
182
- this@ScreenStackFragment.dismissFromContainer()
183
- }
179
+ nativeDismissalObserver?.onNativeDismiss(this@ScreenStackFragment)
184
180
  }
185
181
  }
186
182
 
@@ -223,7 +219,7 @@ class ScreenStackFragment :
223
219
  LinearLayout.LayoutParams.MATCH_PARENT,
224
220
  ).apply {
225
221
  behavior =
226
- if (screen.stackPresentation == Screen.StackPresentation.FORM_SHEET) {
222
+ if (screen.usesFormSheetPresentation()) {
227
223
  createAndConfigureBottomSheetBehaviour()
228
224
  } else if (isToolbarTranslucent) {
229
225
  null
@@ -232,7 +228,7 @@ class ScreenStackFragment :
232
228
  }
233
229
  }
234
230
 
235
- if (screen.stackPresentation == Screen.StackPresentation.FORM_SHEET) {
231
+ if (screen.usesFormSheetPresentation()) {
236
232
  screen.clipToOutline = true
237
233
  // TODO(@kkafar): without this line there is no drawable / outline & nothing shows...? Determine what's going on here
238
234
  attachShapeToScreen(screen)
@@ -241,7 +237,7 @@ class ScreenStackFragment :
241
237
 
242
238
  coordinatorLayout.addView(screen.recycle())
243
239
 
244
- if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) {
240
+ if (!screen.usesFormSheetPresentation()) {
245
241
  appBarLayout =
246
242
  context?.let { AppBarLayout(it) }?.apply {
247
243
  // By default AppBarLayout will have a background color set but since we cover the whole layout
@@ -348,52 +344,39 @@ class ScreenStackFragment :
348
344
  return when (keyboardState) {
349
345
  is KeyboardNotVisible -> {
350
346
  when (screen.sheetDetents.count()) {
351
- 1 -> if (screen.sheetDetents.first() == Screen.SHEET_FIT_TO_CONTENTS) {
352
- behavior.apply {
353
- state = BottomSheetBehavior.STATE_EXPANDED
354
- screen.contentWrapper.get()?.let {
355
- maxHeight = it.height
356
- }
357
- skipCollapsed = true
358
- isFitToContents = true
359
- }
360
- } else {
347
+ 1 ->
361
348
  behavior.apply {
362
- state = BottomSheetBehavior.STATE_EXPANDED
363
- skipCollapsed = true
364
- isFitToContents = true
365
- maxHeight = (screen.sheetDetents.first() * containerHeight).toInt()
349
+ val height =
350
+ if (screen.isSheetFitToContents()) {
351
+ screen.contentWrapper.get()?.height
352
+ } else {
353
+ (screen.sheetDetents.first() * containerHeight).toInt()
354
+ }
355
+ useSingleDetent(height = height)
366
356
  }
367
- }
368
357
 
369
358
  2 ->
370
- behavior.apply {
359
+ behavior.useTwoDetents(
371
360
  state =
372
361
  SheetUtils.sheetStateFromDetentIndex(
373
362
  screen.sheetInitialDetentIndex,
374
363
  screen.sheetDetents.count(),
375
- )
376
- skipCollapsed = false
377
- isFitToContents = true
378
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
379
- maxHeight = (screen.sheetDetents[1] * containerHeight).toInt()
380
- }
364
+ ),
365
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
366
+ secondHeight = (screen.sheetDetents[1] * containerHeight).toInt(),
367
+ )
381
368
 
382
369
  3 ->
383
- behavior.apply {
370
+ behavior.useThreeDetents(
384
371
  state =
385
372
  SheetUtils.sheetStateFromDetentIndex(
386
373
  screen.sheetInitialDetentIndex,
387
374
  screen.sheetDetents.count(),
388
- )
389
- skipCollapsed = false
390
- isFitToContents = false
391
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
392
- expandedOffset =
393
- ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
394
- halfExpandedRatio =
395
- (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
396
- }
375
+ ),
376
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
377
+ halfExpandedRatio = (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat(),
378
+ expandedOffsetFromTop = ((1 - screen.sheetDetents[2]) * containerHeight).toInt(),
379
+ )
397
380
 
398
381
  else -> throw IllegalStateException(
399
382
  "[RNScreens] Invalid detent count ${screen.sheetDetents.count()}. Expected at most 3.",
@@ -411,27 +394,24 @@ class ScreenStackFragment :
411
394
  when (screen.sheetDetents.count()) {
412
395
  1 ->
413
396
  behavior.apply {
414
- state = BottomSheetBehavior.STATE_EXPANDED
415
- skipCollapsed = true
416
- isFitToContents = true
417
- maxHeight = newMaxHeight
397
+ useSingleDetent(height = newMaxHeight)
418
398
  addBottomSheetCallback(keyboardSheetCallback)
419
399
  }
420
400
 
421
401
  2 ->
422
402
  behavior.apply {
423
- state = BottomSheetBehavior.STATE_EXPANDED
424
- skipCollapsed = false
425
- isFitToContents = true
426
- maxHeight = newMaxHeight
403
+ useTwoDetents(
404
+ state = BottomSheetBehavior.STATE_EXPANDED,
405
+ secondHeight = newMaxHeight,
406
+ )
427
407
  addBottomSheetCallback(keyboardSheetCallback)
428
408
  }
429
409
 
430
410
  3 ->
431
411
  behavior.apply {
432
- state = BottomSheetBehavior.STATE_EXPANDED
433
- skipCollapsed = false
434
- isFitToContents = false
412
+ useThreeDetents(
413
+ state = BottomSheetBehavior.STATE_EXPANDED,
414
+ )
435
415
  maxHeight = newMaxHeight
436
416
  addBottomSheetCallback(keyboardSheetCallback)
437
417
  }
@@ -450,30 +430,23 @@ class ScreenStackFragment :
450
430
  behavior.removeBottomSheetCallback(keyboardSheetCallback)
451
431
  when (screen.sheetDetents.count()) {
452
432
  1 ->
453
- behavior.apply {
454
- skipCollapsed = true
455
- isFitToContents = true
456
- maxHeight = (screen.sheetDetents.first() * containerHeight).toInt()
457
- }
433
+ behavior.useSingleDetent(
434
+ height = (screen.sheetDetents.first() * containerHeight).toInt(),
435
+ forceExpandedState = false,
436
+ )
458
437
 
459
438
  2 ->
460
- behavior.apply {
461
- skipCollapsed = false
462
- isFitToContents = true
463
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
464
- maxHeight = (screen.sheetDetents[1] * containerHeight).toInt()
465
- }
439
+ behavior.useTwoDetents(
440
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
441
+ secondHeight = (screen.sheetDetents[1] * containerHeight).toInt(),
442
+ )
466
443
 
467
444
  3 ->
468
- behavior.apply {
469
- skipCollapsed = false
470
- isFitToContents = false
471
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
472
- expandedOffset =
473
- ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
474
- halfExpandedRatio =
475
- (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
476
- }
445
+ behavior.useThreeDetents(
446
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
447
+ halfExpandedRatio = (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat(),
448
+ expandedOffsetFromTop = ((1 - screen.sheetDetents[2]) * containerHeight).toInt(),
449
+ )
477
450
 
478
451
  else -> throw IllegalStateException(
479
452
  "[RNScreens] Invalid detent count ${screen.sheetDetents.count()}. Expected at most 3.",
@@ -498,7 +471,10 @@ class ScreenStackFragment :
498
471
  setTopRightCorner(CornerFamily.ROUNDED, cornerSize)
499
472
  }.build()
500
473
  val shape = MaterialShapeDrawable(shapeAppearanceModel)
501
- shape.setTint((screen.background as? ColorDrawable?)?.color ?: Color.TRANSPARENT)
474
+ val currentColor =
475
+ (screen.background as? ColorDrawable?)?.color
476
+ ?: (screen.background as? MaterialShapeDrawable?)?.tintList?.defaultColor
477
+ shape.setTint(currentColor ?: Color.TRANSPARENT)
502
478
  screen.background = shape
503
479
  }
504
480
 
@@ -595,8 +571,7 @@ class ScreenStackFragment :
595
571
  // ) : CoordinatorLayout(context), ReactCompoundViewGroup, ReactHitSlopView {
596
572
  ) : CoordinatorLayout(context),
597
573
  ReactPointerEventsView {
598
- override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets =
599
- super.onApplyWindowInsets(insets)
574
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets = super.onApplyWindowInsets(insets)
600
575
 
601
576
  private val animationListener: Animation.AnimationListener =
602
577
  object : Animation.AnimationListener {
@@ -0,0 +1,42 @@
1
+ package com.swmansion.rnscreens.bottomsheet
2
+
3
+ import android.view.View
4
+ import com.google.android.material.bottomsheet.BottomSheetBehavior
5
+
6
+ internal fun <T : View> BottomSheetBehavior<T>.useSingleDetent(height: Int? = null, forceExpandedState: Boolean = true): BottomSheetBehavior<T> {
7
+ this.skipCollapsed = true
8
+ this.isFitToContents = true
9
+ if (forceExpandedState) {
10
+ this.state = BottomSheetBehavior.STATE_EXPANDED
11
+ }
12
+ height?.let { maxHeight = height }
13
+ return this
14
+ }
15
+
16
+ internal fun <T : View> BottomSheetBehavior<T>.useTwoDetents(
17
+ @BottomSheetBehavior.StableState state: Int? = null,
18
+ firstHeight: Int? = null,
19
+ secondHeight: Int? = null
20
+ ): BottomSheetBehavior<T> {
21
+ skipCollapsed = false
22
+ isFitToContents = true
23
+ state?.let { this.state = state }
24
+ firstHeight?.let { peekHeight = firstHeight }
25
+ secondHeight?.let { maxHeight = secondHeight }
26
+ return this
27
+ }
28
+
29
+ internal fun <T : View> BottomSheetBehavior<T>.useThreeDetents(
30
+ @BottomSheetBehavior.StableState state: Int? = null,
31
+ firstHeight: Int? = null,
32
+ halfExpandedRatio: Float? = null,
33
+ expandedOffsetFromTop: Int? = null
34
+ ): BottomSheetBehavior<T> {
35
+ skipCollapsed = false
36
+ isFitToContents = false
37
+ state?.let { this.state = state }
38
+ firstHeight?.let { this.peekHeight = firstHeight }
39
+ halfExpandedRatio?.let { this.halfExpandedRatio = halfExpandedRatio }
40
+ expandedOffsetFromTop?.let { this.expandedOffset = expandedOffsetFromTop }
41
+ return this
42
+ }
@@ -27,6 +27,7 @@ import com.swmansion.rnscreens.KeyboardDidHide
27
27
  import com.swmansion.rnscreens.KeyboardNotVisible
28
28
  import com.swmansion.rnscreens.KeyboardState
29
29
  import com.swmansion.rnscreens.KeyboardVisible
30
+ import com.swmansion.rnscreens.NativeDismissalObserver
30
31
  import com.swmansion.rnscreens.R
31
32
  import com.swmansion.rnscreens.Screen
32
33
  import com.swmansion.rnscreens.ScreenContainer
@@ -48,7 +49,8 @@ class DimmingFragment(
48
49
  LifecycleEventObserver,
49
50
  ScreenStackFragmentWrapper,
50
51
  Animation.AnimationListener,
51
- OnApplyWindowInsetsListener {
52
+ OnApplyWindowInsetsListener,
53
+ NativeDismissalObserver {
52
54
  private lateinit var dimmingView: DimmingView
53
55
  private lateinit var containerView: GestureTransparentViewGroup
54
56
 
@@ -65,8 +67,15 @@ class DimmingFragment(
65
67
  private val insetsProxy = InsetsObserverProxy
66
68
 
67
69
  init {
68
- // We register for our child lifecycle as we want to know when it's dismissed via native gesture
69
- nestedFragment.fragment.lifecycle.addObserver(this)
70
+ assert(
71
+ nestedFragment.fragment is ScreenStackFragment,
72
+ ) { "[RNScreens] Dimming fragment is intended for use only with ScreenStackFragment" }
73
+ val fragment = nestedFragment.fragment as ScreenStackFragment
74
+
75
+ // We register for our child lifecycle as we want to know when it starts, because bottom sheet
76
+ // behavior is attached only then & we want to attach our own callbacks to it.
77
+ fragment.lifecycle.addObserver(this)
78
+ fragment.nativeDismissalObserver = this
70
79
  }
71
80
 
72
81
  /**
@@ -111,8 +120,8 @@ class DimmingFragment(
111
120
  computeOffsetFromDetentIndex(
112
121
  (screen.sheetLargestUndimmedDetentIndex + 1).coerceIn(
113
122
  0,
114
- screen.sheetDetents.count() - 1
115
- )
123
+ screen.sheetDetents.count() - 1,
124
+ ),
116
125
  )
117
126
  assert(firstDimmedOffset >= largestUndimmedOffset) {
118
127
  "[RNScreens] Invariant violation: firstDimmedOffset ($firstDimmedOffset) < largestDimmedOffset ($largestUndimmedOffset)"
@@ -173,7 +182,7 @@ class DimmingFragment(
173
182
  // We want dimming view to have always fade animation in current usages.
174
183
  AnimationUtils.loadAnimation(
175
184
  context,
176
- if (enter) R.anim.rns_fade_in else R.anim.rns_fade_out
185
+ if (enter) R.anim.rns_fade_in else R.anim.rns_fade_out,
177
186
  )
178
187
 
179
188
  override fun onCreateView(
@@ -226,10 +235,6 @@ class DimmingFragment(
226
235
  }
227
236
  }
228
237
 
229
- Lifecycle.Event.ON_STOP -> {
230
- dismissSelf(emitDismissedEvent = true)
231
- }
232
-
233
238
  else -> {}
234
239
  }
235
240
  }
@@ -350,13 +355,9 @@ class DimmingFragment(
350
355
  nestedFragment.onViewAnimationEnd()
351
356
  }
352
357
 
353
- override fun tryGetActivity(): Activity? {
354
- return activity
355
- }
358
+ override fun tryGetActivity(): Activity? = activity
356
359
 
357
- override fun tryGetContext(): ReactContext? {
358
- return context as? ReactContext?
359
- }
360
+ override fun tryGetContext(): ReactContext? = context as? ReactContext?
360
361
 
361
362
  override val fragment: Fragment
362
363
  get() = this
@@ -417,7 +418,7 @@ class DimmingFragment(
417
418
  screen.sheetBehavior?.let {
418
419
  (nestedFragment as ScreenStackFragment).configureBottomSheetBehaviour(
419
420
  it,
420
- KeyboardVisible(imeInset.bottom)
421
+ KeyboardVisible(imeInset.bottom),
421
422
  )
422
423
  }
423
424
 
@@ -457,12 +458,12 @@ class DimmingFragment(
457
458
  if (isKeyboardVisible) {
458
459
  (nestedFragment as ScreenStackFragment).configureBottomSheetBehaviour(
459
460
  it,
460
- KeyboardDidHide
461
+ KeyboardDidHide,
461
462
  )
462
463
  } else if (keyboardState != KeyboardNotVisible) {
463
464
  (nestedFragment as ScreenStackFragment).configureBottomSheetBehaviour(
464
465
  it,
465
- KeyboardNotVisible
466
+ KeyboardNotVisible,
466
467
  )
467
468
  } else {
468
469
  }
@@ -485,4 +486,8 @@ class DimmingFragment(
485
486
  ).build()
486
487
  }
487
488
  }
489
+
490
+ override fun onNativeDismiss(dismissed: ScreenStackFragmentWrapper) {
491
+ dismissSelf(emitDismissedEvent = true)
492
+ }
488
493
  }
@@ -5,6 +5,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPS
5
5
  import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
6
6
  import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HALF_EXPANDED
7
7
  import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
8
+ import com.swmansion.rnscreens.Screen
8
9
 
9
10
  object SheetUtils {
10
11
  /**
@@ -125,3 +126,10 @@ object SheetUtils {
125
126
  return false
126
127
  }
127
128
  }
129
+
130
+ fun Screen.isSheetFitToContents(): Boolean =
131
+ stackPresentation === Screen.StackPresentation.FORM_SHEET &&
132
+ sheetDetents.count() == 1 &&
133
+ sheetDetents.first() == Screen.SHEET_FIT_TO_CONTENTS
134
+
135
+ fun Screen.usesFormSheetPresentation(): Boolean = stackPresentation === Screen.StackPresentation.FORM_SHEET
@@ -38,25 +38,34 @@ target_include_directories(
38
38
  ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
39
39
  )
40
40
 
41
- target_link_libraries(
42
- ${LIB_TARGET_NAME}
43
- fbjni
44
- folly_runtime
45
- glog
46
- jsi
47
- react_codegen_rncore
48
- react_debug
49
- react_nativemodule_core
50
- react_render_core
51
- react_render_debug
52
- react_render_graphics
53
- react_render_mapbuffer
54
- react_render_componentregistry
55
- react_utils
56
- rrc_view
57
- turbomodulejsijni
58
- yoga
59
- )
41
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
42
+ target_link_libraries(
43
+ ${LIB_TARGET_NAME}
44
+ ReactAndroid::reactnative
45
+ ReactAndroid::jsi
46
+ fbjni::fbjni
47
+ )
48
+ else()
49
+ target_link_libraries(
50
+ ${LIB_TARGET_NAME}
51
+ fbjni
52
+ folly_runtime
53
+ glog
54
+ jsi
55
+ react_codegen_rncore
56
+ react_debug
57
+ react_nativemodule_core
58
+ react_render_core
59
+ react_render_debug
60
+ react_render_graphics
61
+ react_render_mapbuffer
62
+ react_render_componentregistry
63
+ react_utils
64
+ rrc_view
65
+ turbomodulejsijni
66
+ yoga
67
+ )
68
+ endif()
60
69
 
61
70
  target_compile_options(
62
71
  ${LIB_TARGET_NAME}
package/ios/RNSConvert.h CHANGED
@@ -1,12 +1,17 @@
1
- #ifdef RCT_NEW_ARCH_ENABLED
2
1
  #import <UIKit/UIKit.h>
2
+ #ifdef RCT_NEW_ARCH_ENABLED
3
3
  #import <react/renderer/components/rnscreens/Props.h>
4
+ #endif // RCT_NEW_ARCH_ENABLED
4
5
  #import "RNSEnums.h"
5
6
 
7
+ #ifdef RCT_NEW_ARCH_ENABLED
6
8
  namespace react = facebook::react;
9
+ #endif // RCT_NEW_ARCH_ENABLED
7
10
 
8
11
  @interface RNSConvert : NSObject
9
12
 
13
+ #ifdef RCT_NEW_ARCH_ENABLED
14
+
10
15
  + (UISemanticContentAttribute)UISemanticContentAttributeFromCppEquivalent:
11
16
  (react::RNSScreenStackHeaderConfigDirection)direction;
12
17
 
@@ -42,8 +47,12 @@ namespace react = facebook::react;
42
47
 
43
48
  + (NSMutableArray<NSNumber *> *)arrayFromVector:(const std::vector<CGFloat> &)vector;
44
49
 
45
- + (UIBlurEffectStyle)UIBlurEffectStyleFromCppEquivalent:(react::RNSScreenStackHeaderConfigBlurEffect)blurEffect;
46
-
47
- @end
50
+ + (RNSBlurEffectStyle)RNSBlurEffectStyleFromCppEquivalent:(react::RNSScreenStackHeaderConfigBlurEffect)blurEffect;
48
51
 
49
52
  #endif // RCT_NEW_ARCH_ENABLED
53
+
54
+ /// This method fails (by assertion) when `blurEffect == RNSBlurEffectStyleNone` which has no counter part in the UIKit
55
+ /// type.
56
+ + (UIBlurEffectStyle)tryConvertRNSBlurEffectStyleToUIBlurEffectStyle:(RNSBlurEffectStyle)blurEffect;
57
+
58
+ @end