react-native-screens 5.0.0-alpha.2 → 5.0.0-alpha.3

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 (237) hide show
  1. package/Package.swift +87 -0
  2. package/README.md +0 -7
  3. package/android/src/main/cpp/NativeProxy.cpp +30 -6
  4. package/android/src/main/cpp/NativeProxy.h +7 -1
  5. package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +8 -0
  6. package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
  7. package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
  8. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
  10. package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
  11. package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +3 -1
  12. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +2 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetBehaviorController.kt +49 -18
  14. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +65 -40
  15. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
  16. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetNativeDismissCoordinator.kt +0 -6
  17. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetAvailableHeightProvider.kt +44 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialog.kt +35 -3
  19. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +33 -106
  20. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/interfaces/FormSheetDialogEventEmitter.kt +2 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +61 -15
  22. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetAnimatorFactory.kt +8 -9
  23. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDimmingManager.kt +115 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDismissalOrigin.kt +22 -0
  25. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentation.kt +173 -0
  26. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +141 -49
  27. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationState.kt +1 -1
  28. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetStackRegistry.kt +28 -0
  29. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetDismissEvent.kt +29 -0
  30. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostEventEmitter.kt +7 -0
  31. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/host/FormSheetHostViewManager.kt +2 -0
  32. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +369 -58
  33. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
  34. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +143 -98
  35. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +155 -23
  36. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
  37. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
  38. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +170 -167
  39. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +385 -12
  40. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +0 -4
  41. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +32 -3
  42. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
  43. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +7 -2
  44. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +27 -280
  45. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
  46. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
  47. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +28 -20
  48. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +3 -55
  49. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +1 -10
  50. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuItemConfig.kt +1 -3
  51. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
  52. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +57 -6
  53. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +3 -1
  54. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +1 -0
  55. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +4 -3
  56. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueue.kt +23 -9
  57. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +103 -3
  58. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +13 -0
  59. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
  60. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +4 -0
  61. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +20 -1
  62. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
  63. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +2 -4
  64. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
  65. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +46 -25
  66. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +10 -0
  67. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
  68. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +17 -0
  69. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
  70. package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +7 -0
  71. package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
  72. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
  73. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
  74. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
  75. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
  76. package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
  77. package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
  78. package/ios/RNSEnums.h +2 -0
  79. package/ios/conversion/RNSConversions.h +7 -108
  80. package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
  81. package/ios/legacy/RNSModalScreen.mm +1 -1
  82. package/ios/legacy/RNSScreen.mm +8 -19
  83. package/ios/legacy/RNSScreenStackHeaderConfig.mm +3 -1
  84. package/ios/legacy/RNSScreenStackHeaderSubview.mm +1 -1
  85. package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
  86. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
  87. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
  88. package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
  89. package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
  90. package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
  91. package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
  92. package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
  93. package/ios/safe-area/RNSSafeAreaViewComponentView.mm +2 -2
  94. package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
  95. package/ios/split/RNSSplitAppearanceApplicator.h +4 -4
  96. package/ios/split/RNSSplitAppearanceApplicator.mm +53 -56
  97. package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
  98. package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
  99. package/ios/split/RNSSplitHostComponentView.h +5 -15
  100. package/ios/split/RNSSplitHostComponentView.mm +55 -6
  101. package/ios/split/RNSSplitHostController.h +25 -6
  102. package/ios/split/RNSSplitHostController.mm +24 -92
  103. package/ios/split/RNSSplitHostProviders.h +67 -0
  104. package/ios/split/RNSSplitScreenComponentView.h +0 -39
  105. package/ios/split/RNSSplitScreenComponentView.mm +27 -10
  106. package/ios/split/RNSSplitScreenController.h +26 -3
  107. package/ios/split/RNSSplitScreenController.mm +13 -30
  108. package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
  109. package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
  110. package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
  111. package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
  112. package/ios/stack/conversion/RNSConversions-Stack.h +32 -0
  113. package/ios/stack/conversion/RNSConversions-Stack.mm +55 -0
  114. package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
  115. package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
  116. package/ios/stack/header/RNSStackHeaderConfigComponentView.h +10 -1
  117. package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +67 -35
  118. package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +6 -0
  119. package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
  120. package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
  121. package/ios/stack/header/RNSStackHeaderItemComponentView.h +3 -1
  122. package/ios/stack/header/RNSStackHeaderItemComponentView.mm +15 -2
  123. package/ios/stack/header/RNSStackHeaderItemDataProviding.h +2 -0
  124. package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
  125. package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
  126. package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
  127. package/ios/stack/host/RNSStackNavigationBar.h +25 -0
  128. package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
  129. package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
  130. package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
  131. package/ios/stack/host/RNSStackNavigationController.mm +13 -5
  132. package/ios/stack/host/RNSStackOperation.h +0 -2
  133. package/ios/stack/screen/RNSStackScreenComponentView.mm +9 -2
  134. package/ios/stack/screen/RNSStackScreenController.mm +12 -0
  135. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +8 -0
  136. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +98 -16
  137. package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +40 -9
  138. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
  139. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +1 -1
  140. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +1 -1
  141. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
  142. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
  143. package/ios/tabs/conversion/RNSConversions-Tabs.h +78 -0
  144. package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +8 -71
  145. package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
  146. package/ios/tabs/host/RNSTabsHostComponentView.h +2 -0
  147. package/ios/tabs/host/RNSTabsHostComponentView.mm +10 -3
  148. package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
  149. package/ios/tabs/screen/RNSTabsScreenComponentView.mm +20 -5
  150. package/ios/utils/RNSDefines.h +3 -0
  151. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +34 -19
  152. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  153. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +33 -1
  154. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  155. package/lib/commonjs/components/stack/host/StackHost.js +9 -6
  156. package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
  157. package/lib/commonjs/components/stack/index.js.map +1 -1
  158. package/lib/commonjs/components/tabs/host/TabsHost.ios.js +1 -0
  159. package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
  160. package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  161. package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  162. package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  163. package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
  164. package/lib/commonjs/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  165. package/lib/module/components/stack/header/StackHeaderConfig.android.js +35 -20
  166. package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  167. package/lib/module/components/stack/header/StackHeaderConfig.ios.js +34 -2
  168. package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  169. package/lib/module/components/stack/host/StackHost.js +9 -6
  170. package/lib/module/components/stack/host/StackHost.js.map +1 -1
  171. package/lib/module/components/stack/index.js.map +1 -1
  172. package/lib/module/components/tabs/host/TabsHost.ios.js +1 -0
  173. package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
  174. package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  175. package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  176. package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  177. package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
  178. package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  179. package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +1 -1
  180. package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
  181. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +616 -21
  182. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
  183. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
  184. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +226 -2
  185. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
  186. package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +2 -2
  187. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +2 -0
  188. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
  189. package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
  190. package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
  191. package/lib/typescript/components/stack/host/StackHost.types.d.ts +24 -0
  192. package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
  193. package/lib/typescript/components/stack/index.d.ts +2 -2
  194. package/lib/typescript/components/stack/index.d.ts.map +1 -1
  195. package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
  196. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +16 -0
  197. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
  198. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
  199. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
  200. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +52 -0
  201. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
  202. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +25 -1
  203. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
  204. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +2 -0
  205. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
  206. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +3 -1
  207. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
  208. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +1 -0
  209. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
  210. package/package.json +8 -7
  211. package/react-native.config.js +3 -0
  212. package/src/components/modals/form-sheet/FormSheet.types.ts +1 -1
  213. package/src/components/stack/header/StackHeaderConfig.android.tsx +48 -23
  214. package/src/components/stack/header/StackHeaderConfig.android.types.ts +637 -21
  215. package/src/components/stack/header/StackHeaderConfig.ios.tsx +45 -1
  216. package/src/components/stack/header/StackHeaderConfig.ios.types.ts +238 -2
  217. package/src/components/stack/header/StackHeaderConfig.types.ts +2 -2
  218. package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +2 -0
  219. package/src/components/stack/host/StackHost.tsx +4 -2
  220. package/src/components/stack/host/StackHost.types.ts +26 -0
  221. package/src/components/stack/index.ts +6 -1
  222. package/src/components/tabs/host/TabsHost.ios.tsx +1 -0
  223. package/src/components/tabs/host/TabsHost.ios.types.ts +16 -0
  224. package/src/components/tabs/host/TabsHost.types.ts +3 -0
  225. package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +78 -0
  226. package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +32 -0
  227. package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +2 -0
  228. package/src/fabric/stack/StackHostNativeComponent.ts +11 -2
  229. package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +1 -0
  230. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
  231. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
  232. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
  233. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuSelectionController.kt +0 -83
  234. package/ios/conversion/RNSConversions-Stack.h +0 -32
  235. package/ios/conversion/RNSConversions-Stack.mm +0 -41
  236. package/ios/conversion/always_false.h +0 -31
  237. /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
