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
@@ -53,6 +53,9 @@ namespace react = facebook::react;
53
53
  {
54
54
  UIViewController *controller = screenCtrl;
55
55
  float headerHeightErrata = 0.f;
56
+ // When screens extend under opaque navigation bars (iOS 26+), the `SafeAreaView` rendered inside this wrapper insets
57
+ // the content below the bar, so the bar height is already part of the wrapper's frame and must not be added again.
58
+ const BOOL wrapperFrameIncludesNavigationBar = [RNSScreenStackHeaderConfig screensExtendUnderOpaqueNavigationBar];
56
59
 
57
60
  do {
58
61
  if ([controller isKindOfClass:RNSScreen.class]) {
@@ -60,7 +63,7 @@ namespace react = facebook::react;
60
63
  if ([currentScreen.screenView registerContentWrapper:self contentHeightErrata:headerHeightErrata]) {
61
64
  break;
62
65
  }
63
- } else if ([controller isKindOfClass:RNSNavigationController.class]) {
66
+ } else if (!wrapperFrameIncludesNavigationBar && [controller isKindOfClass:RNSNavigationController.class]) {
64
67
  RNSNavigationController *navigationController = static_cast<RNSNavigationController *>(controller);
65
68
  UINavigationBar *navigationBar = navigationController.navigationBar;
66
69
 
@@ -12,6 +12,7 @@
12
12
  #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
13
13
  #import "RCTSurfaceTouchHandler+RNSUtility.h"
14
14
  #import "RNSDefines.h"
15
+ #import "RNSNavigationBar.h"
15
16
  #import "RNSPercentDrivenInteractiveTransition.h"
16
17
  #import "RNSScreen.h"
17
18
  #import "RNSScreenStackAnimator.h"
@@ -24,6 +25,10 @@
24
25
  #import "UIView+RNSUtility.h"
25
26
  #import "integrations/RNSDismissibleModalProtocol.h"
26
27
 
28
+ #if TARGET_OS_TV
29
+ #import <React/RCTTVRemoteHandler.h>
30
+ #endif // TARGET_OS_TV
31
+
27
32
  namespace react = facebook::react;
28
33
 
29
34
  @interface RNSScreenStackView () <UINavigationControllerDelegate,
@@ -36,9 +41,36 @@ namespace react = facebook::react;
36
41
  @property (nonatomic) BOOL updatingModals;
37
42
  @property (nonatomic) BOOL scheduleModalsUpdate;
38
43
 
44
+ #if TARGET_OS_TV
45
+ @property (nonatomic, assign) BOOL disableDefaultMenuAction;
46
+ @property (nonatomic, assign) BOOL observingTVMenuKeyNotifications;
47
+ #endif // TARGET_OS_TV
48
+
49
+ @end
50
+
51
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
52
+ @interface RNSNavigationController () <RNSNavigationBarLayoutDelegate>
39
53
  @end
54
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
40
55
 
41
- @implementation RNSNavigationController
56
+ @implementation RNSNavigationController {
57
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
58
+ CGRect _lastNavigationBarFrame;
59
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
60
+ }
61
+
62
+ - (instancetype)init
63
+ {
64
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
65
+ self = [super initWithNavigationBarClass:RNSNavigationBar.class toolbarClass:nil];
66
+ if (self != nil && [self.navigationBar isKindOfClass:RNSNavigationBar.class]) {
67
+ static_cast<RNSNavigationBar *>(self.navigationBar).layoutDelegate = self;
68
+ }
69
+ #else // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
70
+ self = [super init];
71
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0) && !TARGET_OS_TV
72
+ return self;
73
+ }
42
74
 
43
75
  #if !TARGET_OS_TV
44
76
  - (UIViewController *)childViewControllerForStatusBarStyle
@@ -59,25 +91,34 @@ namespace react = facebook::react;
59
91
  - (void)viewDidLayoutSubviews
60
92
  {
61
93
  [super viewDidLayoutSubviews];
94
+
95
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
96
+ if (@available(iOS 26.0, *)) {
97
+ [self requestLayoutIfNavigationBarFrameChanged];
98
+ }
99
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
100
+
62
101
  if ([self.topViewController isKindOfClass:[RNSScreen class]]) {
63
102
  RNSScreen *screenController = (RNSScreen *)self.topViewController;
64
- BOOL isNotDismissingModal = screenController.presentedViewController == nil ||
65
- (screenController.presentedViewController != nil &&
66
- ![screenController.presentedViewController isBeingDismissed]);
67
- BOOL isPresentingSearchController =
68
- [screenController.presentedViewController isKindOfClass:UISearchController.class];
69
-
70
- // Calculate header height during simple transition from one screen to another.
71
- // If RNSScreen includes a navigation controller of type RNSNavigationController, it should not calculate
72
- // header height, as it could have nested stack.
73
- if (![screenController hasNestedStack] && (isPresentingSearchController || isNotDismissingModal)) {
74
- [screenController calculateAndNotifyHeaderHeightChangeIsModal:NO];
75
- }
76
-
103
+ [self notifyHeaderHeightChangeToScreen:screenController];
77
104
  [self maybeUpdateHeaderLayoutInfoInShadowTree:screenController];
78
105
  }
79
106
  }
80
107
 
108
+ - (void)notifyHeaderHeightChangeToScreen:(RNSScreen *)screenController
109
+ {
110
+ BOOL isNotDismissingModal = screenController.presentedViewController == nil ||
111
+ (screenController.presentedViewController != nil && ![screenController.presentedViewController isBeingDismissed]);
112
+ BOOL isPresentingSearchController = [screenController.presentedViewController isKindOfClass:UISearchController.class];
113
+
114
+ // Calculate header height during simple transition from one screen to another.
115
+ // If RNSScreen includes a navigation controller of type RNSNavigationController, it should not calculate
116
+ // header height, as it could have nested stack.
117
+ if (![screenController hasNestedStack] && (isPresentingSearchController || isNotDismissingModal)) {
118
+ [screenController calculateAndNotifyHeaderHeightChangeIsModal:NO];
119
+ }
120
+ }
121
+
81
122
  - (UIInterfaceOrientationMask)supportedInterfaceOrientations
82
123
  {
83
124
  return [self topViewController].supportedInterfaceOrientations;
@@ -116,7 +157,61 @@ namespace react = facebook::react;
116
157
 
117
158
  [headerConfig updateHeaderStateInShadowTreeInContextOfNavigationBar:self.navigationBar];
118
159
  }
119
- #endif
160
+
161
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
162
+ - (void)requestLayoutIfNavigationBarFrameChanged API_AVAILABLE(ios(26.0))
163
+ {
164
+ // UIKit positions the navigation bar during layout of our view, but on iOS 26+ it does so after it has computed
165
+ // the safe area insets of the top view controller. The insets are therefore derived from the previous frame of
166
+ // the bar and they are not corrected until the next layout pass, which nobody requests.
167
+ // Since on iOS 26+ the screen is always laid out under the navigation bar, anything that relies on the insets
168
+ // (`SafeAreaView` rendered by `ScreenStackItem`, content inset adjustment of a scroll view) is misplaced by
169
+ // the distance the bar has travelled.
170
+ //
171
+ // When the frame of the bar has changed, we request another layout pass, in which UIKit computes the insets with
172
+ // the bar already in place. It runs in the same frame. The frame of the bar does not depend on the insets of
173
+ // the top view controller, so the bar is not moved in the additional pass and we do not request yet another one.
174
+ const CGRect navigationBarFrame = self.navigationBar.frame;
175
+ if (!CGRectEqualToRect(navigationBarFrame, _lastNavigationBarFrame)) {
176
+ _lastNavigationBarFrame = navigationBarFrame;
177
+ [self.view setNeedsLayout];
178
+ }
179
+ }
180
+
181
+ #pragma mark - RNSNavigationBarLayoutDelegate
182
+
183
+ - (void)navigationBarDidLayoutSubviews:(UINavigationBar *)navigationBar
184
+ {
185
+ // On iOS 26+ UIKit can position the content of the navigation bar after `viewDidLayoutSubviews`, in a layout pass
186
+ // that follows layout of the bar itself (e.g. title view on rotation of iPhone Duo), or without any layout pass of
187
+ // our view at all (bar minimization on iOS 27). None of our views receives a callback when it is moved this way,
188
+ // therefore we request layout of the header subviews. They are laid out later in the same layout pass, after their
189
+ // ancestors, and update their position in the shadow tree then.
190
+ // See https://github.com/software-mansion/react-native-screens-labs/issues/1841
191
+ if (@available(iOS 26.0, *)) {
192
+ if (![self.topViewController isKindOfClass:[RNSScreen class]]) {
193
+ return;
194
+ }
195
+
196
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
197
+ // The bar minimization (iOS 27+) changes the visible height of the bar without changing its frame and without
198
+ // layout of our view, so this is the only place where we can follow it.
199
+ if (@available(iOS 27.0, *)) {
200
+ [self notifyHeaderHeightChangeToScreen:static_cast<RNSScreen *>(self.topViewController)];
201
+ }
202
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
203
+
204
+ auto headerConfig = static_cast<RNSScreen *>(self.topViewController).screenView.findHeaderConfig;
205
+ if (headerConfig == nil || !headerConfig.shouldHeaderBeVisible) {
206
+ return;
207
+ }
208
+
209
+ [headerConfig setNeedsLayoutForHeaderSubviewsInNavigationBar:navigationBar];
210
+ }
211
+ }
212
+
213
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
214
+ #endif // !TARGET_OS_TV
120
215
 
121
216
  - (void)willMoveToParentViewController:(UIViewController *)parent
122
217
  {
@@ -283,8 +378,81 @@ RNS_IGNORE_SUPER_CALL_END
283
378
  [super didMoveToWindow];
284
379
  // for handling nested stacks
285
380
  [self maybeAddToParentAndUpdateContainer];
381
+ #if TARGET_OS_TV
382
+ if (self.window != nil) {
383
+ [self registerForTVMenuKeyNotificationsIfNeeded];
384
+ [self syncTVMenuKeyHandling];
385
+ } else {
386
+ [self unregisterForTVMenuKeyNotificationsIfNeeded];
387
+ }
388
+ #endif // TARGET_OS_TV
389
+ }
390
+
391
+ #if TARGET_OS_TV
392
+
393
+ - (void)registerForTVMenuKeyNotificationsIfNeeded
394
+ {
395
+ if (_observingTVMenuKeyNotifications) {
396
+ return;
397
+ }
398
+ _observingTVMenuKeyNotifications = YES;
399
+ NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
400
+ [center addObserver:self
401
+ selector:@selector(handleTVMenuKeyNotification:)
402
+ name:RCTTVEnableMenuKeyNotification
403
+ object:nil];
404
+ [center addObserver:self
405
+ selector:@selector(handleTVMenuKeyNotification:)
406
+ name:RCTTVDisableMenuKeyNotification
407
+ object:nil];
408
+ }
409
+
410
+ - (void)unregisterForTVMenuKeyNotificationsIfNeeded
411
+ {
412
+ if (!_observingTVMenuKeyNotifications) {
413
+ return;
414
+ }
415
+ _observingTVMenuKeyNotifications = NO;
416
+ NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
417
+ [center removeObserver:self name:RCTTVEnableMenuKeyNotification object:nil];
418
+ [center removeObserver:self name:RCTTVDisableMenuKeyNotification object:nil];
419
+ }
420
+
421
+ - (void)handleTVMenuKeyNotification:(NSNotification *)notification
422
+ {
423
+ [self syncTVMenuKeyHandling];
424
+ }
425
+
426
+ - (BOOL)shouldDisableUIKitMenuBackGesture
427
+ {
428
+ return _disableDefaultMenuAction && [RCTTVRemoteHandler useMenuKey];
429
+ }
430
+
431
+ - (nullable UITapGestureRecognizer *)uiKitMenuBackGestureRecognizer
432
+ {
433
+ for (UIGestureRecognizer *recognizer in _controller.view.gestureRecognizers) {
434
+ if (![recognizer isKindOfClass:UITapGestureRecognizer.class]) {
435
+ continue;
436
+ }
437
+ UITapGestureRecognizer *tapRecognizer = (UITapGestureRecognizer *)recognizer;
438
+ if ([tapRecognizer.allowedPressTypes containsObject:@(UIPressTypeMenu)]) {
439
+ return tapRecognizer;
440
+ }
441
+ }
442
+ return nil;
286
443
  }
287
444
 
445
+ - (void)syncTVMenuKeyHandling
446
+ {
447
+ UITapGestureRecognizer *menuBackGesture = [self uiKitMenuBackGestureRecognizer];
448
+ if (menuBackGesture == nil) {
449
+ return;
450
+ }
451
+ menuBackGesture.enabled = ![self shouldDisableUIKitMenuBackGesture];
452
+ }
453
+
454
+ #endif // TARGET_OS_TV
455
+
288
456
  - (void)maybeAddToParentAndUpdateContainer
289
457
  {
290
458
  BOOL wasScreenMounted = _controller.parentViewController != nil;
@@ -997,6 +1165,15 @@ RNS_IGNORE_SUPER_CALL_END
997
1165
  }
998
1166
  #endif
999
1167
 
1168
+ #if TARGET_OS_TV
1169
+ - (void)navigationController:(UINavigationController *)navigationController
1170
+ didShowViewController:(UIViewController *)viewController
1171
+ animated:(BOOL)animated
1172
+ {
1173
+ [self syncTVMenuKeyHandling];
1174
+ }
1175
+ #endif // TARGET_OS_TV
1176
+
1000
1177
  - (void)markChildUpdated
1001
1178
  {
1002
1179
  // In native stack this should be called only for `preload` purposes.
@@ -1279,6 +1456,13 @@ RNS_IGNORE_SUPER_CALL_END
1279
1456
  _controller.view.backgroundColor = _nativeContainerBackgroundColor;
1280
1457
  }
1281
1458
 
1459
+ #if TARGET_OS_TV
1460
+ if (newScreenProps.disableDefaultMenuAction != oldScreenProps.disableDefaultMenuAction) {
1461
+ _disableDefaultMenuAction = newScreenProps.disableDefaultMenuAction;
1462
+ [self syncTVMenuKeyHandling];
1463
+ }
1464
+ #endif // TARGET_OS_TV
1465
+
1282
1466
  [super updateProps:props oldProps:oldProps];
1283
1467
  }
1284
1468
 
@@ -1375,6 +1559,9 @@ RNS_IGNORE_SUPER_CALL_END
1375
1559
  - (void)prepareForRecycle
1376
1560
  {
1377
1561
  [super prepareForRecycle];
1562
+ #if TARGET_OS_TV
1563
+ [self unregisterForTVMenuKeyNotificationsIfNeeded];
1564
+ #endif // TARGET_OS_TV
1378
1565
  _reactSubviews = [NSMutableArray new];
1379
1566
 
1380
1567
  for (UIViewController *controller in _presentedModals) {
@@ -3,6 +3,7 @@
3
3
  #if defined(__cplusplus)
4
4
  #import <React/RCTConvert.h>
5
5
  #endif // __cplusplus
6
+ #import "RNSDefines.h"
6
7
  #import "RNSReactBaseView.h"
7
8
  #import "RNSScreen.h"
8
9
  #import "RNSScreenStackHeaderSubview.h"
@@ -58,6 +59,17 @@ NS_ASSUME_NONNULL_END
58
59
  animated:(BOOL)animated
59
60
  withConfig:(nonnull RNSScreenStackHeaderConfig *)config;
60
61
 
62
+ /**
63
+ * Returns `YES` when screens in the legacy stack are always laid out under the navigation bar
64
+ * (`edgesForExtendedLayout = UIRectEdgeAll`), also when the header is opaque. In that case the content is inset below
65
+ * an opaque bar by the `SafeAreaView` rendered by `ScreenStackItem` (JS) and the screen's origin in the navigation
66
+ * controller's view is always 0. Otherwise (iOS < 26, tvOS, visionOS) a screen with a visible, opaque header is laid
67
+ * out below the bar (`UIRectEdgeAll - UIRectEdgeTop`).
68
+ *
69
+ * Keep in sync with `getSafeAreaEdges` in `src/legacy/components/ScreenStackItem.tsx`.
70
+ */
71
+ + (BOOL)screensExtendUnderOpaqueNavigationBar;
72
+
61
73
  /**
62
74
  * Returns true iff subview of given `type` is present.
63
75
  *
@@ -99,6 +111,24 @@ NS_ASSUME_NONNULL_END
99
111
  */
100
112
  - (void)updateHeaderStateInShadowTreeInContextOfNavigationBar:(nullable UINavigationBar *)navBar;
101
113
 
114
+ /**
115
+ * Requests `updateViewControllerIfNeeded` to be called once, after the current
116
+ * mounting transaction finishes. Use this instead of calling `updateViewControllerIfNeeded`
117
+ * directly from subviews, so that a single transaction updating several subviews
118
+ * re-applies the config only once, with all subviews already updated.
119
+ */
120
+ - (void)setNeedsViewControllerUpdate;
121
+
122
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
123
+ /**
124
+ * Requests layout of all header subviews attached to the view hierarchy. Header subview updates its state in shadow
125
+ * tree when it is laid out, therefore this method should be called when `navBar` lays out its subviews - the header
126
+ * subviews are laid out later in the same layout pass, after UIKit has positioned the content of the navigation bar.
127
+ * When the content of `navBar` is moved out of the bar (bar minimization on iOS 27+) this method does nothing.
128
+ */
129
+ - (void)setNeedsLayoutForHeaderSubviewsInNavigationBar:(nonnull UINavigationBar *)navBar;
130
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
131
+
102
132
  @end
103
133
 
104
134
  #pragma mark - Experimental
@@ -13,8 +13,8 @@
13
13
  #import <react/renderer/components/rnscreens/EventEmitters.h>
14
14
  #import <react/renderer/components/rnscreens/Props.h>
15
15
  #import <react/renderer/components/rnscreens/RCTComponentViewHelpers.h>
16
+ #import <react/renderer/components/rnscreens/legacy/RNSScreenStackHeaderConfigComponentDescriptor.h>
16
17
  #import <react/utils/ManagedObjectWrapper.h>
17
- #import <rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h>
18
18
  #import "RCTImageComponentView+RNSScreenStackHeaderConfig.h"
19
19
  #import "RNSBackBarButtonItem.h"
20
20
  #import "RNSBarButtonItem.h"
@@ -58,6 +58,9 @@ static const NSNumber *const DEFAULT_TITLE_LARGE_FONT_SIZE = @34;
58
58
  /// Whether a react subview has been added / removed in current transaction. This flag is reset after each react
59
59
  /// transaction via RCTMountingTransactionObserving protocol.
60
60
  bool _addedReactSubviewsInCurrentTransaction;
61
+ /// Whether a react subview requested the config to be re-applied in current transaction.
62
+ /// Consumed & reset in `mountingTransactionDidMount:withSurfaceTelemetry:`.
63
+ bool _needsViewControllerUpdateInCurrentTransaction;
61
64
  RCTImageLoader *_imageLoader;
62
65
  }
63
66
 
@@ -69,6 +72,7 @@ static const NSNumber *const DEFAULT_TITLE_LARGE_FONT_SIZE = @34;
69
72
  _show = YES;
70
73
  _translucent = NO;
71
74
  _addedReactSubviewsInCurrentTransaction = false;
75
+ _needsViewControllerUpdateInCurrentTransaction = false;
72
76
  _lastSendState = react::RNSScreenStackHeaderConfigState(react::Size{}, react::EdgeInsets{}, react::Point{});
73
77
  [self initProps];
74
78
  }
@@ -157,11 +161,18 @@ RNS_IGNORE_SUPER_CALL_END
157
161
  }
