react-native-screens 4.0.0-beta.9 → 4.1.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 (268) hide show
  1. package/README.md +9 -2
  2. package/android/CMakeLists.txt +28 -19
  3. package/android/src/main/cpp/jni-adapter.cpp +3 -0
  4. package/android/src/main/java/com/swmansion/rnscreens/CustomToolbar.kt +13 -3
  5. package/android/src/main/java/com/swmansion/rnscreens/NativeDismissalObserver.kt +12 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +4 -0
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +64 -68
  8. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/BottomSheetBehaviorExt.kt +42 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/DimmingFragment.kt +24 -19
  10. package/android/src/main/java/com/swmansion/rnscreens/bottomsheet/SheetUtils.kt +8 -0
  11. package/android/src/main/java/com/swmansion/rnscreens/ext/ViewExt.kt +10 -3
  12. package/android/src/main/jni/CMakeLists.txt +28 -19
  13. package/android/src/paper/java/com/facebook/react/viewmanagers/RNSScreenManagerDelegate.java +2 -2
  14. package/common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp +1 -1
  15. package/ios/RNSConvert.h +13 -6
  16. package/ios/RNSConvert.mm +130 -94
  17. package/ios/RNSEnums.h +47 -0
  18. package/ios/RNSFullWindowOverlay.mm +4 -0
  19. package/ios/RNSPercentDrivenInteractiveTransition.h +12 -0
  20. package/ios/RNSPercentDrivenInteractiveTransition.mm +69 -0
  21. package/ios/RNSScreen.h +14 -0
  22. package/ios/RNSScreen.mm +35 -9
  23. package/ios/RNSScreenContainer.mm +5 -0
  24. package/ios/RNSScreenFooter.mm +24 -25
  25. package/ios/RNSScreenStack.mm +79 -8
  26. package/ios/RNSScreenStackAnimator.h +13 -1
  27. package/ios/RNSScreenStackAnimator.mm +233 -130
  28. package/ios/RNSScreenStackHeaderConfig.h +10 -7
  29. package/ios/RNSScreenStackHeaderConfig.mm +49 -30
  30. package/ios/RNSScreenStackHeaderSubview.mm +4 -0
  31. package/ios/utils/RNSDefines.h +7 -0
  32. package/lib/commonjs/components/DebugContainer.js +40 -0
  33. package/lib/commonjs/components/DebugContainer.js.map +1 -0
  34. package/lib/commonjs/components/DebugContainer.web.js +15 -0
  35. package/lib/commonjs/components/DebugContainer.web.js.map +1 -0
  36. package/lib/commonjs/components/FullWindowOverlay.js +8 -5
  37. package/lib/commonjs/components/FullWindowOverlay.js.map +1 -1
  38. package/lib/commonjs/components/Screen.js +28 -10
  39. package/lib/commonjs/components/Screen.js.map +1 -1
  40. package/lib/commonjs/components/ScreenContainer.js +3 -5
  41. package/lib/commonjs/components/ScreenContainer.js.map +1 -1
  42. package/lib/commonjs/components/ScreenContainer.web.js +3 -4
  43. package/lib/commonjs/components/ScreenContainer.web.js.map +1 -1
  44. package/lib/commonjs/components/ScreenContentWrapper.js +2 -4
  45. package/lib/commonjs/components/ScreenContentWrapper.js.map +1 -1
  46. package/lib/commonjs/components/ScreenContentWrapper.web.js +1 -2
  47. package/lib/commonjs/components/ScreenContentWrapper.web.js.map +1 -1
  48. package/lib/commonjs/components/ScreenFooter.js +2 -8
  49. package/lib/commonjs/components/ScreenFooter.js.map +1 -1
  50. package/lib/commonjs/components/ScreenFooter.web.js +1 -2
  51. package/lib/commonjs/components/ScreenFooter.web.js.map +1 -1
  52. package/lib/commonjs/components/ScreenStack.js +47 -9
  53. package/lib/commonjs/components/ScreenStack.js.map +1 -1
  54. package/lib/commonjs/components/ScreenStack.web.js +2 -1
  55. package/lib/commonjs/components/ScreenStack.web.js.map +1 -1
  56. package/lib/commonjs/components/ScreenStackHeaderConfig.js +10 -10
  57. package/lib/commonjs/components/ScreenStackHeaderConfig.js.map +1 -1
  58. package/lib/commonjs/components/ScreenStackItem.js +99 -0
  59. package/lib/commonjs/components/ScreenStackItem.js.map +1 -0
  60. package/lib/commonjs/components/SearchBar.js +5 -5
  61. package/lib/commonjs/components/SearchBar.js.map +1 -1
  62. package/lib/commonjs/components/SearchBar.web.js +3 -4
  63. package/lib/commonjs/components/SearchBar.web.js.map +1 -1
  64. package/lib/commonjs/contexts.js +11 -0
  65. package/lib/commonjs/contexts.js.map +1 -0
  66. package/lib/commonjs/core.js +0 -3
  67. package/lib/commonjs/core.js.map +1 -1
  68. package/lib/commonjs/fabric/ModalScreenNativeComponent.js.map +1 -1
  69. package/lib/commonjs/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  70. package/lib/commonjs/gesture-handler/GestureDetectorProvider.js +2 -2
  71. package/lib/commonjs/gesture-handler/GestureDetectorProvider.js.map +1 -1
  72. package/lib/commonjs/gesture-handler/ScreenGestureDetector.js +3 -3
  73. package/lib/commonjs/gesture-handler/ScreenGestureDetector.js.map +1 -1
  74. package/lib/commonjs/gesture-handler/fabricUtils.js +54 -18
  75. package/lib/commonjs/gesture-handler/fabricUtils.js.map +1 -1
  76. package/lib/commonjs/index.js +23 -86
  77. package/lib/commonjs/index.js.map +1 -1
  78. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +4 -0
  79. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  80. package/lib/commonjs/native-stack/views/FooterComponent.js +2 -2
  81. package/lib/commonjs/native-stack/views/FooterComponent.js.map +1 -1
  82. package/lib/commonjs/native-stack/views/HeaderConfig.js +10 -8
  83. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  84. package/lib/commonjs/native-stack/views/NativeStackView.js +34 -39
  85. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  86. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +2 -2
  87. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  88. package/lib/commonjs/reanimated/ReanimatedScreen.js +2 -2
  89. package/lib/commonjs/reanimated/ReanimatedScreen.js.map +1 -1
  90. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +2 -2
  91. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -1
  92. package/lib/commonjs/utils.js +28 -6
  93. package/lib/commonjs/utils.js.map +1 -1
  94. package/lib/module/components/DebugContainer.js +31 -0
  95. package/lib/module/components/DebugContainer.js.map +1 -0
  96. package/lib/module/components/DebugContainer.web.js +6 -0
  97. package/lib/module/components/DebugContainer.web.js.map +1 -0
  98. package/lib/module/components/FullWindowOverlay.js +9 -6
  99. package/lib/module/components/FullWindowOverlay.js.map +1 -1
  100. package/lib/module/components/Screen.js +27 -9
  101. package/lib/module/components/Screen.js.map +1 -1
  102. package/lib/module/components/ScreenContainer.js +2 -4
  103. package/lib/module/components/ScreenContainer.js.map +1 -1
  104. package/lib/module/components/ScreenContainer.web.js +2 -3
  105. package/lib/module/components/ScreenContainer.web.js.map +1 -1
  106. package/lib/module/components/ScreenContentWrapper.js +1 -3
  107. package/lib/module/components/ScreenContentWrapper.js.map +1 -1
  108. package/lib/module/components/ScreenContentWrapper.web.js +0 -1
  109. package/lib/module/components/ScreenContentWrapper.web.js.map +1 -1
  110. package/lib/module/components/ScreenFooter.js +1 -7
  111. package/lib/module/components/ScreenFooter.js.map +1 -1
  112. package/lib/module/components/ScreenFooter.web.js +0 -1
  113. package/lib/module/components/ScreenFooter.web.js.map +1 -1
  114. package/lib/module/components/ScreenStack.js +46 -8
  115. package/lib/module/components/ScreenStack.js.map +1 -1
  116. package/lib/module/components/ScreenStack.web.js +2 -1
  117. package/lib/module/components/ScreenStack.web.js.map +1 -1
  118. package/lib/module/components/ScreenStackHeaderConfig.js +10 -8
  119. package/lib/module/components/ScreenStackHeaderConfig.js.map +1 -1
  120. package/lib/module/components/ScreenStackItem.js +90 -0
  121. package/lib/module/components/ScreenStackItem.js.map +1 -0
  122. package/lib/module/components/SearchBar.js +3 -3
  123. package/lib/module/components/SearchBar.js.map +1 -1
  124. package/lib/module/components/SearchBar.web.js +2 -3
  125. package/lib/module/components/SearchBar.web.js.map +1 -1
  126. package/lib/module/contexts.js +4 -0
  127. package/lib/module/contexts.js.map +1 -0
  128. package/lib/module/core.js +0 -3
  129. package/lib/module/core.js.map +1 -1
  130. package/lib/module/fabric/ModalScreenNativeComponent.js.map +1 -1
  131. package/lib/module/fabric/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  132. package/lib/module/gesture-handler/GestureDetectorProvider.js +1 -1
  133. package/lib/module/gesture-handler/GestureDetectorProvider.js.map +1 -1
  134. package/lib/module/gesture-handler/ScreenGestureDetector.js +3 -3
  135. package/lib/module/gesture-handler/ScreenGestureDetector.js.map +1 -1
  136. package/lib/module/gesture-handler/fabricUtils.js +55 -17
  137. package/lib/module/gesture-handler/fabricUtils.js.map +1 -1
  138. package/lib/module/index.js +12 -18
  139. package/lib/module/index.js.map +1 -1
  140. package/lib/module/native-stack/navigators/createNativeStackNavigator.js +4 -0
  141. package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  142. package/lib/module/native-stack/views/FooterComponent.js +1 -1
  143. package/lib/module/native-stack/views/FooterComponent.js.map +1 -1
  144. package/lib/module/native-stack/views/HeaderConfig.js +3 -1
  145. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  146. package/lib/module/native-stack/views/NativeStackView.js +28 -33
  147. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  148. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +1 -2
  149. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  150. package/lib/module/reanimated/ReanimatedScreen.js +1 -2
  151. package/lib/module/reanimated/ReanimatedScreen.js.map +1 -1
  152. package/lib/module/reanimated/ReanimatedScreenProvider.js +1 -1
  153. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -1
  154. package/lib/module/utils.js +26 -5
  155. package/lib/module/utils.js.map +1 -1
  156. package/lib/typescript/components/DebugContainer.d.ts +15 -0
  157. package/lib/typescript/components/DebugContainer.d.ts.map +1 -0
  158. package/lib/typescript/components/DebugContainer.web.d.ts +4 -0
  159. package/lib/typescript/components/DebugContainer.web.d.ts.map +1 -0
  160. package/lib/typescript/components/FullWindowOverlay.d.ts.map +1 -1
  161. package/lib/typescript/components/Screen.d.ts +2 -7
  162. package/lib/typescript/components/Screen.d.ts.map +1 -1
  163. package/lib/typescript/components/Screen.web.d.ts +1 -1
  164. package/lib/typescript/components/Screen.web.d.ts.map +1 -1
  165. package/lib/typescript/components/ScreenContainer.d.ts +1 -3
  166. package/lib/typescript/components/ScreenContainer.d.ts.map +1 -1
  167. package/lib/typescript/components/ScreenContainer.web.d.ts +2 -3
  168. package/lib/typescript/components/ScreenContainer.web.d.ts.map +1 -1
  169. package/lib/typescript/components/ScreenContentWrapper.d.ts +0 -1
  170. package/lib/typescript/components/ScreenContentWrapper.d.ts.map +1 -1
  171. package/lib/typescript/components/ScreenContentWrapper.web.d.ts +0 -1
  172. package/lib/typescript/components/ScreenContentWrapper.web.d.ts.map +1 -1
  173. package/lib/typescript/components/ScreenFooter.d.ts +0 -4
  174. package/lib/typescript/components/ScreenFooter.d.ts.map +1 -1
  175. package/lib/typescript/components/ScreenFooter.web.d.ts +0 -1
  176. package/lib/typescript/components/ScreenFooter.web.d.ts.map +1 -1
  177. package/lib/typescript/components/ScreenStack.d.ts +1 -1
  178. package/lib/typescript/components/ScreenStack.d.ts.map +1 -1
  179. package/lib/typescript/components/ScreenStack.web.d.ts +2 -1
  180. package/lib/typescript/components/ScreenStack.web.d.ts.map +1 -1
  181. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts +3 -3
  182. package/lib/typescript/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  183. package/lib/typescript/components/ScreenStackHeaderConfig.web.d.ts +1 -1
  184. package/lib/typescript/components/ScreenStackHeaderConfig.web.d.ts.map +1 -1
  185. package/lib/typescript/components/ScreenStackItem.d.ts +11 -0
  186. package/lib/typescript/components/ScreenStackItem.d.ts.map +1 -0
  187. package/lib/typescript/components/SearchBar.d.ts +1 -15
  188. package/lib/typescript/components/SearchBar.d.ts.map +1 -1
  189. package/lib/typescript/components/SearchBar.web.d.ts +2 -3
  190. package/lib/typescript/components/SearchBar.web.d.ts.map +1 -1
  191. package/lib/typescript/contexts.d.ts +5 -0
  192. package/lib/typescript/contexts.d.ts.map +1 -0
  193. package/lib/typescript/core.d.ts +0 -1
  194. package/lib/typescript/core.d.ts.map +1 -1
  195. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts +9 -3
  196. package/lib/typescript/fabric/ModalScreenNativeComponent.d.ts.map +1 -1
  197. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +2 -2
  198. package/lib/typescript/fabric/ScreenNativeComponent.d.ts.map +1 -1
  199. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts +2 -2
  200. package/lib/typescript/fabric/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  201. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts +1 -1
  202. package/lib/typescript/fabric/ScreenStackNativeComponent.d.ts.map +1 -1
  203. package/lib/typescript/gesture-handler/ScreenGestureDetector.d.ts +2 -2
  204. package/lib/typescript/gesture-handler/ScreenGestureDetector.d.ts.map +1 -1
  205. package/lib/typescript/gesture-handler/fabricUtils.d.ts +7 -5
  206. package/lib/typescript/gesture-handler/fabricUtils.d.ts.map +1 -1
  207. package/lib/typescript/index.d.ts +10 -16
  208. package/lib/typescript/index.d.ts.map +1 -1
  209. package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts +3 -0
  210. package/lib/typescript/native-stack/navigators/createNativeStackNavigator.d.ts.map +1 -1
  211. package/lib/typescript/native-stack/types.d.ts +58 -12
  212. package/lib/typescript/native-stack/types.d.ts.map +1 -1
  213. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts +1 -1
  214. package/lib/typescript/native-stack/utils/getDefaultHeaderHeight.d.ts.map +1 -1
  215. package/lib/typescript/native-stack/views/HeaderConfig.d.ts.map +1 -1
  216. package/lib/typescript/native-stack/views/NativeStackView.d.ts.map +1 -1
  217. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts +1 -1
  218. package/lib/typescript/reanimated/ReanimatedNativeStackScreen.d.ts.map +1 -1
  219. package/lib/typescript/reanimated/ReanimatedScreen.d.ts +1 -1
  220. package/lib/typescript/reanimated/ReanimatedScreen.d.ts.map +1 -1
  221. package/lib/typescript/reanimated/ReanimatedScreenProvider.d.ts.map +1 -1
  222. package/lib/typescript/types.d.ts +52 -16
  223. package/lib/typescript/types.d.ts.map +1 -1
  224. package/lib/typescript/utils.d.ts +26 -1
  225. package/lib/typescript/utils.d.ts.map +1 -1
  226. package/native-stack/README.md +5 -4
  227. package/native-stack/package.json +4 -4
  228. package/package.json +1 -1
  229. package/react-native.config.js +16 -28
  230. package/src/components/DebugContainer.tsx +47 -0
  231. package/src/components/DebugContainer.web.tsx +7 -0
  232. package/src/components/FullWindowOverlay.tsx +10 -2
  233. package/src/components/Screen.tsx +38 -24
  234. package/src/components/Screen.web.tsx +1 -1
  235. package/src/components/ScreenContainer.tsx +4 -11
  236. package/src/components/ScreenContainer.web.tsx +2 -3
  237. package/src/components/ScreenContentWrapper.tsx +2 -5
  238. package/src/components/ScreenContentWrapper.web.tsx +1 -2
  239. package/src/components/ScreenFooter.tsx +2 -8
  240. package/src/components/ScreenFooter.web.tsx +1 -2
  241. package/src/components/ScreenStack.tsx +99 -12
  242. package/src/components/ScreenStack.web.tsx +3 -1
  243. package/src/components/ScreenStackHeaderConfig.tsx +25 -14
  244. package/src/components/ScreenStackHeaderConfig.web.tsx +1 -1
  245. package/src/components/ScreenStackItem.tsx +162 -0
  246. package/src/components/SearchBar.tsx +4 -7
  247. package/src/components/SearchBar.web.tsx +2 -3
  248. package/src/contexts.tsx +9 -0
  249. package/src/core.ts +0 -3
  250. package/src/fabric/ModalScreenNativeComponent.ts +11 -3
  251. package/src/fabric/ScreenNativeComponent.ts +2 -2
  252. package/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +2 -1
  253. package/src/fabric/ScreenStackNativeComponent.ts +1 -1
  254. package/src/gesture-handler/GestureDetectorProvider.tsx +2 -2
  255. package/src/gesture-handler/ScreenGestureDetector.tsx +4 -4
  256. package/src/gesture-handler/fabricUtils.ts +74 -27
  257. package/src/index.tsx +11 -37
  258. package/src/native-stack/navigators/createNativeStackNavigator.tsx +3 -0
  259. package/src/native-stack/types.tsx +60 -17
  260. package/src/native-stack/utils/getDefaultHeaderHeight.tsx +1 -1
  261. package/src/native-stack/views/FooterComponent.tsx +1 -1
  262. package/src/native-stack/views/HeaderConfig.tsx +7 -5
  263. package/src/native-stack/views/NativeStackView.tsx +48 -67
  264. package/src/reanimated/ReanimatedNativeStackScreen.tsx +2 -2
  265. package/src/reanimated/ReanimatedScreen.tsx +2 -1
  266. package/src/reanimated/ReanimatedScreenProvider.tsx +2 -1
  267. package/src/types.tsx +72 -15
  268. package/src/utils.ts +27 -5