@@ -2,39 +2,76 @@ package com.swmansion.rnscreens.modals.formsheet.native.presentation
2
2
 
3
3
  import android.animation.Animator
4
4
  import android.animation.AnimatorListenerAdapter
5
+ import android.util.Log
5
6
  import android.view.View
7
+ import androidx.core.view.doOnPreDraw
6
8
  import com.google.android.material.bottomsheet.BottomSheetBehavior
7
9
  import com.swmansion.rnscreens.common.event.ViewAppearanceEventEmitter
8
- import com.swmansion.rnscreens.modals.dimmingview.DimmingViewManager
9
- import com.swmansion.rnscreens.modals.formsheet.native.core.FormSheetDialog
10
10
 
11
11
  internal class FormSheetPresentationManager(
12
- private val dialog: FormSheetDialog,
13
- private val bottomSheetView: View?,
14
- private val dimmingManager: DimmingViewManager,
12
+ private val presentationFactory: () -> FormSheetPresentation,
13
+ private val dimmingManager: FormSheetDimmingManager,
15
14
  private val onNativeDismiss: () -> Unit,
15
+ private val onDismiss: () -> Unit,
16
16
  ) {
17
17
  internal var appearanceEventEmitter: ViewAppearanceEventEmitter? = null
18
18
 
19
+ internal var currentPresentation: FormSheetPresentation? = null
20
+ private set
21
+
22
+ private val bottomSheetView: View?
23
+ get() = currentPresentation?.bottomSheetView
24
+
19
25
  private var state = FormSheetPresentationState.DISMISSED
20
- private var targetIsOpen = false
26
+ private var shouldBeOpen = false
27
+ private var shouldSkipExitAnimation = false
28
+
29
+ private var dismissalOrigin = FormSheetDismissalOrigin.UNSPECIFIED
21
30
 
22
31
  private val animatorFactory = FormSheetAnimatorFactory(dimmingManager)
23
32
  private var currentSheetAnimator: Animator? = null
24
33
 
25
- internal fun setup() {
26
- bottomSheetView?.let { view ->
27
- dimmingManager.attachToBehavior(BottomSheetBehavior.from(view))
34
+ internal fun requestProgrammaticStateUpdate(shouldBeOpen: Boolean) {
35
+ if (shouldBeOpen) {
36
+ handlePresent()
37
+ } else {
38
+ handleProgrammaticDismiss()
39
+ }
40
+ }
41
+
42
+ private fun handlePresent() {
43
+ updatePresentationState(shouldBeOpen = true, origin = FormSheetDismissalOrigin.UNSPECIFIED)
44
+ }
45
+
46
+ private fun handleProgrammaticDismiss() {
47
+ updatePresentationState(shouldBeOpen = false, origin = FormSheetDismissalOrigin.PROGRAMMATIC_JS)
48
+ }
49
+
50
+ internal fun handleNativeDismiss() {
51
+ if (state == FormSheetPresentationState.DISMISSING || state == FormSheetPresentationState.DISMISSED) {
52
+ return
28
53
  }
54
+
55
+ updatePresentationState(shouldBeOpen = false, origin = FormSheetDismissalOrigin.USER)
29
56
  }
30
57
 
31
- internal fun updatePresentationState(isOpen: Boolean) {
32
- targetIsOpen = isOpen
58
+ private fun updatePresentationState(
59
+ shouldBeOpen: Boolean,
60
+ origin: FormSheetDismissalOrigin,
61
+ ) {
62
+ // The origin belongs to the request that transitioned the target to closed -
63
+ // a repeated close request must not override it. Once a dismissal is in flight,
64
+ // it keeps the origin that started it until the completion events are emitted.
65
+ val isRepeatCloseRequest = !shouldBeOpen && !this.shouldBeOpen
66
+ if (state != FormSheetPresentationState.DISMISSING && !isRepeatCloseRequest) {
67
+ dismissalOrigin = origin
68
+ }
69
+ this.shouldBeOpen = shouldBeOpen
33
70
  resolvePresentationState()
34
71
  }
35
72
 
36
73
  private fun resolvePresentationState() {
37
- if (targetIsOpen) {
74
+ if (shouldBeOpen) {
38
75
  presentIfNeeded()
39
76
  } else {
40
77
  dismissIfNeeded()
@@ -47,13 +84,23 @@ internal class FormSheetPresentationManager(
47
84
  }
48
85
 
49
86
  state = FormSheetPresentationState.PRESENTING
87
+ val presentation = presentationFactory().also { currentPresentation = it }
88
+ presentation.sheetBehavior?.let(dimmingManager::attachToBehavior)
89
+
90
+ FormSheetStackRegistry.register(this)
50
91
  appearanceEventEmitter?.emitOnWillAppear()
51
- dialog.setOnShowListener {
52
- dialog.setOnShowListener(null)
53
- dimmingManager.onDialogShow()
92
+ presentation.bottomSheetView?.let(::keepOffscreenUntilEnterAnimation)
93
+ presentation.dialog.setOnShowListener {
94
+ presentation.dialog.setOnShowListener(null)
95
+
96
+ // Every sheet dims the surface inside the window below, attaching an overlay to the sheet
97
+ // directly below in the stack, or to the DecorView when this sheet is the
98
+ // bottom-most one.
99
+ dimmingManager.attachDimming(FormSheetStackRegistry.sheetBelow(this)?.bottomSheetView)
100
+
54
101
  startEnterAnimation()
55
102
  }
56
- dialog.show()
103
+ presentation.dialog.show()
57
104
  }
58
105
 
59
106
  private fun dismissIfNeeded() {
@@ -62,6 +109,12 @@ internal class FormSheetPresentationManager(
62
109
  }
63
110
 
64
111
  state = FormSheetPresentationState.DISMISSING
112
+ currentPresentation?.setKeyboardTrackingEnabled(false)
113
+ dismissSheetsAbove()
114
+ // Leaving the stack immediately is deliberate, if another sheet is presented during this exit animation,
115
+ // it must stack on a "stable" sheet - the one we don't intend to dismiss. This window is about to be
116
+ // torn down.
117
+ FormSheetStackRegistry.unregister(this)
65
118
  appearanceEventEmitter?.emitOnWillDisappear()
66
119
 
67
120
  val isSheetHidden =
@@ -74,10 +127,59 @@ internal class FormSheetPresentationManager(
74
127
  return
75
128
  }
76
129
 
130
+ if (shouldSkipExitAnimation) {
131
+ performInstantDismiss()
132
+ return
133
+ }
134
+
77
135
  startExitAnimation()
78
136
  }
79
137
 
138
+ // Dismissing a sheet from the middle of the stack should dismiss all sheets above it,
139
+ // mirroring the iOS presentation chain teardown. Sheets are dismissed top-down.
140
+ private fun dismissSheetsAbove() {
141
+ FormSheetStackRegistry.sheetsAbove(this).asReversed().forEach {
142
+ it.handleDismissFromCascade()
143
+ }
144
+ }
145
+
146
+ private fun handleDismissFromCascade() {
147
+ if (state == FormSheetPresentationState.DISMISSING || state == FormSheetPresentationState.DISMISSED) {
148
+ return
149
+ }
150
+
151
+ shouldSkipExitAnimation = true
152
+ updatePresentationState(false, FormSheetDismissalOrigin.USER)
153
+ }
154
+
155
+ private fun performInstantDismiss() {
156
+ currentSheetAnimator?.removeAllListeners()
157
+ currentSheetAnimator?.cancel()
158
+ currentSheetAnimator = null
159
+
160
+ performDismiss()
161
+ }
162
+
163
+ /**
164
+ * `Dialog.show()` **posts** the show message behind the sync barrier of the traversal scheduled while
165
+ * adding the decor to the window, so the Dialog always draws its first frame before `OnShowListener`
166
+ * (with our custom enter animation) runs. A freshly created sheet rests at `translationY = 0`, so that
167
+ * frame would show it at its final position and the enter animator would then snap it back
168
+ * off-screen.
169
+ *
170
+ * Applying the translation on the first pre-draw - after the layout, when the sheet height is
171
+ * already known, but before anything is drawn - keeps the sheet off-screen from the very first frame.
172
+ */
173
+ private fun keepOffscreenUntilEnterAnimation(view: View) {
174
+ view.doOnPreDraw {
175
+ if (currentSheetAnimator == null) {
176
+ view.translationY = view.height.toFloat()
177
+ }
178
+ }
179
+ }
180
+
80
181
  private fun startEnterAnimation() {
182
+ val bottomSheetView = bottomSheetView
81
183
  if (bottomSheetView == null) {
82
184
  onPresentationComplete()
83
185
  return
@@ -106,6 +208,7 @@ internal class FormSheetPresentationManager(
106
208
  }
107
209
 
108
210
  private fun startExitAnimation() {
211
+ val bottomSheetView = bottomSheetView
109
212
  if (bottomSheetView == null) {
110
213
  performDismiss()
111
214
  return
@@ -125,7 +228,6 @@ internal class FormSheetPresentationManager(
125
228
  dimmingManager.isTransitionAnimationRunning = false
126
229
 
127
230
  if (currentSheetAnimator == this@apply) currentSheetAnimator = null
128
- syncBehaviorStateAfterExitAnimationComplete(bottomSheetView)
129
231
  performDismiss()
130
232
  }
131
233
  },
@@ -135,13 +237,17 @@ internal class FormSheetPresentationManager(
135
237
  }
136
238
 
137
239
  private fun performDismiss() {
138
- dialog.dismiss()
240
+ shouldSkipExitAnimation = false
241
+ dimmingManager.detachDimming()
242
+ currentPresentation?.destroy()
243
+ currentPresentation = null
139
244
  onDismissComplete()
140
245
  }
141
246
 
142
247
  private fun onPresentationComplete() {
143
248
  if (state == FormSheetPresentationState.PRESENTING) {
144
249
  state = FormSheetPresentationState.PRESENTED
250
+ currentPresentation?.setKeyboardTrackingEnabled(true)
145
251
  appearanceEventEmitter?.emitOnDidAppear()
146
252
  // ensure state hasn't updated during presentation
147
253
  resolvePresentationState()
@@ -152,46 +258,32 @@ internal class FormSheetPresentationManager(
152
258
  if (state == FormSheetPresentationState.DISMISSING) {
153
259
  state = FormSheetPresentationState.DISMISSED
154
260
  appearanceEventEmitter?.emitOnDidDisappear()
261
+
262
+ when (dismissalOrigin) {
263
+ FormSheetDismissalOrigin.USER -> onNativeDismiss()
264
+ FormSheetDismissalOrigin.PROGRAMMATIC_JS -> onDismiss()
265
+ FormSheetDismissalOrigin.UNSPECIFIED ->
266
+ Log.e(
267
+ "[RNScreens]",
268
+ "FormSheet dismissal completed without a recorded origin; no dismissal event emitted",
269
+ )
270
+ }
271
+ dismissalOrigin = FormSheetDismissalOrigin.UNSPECIFIED
272
+
155
273
  // ensure state hasn't updated during dismissal
156
274
  resolvePresentationState()
157
275
  }
158
276
  }
159
277
 
160
- internal fun handleNativeDismiss() {
161
- if (state == FormSheetPresentationState.DISMISSING || state == FormSheetPresentationState.DISMISSED) {
162
- return
163
- }
164
-
165
- onNativeDismiss()
166
- updatePresentationState(isOpen = false)
167
- }
168
-
169
- /**
170
- * Synchronizes the BottomSheetBehavior state with our custom exit animation.
171
- *
172
- * Since our custom ExitAnimator uses `translationY` for visual movement, the physical
173
- * `top` of the view remains at the top of the screen. If we just call `state = STATE_HIDDEN`,
174
- * Material will attempt to align the layout and enter `STATE_SETTLING`, leaving the state
175
- * machine corrupted for the next open.
176
- *
177
- * To fix this, we manually push the physical `top` to the bottom of the screen.
178
- * This makes the behavior skip the animation and synchronously switch to `STATE_HIDDEN`,
179
- * properly cleaning up its internal state on dismissal.
180
- */
181
- private fun syncBehaviorStateAfterExitAnimationComplete(view: View) {
182
- val behavior = BottomSheetBehavior.from(view)
183
- val parent = view.parent as? View
184
- val targetTop = parent?.height ?: view.height
185
-
186
- view.offsetTopAndBottom(targetTop - view.top)
187
- behavior.state = BottomSheetBehavior.STATE_HIDDEN
188
- }
189
-
190
278
  internal fun destroy() {
279
+ FormSheetStackRegistry.unregister(this)
280
+ dimmingManager.detachDimming()
281
+
191
282
  currentSheetAnimator?.cancel()
192
283
  currentSheetAnimator = null
193
284
 
194
- dialog.setOnShowListener(null)
285
+ currentPresentation?.destroy()
286
+ currentPresentation = null
195
287
 
196
288
  state = FormSheetPresentationState.DISMISSED
197
289
  }
@@ -27,7 +27,7 @@ internal enum class FormSheetPresentationState {
27
27
  /**
28
28
  * The manager is actively preparing to show the sheet. `presentIfNeeded()` has been called.
29
29
  * During this state, `dialog.show()` is executed. The manager waits for the `onShowListener`
30
- * to fire, requests DimmingView attachment from `dimmingManager` and runs starts entrance animation.
30
+ * to fire, attaches the dimming through `dimmingManager` and starts the entrance animation.
31
31
  * Once the enter animator finishes, the state moves to [PRESENTED].
32
32
  * **Transitional state** from [DISMISSED] to [PRESENTED].
33
33
  */
@@ -0,0 +1,28 @@
1
+ package com.swmansion.rnscreens.modals.formsheet.native.presentation
2
+
3
+ internal object FormSheetStackRegistry {
4
+ private val stack = mutableListOf<FormSheetPresentationManager>()
5
+
6
+ internal fun register(sheet: FormSheetPresentationManager) {
7
+ if (!stack.contains(sheet)) {
8
+ stack.add(sheet)
9
+ }
10
+ }
11
+
12
+ internal fun unregister(sheet: FormSheetPresentationManager) {
13
+ stack.remove(sheet)
14
+ }
15
+
16
+ internal fun sheetsAbove(sheet: FormSheetPresentationManager): List<FormSheetPresentationManager> {
17
+ val index = stack.indexOf(sheet)
18
+ if (index < 0) {
19
+ return emptyList()
20
+ }
21
+ return stack.drop(index + 1)
22
+ }
23
+
24
+ internal fun sheetBelow(sheet: FormSheetPresentationManager): FormSheetPresentationManager? {
25
+ val index = stack.indexOf(sheet)
26
+ return if (index > 0) stack[index - 1] else null
27
+ }
28
+ }
@@ -0,0 +1,29 @@
1
+ package com.swmansion.rnscreens.modals.formsheet.react.event
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.WritableMap
5
+ import com.facebook.react.uimanager.events.Event
6
+ import com.swmansion.rnscreens.common.event.NamingAwareEventType
7
+
8
+ class FormSheetDismissEvent(
9
+ surfaceId: Int,
10
+ viewId: Int,
11
+ ) : Event<FormSheetDismissEvent>(surfaceId, viewId),
12
+ NamingAwareEventType {
13
+ override fun getEventName(): String = EVENT_NAME
14
+
15
+ override fun getEventRegistrationName() = EVENT_REGISTRATION_NAME
16
+
17
+ override fun getEventData(): WritableMap? = Arguments.createMap()
18
+
19
+ override fun canCoalesce(): Boolean = false
20
+
21
+ companion object : NamingAwareEventType {
22
+ const val EVENT_NAME = "topDismiss"
23
+ const val EVENT_REGISTRATION_NAME = "onDismiss"
24
+
25
+ override fun getEventName() = EVENT_NAME
26
+
27
+ override fun getEventRegistrationName() = EVENT_REGISTRATION_NAME
28
+ }
29
+ }
@@ -6,6 +6,7 @@ import com.swmansion.rnscreens.modals.formsheet.native.interfaces.FormSheetDialo
6
6
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDetentChangedEvent
7
7
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDidAppearEvent
8
8
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDidDisappearEvent
9
+ import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDismissEvent
9
10
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetNativeDismissEvent
10
11
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetNativeDismissPreventedEvent
11
12
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetSyncFlushEvent
@@ -17,6 +18,12 @@ internal class FormSheetHostEventEmitter(
17
18
  viewTag: Int,
18
19
  ) : BaseEventEmitter(reactContext, viewTag),
19
20
  FormSheetDialogEventEmitter {
21
+ override fun emitOnDismissEvent() {
22
+ reactEventDispatcher.dispatchEvent(
23
+ FormSheetDismissEvent(surfaceId, viewTag),
24
+ )
25
+ }
26
+
20
27
  override fun emitOnNativeDismissEvent() {
21
28
  reactEventDispatcher.dispatchEvent(
22
29
  FormSheetNativeDismissEvent(surfaceId, viewTag),
@@ -14,6 +14,7 @@ import com.swmansion.rnscreens.helpers.makeEventRegistrationInfo
14
14
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDetentChangedEvent
15
15
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDidAppearEvent
16
16
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDidDisappearEvent
17
+ import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetDismissEvent
17
18
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetNativeDismissEvent
18
19
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetNativeDismissPreventedEvent
19
20
  import com.swmansion.rnscreens.modals.formsheet.react.event.FormSheetSyncFlushEvent
@@ -134,6 +135,7 @@ class FormSheetHostViewManager :
134
135
 
135
136
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
136
137
  mutableMapOf(
138
+ makeEventRegistrationInfo(FormSheetDismissEvent),
137
139
  makeEventRegistrationInfo(FormSheetNativeDismissEvent),
138
140
  makeEventRegistrationInfo(FormSheetSyncFlushEvent),
139
141
  makeEventRegistrationInfo(FormSheetWillAppearEvent),