158
162
  }
159
163
 
164
+ - (void)setNeedsViewControllerUpdate
165
+ {
166
+ _needsViewControllerUpdateInCurrentTransaction = true;
167
+ }
168
+
160
169
  - (void)layoutNavigationControllerView
161
170
  {
162
- // We need to layout navigation controller view after translucent prop changes, because otherwise
163
- // frame of RNSScreen will not be changed and screen content will remain the same size.
164
- // For more details look at https://github.com/software-mansion/react-native-screens/issues/1158
171
+ // We need to layout navigation controller view after `translucent` / `hidden` prop changes. Below iOS 26 the frame
172
+ // of RNSScreen depends on them (`edgesForExtendedLayout`), so without the layout pass the screen content would
173
+ // remain the same size (https://github.com/software-mansion/react-native-screens/issues/1158). On iOS 26+ the frame
174
+ // does not change, but the layout pass still refreshes the header layout info in the shadow tree and the safe area
175
+ // insets consumed by the `SafeAreaView` rendered by `ScreenStackItem`.
165
176
  UIViewController *vc = _screenView.controller;
166
177
  UINavigationController *navctr = vc.navigationController;
167
178
  [navctr.view setNeedsLayout];
@@ -194,17 +205,10 @@ RNS_IGNORE_SUPER_CALL_END
194
205
  return;
195
206
  }