package/README.md CHANGED
@@ -106,9 +106,13 @@ Screens are already integrated with the React Native's most popular navigation l
106
106
 
107
107
  ## Supported react-native version
108
108
 
109
+ ### Support for Paper
110
+
111
+ Paper is the default rendering system for React Native versions prior to 0.76.
112
+
109
113
  | library version | react-native version |
110
114
  | --------------- | -------------------- |
111
- | 3.33.0+ | 0.72.0+
115
+ | 3.33.0+ | 0.72.0+ |
112
116
  | 3.32.0+ | 0.71.0+ |
113
117
  | 3.30.0+ | 0.68.0+ |
114
118
  | 3.14.0+ | 0.64.0+ |
@@ -123,6 +127,7 @@ Here's a table with summary of supported `react-native` versions when Fabric is
123
127
 
124
128
  | library version | react-native version |
125
129
  | --------------- | -------------------- |
130
+ | 3.35.0+ | 0.76.0+ |
126
131
  | 3.33.0+ | 0.75.0+ |
127
132
  | 3.32.0+ | 0.74.0+ |
128
133
  | 3.28.0+ | 0.73.0+ |
@@ -133,6 +138,9 @@ Here's a table with summary of supported `react-native` versions when Fabric is
133
138
 
134
139
  ## Usage with [react-navigation](https://github.com/react-navigation/react-navigation)
