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

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 (456) hide show
  1. package/Package.swift +87 -0
  2. package/README.md +0 -11
  3. package/android/build.gradle +1 -0
  4. package/android/consumer-rules.pro +3 -0
  5. package/android/src/fabric/java/com/swmansion/rnscreens/legacy/FabricEnabledHeaderConfigViewGroup.kt +2 -0
  6. package/android/src/fabric/java/com/swmansion/rnscreens/legacy/FabricEnabledHeaderSubviewViewGroup.kt +2 -0
  7. package/android/src/fabric/java/com/swmansion/rnscreens/legacy/FabricEnabledViewGroup.kt +18 -3
  8. package/android/src/main/cpp/NativeProxy.cpp +30 -6
  9. package/android/src/main/cpp/NativeProxy.h +7 -1
  10. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -2
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreensModule.kt +7 -3
  12. package/android/src/main/java/com/swmansion/rnscreens/common/colorscheme/ColorSchemeCoordinator.kt +11 -1
  13. package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +17 -0
  14. package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
  15. package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
  16. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
  18. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/coordinator/FormSheetAppearanceCoordinator.kt +2 -2
  19. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/coordinator/FormSheetBehaviorController.kt +51 -20
  20. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/coordinator/FormSheetDimensionsCoordinator.kt +159 -0
  21. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
  22. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/coordinator/FormSheetNativeDismissCoordinator.kt +2 -8
  23. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/dialog/FormSheetAvailableHeightProvider.kt +44 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native/core → core/modals/formsheet/dialog}/FormSheetContainer.kt +1 -1
  25. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native/core → core/modals/formsheet/dialog}/FormSheetDialog.kt +36 -4
  26. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/dialog/FormSheetDialogManager.kt +107 -0
  27. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/interfaces/FormSheetContentSizeChangeDelegate.kt +1 -1
  28. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/interfaces/FormSheetContentSizeChangeProvider.kt +1 -1
  29. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/interfaces/FormSheetDialogEventEmitter.kt +3 -1
  30. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/model/FormSheetConfig.kt +1 -1
  31. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/model/FormSheetDetents.kt +152 -0
  32. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/presentation/FormSheetAnimatorFactory.kt +9 -10
  33. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/presentation/FormSheetDimmingManager.kt +103 -0
  34. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/presentation/FormSheetDismissalOrigin.kt +22 -0
  35. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/presentation/FormSheetPresentation.kt +173 -0
  36. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/presentation/FormSheetPresentationManager.kt +290 -0
  37. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/native → core/modals/formsheet}/presentation/FormSheetPresentationState.kt +2 -2
  38. package/android/src/main/java/com/swmansion/rnscreens/core/modals/formsheet/presentation/FormSheetStackRegistry.kt +28 -0
  39. package/android/src/main/java/com/swmansion/rnscreens/ext/FragmentManagerExt.kt +6 -0
  40. package/android/src/main/java/com/swmansion/rnscreens/helpers/FragmentManagerHelper.kt +0 -3
  41. package/android/src/main/java/com/swmansion/rnscreens/helpers/NoTintDrawable.kt +31 -0
  42. package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
  43. package/android/src/main/java/com/swmansion/rnscreens/helpers/ViewFinder.kt +0 -17
  44. package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +32 -3
  45. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenContainer.kt +35 -3
  46. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +15 -0
  47. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStackHeaderConfig.kt +7 -1
  48. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStackHeaderSubviewManager.kt +7 -0
  49. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStackViewManager.kt +6 -0
  50. package/android/src/main/java/com/swmansion/rnscreens/legacy/bottomsheet/DimmingView.kt +2 -0
  51. package/android/src/main/java/com/swmansion/rnscreens/legacy/stack/views/ScreensCoordinatorLayout.kt +2 -0
  52. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/contentwrapper/FormSheetContentWrapper.kt +3 -3
  53. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/contentwrapper/FormSheetContentWrapperViewManager.kt +1 -1
  54. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetDetentChangedEvent.kt +1 -1
  55. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetDidAppearEvent.kt +1 -1
  56. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetDidDisappearEvent.kt +1 -1
  57. package/android/src/main/java/com/swmansion/rnscreens/react/modals/formsheet/event/FormSheetDismissEvent.kt +29 -0
  58. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetNativeDismissEvent.kt +1 -1
  59. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetNativeDismissPreventedEvent.kt +1 -1
  60. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetSyncFlushEvent.kt +1 -1
  61. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetWillAppearEvent.kt +1 -1
  62. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/event/FormSheetWillDisappearEvent.kt +1 -1
  63. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/host/FormSheetContentView.kt +3 -3
  64. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/host/FormSheetHost.kt +5 -3
  65. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/host/FormSheetHostEventEmitter.kt +17 -10
  66. package/android/src/main/java/com/swmansion/rnscreens/{modals/formsheet/react → react/modals/formsheet}/host/FormSheetHostViewManager.kt +11 -9
  67. package/android/src/main/java/com/swmansion/rnscreens/safearea/OnInterfaceInsetsChangeListener.kt +15 -0
  68. package/android/src/main/java/com/swmansion/rnscreens/safearea/SafeAreaProvider.kt +8 -8
  69. package/android/src/main/java/com/swmansion/rnscreens/safearea/SafeAreaView.kt +3 -2
  70. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +360 -101
  71. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
  72. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +211 -113
  73. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +156 -24
  74. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
  75. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderToolbar.kt +74 -0
  76. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
  77. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +162 -228
  78. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +385 -12
  79. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +5 -6
  80. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +29 -6
  81. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
  82. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +8 -7
  83. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +27 -280
  84. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
  85. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
  86. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +28 -20
  87. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +3 -55
  88. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +1 -10
  89. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuItemConfig.kt +1 -3
  90. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
  91. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +57 -6
  92. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +3 -1
  93. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +1 -0
  94. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +4 -3
  95. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueue.kt +23 -9
  96. package/android/src/main/java/com/swmansion/rnscreens/stack/host/FragmentOperation.kt +1 -0
  97. package/android/src/main/java/com/swmansion/rnscreens/stack/host/FragmentOperationExecutor.kt +2 -1
  98. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +159 -21
  99. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainerDelegate.kt +7 -0
  100. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainerUpdateCoordinator.kt +5 -3
  101. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +27 -5
  102. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
  103. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackUpdateBatchStateProviding.kt +10 -0
  104. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/PreventNativeDismissCallback.kt +2 -2
  105. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +4 -0
  106. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +50 -10
  107. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
  108. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceApplicator.kt +106 -10
  109. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +46 -7
  110. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceModel.kt +3 -0
  111. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/CustomBottomNavigationView.kt +21 -1
  112. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
  113. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +72 -36
  114. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainerDelegate.kt +11 -0
  115. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +22 -2
  116. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
  117. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +58 -17
  118. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenDelegate.kt +6 -0
  119. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
  120. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenIcon.kt +82 -0
  121. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenIconTinting.kt +17 -0
  122. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenViewManager.kt +26 -19
  123. package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +20 -6
  124. package/android/src/main/java/com/swmansion/rnscreens/utils/RNSLog.kt +22 -6
  125. package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
  126. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
  127. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
  128. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
  129. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
  130. package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
  131. package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
  132. package/ios/RNSEnums.h +16 -1
  133. package/ios/conversion/RNSConversions.h +7 -108
  134. package/ios/helpers/image/RNSImageLoadingHelper.h +7 -0
  135. package/ios/helpers/image/RNSImageLoadingHelper.mm +9 -0
  136. package/ios/legacy/RNSBarButtonItem.mm +15 -0
  137. package/ios/legacy/RNSConvert.h +6 -0
  138. package/ios/legacy/RNSConvert.mm +17 -0
  139. package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
  140. package/ios/legacy/RNSModalScreen.mm +1 -1
  141. package/ios/legacy/RNSNavigationBar.h +31 -0
  142. package/ios/legacy/RNSNavigationBar.mm +15 -0
  143. package/ios/legacy/RNSScreen.mm +130 -31
  144. package/ios/legacy/RNSScreenContentWrapper.mm +4 -1
  145. package/ios/legacy/RNSScreenStack.mm +202 -15
  146. package/ios/legacy/RNSScreenStackHeaderConfig.h +30 -0
  147. package/ios/legacy/RNSScreenStackHeaderConfig.mm +72 -17
  148. package/ios/legacy/RNSScreenStackHeaderSubview.mm +34 -1
  149. package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
  150. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
  151. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
  152. package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
  153. package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
  154. package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
  155. package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
  156. package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
  157. package/ios/safe-area/RNSSafeAreaViewComponentView.mm +3 -14
  158. package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
  159. package/ios/split/RNSSplitAppearanceApplicator.h +4 -4
  160. package/ios/split/RNSSplitAppearanceApplicator.mm +53 -56
  161. package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
  162. package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
  163. package/ios/split/RNSSplitHostComponentView.h +5 -15
  164. package/ios/split/RNSSplitHostComponentView.mm +55 -6
  165. package/ios/split/RNSSplitHostController.h +25 -6
  166. package/ios/split/RNSSplitHostController.mm +24 -92
  167. package/ios/split/RNSSplitHostProviders.h +67 -0
  168. package/ios/split/RNSSplitScreenComponentView.h +0 -39
  169. package/ios/split/RNSSplitScreenComponentView.mm +27 -10
  170. package/ios/split/RNSSplitScreenController.h +26 -3
  171. package/ios/split/RNSSplitScreenController.mm +13 -30
  172. package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
  173. package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
  174. package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
  175. package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
  176. package/ios/stack/conversion/RNSConversions-Stack.h +62 -0
  177. package/ios/stack/conversion/RNSConversions-Stack.mm +134 -0
  178. package/ios/stack/header/RNSHeaderItemVisibilityPriority.h +9 -0
  179. package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
  180. package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
  181. package/ios/stack/header/RNSStackHeaderConfigComponentView.h +14 -1
  182. package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +103 -37
  183. package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +11 -0
  184. package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
  185. package/ios/stack/header/RNSStackHeaderContentFactory.mm +3 -0
  186. package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
  187. package/ios/stack/header/RNSStackHeaderItemComponentView.h +12 -3
  188. package/ios/stack/header/RNSStackHeaderItemComponentView.mm +72 -5
  189. package/ios/stack/header/RNSStackHeaderItemDataProviding.h +7 -0
  190. package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
  191. package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
  192. package/ios/stack/header/RNSStackHeaderMenuCoordinator.h +13 -0
  193. package/ios/stack/header/RNSStackHeaderMenuCoordinator.mm +24 -0
  194. package/ios/stack/header/RNSStackHeaderMenuFinder.h +8 -1
  195. package/ios/stack/header/RNSStackHeaderMenuFinder.mm +26 -9
  196. package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
  197. package/ios/stack/host/RNSStackNavigationBar.h +25 -0
  198. package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
  199. package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
  200. package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
  201. package/ios/stack/host/RNSStackNavigationController.mm +13 -5
  202. package/ios/stack/host/RNSStackOperation.h +0 -2
  203. package/ios/stack/screen/RNSStackScreenComponentView.h +2 -1
  204. package/ios/stack/screen/RNSStackScreenComponentView.mm +32 -2
  205. package/ios/stack/screen/RNSStackScreenController.mm +12 -0
  206. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +8 -0
  207. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +179 -24
  208. package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +110 -16
  209. package/ios/tabs/RNSTabBarItemCoordinator.h +16 -0
  210. package/ios/tabs/RNSTabBarItemCoordinator.mm +143 -0
  211. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
  212. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +1 -1
  213. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +1 -1
  214. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
  215. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
  216. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryWrapperView.h +24 -0
  217. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryWrapperView.mm +22 -0
  218. package/ios/tabs/conversion/RNSConversions-Tabs.h +100 -0
  219. package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +105 -74
  220. package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
  221. package/ios/tabs/host/RNSTabBarController.h +16 -0
  222. package/ios/tabs/host/RNSTabBarController.mm +516 -107
  223. package/ios/tabs/host/RNSTabsHostComponentView.h +4 -0
  224. package/ios/tabs/host/RNSTabsHostComponentView.mm +41 -4
  225. package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
  226. package/ios/tabs/screen/RNSTabsScreenComponentView.h +21 -0
  227. package/ios/tabs/screen/RNSTabsScreenComponentView.mm +56 -56
  228. package/ios/tabs/screen/RNSTabsScreenViewController.mm +1 -0
  229. package/ios/utils/RNSDefines.h +15 -7
  230. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +37 -21
  231. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  232. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +41 -4
  233. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  234. package/lib/commonjs/components/stack/header/StackHeaderConfig.js +17 -0
  235. package/lib/commonjs/components/stack/header/StackHeaderConfig.js.map +1 -0
  236. package/lib/commonjs/components/stack/header/ios/StackHeaderItem.ios.js +4 -1
  237. package/lib/commonjs/components/stack/header/ios/StackHeaderItem.ios.js.map +1 -1
  238. package/lib/commonjs/components/stack/host/StackHost.js +17 -7
  239. package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
  240. package/lib/commonjs/components/stack/host/StackHost.web.js +0 -2
  241. package/lib/commonjs/components/stack/host/StackHost.web.js.map +1 -1
  242. package/lib/commonjs/components/stack/index.js.map +1 -1
  243. package/lib/commonjs/components/tabs/host/TabsHost.ios.js +3 -0
  244. package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
  245. package/lib/commonjs/components/tabs/host/{TabsHost.web.js → TabsHost.js} +1 -1
  246. package/lib/commonjs/components/tabs/host/TabsHost.js.map +1 -0
  247. package/lib/commonjs/components/tabs/index.js.map +1 -1
  248. package/lib/commonjs/components/tabs/screen/TabsScreen.android.js +3 -1
  249. package/lib/commonjs/components/tabs/screen/TabsScreen.android.js.map +1 -1
  250. package/lib/commonjs/components/tabs/screen/TabsScreen.ios.js +10 -1
  251. package/lib/commonjs/components/tabs/screen/TabsScreen.ios.js.map +1 -1
  252. package/lib/commonjs/components/tabs/screen/{TabsScreen.web.js → TabsScreen.js} +1 -1
  253. package/lib/commonjs/components/tabs/screen/TabsScreen.js.map +1 -0
  254. package/lib/commonjs/components/{stack/header/StackHeaderConfig.d.js → tabs/screen/TabsScreenIcon.types.js} +1 -1
  255. package/lib/commonjs/components/{stack/header/StackHeaderConfig.d.js.map → tabs/screen/TabsScreenIcon.types.js.map} +1 -1
  256. package/lib/commonjs/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  257. package/lib/commonjs/fabric/legacy/ScreenStackNativeComponent.js.map +1 -1
  258. package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  259. package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  260. package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  261. package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
  262. package/lib/commonjs/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  263. package/lib/commonjs/fabric/tabs/TabsScreenAndroidNativeComponent.js.map +1 -1
  264. package/lib/commonjs/fabric/tabs/TabsScreenIOSNativeComponent.js +1 -1
  265. package/lib/commonjs/fabric/tabs/TabsScreenIOSNativeComponent.js.map +1 -1
  266. package/lib/commonjs/legacy/components/ScreenStackItem.js +31 -11
  267. package/lib/commonjs/legacy/components/ScreenStackItem.js.map +1 -1
  268. package/lib/module/components/stack/header/StackHeaderConfig.android.js +39 -23
  269. package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  270. package/lib/module/components/stack/header/StackHeaderConfig.ios.js +43 -6
  271. package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  272. package/lib/module/components/stack/header/StackHeaderConfig.js +10 -0
  273. package/lib/module/components/stack/header/StackHeaderConfig.js.map +1 -0
  274. package/lib/module/components/stack/header/ios/StackHeaderItem.ios.js +4 -1
  275. package/lib/module/components/stack/header/ios/StackHeaderItem.ios.js.map +1 -1
  276. package/lib/module/components/stack/host/StackHost.js +18 -8
  277. package/lib/module/components/stack/host/StackHost.js.map +1 -1
  278. package/lib/module/components/stack/host/StackHost.web.js +0 -3
  279. package/lib/module/components/stack/host/StackHost.web.js.map +1 -1
  280. package/lib/module/components/stack/index.js.map +1 -1
  281. package/lib/module/components/tabs/host/TabsHost.ios.js +3 -0
  282. package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
  283. package/{src/components/tabs/host/TabsHost.web.tsx → lib/module/components/tabs/host/TabsHost.js} +1 -2
  284. package/lib/module/components/tabs/host/TabsHost.js.map +1 -0
  285. package/lib/module/components/tabs/index.js.map +1 -1
  286. package/lib/module/components/tabs/screen/TabsScreen.android.js +3 -1
  287. package/lib/module/components/tabs/screen/TabsScreen.android.js.map +1 -1
  288. package/lib/module/components/tabs/screen/TabsScreen.ios.js +10 -1
  289. package/lib/module/components/tabs/screen/TabsScreen.ios.js.map +1 -1
  290. package/{src/components/tabs/screen/TabsScreen.web.tsx → lib/module/components/tabs/screen/TabsScreen.js} +1 -2
  291. package/lib/module/components/tabs/screen/TabsScreen.js.map +1 -0
  292. package/lib/module/components/tabs/screen/TabsScreenIcon.types.js +2 -0
  293. package/lib/module/components/{stack/header/StackHeaderConfig.d.js.map → tabs/screen/TabsScreenIcon.types.js.map} +1 -1
  294. package/lib/module/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  295. package/lib/module/fabric/legacy/ScreenStackNativeComponent.js.map +1 -1
  296. package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  297. package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  298. package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  299. package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
  300. package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  301. package/lib/module/fabric/tabs/TabsScreenAndroidNativeComponent.js.map +1 -1
  302. package/lib/module/fabric/tabs/TabsScreenIOSNativeComponent.js +1 -1
  303. package/lib/module/fabric/tabs/TabsScreenIOSNativeComponent.js.map +1 -1
  304. package/lib/module/legacy/components/ScreenStackItem.js +31 -11
  305. package/lib/module/legacy/components/ScreenStackItem.js.map +1 -1
  306. package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +1 -1
  307. package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts +6 -3
  308. package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
  309. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +620 -24
  310. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
  311. package/lib/typescript/components/stack/header/StackHeaderConfig.d.ts +8 -0
  312. package/lib/typescript/components/stack/header/StackHeaderConfig.d.ts.map +1 -0
  313. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts +6 -3
  314. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
  315. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +361 -2
  316. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
  317. package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +4 -2
  318. package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts.map +1 -1
  319. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.d.ts.map +1 -1
  320. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +7 -0
  321. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
  322. package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
  323. package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
  324. package/lib/typescript/components/stack/host/StackHost.types.d.ts +47 -0
  325. package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
  326. package/lib/typescript/components/stack/host/StackHost.web.d.ts +1 -3
  327. package/lib/typescript/components/stack/host/StackHost.web.d.ts.map +1 -1
  328. package/lib/typescript/components/stack/index.d.ts +4 -3
  329. package/lib/typescript/components/stack/index.d.ts.map +1 -1
  330. package/lib/typescript/components/tabs/host/TabsHost.d.ts +5 -0
  331. package/lib/typescript/components/tabs/host/TabsHost.d.ts.map +1 -0
  332. package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
  333. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +72 -0
  334. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
  335. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
  336. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
  337. package/lib/typescript/components/tabs/index.d.ts +4 -6
  338. package/lib/typescript/components/tabs/index.d.ts.map +1 -1
  339. package/lib/typescript/components/tabs/screen/TabsScreen.android.d.ts.map +1 -1
  340. package/lib/typescript/components/tabs/screen/TabsScreen.android.types.d.ts +42 -7
  341. package/lib/typescript/components/tabs/screen/TabsScreen.android.types.d.ts.map +1 -1
  342. package/lib/typescript/components/tabs/screen/TabsScreen.d.ts +5 -0
  343. package/lib/typescript/components/tabs/screen/TabsScreen.d.ts.map +1 -0
  344. package/lib/typescript/components/tabs/screen/TabsScreen.ios.d.ts.map +1 -1
  345. package/lib/typescript/components/tabs/screen/TabsScreen.ios.types.d.ts +78 -13
  346. package/lib/typescript/components/tabs/screen/TabsScreen.ios.types.d.ts.map +1 -1
  347. package/lib/typescript/components/tabs/screen/TabsScreenIcon.types.d.ts +91 -0
  348. package/lib/typescript/components/tabs/screen/TabsScreenIcon.types.d.ts.map +1 -0
  349. package/lib/typescript/components/tabs/screen/index.d.ts +1 -0
  350. package/lib/typescript/components/tabs/screen/index.d.ts.map +1 -1
  351. package/lib/typescript/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.d.ts +2 -0
  352. package/lib/typescript/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  353. package/lib/typescript/fabric/legacy/ScreenStackNativeComponent.d.ts +1 -0
  354. package/lib/typescript/fabric/legacy/ScreenStackNativeComponent.d.ts.map +1 -1
  355. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +52 -0
  356. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
  357. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +29 -1
  358. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
  359. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +8 -0
  360. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
  361. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +3 -1
  362. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
  363. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +4 -0
  364. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
  365. package/lib/typescript/fabric/tabs/TabsScreenAndroidNativeComponent.d.ts +6 -0
  366. package/lib/typescript/fabric/tabs/TabsScreenAndroidNativeComponent.d.ts.map +1 -1
  367. package/lib/typescript/fabric/tabs/TabsScreenIOSNativeComponent.d.ts +10 -1
  368. package/lib/typescript/fabric/tabs/TabsScreenIOSNativeComponent.d.ts.map +1 -1
  369. package/lib/typescript/legacy/components/ScreenStackItem.d.ts +25 -0
  370. package/lib/typescript/legacy/components/ScreenStackItem.d.ts.map +1 -1
  371. package/lib/typescript/legacy/components/helpers/prepareHeaderBarButtonItems.d.ts +4 -0
  372. package/lib/typescript/legacy/components/helpers/prepareHeaderBarButtonItems.d.ts.map +1 -1
  373. package/lib/typescript/legacy/types.d.ts +30 -0
  374. package/lib/typescript/legacy/types.d.ts.map +1 -1
  375. package/package.json +11 -8
  376. package/react-native.config.js +3 -0
  377. package/src/components/modals/form-sheet/FormSheet.types.ts +1 -1
  378. package/src/components/stack/header/StackHeaderConfig.android.tsx +54 -43
  379. package/src/components/stack/header/StackHeaderConfig.android.types.ts +641 -24
  380. package/src/components/stack/header/StackHeaderConfig.ios.tsx +55 -17
  381. package/src/components/stack/header/StackHeaderConfig.ios.types.ts +384 -2
  382. package/src/components/stack/header/StackHeaderConfig.tsx +12 -0
  383. package/src/components/stack/header/StackHeaderConfig.types.ts +4 -2
  384. package/src/components/stack/header/ios/StackHeaderItem.ios.tsx +9 -1
  385. package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +7 -0
  386. package/src/components/stack/host/StackHost.tsx +12 -3
  387. package/src/components/stack/host/StackHost.types.ts +50 -0
  388. package/src/components/stack/host/StackHost.web.tsx +1 -4
  389. package/src/components/stack/index.ts +14 -1
  390. package/src/components/tabs/host/TabsHost.ios.tsx +3 -0
  391. package/src/components/tabs/host/TabsHost.ios.types.ts +76 -0
  392. package/src/components/tabs/host/TabsHost.tsx +7 -0
  393. package/src/components/tabs/host/TabsHost.types.ts +3 -0
  394. package/src/components/tabs/index.ts +9 -0
  395. package/src/components/tabs/screen/TabsScreen.android.tsx +8 -3
  396. package/src/components/tabs/screen/TabsScreen.android.types.ts +42 -7
  397. package/src/components/tabs/screen/TabsScreen.ios.tsx +22 -5
  398. package/src/components/tabs/screen/TabsScreen.ios.types.ts +79 -17
  399. package/src/components/tabs/screen/TabsScreen.tsx +7 -0
  400. package/src/components/tabs/screen/TabsScreenIcon.types.ts +117 -0
  401. package/src/components/tabs/screen/index.ts +1 -0
  402. package/src/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.ts +6 -0
  403. package/src/fabric/legacy/ScreenStackNativeComponent.ts +2 -0
  404. package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +78 -0
  405. package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +43 -0
  406. package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +13 -0
  407. package/src/fabric/stack/StackHostNativeComponent.ts +11 -2
  408. package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +8 -0
  409. package/src/fabric/tabs/TabsScreenAndroidNativeComponent.ts +9 -0
  410. package/src/fabric/tabs/TabsScreenIOSNativeComponent.ts +20 -2
  411. package/src/legacy/components/ScreenStackItem.tsx +59 -12
  412. package/src/legacy/types.ts +31 -0
  413. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenModalFragment.kt +0 -281
  414. package/android/src/main/java/com/swmansion/rnscreens/legacy/bottomsheet/BottomSheetDialogRootView.kt +0 -104
  415. package/android/src/main/java/com/swmansion/rnscreens/legacy/bottomsheet/BottomSheetDialogScreen.kt +0 -26
  416. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
  417. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
  418. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
  419. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +0 -134
  420. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +0 -162
  421. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +0 -106
  422. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +0 -198
  423. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuSelectionController.kt +0 -83
  424. package/ios/conversion/RNSConversions-Stack.h +0 -32
  425. package/ios/conversion/RNSConversions-Stack.mm +0 -41
  426. package/ios/conversion/always_false.h +0 -31
  427. package/lib/commonjs/components/stack/header/StackHeaderConfig.web.js +0 -10
  428. package/lib/commonjs/components/stack/header/StackHeaderConfig.web.js.map +0 -1
  429. package/lib/commonjs/components/tabs/host/TabsHost.d.js +0 -2
  430. package/lib/commonjs/components/tabs/host/TabsHost.d.js.map +0 -1
  431. package/lib/commonjs/components/tabs/host/TabsHost.web.js.map +0 -1
  432. package/lib/commonjs/components/tabs/screen/TabsScreen.d.js +0 -2
  433. package/lib/commonjs/components/tabs/screen/TabsScreen.d.js.map +0 -1
  434. package/lib/commonjs/components/tabs/screen/TabsScreen.web.js.map +0 -1
  435. package/lib/module/components/stack/header/StackHeaderConfig.d.js +0 -2
  436. package/lib/module/components/stack/header/StackHeaderConfig.web.js +0 -4
  437. package/lib/module/components/stack/header/StackHeaderConfig.web.js.map +0 -1
  438. package/lib/module/components/tabs/host/TabsHost.d.js +0 -2
  439. package/lib/module/components/tabs/host/TabsHost.d.js.map +0 -1
  440. package/lib/module/components/tabs/host/TabsHost.web.js +0 -4
  441. package/lib/module/components/tabs/host/TabsHost.web.js.map +0 -1
  442. package/lib/module/components/tabs/screen/TabsScreen.d.js +0 -2
  443. package/lib/module/components/tabs/screen/TabsScreen.d.js.map +0 -1
  444. package/lib/module/components/tabs/screen/TabsScreen.web.js +0 -4
  445. package/lib/module/components/tabs/screen/TabsScreen.web.js.map +0 -1
  446. package/lib/typescript/components/stack/header/StackHeaderConfig.web.d.ts +0 -7
  447. package/lib/typescript/components/stack/header/StackHeaderConfig.web.d.ts.map +0 -1
  448. package/lib/typescript/components/tabs/host/TabsHost.web.d.ts +0 -7
  449. package/lib/typescript/components/tabs/host/TabsHost.web.d.ts.map +0 -1
  450. package/lib/typescript/components/tabs/screen/TabsScreen.web.d.ts +0 -7
  451. package/lib/typescript/components/tabs/screen/TabsScreen.web.d.ts.map +0 -1
  452. package/src/components/stack/header/StackHeaderConfig.d.ts +0 -22
  453. package/src/components/stack/header/StackHeaderConfig.web.tsx +0 -5
  454. package/src/components/tabs/host/TabsHost.d.ts +0 -12
  455. package/src/components/tabs/screen/TabsScreen.d.ts +0 -12
  456. /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