196
207
 
208
+ // Screen's content offset in shadow tree matches its actual native origin (see `-[RNSScreenView updateBounds]`),
209
+ // therefore navigation bar's frame in screen's coordinate space can be used directly.
197
210
  CGRect navBarFrameInScreenView = [navigationBar convertRect:navigationBar.bounds toView:_screenView];
198
211
 
199
- // On iOS 26+ in landscape mode there is a bug with `edgesForExtendedLayout` for non-transparent
200
- // header. We're applying SAV to fix it but we need to take it into account for HeaderConfig's
201
- // origin as well.
202
- #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
203
- if (!_translucent && self.shouldHeaderBeVisible) {
204
- navBarFrameInScreenView.origin.y -= _screenView.safeAreaInsets.top;
205
- }
206
- #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
207
-
208
212
  [self updateShadowStateWithSize:navigationBar.frame.size
209
213
  edgeInsets:[self computeEdgeInsetsOfNavigationBar:navigationBar]
210
214
  frameOrigin:navBarFrameInScreenView.origin];
@@ -213,6 +217,24 @@ RNS_IGNORE_SUPER_CALL_END
213
217
  }
214
218
  }
215
219
 
220
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
221
+ - (void)setNeedsLayoutForHeaderSubviewsInNavigationBar:(nonnull UINavigationBar *)navigationBar
222
+ {
223
+ // During the bar minimization (iOS 27+) UIKit moves the content view of the navigation bar above the bar, on each
224
+ // frame of the scroll. The header subviews are not visible then, therefore we do not follow their position, to
225
+ // avoid state update on each frame. When the bar is restored, its content view is back at the origin of the bar.
226
+ if (CGRectGetMinY(navigationBar.rnscreens_findContentView.frame) < 0) {
227
+ return;
228
+ }
229
+
230
+ for (RNSScreenStackHeaderSubview *subview in self.reactSubviews) {
231
+ if (subview.window != nil) {
232
+ [subview setNeedsLayout];
233
+ }
234
+ }
235
+ }
236
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
237
+
216
238
  - (NSDirectionalEdgeInsets)computeEdgeInsetsOfNavigationBar:(nonnull UINavigationBar *)navigationBar