135
140
 
141
+ > [!CAUTION]
142
+ > JS API of the native stack has been moved from `react-native-screens/native-stack` to `@react-navigation/native-stack` since version v6. Currently, native stack v5 (imported from `react-native-screens/native-stack`) is deprecated and will be removed in the upcoming **minor** release. `react-native-screens` v4 will support only `@react-navigation/native-stack` v7.
143
+
136
144
  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
145
 
138
146
  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 +192,6 @@ You can also disable the usage of native screens per navigator with [`detachInac
184
192
  To take advantage of the native stack navigator primitive for React Navigation that leverages `UINavigationController` on iOS and `Fragment` on Android, please refer:
185
193
 
186
194
  - 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
195
 
189
196
  ## `FullWindowOverlay`
190
197
 
@@ -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
@@ -18,6 +18,9 @@ Java_com_swmansion_rnscreens_ScreensModule_nativeInstall(
18
18
  return;
19
19
  }
20
20
  jsi::Runtime &rt = *runtime;
21
+ if (globalThis) {
22
+ env->DeleteGlobalRef(globalThis);
23
+ }
21
24
  globalThis = env->NewGlobalRef(thiz);
22
25
  JavaVM *jvm;
23
26
  env->GetJavaVM(&jvm);
@@ -3,9 +3,11 @@ package com.swmansion.rnscreens
3
3
  import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.os.Build
6
+ import android.view.WindowManager
6
7
  import androidx.appcompat.widget.Toolbar
7
8
  import com.facebook.react.modules.core.ChoreographerCompat
8
9
  import com.facebook.react.modules.core.ReactChoreographer
10
+ import com.facebook.react.uimanager.ThemedReactContext
9
11
 
10
12
  // This class is used to store config closer to search bar
11
13
  @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
@@ -18,9 +20,11 @@ open class CustomToolbar(
18
20
  object : ChoreographerCompat.FrameCallback() {
19
21
  override fun doFrame(frameTimeNanos: Long) {
20
22
  isLayoutEnqueued = false
23
+ // The following measure specs are selected to work only with Android APIs <= 29.
24
+ // See https://github.com/software-mansion/react-native-screens/pull/2439
21
25
  measure(
22
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
23
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
26
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
27
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST),
24
28
  )
25
29
  layout(left, top, right, bottom)
26
30
  }
@@ -28,7 +32,13 @@ open class CustomToolbar(
28
32
 
29
33
  override fun requestLayout() {
30
34
  super.requestLayout()
31
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
35
+ val softInputMode =
36
+ (context as ThemedReactContext)
37
+ .currentActivity
38
+ ?.window
39
+ ?.attributes
40
+ ?.softInputMode
41
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q && softInputMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) {
32
42
  // Below Android API 29, layout is not being requested when subviews are being added to the layout,
33
43
  // leading to having their subviews in position 0,0 of the toolbar (as Android don't calculate
34
44
  // the position of each subview, even if Yoga has correctly set their width and height).
@@ -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
+ }
@@ -27,6 +27,7 @@ import com.google.android.material.shape.ShapeAppearanceModel
27
27
  import com.swmansion.rnscreens.events.HeaderHeightChangeEvent
28
28
  import com.swmansion.rnscreens.events.SheetDetentChangedEvent
29
29
  import com.swmansion.rnscreens.ext.isInsideScrollViewWithRemoveClippedSubviews
30
+ import java.lang.ref.WeakReference
30
31
 
31
32
  @SuppressLint("ViewConstructor") // Only we construct this view, it is never inflated.
32
33
  class Screen(
@@ -36,6 +37,8 @@ class Screen(
36
37
  val fragment: Fragment?
37
38
  get() = fragmentWrapper?.fragment
38
39
 
40
+ var contentWrapper = WeakReference<ScreenContentWrapper>(null)
41
+
39
42
  val sheetBehavior: BottomSheetBehavior<Screen>?
40
43
  get() = (layoutParams as? CoordinatorLayout.LayoutParams)?.behavior as? BottomSheetBehavior<Screen>
41
44
 
@@ -128,6 +131,7 @@ class Screen(
128
131
 
129
132
  fun registerLayoutCallbackForWrapper(wrapper: ScreenContentWrapper) {
130
133
  wrapper.delegate = this
134
+ this.contentWrapper = WeakReference(wrapper)
131
135
  }
132
136
 
133
137
  override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
@@ -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
@@ -154,25 +158,25 @@ class ScreenStackFragment :
154
158
  ) {
155
159
  if (SheetUtils.isStateStable(newState)) {
156
160
  lastStableState = newState
157
- screen.notifySheetDetentChange(SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()), true)
161
+ screen.notifySheetDetentChange(
162
+ SheetUtils.detentIndexFromSheetState(
163
+ lastStableState,
164
+ screen.sheetDetents.count(),
165
+ ),
166
+ true,
167
+ )
158
168
  } else if (newState == BottomSheetBehavior.STATE_DRAGGING) {
159
169
  screen.notifySheetDetentChange(
160
- SheetUtils.detentIndexFromSheetState(lastStableState, screen.sheetDetents.count()),
170
+ SheetUtils.detentIndexFromSheetState(
171
+ lastStableState,
172
+ screen.sheetDetents.count(),
173
+ ),
161
174
  false,
162
175
  )
163
176
  }
164
177
 
165
178
  if (newState == BottomSheetBehavior.STATE_HIDDEN) {
166
- // If we are wrapped in DimmingFragment we want it to be removed alongside
167
- // => we use its fragment manager. Otherwise we just remove this fragment.
168
- if (this@ScreenStackFragment.parentFragment is DimmingFragment) {
169
- parentFragmentManager.commit {
170
- setReorderingAllowed(true)
171
- remove(this@ScreenStackFragment)
172
- }
173
- } else {
174
- this@ScreenStackFragment.dismissFromContainer()
175
- }
179
+ nativeDismissalObserver?.onNativeDismiss(this@ScreenStackFragment)
176
180
  }
177
181
  }
178
182
 
@@ -215,7 +219,7 @@ class ScreenStackFragment :
215
219
  LinearLayout.LayoutParams.MATCH_PARENT,
216
220
  ).apply {
217
221
  behavior =
218
- if (screen.stackPresentation == Screen.StackPresentation.FORM_SHEET) {
222
+ if (screen.usesFormSheetPresentation()) {
219
223
  createAndConfigureBottomSheetBehaviour()
220
224
  } else if (isToolbarTranslucent) {
221
225
  null
@@ -224,7 +228,7 @@ class ScreenStackFragment :
224
228
  }
225
229
  }
226
230
 
227
- if (screen.stackPresentation == Screen.StackPresentation.FORM_SHEET) {
231
+ if (screen.usesFormSheetPresentation()) {
228
232
  screen.clipToOutline = true
229
233
  // TODO(@kkafar): without this line there is no drawable / outline & nothing shows...? Determine what's going on here
230
234
  attachShapeToScreen(screen)
@@ -233,7 +237,7 @@ class ScreenStackFragment :
233
237
 
234
238
  coordinatorLayout.addView(screen.recycle())
235
239
 
236
- if (screen.stackPresentation != Screen.StackPresentation.FORM_SHEET) {
240
+ if (!screen.usesFormSheetPresentation()) {
237
241
  appBarLayout =
238
242
  context?.let { AppBarLayout(it) }?.apply {
239
243
  // By default AppBarLayout will have a background color set but since we cover the whole layout
@@ -342,39 +346,37 @@ class ScreenStackFragment :
342
346
  when (screen.sheetDetents.count()) {
343
347
  1 ->
344
348
  behavior.apply {
345
- state = BottomSheetBehavior.STATE_EXPANDED
346
- skipCollapsed = true
347
- isFitToContents = true
348
- 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)
349
356
  }
350
357
 
351
358
  2 ->
352
- behavior.apply {
359
+ behavior.useTwoDetents(
353
360
  state =
354
361
  SheetUtils.sheetStateFromDetentIndex(
355
362
  screen.sheetInitialDetentIndex,
356
363
  screen.sheetDetents.count(),
357
- )
358
- skipCollapsed = false
359
- isFitToContents = true
360
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
361
- maxHeight = (screen.sheetDetents[1] * containerHeight).toInt()
362
- }
364
+ ),
365
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
366
+ secondHeight = (screen.sheetDetents[1] * containerHeight).toInt(),
367
+ )
363
368
 
364
369
  3 ->
365
- behavior.apply {
370
+ behavior.useThreeDetents(
366
371
  state =
367
372
  SheetUtils.sheetStateFromDetentIndex(
368
373
  screen.sheetInitialDetentIndex,
369
374
  screen.sheetDetents.count(),
370
- )
371
- skipCollapsed = false
372
- isFitToContents = false
373
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
374
- expandedOffset = ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
375
- halfExpandedRatio =
376
- (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
377
- }
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
+ )
378
380
 
379
381
  else -> throw IllegalStateException(
380
382
  "[RNScreens] Invalid detent count ${screen.sheetDetents.count()}. Expected at most 3.",
@@ -392,27 +394,24 @@ class ScreenStackFragment :
392
394
  when (screen.sheetDetents.count()) {
393
395
  1 ->
394
396
  behavior.apply {
395
- state = BottomSheetBehavior.STATE_EXPANDED
396
- skipCollapsed = true
397
- isFitToContents = true
398
- maxHeight = newMaxHeight
397
+ useSingleDetent(height = newMaxHeight)
399
398
  addBottomSheetCallback(keyboardSheetCallback)
400
399
  }
401
400
 
402
401
  2 ->
403
402
  behavior.apply {
404
- state = BottomSheetBehavior.STATE_EXPANDED
405
- skipCollapsed = false
406
- isFitToContents = true
407
- maxHeight = newMaxHeight
403
+ useTwoDetents(
404
+ state = BottomSheetBehavior.STATE_EXPANDED,
405
+ secondHeight = newMaxHeight,
406
+ )
408
407
  addBottomSheetCallback(keyboardSheetCallback)
409
408
  }
410
409
 
411
410
  3 ->
412
411
  behavior.apply {
413
- state = BottomSheetBehavior.STATE_EXPANDED
414
- skipCollapsed = false
415
- isFitToContents = false
412
+ useThreeDetents(
413
+ state = BottomSheetBehavior.STATE_EXPANDED,
414
+ )
416
415
  maxHeight = newMaxHeight
417
416
  addBottomSheetCallback(keyboardSheetCallback)
418
417
  }
@@ -431,29 +430,23 @@ class ScreenStackFragment :
431
430
  behavior.removeBottomSheetCallback(keyboardSheetCallback)
432
431
  when (screen.sheetDetents.count()) {
433
432
  1 ->
434
- behavior.apply {
435
- skipCollapsed = true
436
- isFitToContents = true
437
- maxHeight = (screen.sheetDetents.first() * containerHeight).toInt()
438
- }
433
+ behavior.useSingleDetent(
434
+ height = (screen.sheetDetents.first() * containerHeight).toInt(),
435
+ forceExpandedState = false,
436
+ )
439
437
 
440
438
  2 ->
441
- behavior.apply {
442
- skipCollapsed = false
443
- isFitToContents = true
444
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
445
- maxHeight = (screen.sheetDetents[1] * containerHeight).toInt()
446
- }
439
+ behavior.useTwoDetents(
440
+ firstHeight = (screen.sheetDetents[0] * containerHeight).toInt(),
441
+ secondHeight = (screen.sheetDetents[1] * containerHeight).toInt(),
442
+ )
447
443
 
448
444
  3 ->
449
- behavior.apply {
450
- skipCollapsed = false
451
- isFitToContents = false
452
- peekHeight = (screen.sheetDetents[0] * containerHeight).toInt()
453
- expandedOffset = ((1 - screen.sheetDetents[2]) * containerHeight).toInt()
454
- halfExpandedRatio =
455
- (screen.sheetDetents[1] / screen.sheetDetents[2]).toFloat()
456
- }
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
+ )
457
450
 
458
451
  else -> throw IllegalStateException(
459
452
  "[RNScreens] Invalid detent count ${screen.sheetDetents.count()}. Expected at most 3.",
@@ -478,7 +471,10 @@ class ScreenStackFragment :
478
471
  setTopRightCorner(CornerFamily.ROUNDED, cornerSize)
479
472
  }.build()
480
473
  val shape = MaterialShapeDrawable(shapeAppearanceModel)
481
- 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)
482
478
  screen.background = shape
483
479
  }
484
480
 
@@ -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
@@ -40,10 +40,17 @@ internal fun View.isInsideScrollViewWithRemoveClippedSubviews(): Boolean {
40
40
  }
41
41
  var parentView = this.parent
42
42
  while (parentView is ViewGroup && parentView !is ScreenStack) {
43
- if (parentView is ReactScrollView) {
44
- return parentView.removeClippedSubviews
43
+ when (parentView) {
44
+ is ReactHorizontalScrollView -> {
45
+ return parentView.removeClippedSubviews
46
+ }
47
+ is ReactScrollView -> {
48
+ return parentView.removeClippedSubviews
49
+ }
50
+ else -> {
51
+ parentView = parentView.parent
52
+ }
45
53
  }
46
- parentView = parentView.parent
47
54
  }
48
55
  return false
49
56
  }