@@ -4,12 +4,22 @@
4
4
  #include <react/renderer/mounting/MountingOverrideDelegate.h>
5
5
  #include <react/renderer/mounting/ShadowView.h>
6
6
 
7
+ #include <cstdint>
8
+ #include <functional>
9
+ #include <mutex>
10
+
7
11
  using namespace facebook::react;
8
12
 
9
13
  struct RNSScreenRemovalListener : public MountingOverrideDelegate {
10
- std::function<void(int)> listenerFunction_;
11
- RNSScreenRemovalListener(std::function<void(int)> &&listenerFunction_)
12
- : listenerFunction_(std::move(listenerFunction_)) {}
14
+ RNSScreenRemovalListener() = default;
15
+
16
+ // RN core lacks a `removeMountingOverrideDelegate` API, so this instance is
17
+ // process-immortal and swaps its callback instead of being replaced. The
18
+ // ownership token keeps a stale proxy's teardown from clearing a newer
19
+ // proxy's listener.
20
+ // See https://github.com/software-mansion/react-native-screens/pull/4413
21
+ uint64_t setListener(std::function<void(int)> &&listenerFunction);
22
+ void clearListener(uint64_t token);
13
23
 
14
24
  bool shouldOverridePullTransaction() const override;
15
25
  std::optional<MountingTransaction> pullTransaction(
@@ -17,4 +27,9 @@ struct RNSScreenRemovalListener : public MountingOverrideDelegate {
17
27
  MountingTransaction::Number number,
18
28
  const TransactionTelemetry &telemetry,
19
29
  ShadowViewMutationList mutations) const override;
30
+
31
+ private:
32
+ mutable std::mutex listenerMutex_;
33
+ std::function<void(int)> listenerFunction_;
34
+ uint64_t currentToken_{0};
20
35
  };
package/ios/RNSEnums.h CHANGED
@@ -1,5 +1,7 @@
1
1
  #pragma once
2
2
 
3
+ #import <UIKit/UIKit.h>
4
+
3
5
  typedef NS_ENUM(NSInteger, RNSScrollEdgeEffect) {
4
6
  RNSScrollEdgeEffectAutomatic,
5
7
  RNSScrollEdgeEffectHard,
@@ -49,11 +51,22 @@ typedef NS_ENUM(NSInteger, RNSBlurEffectStyle) {
49
51
 
50
52
  typedef NS_ENUM(NSInteger, RNSTabsIconType) {
51
53
  RNSTabsIconTypeImage,
52
- RNSTabsIconTypeTemplate,
53
54
  RNSTabsIconTypeSfSymbol,
54
55
  RNSTabsIconTypeXcasset,
55
56
  };
56
57
 
58
+ typedef NS_ENUM(NSInteger, RNSTabsIconImageRenderingMode) {
59
+ RNSTabsIconImageRenderingModeDefault,
60
+ RNSTabsIconImageRenderingModeTemplate,
61
+ RNSTabsIconImageRenderingModeOriginal,
62
+ };
63
+
64
+ typedef NS_ENUM(NSInteger, RNSTabsIconSymbolRenderingMode) {
65
+ RNSTabsIconSymbolRenderingModeDefault,
66
+ RNSTabsIconSymbolRenderingModeMonochrome,
67
+ RNSTabsIconSymbolRenderingModeOriginal,
68
+ };
69
+
57
70
  typedef NS_ENUM(NSInteger, RNSOrientation) {
58
71
  RNSOrientationInherit,
59
72
  RNSOrientationAll,
@@ -82,6 +95,8 @@ typedef NS_ENUM(NSInteger, RNSTabsScreenSystemItem) {
82
95
  RNSTabsScreenSystemItemTopRated
83
96
  };
84
97
 
98
+ typedef NS_ENUM(NSInteger, RNSTabsScreenTabRole) { RNSTabsScreenTabRoleNone, RNSTabsScreenTabRoleSearch };
99
+
85
100
  typedef NS_ENUM(NSInteger, RNSTabsBottomAccessoryEnvironment) {
86
101
  RNSTabsBottomAccessoryEnvironmentRegular,
87
102
  RNSTabsBottomAccessoryEnvironmentInline
@@ -1,125 +1,24 @@
1
1
  #pragma once
2
2
 
3
3
  #if defined(__cplusplus)
4
- #import <React/RCTImageSource.h>
5
- #import <react/renderer/components/rnscreens/EventEmitters.h>
6
- #import <react/renderer/components/rnscreens/Props.h>
7
- #import <optional>
8
- #import "RNSDefines.h"
9
- #import "RNSEnums.h"
10
- #import "RNSTabsNavigationState.h"
11
-
4
+ #import <UIKit/UIKit.h>
12
5
  #import <folly/dynamic.h>
6
+ #import "RNSEnums.h"
13
7
 
14
8
  namespace rnscreens::conversion {
15
9
 
16
- namespace react = facebook::react;
17
-
18
10
  // copied from FollyConvert.mm
19
11
  id RNSConvertFollyDynamicToId(const folly::dynamic &dyn);
20
12
 
21
- std::optional<UIBlurEffectStyle> RNSMaybeUIBlurEffectStyleFromString(NSString *blurEffectString);
22
-
23
- UIBlurEffect *RNSUIBlurEffectFromString(NSString *blurEffectString);
24
-
25
- std::optional<UIBlurEffectStyle> RNSMaybeUIBlurEffectStyleFromRNSBlurEffectStyle(RNSBlurEffectStyle blurEffect);
26
-
27
- UIBlurEffect *RNSUIBlurEffectFromRNSBlurEffectStyle(RNSBlurEffectStyle blurEffect);
28
-
29
- #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
30
-
31
- API_AVAILABLE(ios(26.0))
32
- UITabBarMinimizeBehavior UITabBarMinimizeBehaviorFromRNSTabsHostTabBarMinimizeBehavior(
33
- react::RNSTabsHostIOSTabBarMinimizeBehavior tabBarMinimizeBehavior);
34
-
35
- #endif // Check for iOS >= 26
36
-
37
- #if RNS_IPHONE_OS_VERSION_AVAILABLE(18_0)
38
-
39
- API_AVAILABLE(ios(18.0))
40
- UITabBarControllerMode UITabBarControllerModeFromRNSTabsHostTabBarControllerMode(
41
- react::RNSTabsHostIOSTabBarControllerMode tabBarControllerMode);
42
-
43
- #endif // Check for iOS >= 18
44
-
45
- react::RNSTabsHostIOSEventEmitter::OnTabSelectionRejectedRejectionReason
46
- RNSOnTabSelectionRejectedRejectionReasonFromRNSTabsNavigationStateRejectionReason(
47
- RNSTabsNavigationStateRejectionReason reason);
48
-
49
- react::RNSTabsHostIOSEventEmitter::OnTabSelectedActionOrigin RNSOnTabSelectedActionOriginFromRNSTabsActionOrigin(
50
- RNSTabsActionOrigin actionOrigin);
51
-
52
- RNSTabsIconType RNSTabsIconTypeFromIcon(react::RNSTabsScreenIOSIconType iconType);
53
-
54
- RNSTabsScreenSystemItem RNSTabsScreenSystemItemFromReactRNSTabsScreenSystemItem(
55
- react::RNSTabsScreenIOSSystemItem systemItem);
56
-
57
- UITabBarSystemItem RNSTabsScreenSystemItemToUITabBarSystemItem(RNSTabsScreenSystemItem systemItem);
58
-
59
- #if RNS_TABS_BOTTOM_ACCESSORY_AVAILABLE
60
-
61
- API_AVAILABLE(ios(26.0))
62
- std::optional<react::RNSTabsBottomAccessoryEventEmitter::OnEnvironmentChangeEnvironment>
63
- RNSTabsBottomAccessoryOnEnvironmentChangePayloadFromUITabAccessoryEnvironment(UITabAccessoryEnvironment environment);
64
-
65
- RNSTabsBottomAccessoryEnvironment RNSTabsBottomAccessoryEnvironmentFromCppEquivalent(
66
- react::RNSTabsBottomAccessoryContentEnvironment environment);
67
-
68
- #endif // RNS_TABS_BOTTOM_ACCESSORY_AVAILABLE
69
-
70
- UIUserInterfaceStyle UIUserInterfaceStyleFromTabsScreenCppEquivalent(
71
- react::RNSTabsScreenIOSUserInterfaceStyle userInterfaceStyle);
72
-
73
- RCTImageSource *RCTImageSourceFromImageSourceAndIconType(const facebook::react::ImageSource *imageSource,
74
- RNSTabsIconType iconType);
75
-
76
- RNSOrientation RNSOrientationFromRNSTabsScreenOrientation(react::RNSTabsScreenIOSOrientation orientation);
77
-
78
13
  #if !TARGET_OS_TV
79
- UIInterfaceOrientationMask UIInterfaceOrientationMaskFromRNSOrientation(RNSOrientation orientation);
14
+ UIInterfaceOrientationMask UIInterfaceOrientationMaskFromRNSOrientation(
15
+ RNSOrientation orientation);
80
16
 
81
- RNSOrientation RNSOrientationFromUIInterfaceOrientationMask(UIInterfaceOrientationMask orientationMask);
17
+ // Currently unused in stack v5. Maybe remove after stopping support for v4.
18
+ RNSOrientation RNSOrientationFromUIInterfaceOrientationMask(
19
+ UIInterfaceOrientationMask orientationMask);
82
20
  #endif // !TARGET_OS_TV
83
21
 
84
- UITraitEnvironmentLayoutDirection UITraitEnvironmentLayoutDirectionFromTabsHostCppEquivalent(
85
- react::RNSTabsHostIOSLayoutDirection layoutDirection);
86
-
87
- UIUserInterfaceStyle UIUserInterfaceStyleFromHostProp(react::RNSTabsHostIOSColorScheme colorScheme);
88
-
89
- #pragma mark SplitHost props
90
-
91
- UISplitViewControllerSplitBehavior SplitViewPreferredSplitBehaviorFromHostProp(
92
- react::RNSSplitHostPreferredSplitBehavior behavior);
93
-
94
- UISplitViewControllerPrimaryEdge SplitViewPrimaryEdgeFromHostProp(react::RNSSplitHostPrimaryEdge primaryEdge);
95
-
96
- UISplitViewControllerDisplayMode SplitViewPreferredDisplayModeFromHostProp(
97
- react::RNSSplitHostPreferredDisplayMode displayMode);
98
-
99
- #if !TARGET_OS_TV
100
- UISplitViewControllerBackgroundStyle SplitViewPrimaryBackgroundStyleFromHostProp(
101
- react::RNSSplitHostPrimaryBackgroundStyle primaryBackgroundStyle);
102
- #endif // !TARGET_OS_TV
103
-
104
- UISplitViewControllerDisplayModeButtonVisibility SplitViewDisplayModeButtonVisibilityFromHostProp(
105
- react::RNSSplitHostDisplayModeButtonVisibility displayModeButtonVisibility);
106
-
107
- std::string UISplitViewControllerDisplayModeToString(UISplitViewControllerDisplayMode displayMode);
108
-
109
- std::optional<UISplitViewControllerColumn> SplitViewTopColumnForCollapsingFromHostProp(
110
- react::RNSSplitHostTopColumnForCollapsing topColumnForCollapsing);
111
-
112
- RNSOrientation RNSOrientationFromRNSSplitHostOrientation(react::RNSSplitHostOrientation orientation);
113
-
114
- UIUserInterfaceStyle UIUserInterfaceStyleFromHostProp(react::RNSSplitHostColorScheme colorScheme);
115
-
116
- #pragma mark SplitScreen props
117
-
118
- RNSSplitScreenColumnType RNSSplitScreenColumnTypeFromScreenProp(react::RNSSplitScreenColumnType columnType);
119
-
120
22
  }; // namespace rnscreens::conversion
121
23
 
122
- #import "RNSConversions-ScrollViewMarker.h"
123
- #import "RNSConversions-Stack.h"
124
-
125
24
  #endif // defined(__cplusplus)
@@ -27,6 +27,13 @@
27
27
  asTemplate:(BOOL)isTemplate
28
28
  completionBlock:(void (^_Nonnull)(UIImage *_Nullable image))imageLoadingCompletionBlock;
29
29
 
30
+ /**
31
+ * Loads a symbol image by name: a built-in SF Symbol if one matches, otherwise a custom
32
+ * symbol from the app's asset catalog (custom symbols are semantically SF Symbols, but
33
+ * UIKit only resolves them via `imageNamed:`).
34
+ */
35
+ + (nullable UIImage *)symbolImageNamed:(nonnull NSString *)name;
36
+
30
37
  @end
31
38
 
32
39
  #endif // defined(__cplusplus)
@@ -59,6 +59,15 @@
59
59
  }];
60
60
  }
61
61
 
62
+ + (nullable UIImage *)symbolImageNamed:(nonnull NSString *)name
63
+ {
64
+ UIImage *image = [UIImage systemImageNamed:name];
65
+ if (image == nil) {
66
+ image = [UIImage imageNamed:name];
67
+ }
68
+ return image;
69
+ }
70
+
62
71
  + (nullable UIImage *)handleRenderingModeForImage:(nullable UIImage *)image isTemplate:(BOOL)isTemplate
63
72
  {
64
73
  if (isTemplate) {
@@ -89,6 +89,21 @@ static UIMenuOptions RNSMakeUIMenuOptionsFromConfig(NSDictionary *config);
89
89
  }
90
90
  #endif
91
91
 
92
+ // tvOS and visionOS are excluded on purpose: `visibilityPriority` exists there, but the only
93
+ // supported value is `standard`, which is already the default.
94
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV && !TARGET_OS_VISION
95
+ if (@available(iOS 27.0, *)) {
96
+ NSString *visibilityPriority = dict[@"visibilityPriority"];
97
+ if ([visibilityPriority isEqualToString:@"low"]) {
98
+ self.visibilityPriority = UIBarButtonItemVisibilityPriorityLow;
99
+ } else if ([visibilityPriority isEqualToString:@"high"]) {
100
+ self.visibilityPriority = UIBarButtonItemVisibilityPriorityHigh;
101
+ } else if ([visibilityPriority isEqualToString:@"standard"]) {
102
+ self.visibilityPriority = UIBarButtonItemVisibilityPriorityStandard;
103
+ }
104
+ }
105
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV && !TARGET_OS_VISION
106
+
92
107
  NSString *variant = dict[@"variant"];
93
108
  if (variant) {
94
109
  if ([variant isEqualToString:@"done"]) {
@@ -4,6 +4,7 @@
4
4
  #if defined(__cplusplus)
5
5
  #import <react/renderer/components/rnscreens/Props.h>
6
6
  #endif // __cplusplus
7
+ #import "RNSDefines.h"
7
8
  #import "RNSLegacyEnums.h"
8
9
 
9
10
  #if defined(__cplusplus)
@@ -31,6 +32,11 @@ namespace react = facebook::react;
31
32
  + (RNSScreenStackHeaderSubviewType)RNSScreenStackHeaderSubviewTypeFromCppEquivalent:
32
33
  (react::RNSScreenStackHeaderSubviewType)subviewType;
33
34
 
35
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
36
+ + (UIBarButtonItemVisibilityPriority)UIBarButtonItemVisibilityPriorityFromCppEquivalent:
37
+ (react::RNSScreenStackHeaderSubviewVisibilityPriority)visibilityPriority API_AVAILABLE(ios(27.0));
38
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
39
+
34
40
  + (RNSScreenReplaceAnimation)RNSScreenReplaceAnimationFromCppEquivalent:
35
41
  (react::RNSScreenReplaceAnimation)replaceAnimation;
36
42
 
@@ -118,6 +118,23 @@
118
118
  }
119
119
  }
120
120
 
121
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
122
+ + (UIBarButtonItemVisibilityPriority)UIBarButtonItemVisibilityPriorityFromCppEquivalent:
123
+ (react::RNSScreenStackHeaderSubviewVisibilityPriority)visibilityPriority
124
+ {
125
+ switch (visibilityPriority) {
126
+ using enum react::RNSScreenStackHeaderSubviewVisibilityPriority;
127
+
128
+ case Low:
129
+ return UIBarButtonItemVisibilityPriorityLow;
130
+ case High:
131
+ return UIBarButtonItemVisibilityPriorityHigh;
132
+ case Standard:
133
+ return UIBarButtonItemVisibilityPriorityStandard;
134
+ }
135
+ }
136
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
137
+
121
138
  + (RNSScreenReplaceAnimation)RNSScreenReplaceAnimationFromCppEquivalent:
122
139
  (react::RNSScreenReplaceAnimation)replaceAnimation
123
140
  {
@@ -9,7 +9,7 @@
9
9
  #import <react/renderer/components/rnscreens/ComponentDescriptors.h>
10
10
  #import <react/renderer/components/rnscreens/Props.h>
11
11
  #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
12
- #import <rnscreens/RNSFullWindowOverlayComponentDescriptor.h>
12
+ #import <react/renderer/components/rnscreens/legacy/RNSFullWindowOverlayComponentDescriptor.h>
13
13
 
14
14
  @implementation RNSFullWindowOverlayContainer
15
15
 
@@ -1,7 +1,7 @@
1
1
  #import "RNSModalScreen.h"
2
2
 
3
3
  #import <React/RCTFabricComponentsPlugins.h>
4
- #import <rnscreens/RNSModalScreenComponentDescriptor.h>
4
+ #import <react/renderer/components/rnscreens/legacy/RNSModalScreenComponentDescriptor.h>
5
5
 
6
6
  @implementation RNSModalScreen
7
7
 
@@ -0,0 +1,31 @@
1
+ #pragma once
2
+
3
+ #import <UIKit/UIKit.h>
4
+ #import "RNSDefines.h"
5
+
6
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
7
+
8
+ NS_ASSUME_NONNULL_BEGIN
9
+
10
+ @protocol RNSNavigationBarLayoutDelegate <NSObject>
11
+
12
+ - (void)navigationBarDidLayoutSubviews:(UINavigationBar *)navigationBar;
13
+
14
+ @end
15
+
16
+ /**
17
+ * Navigation bar used by the legacy stack (`RNSNavigationController`).
18
+ *
19
+ * It reports its layout passes to the `layoutDelegate`. On iOS 26+ UIKit can move the content of the navigation bar
20
+ * (e.g. on rotation or fold of iPhone Duo, or during the bar minimization on iOS 27) without any layout pass of the
21
+ * navigation controller's view, and layout of the bar is the only callback we receive in such a case.
22
+ */
23
+ @interface RNSNavigationBar : UINavigationBar
24
+
25
+ @property (nonatomic, weak, nullable) id<RNSNavigationBarLayoutDelegate> layoutDelegate;
26
+
27
+ @end
28
+
29
+ NS_ASSUME_NONNULL_END
30
+
31
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
@@ -0,0 +1,15 @@
1
+ #import "RNSNavigationBar.h"
2
+
3
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
4
+
5
+ @implementation RNSNavigationBar
6
+
7
+ - (void)layoutSubviews
8
+ {
9
+ [super layoutSubviews];
10
+ [_layoutDelegate navigationBarDidLayoutSubviews:self];
11
+ }
12
+
13
+ @end
14
+
15
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
@@ -14,7 +14,7 @@
14
14
  #import <react/renderer/components/rnscreens/EventEmitters.h>
15
15
  #import <react/renderer/components/rnscreens/Props.h>
16
16
  #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
17
- #import <rnscreens/RNSScreenComponentDescriptor.h>
17
+ #import <react/renderer/components/rnscreens/legacy/RNSScreenComponentDescriptor.h>
18
18
  #import "RNSConvert.h"
19
19
  #import "RNSHeaderHeightChangeEvent.h"
20
20
  #import "RNSScreenViewEvent.h"
@@ -53,6 +53,9 @@ struct ContentWrapperBox {
53
53
 
54
54
  @implementation RNSScreenView {
55
55
  __weak RCTScrollViewComponentView *_sheetsScrollView;
56
+ /// Tag of `_sheetsScrollView` at the time we started observing it. Fabric changes the tag when it recycles
57
+ /// the view, so a mismatch means the instance now belongs to some other component.
58
+ NSInteger _sheetsScrollViewTag;
56
59
 
57
60
  /// Up-to-date only when sheet is in `fitToContents` mode.
58
61
  CGFloat _sheetContentHeight;
@@ -99,6 +102,7 @@ struct ContentWrapperBox {
99
102
  _sheetExpandsWhenScrolledToEdge = YES;
100
103
  #endif // !TARGET_OS_TV
101
104
  _sheetsScrollView = nil;
105
+ _sheetsScrollViewTag = 0;
102
106
  _sheetContentHeight = 0.0;
103
107
  _markedForUnmountInCurrentTransaction = NO;
104
108
  _synchronousShadowStateUpdatesEnabled = YES;
@@ -134,16 +138,24 @@ RNS_IGNORE_SUPER_CALL_END
134
138
  if (_state != nullptr) {
135
139
  RNSScreenStackHeaderConfig *config = [self findHeaderConfig];
136
140
 
137
- // * in large title, ScrollView handles the offset of content so we cannot set it here also
138
- // * TODO: Why is it assumed in comment above, that large title uses scrollview here? What if only SafeAreaView is
141
+ // The content offset sent to the shadow tree must match the screen's native origin in the navigation controller's
142
+ // view. It is used by measurements & hit testing only, the size is delivered separately (`frameSize`).
143
+ // * On iOS 26+ (see `+[RNSScreenStackHeaderConfig screensExtendUnderOpaqueNavigationBar]`) the screen is always
144
+ // laid out under the navigation bar, so the origin is 0 and the `SafeAreaView` rendered by `ScreenStackItem`
145
+ // insets the content below an opaque bar. All branches below evaluate to 0 in that case.
146
+ // * Below iOS 26, when config.translucent == true, we use `edgesForExtendedLayout` and the screen is laid out
147
+ // under the navigation bar, therefore there is no need to set content offset in shadow tree.
148
+ // * Below iOS 26, in large title, ScrollView handles the offset of content so we cannot set it here also.
149
+ // TODO: Why is it assumed in comment above, that large title uses scrollview here? What if only SafeAreaView is
139
150
  // used?
140
- // * When config.translucent == true, we currently use `edgesForExtendedLayout` and the screen is laid out under the
141
- // navigation bar, therefore there is no need to set content offset in shadow tree.
142
151
  // * When this view is the modal root controller (presented in separate view hierarchy) it does not have navigation
143
152
  // bar! We send non-zero size to JS, for some reason. TODO: this needs to be investigated.
144
- const CGFloat effectiveContentOffsetY = config.largeTitle || config.translucent || self.isPresentedAsNativeModal
145
- ? 0
146
- : [_controller calculateHeaderHeightIsModal:self.isPresentedAsNativeModal];
153
+ // * Otherwise the offset must match the actual native origin of the screen. We can not derive it from the
154
+ // navigation bar geometry, because UIKit does not always lay out the screen right below the navigation bar
155
+ // (e.g. on iOS 26 `edgesForExtendedLayout` ignores the navigation bar's origin offset).
156
+ // See https://github.com/software-mansion/react-native-screens-labs/issues/1841
157
+ const CGFloat effectiveContentOffsetY =
158
+ config.largeTitle || config.translucent || self.isPresentedAsNativeModal ? 0 : [self originInNavigationView].y;
147
159
 
148
160
  auto newState = react::RNSScreenState{RCTSizeFromCGSize(self.bounds.size), {0, effectiveContentOffsetY}};
149
161
 
@@ -176,8 +188,26 @@ RNS_IGNORE_SUPER_CALL_END
176
188
  }
177
189
  }
178
190
 
191
+ // Returns origin of the screen in the coordinate space of its navigation controller's view, which matches
192
+ // the coordinate space of the screen stack in the shadow tree.
193
+ - (CGPoint)originInNavigationView
194
+ {
195
+ UIView *navigationView = _controller.navigationController.view;
196
+ if (navigationView == nil || ![self isDescendantOfView:navigationView]) {
197
+ return CGPointZero;
198
+ }
199
+ return [self convertPoint:CGPointZero toView:navigationView];
200
+ }
201
+
179
202
  - (void)applyFrameCorrectionForDescendantScrollView
180
203
  {
204
+ // A dismissed sheet can still receive a layout pass after React has deleted it. By then Fabric
205
+ // may have recycled its scroll view into the screen that replaced the sheet, and sizing that
206
+ // scroll view to the sheet would clip the new screen. See #4651.
207
+ if (_invalidated) {
208
+ return;
209
+ }
210
+
181
211
  RCTScrollViewComponentView *scrollView = [self tryFindDescendantScrollView];
182
212
  if (_sheetsScrollView != scrollView) {
183
213
  [_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
@@ -187,6 +217,8 @@ RNS_IGNORE_SUPER_CALL_END
187
217
  // we are going to overwrite it anyway.
188
218
  [scrollView addObserver:self forKeyPath:@"bounds" options:0 context:nil];
189
219
  }
220
+ // Refreshed even for the same instance: Fabric might have recycled it back into this sheet.
221
+ _sheetsScrollViewTag = scrollView != nil ? scrollView.tag : 0;
190
222
  if (scrollView != nil) {
191
223
  [self correctScrollViewFrame:scrollView withHeader:nil];
192
224
  }
@@ -215,6 +247,16 @@ RNS_IGNORE_SUPER_CALL_END
215
247
  return;
216
248
  }
217
249
 
250
+ // The sheet's content can remove its scroll view while the sheet stays presented. Fabric then recycles
251
+ // the instance (possibly into another screen), which changes its tag. Stop observing it instead of
252
+ // forcing it to this screen's frame. See #4785.
253
+ if (scrollView.tag != _sheetsScrollViewTag) {
254
+ [scrollView removeObserver:self forKeyPath:@"bounds" context:nil];
255
+ _sheetsScrollView = nil;
256
+ _sheetsScrollViewTag = 0;
257
+ return;
258
+ }
259
+
218
260
  RNSScreenContentWrapper *_Nullable contentWrapper = _contentWrapperBox.contentWrapper;
219
261
  if (contentWrapper != nil && [contentWrapper coerceChildScrollViewComponentSizeToSize:self.frame.size]) {
220
262
  return;
@@ -777,6 +819,7 @@ RNS_IGNORE_SUPER_CALL_END
777
819
  if (_sheetsScrollView != nil) {
778
820
  [_sheetsScrollView removeObserver:self forKeyPath:@"bounds" context:nil];
779
821
  _sheetsScrollView = nil;
822
+ _sheetsScrollViewTag = 0;
780
823
  }
781
824
 
782
825
  // We want to run after container updates are performed (transitions etc.)
@@ -1421,6 +1464,7 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1421
1464
  BOOL _isSwiping;
1422
1465
  BOOL _shouldNotify;
1423
1466
  BOOL _isRemovedFromParent;
1467
+ BOOL _hasNotifiedDismissed;
1424
1468
  }
1425
1469
 
1426
1470
  #pragma mark - Common
@@ -1432,6 +1476,7 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1432
1476
  _fakeView = [UIView new];
1433
1477
  _shouldNotify = YES;
1434
1478
  _isRemovedFromParent = NO;
1479
+ _hasNotifiedDismissed = NO;
1435
1480
  }
1436
1481
  return self;
1437
1482
  }
@@ -1528,7 +1573,7 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1528
1573
  [self.screenView notifyDismissCancelledWithDismissCount:_dismissCount];
1529
1574
  } else {
1530
1575
  // screen dismissed, send event
1531
- [self.screenView notifyDismissedWithCount:_dismissCount];
1576
+ [self notifyDismissedIfNeeded];
1532
1577
  }
1533
1578
  }
1534
1579
  // same flow as in viewDidAppear
@@ -1546,10 +1591,12 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1546
1591
  [super viewDidLayoutSubviews];
1547
1592
 
1548
1593
  // The below code makes the screen view adapt dimensions provided by the system. We take these
1549
- // into account only when the view is mounted under RNSNavigationController in which case system
1550
- // provides additional padding to account for possible header, and in the case when screen is
1551
- // shown as a native modal, as the final dimensions of the modal on iOS 12+ are shorter than the
1552
- // screen size
1594
+ // into account only when the view is mounted under RNSNavigationController, in which case the
1595
+ // navigation controller sizes the screen (below iOS 26 an opaque navigation bar is excluded from
1596
+ // the screen's frame, on iOS 26+ the screen always spans under the bar, see
1597
+ // `+[RNSScreenStackHeaderConfig screensExtendUnderOpaqueNavigationBar]`), and in the case when
1598
+ // screen is shown as a native modal, as the final dimensions of the modal on iOS 12+ are shorter
1599
+ // than the screen size.
1553
1600
  BOOL isDisplayedWithinUINavController = [self.parentViewController isKindOfClass:[RNSNavigationController class]];
1554
1601
  BOOL isTabScreen = [self.parentViewController isKindOfClass:RNSTabBarController.class];
1555
1602
 
@@ -1582,24 +1629,6 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1582
1629
  return NO;
1583
1630
  }
1584
1631
 
1585
- - (CGSize)getStatusBarHeightIsModal:(BOOL)isModal
1586
- {
1587
- #if !TARGET_OS_TV && !TARGET_OS_VISION
1588
- CGSize fallbackStatusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
1589
-
1590
- CGSize primaryStatusBarSize = self.view.window.windowScene.statusBarManager.statusBarFrame.size;
1591
- if (primaryStatusBarSize.height == 0 || primaryStatusBarSize.width == 0) {
1592
- return fallbackStatusBarSize;
1593
- }
1594
-
1595
- return primaryStatusBarSize;
1596
-
1597
- #else
1598
- // TVOS does not have status bar.
1599
- return CGSizeMake(0, 0);
1600
- #endif // !TARGET_OS_TV
1601
- }
1602
-
1603
1632
  - (UINavigationController *)getVisibleNavigationControllerIsModal:(BOOL)isModal
1604
1633
  {
1605
1634
  UINavigationController *navctr = self.navigationController;
@@ -1631,6 +1660,12 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1631
1660
  return 0;
1632
1661
  }
1633
1662
 
1663
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV
1664
+ if (@available(iOS 27.0, *)) {
1665
+ return [self calculateMinimizationAwareHeaderHeightInNavigationController:navctr];
1666
+ }
1667
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV
1668
+
1634
1669
  CGFloat navbarHeight = navctr.navigationBar.frame.size.height;
1635
1670
  #if !TARGET_OS_TV
1636
1671
  CGFloat navbarInset = navctr.navigationBar.frame.origin.y;
@@ -1642,6 +1677,35 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1642
1677
  return navbarHeight + navbarInset;
1643
1678
  }
1644
1679
 
1680
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV
1681
+ // On iOS 27 the navigation bar can minimize in response to scrolling (`UIBarMinimization`). The frame of
1682
+ // `UINavigationBar` does not follow the minimization, only its subviews (background, content view, large title,
1683
+ // search bar) do - they are shifted up within the bar. Therefore we measure the bottom edge of the subviews
1684
+ // instead, in the coordinate space of the navigation controller's view. The value is clamped to the bar's frame,
1685
+ // which is the maximum extent of the bar in the expanded state.
1686
+ - (CGFloat)calculateMinimizationAwareHeaderHeightInNavigationController:(UINavigationController *)navctr
1687
+ API_AVAILABLE(ios(27.0))
1688
+ {
1689
+ UINavigationBar *navbar = navctr.navigationBar;
1690
+ CGFloat navbarMaxY = CGRectGetMaxY([navbar convertRect:navbar.bounds toView:navctr.view]);
1691
+ CGFloat maxY = -CGFLOAT_MAX;
1692
+
1693
+ for (UIView *subview in navbar.subviews) {
1694
+ if (subview.isHidden || CGRectIsEmpty(subview.frame)) {
1695
+ continue;
1696
+ }
1697
+ maxY = MAX(maxY, CGRectGetMaxY([navbar convertRect:subview.frame toView:navctr.view]));
1698
+ }
1699
+
1700
+ if (maxY == -CGFLOAT_MAX) {
1701
+ // No measurable subviews, same as the pre-iOS 27 formula.
1702
+ return navbarMaxY;
1703
+ }
1704
+
1705
+ return MIN(maxY, navbarMaxY);
1706
+ }
1707
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV
1708
+
1645
1709
  - (void)calculateAndNotifyHeaderHeightChangeIsModal:(BOOL)isModal
1646
1710
  {
1647
1711
  CGFloat totalHeight = [self calculateHeaderHeightIsModal:isModal];
@@ -1709,6 +1773,34 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1709
1773
  _isRemovedFromParent = YES;
1710
1774
  }
1711
1775
 
1776
+ - (BOOL)isNativelyDismissedFromContainer
1777
+ {
1778
+ if (self.presentingViewController != nil) {
1779
+ return NO;
1780
+ }
1781
+ if (self.parentViewController == nil) {
1782
+ return YES;
1783
+ }
1784
+ if ([self.parentViewController isKindOfClass:UINavigationController.class]) {
1785
+ UINavigationController *navigationController = (UINavigationController *)self.parentViewController;
1786
+ return ![navigationController.viewControllers containsObject:self];
1787
+ }
1788
+ return NO;
1789
+ }
1790
+
1791
+ - (void)notifyDismissedIfNeeded
1792
+ {
1793
+ if (_hasNotifiedDismissed || self.screenView.preventNativeDismiss) {
1794
+ return;
1795
+ }
1796
+ if (![self isNativelyDismissedFromContainer]) {
1797
+ return;
1798
+ }
1799
+ _hasNotifiedDismissed = YES;
1800
+ _isRemovedFromParent = YES;
1801
+ [self.screenView notifyDismissedWithCount:_dismissCount];
1802
+ }
1803
+
1712
1804
  #pragma mark - transition progress related methods
1713
1805
 
1714
1806
  - (void)setupProgressNotification
@@ -1731,12 +1823,19 @@ Class<RCTComponentViewProtocol> RNSScreenCls(void)
1731
1823
  [self->_animationTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
1732
1824
  };
1733
1825
 
1826
+ BOOL notifyDismissWhenTransitionEnds = _closing;
1734
1827
  [self.transitionCoordinator
1735
1828
  animateAlongsideTransition:animation
1736
1829
  completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
1737
1830
  [self->_animationTimer setPaused:YES];
1738
1831
  [self->_animationTimer invalidate];
1739
1832
  [self->_fakeView removeFromSuperview];
1833
+ // iOS 27 can skip viewDidDisappear when a tab switch
1834
+ // interrupts popToRoot. If this screen was popped,
1835
+ // notify JS when the transition ends.
1836
+ if (notifyDismissWhenTransitionEnds) {
1837
+ [self notifyDismissedIfNeeded];
1838
+ }
1740
1839
  }];
1741
1840
  }
1742
1841
  }