217
239
  {
218
240
  NSDirectionalEdgeInsets navBarMargins = [navigationBar directionalLayoutMargins];
@@ -353,6 +375,18 @@ RNS_IGNORE_SUPER_CALL_END
353
375
  return nil;
354
376
  }
355
377
 
378
+ + (BOOL)screensExtendUnderOpaqueNavigationBar
379
+ {
380
+ #if TARGET_OS_TV || TARGET_OS_VISION
381
+ return NO;
382
+ #else // TARGET_OS_TV || TARGET_OS_VISION
383
+ if (@available(iOS 26.0, *)) {
384
+ return YES;
385
+ }
386
+ return NO;
387
+ #endif // TARGET_OS_TV || TARGET_OS_VISION
388
+ }
389
+
356
390
  + (void)willShowViewController:(UIViewController *)vc
357
391
  animated:(BOOL)animated
358
392
  withConfig:(RNSScreenStackHeaderConfig *)config
@@ -494,12 +528,16 @@ RNS_IGNORE_SUPER_CALL_END
494
528
  BOOL wasHidden = navctr.navigationBarHidden;
495
529
  BOOL shouldHide = config == nil || !config.shouldHeaderBeVisible;
496
530
 
497
- if (!shouldHide && !config.translucent) {
498
- // when nav bar is not translucent we change edgesForExtendedLayout to avoid system laying out
499
- // the screen underneath navigation controllers
531
+ if (!shouldHide && !config.translucent && ![self screensExtendUnderOpaqueNavigationBar]) {
532
+ // When nav bar is not translucent we change edgesForExtendedLayout to avoid system laying out
533
+ // the screen underneath navigation controllers.
500
534
  vc.edgesForExtendedLayout = UIRectEdgeAll - UIRectEdgeTop;
501
535
  } else {
502
- // system default is UIRectEdgeAll
536
+ // System default is UIRectEdgeAll - the screen is laid out under the navigation bar.
537
+ // On iOS 26+ this is also the case for an opaque header: UIKit does not reliably lay out the screen right below
538
+ // the bar when the top edge is excluded (it ignores the bar's origin offset, e.g. in landscape or on iPhone Duo),
539
+ // so we let the screen extend under the bar and inset the content with the `SafeAreaView` rendered by
540
+ // `ScreenStackItem`. See https://github.com/software-mansion/react-native-screens-labs/issues/1841
503
541
  vc.edgesForExtendedLayout = UIRectEdgeAll;
504
542
  }
505
543
 
@@ -523,6 +561,16 @@ RNS_IGNORE_SUPER_CALL_END
523
561
  }
524
562
  navitem.largeTitleDisplayMode =
525
563
  config.largeTitle ? UINavigationItemLargeTitleDisplayModeAlways : UINavigationItemLargeTitleDisplayModeNever;
564
+
565
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
566
+ if (@available(iOS 27.0, *)) {
567
+ // Due to native limitations related to opaque header and minimization behavior, we disable it for opaque headers.
568
+ UIBarMinimization *minimization = [UIBarMinimization new];
569
+ minimization.minimizationBehavior =
570
+ config.translucent ? UIBarMinimizationBehaviorAutomatic : UIBarMinimizationBehaviorNever;
571
+ navitem.navigationBarMinimization = minimization;
572
+ }
573
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0)
526
574
  #endif
527
575
 
528
576
  UINavigationBarAppearance *appearance = [self buildAppearance:vc withConfig:config];
@@ -905,8 +953,13 @@ RNS_IGNORE_SUPER_CALL_END
905
953
  if (self.shouldHeaderBeVisible) {
906
954
  [self layoutNavigationControllerView];
907
955
  }
956
+ } else if (_needsViewControllerUpdateInCurrentTransaction) {
957
+ // Subviews (e.g. their `visibilityPriority`) changed in this transaction. Re-apply the config once,
958
+ // now that all of them have already received their new props.
959
+ [self updateViewControllerIfNeeded];
908
960
  }
909
961
  _addedReactSubviewsInCurrentTransaction = false;
962
+ _needsViewControllerUpdateInCurrentTransaction = false;
910
963
  }
911
964
 
912
965
  - (void)replaceNavigationBarViewsWithSnapshotOfSubview:(RNSScreenStackHeaderSubview *)childComponentView
@@ -947,6 +1000,7 @@ RNS_IGNORE_SUPER_CALL_END
947
1000
  }
948
1001
  }
949
1002
 
1003
+ #ifndef NDEBUG
950
1004
  static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
951
1005
  {
952
1006
  switch (resizeMode) {
@@ -965,6 +1019,7 @@ static RCTResizeMode resizeModeFromCppEquiv(react::ImageResizeMode resizeMode)
965
1019
  return RCTResizeModeStretch;
966
1020
  }
967
1021
  }
1022
+ #endif // !NDEBUG
968
1023
 
969
1024
  + (RCTImageSource *)imageSourceFromImageView:(RCTImageComponentView *)view
970
1025
  {
@@ -10,7 +10,7 @@
10
10
  #import <React/RCTConversions.h>
11
11
  #import <React/RCTFabricComponentsPlugins.h>
12
12
 
13
- #import <rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h>
13
+ #import <react/renderer/components/rnscreens/legacy/RNSScreenStackHeaderSubviewComponentDescriptor.h>
14
14
 
15
15
  namespace react = facebook::react;
16
16
 
@@ -21,6 +21,7 @@ namespace react = facebook::react;
21
21
  // The cycle is cleared via `invalidateUIBarButtonItem` method, called by `invalidate` callback.
22
22
  UIBarButtonItem *_barButtonItem;
23
23
  BOOL _hidesSharedBackground;
24
+ react::RNSScreenStackHeaderSubviewVisibilityPriority _visibilityPriority;
24
25
  }
25
26
 
26
27
  #pragma mark - Common
@@ -112,6 +113,7 @@ namespace react = facebook::react;
112
113
  _props = defaultProps;
113
114
  _lastScheduledFrame = CGRectZero;
114
115
  _synchronousShadowStateUpdatesEnabled = YES;
116
+ _visibilityPriority = react::RNSScreenStackHeaderSubviewVisibilityPriority::Standard;
115
117
  }
116
118
 
117
119
  return self;
@@ -125,6 +127,7 @@ namespace react = facebook::react;
125
127
 
126
128
  [self setType:[RNSConvert RNSScreenStackHeaderSubviewTypeFromCppEquivalent:newHeaderSubviewProps.type]];
127
129
  [self setHidesSharedBackground:newHeaderSubviewProps.hidesSharedBackground];
130
+ [self setVisibilityPriority:newHeaderSubviewProps.visibilityPriority];
128
131
  [self setSynchronousShadowStateUpdatesEnabled:newHeaderSubviewProps.synchronousShadowStateUpdatesEnabled];
129
132
  [super updateProps:props oldProps:oldProps];
130
133
  }
@@ -280,6 +283,17 @@ RNS_IGNORE_SUPER_CALL_END
280
283
  }
281
284
  }
282
285
  #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(26_0)
286
+
287
+ // tvOS and visionOS are excluded on purpose: `visibilityPriority` exists there, but the only
288
+ // supported value is `standard`, which is already the default.
289
+ #if RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV && !TARGET_OS_VISION
290
+ if (@available(iOS 27.0, *)) {
291
+ if (_barButtonItem != nil) {
292
+ _barButtonItem.visibilityPriority =
293
+ [RNSConvert UIBarButtonItemVisibilityPriorityFromCppEquivalent:_visibilityPriority];
294
+ }
295
+ }
296
+ #endif // RNS_IPHONE_OS_VERSION_AVAILABLE(27_0) && !TARGET_OS_TV && !TARGET_OS_VISION
283
297
  }
284
298
 
285
299
  - (void)setHidesSharedBackground:(BOOL)hidesSharedBackground
@@ -288,6 +302,25 @@ RNS_IGNORE_SUPER_CALL_END
288
302
  [self configureBarButtonItem];
289
303
  }
290
304
 
305
+ - (void)setVisibilityPriority:(react::RNSScreenStackHeaderSubviewVisibilityPriority)visibilityPriority
306
+ {
307
+ if (visibilityPriority == _visibilityPriority) {
308
+ return;
309
+ }
310
+
311
+ _visibilityPriority = visibilityPriority;
312
+ [self configureBarButtonItem];
313
+
314
+ // Changing the priority of an item that is already in the bar is not enough:
315
+ // the bar only re-evaluates which items fit when it is handed its items again,
316
+ // which the header does whenever it re-applies its config. We defer that until
317
+ // the end of the mounting transaction, so that sibling subviews updated in the
318
+ // same transaction are taken into account & the config is re-applied only once.
319
+ if (_barButtonItem != nil) {
320
+ [[self getHeaderConfig] setNeedsViewControllerUpdate];
321
+ }
322
+ }
323
+
291
324
  #pragma mark - Dynamic frameworks support
292
325
 
293
326
  // Needed because of this: https://github.com/facebook/react-native/pull/37274
@@ -101,7 +101,8 @@
101
101
  {
102
102
  #if !TARGET_OS_TV && !TARGET_OS_VISION
103
103
  dispatch_async(dispatch_get_main_queue(), ^{
104
- UIInterfaceOrientationMask orientationMask = [RCTKeyWindow().rootViewController supportedInterfaceOrientations];
104
+ UIWindow *window = RCTKeyWindow();
105
+ UIInterfaceOrientationMask orientationMask = [window.rootViewController supportedInterfaceOrientations];
105
106
 
106
107
  UIInterfaceOrientation currentDeviceOrientation =
107
108
  [RNSScreenWindowTraits interfaceOrientationFromDeviceOrientation:[[UIDevice currentDevice] orientation]];
@@ -130,17 +131,7 @@
130
131
  if (newOrientation != UIInterfaceOrientationUnknown) {
131
132
  #if RNS_IPHONE_OS_VERSION_AVAILABLE(16_0)
132
133
  if (@available(iOS 16.0, *)) {
133
- NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
134
-
135
- // when an app supports multiple scenes (e.g. CarPlay), it is possible that
136
- // UIWindowScene is not the first scene, or it may not be present at all
137
- UIWindowScene *scene = nil;
138
- for (id connectedScene in array) {
139
- if ([connectedScene isKindOfClass:[UIWindowScene class]]) {
140
- scene = connectedScene;
141
- break;
142
- }
143
- }
134
+ UIWindowScene *scene = window.windowScene;
144
135
 
145
136
  if (scene == nil) {
146
137
  return;
@@ -154,7 +145,8 @@
154
145
 
155
146
  // `attemptRotationToDeviceOrientation` is deprecated for modern OS versions
156
147
  // so we need to use `setNeedsUpdateOfSupportedInterfaceOrientations`
157
- UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
148
+
149
+ UIViewController *topController = window.rootViewController;
158
150
  while (topController.presentedViewController) {
159
151
  topController = topController.presentedViewController;
160
152
  }
@@ -10,13 +10,11 @@ NS_ASSUME_NONNULL_BEGIN
10
10
 
11
11
  @interface RNSFormSheetConfigurationApplicator : NSObject
12
12
 
13
- - (void)applyConfigurationIfNeededWithAppearanceProvider:(id<RNSFormSheetAppearanceProvider>)appearanceProvider
13
+ + (void)applyConfigurationIfNeededWithAppearanceProvider:(id<RNSFormSheetAppearanceProvider>)appearanceProvider
14
14
  behaviorProvider:(id<RNSFormSheetBehaviorProvider>)behaviorProvider
15
15
  controller:(RNSFormSheetContentController *)controller
16
16
  coordinator:(RNSFormSheetUpdateCoordinator *)coordinator;
17
17
 
18
- - (void)resetInitialDetent;
19
-
20
18
  @end
21
19
 
22
20
  NS_ASSUME_NONNULL_END