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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (585) hide show
  1. package/Package.swift +87 -0
  2. package/README.md +0 -8
  3. package/RNScreens.podspec +2 -6
  4. package/android/build.gradle +26 -1
  5. package/android/src/fabric/java/com/swmansion/rnscreens/NativeProxy.kt +5 -0
  6. package/android/src/main/cpp/NativeProxy.cpp +30 -6
  7. package/android/src/main/cpp/NativeProxy.h +7 -1
  8. package/android/src/main/java/com/swmansion/rnscreens/RNScreensPackage.kt +2 -2
  9. package/android/src/main/java/com/swmansion/rnscreens/common/container/Container.kt +8 -0
  10. package/android/src/main/java/com/swmansion/rnscreens/common/container/ContainerItem.kt +13 -1
  11. package/android/src/main/java/com/swmansion/rnscreens/common/text/ReactTextAppearance.kt +62 -0
  12. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearance.kt +20 -0
  13. package/android/src/main/java/com/swmansion/rnscreens/common/text/TextAppearanceDefaults.kt +65 -0
  14. package/android/src/main/java/com/swmansion/rnscreens/helpers/PropIconResolver.kt +17 -23
  15. package/android/src/main/java/com/swmansion/rnscreens/legacy/Screen.kt +25 -7
  16. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStack.kt +2 -0
  17. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenStackFragment.kt +39 -10
  18. package/android/src/main/java/com/swmansion/rnscreens/legacy/ScreenViewManager.kt +5 -0
  19. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetAppearanceCoordinator.kt → native/coordinator/FormSheetAppearanceCoordinator.kt} +2 -1
  20. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetBehaviorController.kt → native/coordinator/FormSheetBehaviorController.kt} +74 -19
  21. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetDimensionsCoordinator.kt +159 -0
  22. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetKeyboardCoordinator.kt +101 -0
  23. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/coordinator/FormSheetNativeDismissCoordinator.kt +44 -0
  24. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetAvailableHeightProvider.kt +44 -0
  25. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContainer.kt → native/core/FormSheetContainer.kt} +1 -1
  26. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialog.kt +115 -0
  27. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/core/FormSheetDialogManager.kt +89 -0
  28. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContentSizeChangeDelegate.kt → native/interfaces/FormSheetContentSizeChangeDelegate.kt} +1 -1
  29. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContentSizeChangeProvider.kt → native/interfaces/FormSheetContentSizeChangeProvider.kt} +1 -1
  30. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetDialogEventEmitter.kt → native/interfaces/FormSheetDialogEventEmitter.kt} +5 -1
  31. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetConfig.kt → native/model/FormSheetConfig.kt} +5 -1
  32. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/model/FormSheetDetents.kt +152 -0
  33. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetAnimatorFactory.kt → native/presentation/FormSheetAnimatorFactory.kt} +9 -10
  34. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDimmingManager.kt +115 -0
  35. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetDismissalOrigin.kt +22 -0
  36. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentation.kt +173 -0
  37. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetPresentationManager.kt +290 -0
  38. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetPresentationState.kt → native/presentation/FormSheetPresentationState.kt} +2 -2
  39. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/native/presentation/FormSheetStackRegistry.kt +28 -0
  40. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContentWrapper.kt → react/contentwrapper/FormSheetContentWrapper.kt} +3 -1
  41. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContentWrapperViewManager.kt → react/contentwrapper/FormSheetContentWrapperViewManager.kt} +1 -1
  42. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetDetentChangedEvent.kt → react/event/FormSheetDetentChangedEvent.kt} +1 -1
  43. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetDidAppearEvent.kt → react/event/FormSheetDidAppearEvent.kt} +1 -1
  44. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetDidDisappearEvent.kt → react/event/FormSheetDidDisappearEvent.kt} +1 -1
  45. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetDismissEvent.kt +29 -0
  46. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetNativeDismissEvent.kt → react/event/FormSheetNativeDismissEvent.kt} +1 -1
  47. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/react/event/FormSheetNativeDismissPreventedEvent.kt +29 -0
  48. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetSyncFlushEvent.kt → react/event/FormSheetSyncFlushEvent.kt} +1 -1
  49. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetWillAppearEvent.kt → react/event/FormSheetWillAppearEvent.kt} +1 -1
  50. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetWillDisappearEvent.kt → react/event/FormSheetWillDisappearEvent.kt} +1 -1
  51. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetContentView.kt → react/host/FormSheetContentView.kt} +3 -1
  52. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetHost.kt → react/host/FormSheetHost.kt} +6 -1
  53. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetHostEventEmitter.kt → react/host/FormSheetHostEventEmitter.kt} +23 -1
  54. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/{FormSheetHostViewManager.kt → react/host/FormSheetHostViewManager.kt} +13 -2
  55. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderApplicator.kt +380 -457
  56. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderBackPressHandler.kt +11 -0
  57. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderCoordinatorLayout.kt +150 -182
  58. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderFrameSynchronizer.kt +63 -0
  59. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderAppBarLayout.kt +240 -0
  60. package/android/src/main/java/com/swmansion/rnscreens/stack/header/{StackHeaderAppBarLayoutBehavior.kt → appbar/StackHeaderAppBarLayoutBehavior.kt} +1 -1
  61. package/android/src/main/java/com/swmansion/rnscreens/stack/header/appbar/StackHeaderContentScrimDrawable.kt +36 -0
  62. package/android/src/main/java/com/swmansion/rnscreens/stack/header/{StackHeaderScrollingViewBehavior.kt → appbar/StackHeaderScrollingViewBehavior.kt} +1 -1
  63. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderCollapsedTitleGravityMode.kt +6 -0
  64. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfig.kt +192 -167
  65. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigViewManager.kt +393 -13
  66. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationObserver.kt +0 -4
  67. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderConfigurationProviding.kt +33 -3
  68. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderDelegate.kt +0 -7
  69. package/android/src/main/java/com/swmansion/rnscreens/stack/header/config/StackHeaderInvalidationFlags.kt +9 -3
  70. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuApplicator.kt +195 -0
  71. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuController.kt +448 -0
  72. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuDelegate.kt +10 -0
  73. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuMapper.kt +43 -21
  74. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuConfig.kt +8 -0
  75. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuElementConfig.kt → model/StackHeaderToolbarMenuElementConfig.kt} +1 -1
  76. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuGroupConfig.kt → model/StackHeaderToolbarMenuGroupConfig.kt} +1 -1
  77. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuGroupMetadata.kt +11 -0
  78. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuItemConfig.kt → model/StackHeaderToolbarMenuItemConfig.kt} +2 -4
  79. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuItemDefaults.kt → model/StackHeaderToolbarMenuItemDefaults.kt} +1 -1
  80. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuItemIconSource.kt → model/StackHeaderToolbarMenuItemIconSource.kt} +1 -1
  81. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuItemShowAsAction.kt → model/StackHeaderToolbarMenuItemShowAsAction.kt} +1 -1
  82. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuItemType.kt → model/StackHeaderToolbarMenuItemType.kt} +1 -1
  83. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/model/StackHeaderToolbarMenuModel.kt +180 -0
  84. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarFieldUpdate.kt → update/StackHeaderToolbarFieldUpdate.kt} +1 -1
  85. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementOptions.kt +84 -0
  86. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementRawUpdate.kt +15 -0
  87. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuElementUpdate.kt +11 -0
  88. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuIconResolver.kt +18 -0
  89. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/{StackHeaderToolbarMenuUpdateQueue.kt → update/StackHeaderToolbarMenuUpdateQueue.kt} +24 -52
  90. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/update/StackHeaderToolbarMenuUpdateQueueDelegate.kt +9 -0
  91. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackContainer.kt +103 -3
  92. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHost.kt +13 -0
  93. package/android/src/main/java/com/swmansion/rnscreens/stack/host/StackHostViewManager.kt +14 -0
  94. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreen.kt +5 -0
  95. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragment.kt +20 -1
  96. package/android/src/main/java/com/swmansion/rnscreens/stack/screen/StackScreenFragmentDelegate.kt +12 -0
  97. package/android/src/main/java/com/swmansion/rnscreens/tabs/appearance/TabsAppearanceCoordinator.kt +2 -4
  98. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/MenuHelpers.kt +5 -23
  99. package/android/src/main/java/com/swmansion/rnscreens/tabs/container/TabsContainer.kt +46 -25
  100. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHost.kt +10 -0
  101. package/android/src/main/java/com/swmansion/rnscreens/tabs/host/TabsHostA11yCoordinator.kt +23 -2
  102. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreen.kt +17 -0
  103. package/android/src/main/java/com/swmansion/rnscreens/tabs/screen/TabsScreenFragment.kt +3 -0
  104. package/android/src/main/java/com/swmansion/rnscreens/utils/DimensionUtils.kt +7 -0
  105. package/android/src/main/java/com/swmansion/rnscreens/utils/StyleUtils.kt +22 -0
  106. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_available_space.xml +8 -0
  107. package/android/src/main/res/base/layout/rns_collapsing_toolbar_large_entire_space.xml +8 -0
  108. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_available_space.xml +8 -0
  109. package/android/src/main/res/base/layout/rns_collapsing_toolbar_medium_entire_space.xml +8 -0
  110. package/common/cpp/react/renderer/components/rnscreens/legacy/RNSScreenShadowNode.cpp +10 -5
  111. package/cpp/legacy/RNSScreenRemovalListener.cpp +31 -1
  112. package/cpp/legacy/RNSScreenRemovalListener.h +18 -3
  113. package/ios/RNSEnums.h +2 -2
  114. package/ios/RNSOrientationProviding.h +0 -2
  115. package/ios/RNSReactMountingTransactionObserving.h +15 -0
  116. package/ios/conversion/RNSConversions.h +7 -108
  117. package/ios/legacy/RNSBarButtonItem.mm +12 -5
  118. package/ios/legacy/RNSFullWindowOverlay.mm +1 -1
  119. package/ios/legacy/RNSModalScreen.mm +1 -1
  120. package/ios/legacy/RNSScreen.h +8 -1
  121. package/ios/legacy/RNSScreen.mm +47 -36
  122. package/ios/legacy/RNSScreenContentWrapper.mm +9 -0
  123. package/ios/legacy/RNSScreenFooter.mm +2 -0
  124. package/ios/legacy/RNSScreenStack.mm +9 -4
  125. package/ios/legacy/RNSScreenStackHeaderConfig.mm +3 -1
  126. package/ios/legacy/RNSScreenStackHeaderSubview.mm +1 -1
  127. package/ios/legacy/RNSScreenWindowTraits.mm +5 -13
  128. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.h +1 -3
  129. package/ios/modals/form-sheet/RNSFormSheetConfigurationApplicator.mm +11 -22
  130. package/ios/modals/form-sheet/RNSFormSheetContentController.h +1 -1
  131. package/ios/modals/form-sheet/RNSFormSheetContentController.mm +7 -18
  132. package/ios/modals/form-sheet/RNSFormSheetContentWrapperComponentView.mm +9 -0
  133. package/ios/modals/form-sheet/RNSFormSheetHostComponentView.mm +4 -4
  134. package/ios/modals/form-sheet/RNSFormSheetHostShadowStateProxy.mm +2 -2
  135. package/ios/modals/form-sheet/RNSFormSheetUpdateFlags.h +3 -0
  136. package/ios/safe-area/RNSSafeAreaViewComponentView.mm +2 -2
  137. package/ios/scroll-to-top-guard/RNSScrollToTopGuard.h +17 -0
  138. package/ios/scroll-to-top-guard/RNSScrollToTopGuard.mm +57 -0
  139. package/ios/scroll-to-top-guard/RNSScrollToTopGuardGestureRecognizer.h +28 -0
  140. package/ios/scroll-to-top-guard/RNSScrollToTopGuardGestureRecognizer.mm +64 -0
  141. package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.mm +2 -3
  142. package/ios/split/RNSSplitAppearanceApplicator.h +36 -0
  143. package/ios/split/RNSSplitAppearanceApplicator.mm +182 -0
  144. package/ios/split/RNSSplitAppearanceCoordinator.h +26 -0
  145. package/ios/split/RNSSplitAppearanceCoordinator.mm +27 -0
  146. package/ios/split/RNSSplitAppearanceUpdateFlags.h +14 -0
  147. package/ios/split/RNSSplitHostComponentEventEmitter.h +1 -0
  148. package/ios/split/RNSSplitHostComponentEventEmitter.mm +1 -1
  149. package/ios/split/RNSSplitHostComponentView.h +5 -15
  150. package/ios/split/RNSSplitHostComponentView.mm +56 -7
  151. package/ios/split/RNSSplitHostController.h +105 -0
  152. package/ios/split/RNSSplitHostController.mm +492 -0
  153. package/ios/split/RNSSplitHostProviders.h +67 -0
  154. package/ios/split/RNSSplitNavigationController.h +31 -0
  155. package/ios/split/RNSSplitNavigationController.mm +44 -0
  156. package/ios/split/RNSSplitNavigationControllerFrameObserver.h +32 -0
  157. package/ios/split/RNSSplitNavigationControllerFrameObserver.mm +80 -0
  158. package/ios/split/RNSSplitNavigationControllerFrameOriginChangeDelegate.h +15 -0
  159. package/ios/split/RNSSplitScreenComponentView.h +0 -39
  160. package/ios/split/RNSSplitScreenComponentView.mm +35 -19
  161. package/ios/split/RNSSplitScreenController.h +68 -0
  162. package/ios/split/RNSSplitScreenController.mm +113 -0
  163. package/ios/split/RNSSplitScreenShadowStateProxy.h +1 -40
  164. package/ios/split/RNSSplitScreenShadowStateProxy.mm +1 -26
  165. package/ios/split/conversion/RNSConversions-SplitView.h +56 -0
  166. package/ios/{conversion → split/conversion}/RNSConversions-SplitView.mm +4 -1
  167. package/ios/stack/conversion/RNSConversions-Stack.h +32 -0
  168. package/ios/stack/conversion/RNSConversions-Stack.mm +55 -0
  169. package/ios/stack/header/RNSStackHeaderAppearanceMapper.h +26 -0
  170. package/ios/stack/header/RNSStackHeaderAppearanceMapper.mm +88 -0
  171. package/ios/stack/header/RNSStackHeaderConfigComponentView.h +11 -1
  172. package/ios/stack/header/RNSStackHeaderConfigComponentView.mm +108 -38
  173. package/ios/stack/header/RNSStackHeaderConfigDataProviding.h +9 -0
  174. package/ios/stack/header/RNSStackHeaderConfigShadowStateProxy.mm +1 -1
  175. package/ios/stack/header/RNSStackHeaderIconResolver.mm +7 -0
  176. package/ios/stack/header/RNSStackHeaderItemComponentView.h +3 -1
  177. package/ios/stack/header/RNSStackHeaderItemComponentView.mm +15 -2
  178. package/ios/stack/header/RNSStackHeaderItemDataProviding.h +2 -0
  179. package/ios/stack/header/RNSStackHeaderItemShadowStateProxy.mm +1 -1
  180. package/ios/stack/header/RNSStackHeaderItemSpacerComponentView.mm +2 -1
  181. package/ios/stack/header/RNSStackHeaderMenuCoordinator.h +9 -0
  182. package/ios/stack/header/RNSStackHeaderMenuCoordinator.mm +15 -0
  183. package/ios/stack/header/RNSStackHeaderMenuFinder.h +18 -3
  184. package/ios/stack/header/RNSStackHeaderMenuFinder.mm +21 -3
  185. package/ios/stack/header/RNSStackHeaderMenuMapper.mm +4 -0
  186. package/ios/stack/host/RNSStackHostComponentView.mm +3 -1
  187. package/ios/stack/host/RNSStackNavigationBar.h +25 -0
  188. package/ios/stack/host/RNSStackNavigationBar.mm +80 -0
  189. package/ios/stack/host/RNSStackNavigationBarCoordinator.h +8 -0
  190. package/ios/stack/host/RNSStackNavigationBarCoordinator.mm +11 -0
  191. package/ios/stack/host/RNSStackNavigationController.mm +14 -6
  192. package/ios/stack/host/RNSStackOperation.h +0 -2
  193. package/ios/stack/screen/RNSStackScreenComponentView.mm +9 -4
  194. package/ios/stack/screen/RNSStackScreenController.mm +12 -0
  195. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.h +14 -1
  196. package/ios/stack/screen/RNSStackScreenHeaderCoordinator.mm +159 -28
  197. package/ios/tabs/RNSTabBarAppearanceCoordinator.mm +40 -9
  198. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h +1 -1
  199. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm +4 -1
  200. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm +5 -2
  201. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm +1 -1
  202. package/ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm +1 -1
  203. package/ios/tabs/conversion/RNSConversions-Tabs.h +78 -0
  204. package/ios/{conversion → tabs/conversion}/RNSConversions-Tabs.mm +8 -71
  205. package/ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h +1 -1
  206. package/ios/tabs/host/RNSTabBarController.h +5 -12
  207. package/ios/tabs/host/RNSTabBarController.mm +1 -1
  208. package/ios/tabs/host/RNSTabsHostComponentView.h +2 -0
  209. package/ios/tabs/host/RNSTabsHostComponentView.mm +10 -3
  210. package/ios/tabs/host/RNSTabsHostEventEmitter.mm +1 -1
  211. package/ios/tabs/screen/RNSTabsScreenComponentView.mm +20 -5
  212. package/ios/utils/RNSDefines.h +3 -0
  213. package/lib/commonjs/components/scroll-to-top-guard/ScrollToTopGuard.ios.js +25 -0
  214. package/lib/commonjs/components/scroll-to-top-guard/ScrollToTopGuard.ios.js.map +1 -0
  215. package/lib/commonjs/components/scroll-to-top-guard/ScrollToTopGuard.js +24 -0
  216. package/lib/commonjs/components/scroll-to-top-guard/ScrollToTopGuard.js.map +1 -0
  217. package/lib/commonjs/components/scroll-to-top-guard/index.js +13 -0
  218. package/lib/commonjs/components/scroll-to-top-guard/index.js.map +1 -0
  219. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js +34 -19
  220. package/lib/commonjs/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  221. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js +44 -13
  222. package/lib/commonjs/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  223. package/lib/commonjs/components/stack/header/ios/StackHeaderItem.ios.js +1 -22
  224. package/lib/commonjs/components/stack/header/ios/StackHeaderItem.ios.js.map +1 -1
  225. package/lib/commonjs/components/stack/header/ios/iconUtils.ios.js +33 -2
  226. package/lib/commonjs/components/stack/header/ios/iconUtils.ios.js.map +1 -1
  227. package/lib/commonjs/components/stack/header/utils.js +6 -9
  228. package/lib/commonjs/components/stack/header/utils.js.map +1 -1
  229. package/lib/commonjs/components/stack/host/StackHost.js +9 -6
  230. package/lib/commonjs/components/stack/host/StackHost.js.map +1 -1
  231. package/lib/commonjs/components/stack/index.js.map +1 -1
  232. package/lib/commonjs/components/tabs/host/TabsHost.ios.js +1 -0
  233. package/lib/commonjs/components/tabs/host/TabsHost.ios.js.map +1 -1
  234. package/lib/commonjs/experimental/index.js +11 -0
  235. package/lib/commonjs/experimental/index.js.map +1 -1
  236. package/lib/commonjs/fabric/ScrollViewMarkerNativeComponent.js.map +1 -1
  237. package/lib/commonjs/fabric/legacy/FullWindowOverlayNativeComponent.js.map +1 -1
  238. package/lib/commonjs/fabric/legacy/ModalScreenNativeComponent.js.map +1 -1
  239. package/lib/commonjs/fabric/legacy/ScreenContainerNativeComponent.js.map +1 -1
  240. package/lib/commonjs/fabric/legacy/ScreenFooterNativeComponent.js.map +1 -1
  241. package/lib/commonjs/fabric/legacy/ScreenNativeComponent.js.map +1 -1
  242. package/lib/commonjs/fabric/legacy/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  243. package/lib/commonjs/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  244. package/lib/commonjs/fabric/legacy/ScreenStackNativeComponent.js.map +1 -1
  245. package/lib/commonjs/fabric/legacy/SearchBarNativeComponent.js.map +1 -1
  246. package/lib/commonjs/fabric/modals/form-sheet/FormSheetHostNativeComponent.js.map +1 -1
  247. package/lib/commonjs/fabric/safe-area/SafeAreaViewNativeComponent.js.map +1 -1
  248. package/lib/commonjs/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.js +12 -0
  249. package/lib/commonjs/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.js.map +1 -0
  250. package/lib/commonjs/fabric/split/SplitHostNativeComponent.js.map +1 -1
  251. package/lib/commonjs/fabric/split/SplitScreenNativeComponent.js.map +1 -1
  252. package/lib/commonjs/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  253. package/lib/commonjs/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  254. package/lib/commonjs/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  255. package/lib/commonjs/fabric/stack/StackHeaderItemSpacerIOSNativeComponent.js.map +1 -1
  256. package/lib/commonjs/fabric/stack/StackHeaderSubviewAndroidNativeComponent.js.map +1 -1
  257. package/lib/commonjs/fabric/stack/StackHostNativeComponent.js.map +1 -1
  258. package/lib/commonjs/fabric/stack/StackScreenNativeComponent.js.map +1 -1
  259. package/lib/commonjs/fabric/tabs/TabsBottomAccessoryContentNativeComponent.js.map +1 -1
  260. package/lib/commonjs/fabric/tabs/TabsBottomAccessoryNativeComponent.js.map +1 -1
  261. package/lib/commonjs/fabric/tabs/TabsHostAndroidNativeComponent.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.map +1 -1
  265. package/lib/commonjs/flags.js +22 -1
  266. package/lib/commonjs/flags.js.map +1 -1
  267. package/lib/commonjs/legacy/components/Screen.js +6 -1
  268. package/lib/commonjs/legacy/components/Screen.js.map +1 -1
  269. package/lib/commonjs/legacy/components/ScreenStackHeaderConfig.js +5 -0
  270. package/lib/commonjs/legacy/components/ScreenStackHeaderConfig.js.map +1 -1
  271. package/lib/commonjs/legacy/components/ScreenStackItem.js.map +1 -1
  272. package/lib/commonjs/legacy/components/SearchBar.js +16 -16
  273. package/lib/commonjs/legacy/components/SearchBar.js.map +1 -1
  274. package/lib/commonjs/legacy/components/helpers/prepareHeaderBarButtonItems.js +3 -0
  275. package/lib/commonjs/legacy/components/helpers/prepareHeaderBarButtonItems.js.map +1 -1
  276. package/lib/commonjs/legacy/gesture-handler/fabricUtils.js.map +1 -1
  277. package/lib/commonjs/legacy/useTransitionProgress.js.map +1 -1
  278. package/lib/module/components/scroll-to-top-guard/ScrollToTopGuard.ios.js +20 -0
  279. package/lib/module/components/scroll-to-top-guard/ScrollToTopGuard.ios.js.map +1 -0
  280. package/lib/module/components/scroll-to-top-guard/ScrollToTopGuard.js +18 -0
  281. package/lib/module/components/scroll-to-top-guard/ScrollToTopGuard.js.map +1 -0
  282. package/lib/module/components/scroll-to-top-guard/index.js +2 -0
  283. package/lib/module/components/scroll-to-top-guard/index.js.map +1 -0
  284. package/lib/module/components/stack/header/StackHeaderConfig.android.js +35 -20
  285. package/lib/module/components/stack/header/StackHeaderConfig.android.js.map +1 -1
  286. package/lib/module/components/stack/header/StackHeaderConfig.ios.js +48 -17
  287. package/lib/module/components/stack/header/StackHeaderConfig.ios.js.map +1 -1
  288. package/lib/module/components/stack/header/ios/StackHeaderItem.ios.js +1 -22
  289. package/lib/module/components/stack/header/ios/StackHeaderItem.ios.js.map +1 -1
  290. package/lib/module/components/stack/header/ios/iconUtils.ios.js +31 -2
  291. package/lib/module/components/stack/header/ios/iconUtils.ios.js.map +1 -1
  292. package/lib/module/components/stack/header/utils.js +5 -8
  293. package/lib/module/components/stack/header/utils.js.map +1 -1
  294. package/lib/module/components/stack/host/StackHost.js +9 -6
  295. package/lib/module/components/stack/host/StackHost.js.map +1 -1
  296. package/lib/module/components/stack/index.js.map +1 -1
  297. package/lib/module/components/tabs/host/TabsHost.ios.js +1 -0
  298. package/lib/module/components/tabs/host/TabsHost.ios.js.map +1 -1
  299. package/lib/module/experimental/index.js +1 -0
  300. package/lib/module/experimental/index.js.map +1 -1
  301. package/lib/module/fabric/ScrollViewMarkerNativeComponent.js.map +1 -1
  302. package/lib/module/fabric/legacy/FullWindowOverlayNativeComponent.js.map +1 -1
  303. package/lib/module/fabric/legacy/ModalScreenNativeComponent.js.map +1 -1
  304. package/lib/module/fabric/legacy/ScreenContainerNativeComponent.js.map +1 -1
  305. package/lib/module/fabric/legacy/ScreenFooterNativeComponent.js.map +1 -1
  306. package/lib/module/fabric/legacy/ScreenNativeComponent.js.map +1 -1
  307. package/lib/module/fabric/legacy/ScreenStackHeaderConfigNativeComponent.js.map +1 -1
  308. package/lib/module/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.js.map +1 -1
  309. package/lib/module/fabric/legacy/ScreenStackNativeComponent.js.map +1 -1
  310. package/lib/module/fabric/legacy/SearchBarNativeComponent.js.map +1 -1
  311. package/lib/module/fabric/modals/form-sheet/FormSheetHostNativeComponent.js.map +1 -1
  312. package/lib/module/fabric/safe-area/SafeAreaViewNativeComponent.js.map +1 -1
  313. package/lib/module/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.js +7 -0
  314. package/lib/module/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.js.map +1 -0
  315. package/lib/module/fabric/split/SplitHostNativeComponent.js.map +1 -1
  316. package/lib/module/fabric/split/SplitScreenNativeComponent.js.map +1 -1
  317. package/lib/module/fabric/stack/StackHeaderConfigAndroidNativeComponent.js.map +1 -1
  318. package/lib/module/fabric/stack/StackHeaderConfigIOSNativeComponent.js.map +1 -1
  319. package/lib/module/fabric/stack/StackHeaderItemIOSNativeComponent.js.map +1 -1
  320. package/lib/module/fabric/stack/StackHeaderItemSpacerIOSNativeComponent.js.map +1 -1
  321. package/lib/module/fabric/stack/StackHeaderSubviewAndroidNativeComponent.js.map +1 -1
  322. package/lib/module/fabric/stack/StackHostNativeComponent.js.map +1 -1
  323. package/lib/module/fabric/stack/StackScreenNativeComponent.js.map +1 -1
  324. package/lib/module/fabric/tabs/TabsBottomAccessoryContentNativeComponent.js.map +1 -1
  325. package/lib/module/fabric/tabs/TabsBottomAccessoryNativeComponent.js.map +1 -1
  326. package/lib/module/fabric/tabs/TabsHostAndroidNativeComponent.js.map +1 -1
  327. package/lib/module/fabric/tabs/TabsHostIOSNativeComponent.js.map +1 -1
  328. package/lib/module/fabric/tabs/TabsScreenAndroidNativeComponent.js.map +1 -1
  329. package/lib/module/fabric/tabs/TabsScreenIOSNativeComponent.js.map +1 -1
  330. package/lib/module/flags.js +22 -1
  331. package/lib/module/flags.js.map +1 -1
  332. package/lib/module/legacy/components/Screen.js +6 -1
  333. package/lib/module/legacy/components/Screen.js.map +1 -1
  334. package/lib/module/legacy/components/ScreenStackHeaderConfig.js +5 -0
  335. package/lib/module/legacy/components/ScreenStackHeaderConfig.js.map +1 -1
  336. package/lib/module/legacy/components/ScreenStackItem.js.map +1 -1
  337. package/lib/module/legacy/components/SearchBar.js +17 -17
  338. package/lib/module/legacy/components/SearchBar.js.map +1 -1
  339. package/lib/module/legacy/components/helpers/prepareHeaderBarButtonItems.js +4 -0
  340. package/lib/module/legacy/components/helpers/prepareHeaderBarButtonItems.js.map +1 -1
  341. package/lib/module/legacy/gesture-handler/fabricUtils.js.map +1 -1
  342. package/lib/module/legacy/useTransitionProgress.js.map +1 -1
  343. package/lib/module/private/hooks/useRenderDebugInfo.js.map +1 -1
  344. package/lib/typescript/components/modals/form-sheet/FormSheet.types.d.ts +3 -3
  345. package/lib/typescript/components/safe-area/SafeAreaView.web.d.ts +5 -2
  346. package/lib/typescript/components/safe-area/SafeAreaView.web.d.ts.map +1 -1
  347. package/lib/typescript/components/scroll-to-top-guard/ScrollToTopGuard.d.ts +15 -0
  348. package/lib/typescript/components/scroll-to-top-guard/ScrollToTopGuard.d.ts.map +1 -0
  349. package/lib/typescript/components/scroll-to-top-guard/ScrollToTopGuard.ios.d.ts +12 -0
  350. package/lib/typescript/components/scroll-to-top-guard/ScrollToTopGuard.ios.d.ts.map +1 -0
  351. package/lib/typescript/components/scroll-to-top-guard/index.d.ts +2 -0
  352. package/lib/typescript/components/scroll-to-top-guard/index.d.ts.map +1 -0
  353. package/lib/typescript/components/stack/header/StackHeaderConfig.android.d.ts.map +1 -1
  354. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts +639 -20
  355. package/lib/typescript/components/stack/header/StackHeaderConfig.android.types.d.ts.map +1 -1
  356. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.d.ts.map +1 -1
  357. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts +239 -2
  358. package/lib/typescript/components/stack/header/StackHeaderConfig.ios.types.d.ts.map +1 -1
  359. package/lib/typescript/components/stack/header/StackHeaderConfig.types.d.ts +2 -2
  360. package/lib/typescript/components/stack/header/StackHeaderConfig.web.d.ts +5 -2
  361. package/lib/typescript/components/stack/header/StackHeaderConfig.web.d.ts.map +1 -1
  362. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.d.ts.map +1 -1
  363. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts +2 -0
  364. package/lib/typescript/components/stack/header/ios/StackHeaderItem.ios.types.d.ts.map +1 -1
  365. package/lib/typescript/components/stack/header/ios/iconUtils.ios.d.ts +3 -0
  366. package/lib/typescript/components/stack/header/ios/iconUtils.ios.d.ts.map +1 -1
  367. package/lib/typescript/components/stack/header/utils.d.ts +1 -2
  368. package/lib/typescript/components/stack/header/utils.d.ts.map +1 -1
  369. package/lib/typescript/components/stack/host/StackHost.d.ts +1 -1
  370. package/lib/typescript/components/stack/host/StackHost.d.ts.map +1 -1
  371. package/lib/typescript/components/stack/host/StackHost.types.d.ts +26 -2
  372. package/lib/typescript/components/stack/host/StackHost.types.d.ts.map +1 -1
  373. package/lib/typescript/components/stack/host/StackHost.web.d.ts +6 -2
  374. package/lib/typescript/components/stack/host/StackHost.web.d.ts.map +1 -1
  375. package/lib/typescript/components/stack/index.d.ts +2 -2
  376. package/lib/typescript/components/stack/index.d.ts.map +1 -1
  377. package/lib/typescript/components/stack/screen/StackScreen.web.d.ts +5 -2
  378. package/lib/typescript/components/stack/screen/StackScreen.web.d.ts.map +1 -1
  379. package/lib/typescript/components/tabs/host/TabsHost.ios.d.ts.map +1 -1
  380. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts +16 -0
  381. package/lib/typescript/components/tabs/host/TabsHost.ios.types.d.ts.map +1 -1
  382. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts +3 -0
  383. package/lib/typescript/components/tabs/host/TabsHost.types.d.ts.map +1 -1
  384. package/lib/typescript/components/tabs/host/TabsHost.web.d.ts +5 -2
  385. package/lib/typescript/components/tabs/host/TabsHost.web.d.ts.map +1 -1
  386. package/lib/typescript/components/tabs/screen/TabsScreen.types.d.ts +7 -3
  387. package/lib/typescript/components/tabs/screen/TabsScreen.types.d.ts.map +1 -1
  388. package/lib/typescript/components/tabs/screen/TabsScreen.web.d.ts +5 -2
  389. package/lib/typescript/components/tabs/screen/TabsScreen.web.d.ts.map +1 -1
  390. package/lib/typescript/experimental/index.d.ts +1 -0
  391. package/lib/typescript/experimental/index.d.ts.map +1 -1
  392. package/lib/typescript/fabric/NativeScreensModule.d.ts +1 -1
  393. package/lib/typescript/fabric/ScrollViewMarkerNativeComponent.d.ts +2 -2
  394. package/lib/typescript/fabric/ScrollViewMarkerNativeComponent.d.ts.map +1 -1
  395. package/lib/typescript/fabric/legacy/FullWindowOverlayNativeComponent.d.ts +2 -2
  396. package/lib/typescript/fabric/legacy/FullWindowOverlayNativeComponent.d.ts.map +1 -1
  397. package/lib/typescript/fabric/legacy/ModalScreenNativeComponent.d.ts +3 -2
  398. package/lib/typescript/fabric/legacy/ModalScreenNativeComponent.d.ts.map +1 -1
  399. package/lib/typescript/fabric/legacy/ScreenContainerNativeComponent.d.ts +2 -2
  400. package/lib/typescript/fabric/legacy/ScreenContainerNativeComponent.d.ts.map +1 -1
  401. package/lib/typescript/fabric/legacy/ScreenContentWrapperNativeComponent.d.ts +2 -2
  402. package/lib/typescript/fabric/legacy/ScreenContentWrapperNativeComponent.d.ts.map +1 -1
  403. package/lib/typescript/fabric/legacy/ScreenFooterNativeComponent.d.ts +2 -2
  404. package/lib/typescript/fabric/legacy/ScreenFooterNativeComponent.d.ts.map +1 -1
  405. package/lib/typescript/fabric/legacy/ScreenNativeComponent.d.ts +3 -2
  406. package/lib/typescript/fabric/legacy/ScreenNativeComponent.d.ts.map +1 -1
  407. package/lib/typescript/fabric/legacy/ScreenNavigationContainerNativeComponent.d.ts +2 -2
  408. package/lib/typescript/fabric/legacy/ScreenNavigationContainerNativeComponent.d.ts.map +1 -1
  409. package/lib/typescript/fabric/legacy/ScreenStackHeaderConfigNativeComponent.d.ts +3 -3
  410. package/lib/typescript/fabric/legacy/ScreenStackHeaderConfigNativeComponent.d.ts.map +1 -1
  411. package/lib/typescript/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.d.ts +2 -2
  412. package/lib/typescript/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.d.ts.map +1 -1
  413. package/lib/typescript/fabric/legacy/ScreenStackNativeComponent.d.ts +2 -2
  414. package/lib/typescript/fabric/legacy/ScreenStackNativeComponent.d.ts.map +1 -1
  415. package/lib/typescript/fabric/legacy/SearchBarNativeComponent.d.ts +6 -6
  416. package/lib/typescript/fabric/legacy/SearchBarNativeComponent.d.ts.map +1 -1
  417. package/lib/typescript/fabric/modals/form-sheet/FormSheetContentWrapperNativeComponent.d.ts +2 -2
  418. package/lib/typescript/fabric/modals/form-sheet/FormSheetContentWrapperNativeComponent.d.ts.map +1 -1
  419. package/lib/typescript/fabric/modals/form-sheet/FormSheetHostNativeComponent.d.ts +2 -2
  420. package/lib/typescript/fabric/modals/form-sheet/FormSheetHostNativeComponent.d.ts.map +1 -1
  421. package/lib/typescript/fabric/safe-area/SafeAreaViewNativeComponent.d.ts +2 -2
  422. package/lib/typescript/fabric/safe-area/SafeAreaViewNativeComponent.d.ts.map +1 -1
  423. package/lib/typescript/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.d.ts +6 -0
  424. package/lib/typescript/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.d.ts.map +1 -0
  425. package/lib/typescript/fabric/split/SplitHostNativeComponent.d.ts +1 -1
  426. package/lib/typescript/fabric/split/SplitHostNativeComponent.d.ts.map +1 -1
  427. package/lib/typescript/fabric/split/SplitScreenNativeComponent.d.ts +2 -2
  428. package/lib/typescript/fabric/split/SplitScreenNativeComponent.d.ts.map +1 -1
  429. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts +53 -0
  430. package/lib/typescript/fabric/stack/StackHeaderConfigAndroidNativeComponent.d.ts.map +1 -1
  431. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts +27 -2
  432. package/lib/typescript/fabric/stack/StackHeaderConfigIOSNativeComponent.d.ts.map +1 -1
  433. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts +4 -2
  434. package/lib/typescript/fabric/stack/StackHeaderItemIOSNativeComponent.d.ts.map +1 -1
  435. package/lib/typescript/fabric/stack/StackHeaderItemSpacerIOSNativeComponent.d.ts +2 -2
  436. package/lib/typescript/fabric/stack/StackHeaderItemSpacerIOSNativeComponent.d.ts.map +1 -1
  437. package/lib/typescript/fabric/stack/StackHeaderSubviewAndroidNativeComponent.d.ts +2 -2
  438. package/lib/typescript/fabric/stack/StackHeaderSubviewAndroidNativeComponent.d.ts.map +1 -1
  439. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts +4 -2
  440. package/lib/typescript/fabric/stack/StackHostNativeComponent.d.ts.map +1 -1
  441. package/lib/typescript/fabric/stack/StackScreenNativeComponent.d.ts +2 -2
  442. package/lib/typescript/fabric/stack/StackScreenNativeComponent.d.ts.map +1 -1
  443. package/lib/typescript/fabric/tabs/TabsBottomAccessoryContentNativeComponent.d.ts +2 -2
  444. package/lib/typescript/fabric/tabs/TabsBottomAccessoryContentNativeComponent.d.ts.map +1 -1
  445. package/lib/typescript/fabric/tabs/TabsBottomAccessoryNativeComponent.d.ts +2 -2
  446. package/lib/typescript/fabric/tabs/TabsBottomAccessoryNativeComponent.d.ts.map +1 -1
  447. package/lib/typescript/fabric/tabs/TabsHostAndroidNativeComponent.d.ts +2 -2
  448. package/lib/typescript/fabric/tabs/TabsHostAndroidNativeComponent.d.ts.map +1 -1
  449. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts +3 -2
  450. package/lib/typescript/fabric/tabs/TabsHostIOSNativeComponent.d.ts.map +1 -1
  451. package/lib/typescript/fabric/tabs/TabsScreenAndroidNativeComponent.d.ts +2 -2
  452. package/lib/typescript/fabric/tabs/TabsScreenAndroidNativeComponent.d.ts.map +1 -1
  453. package/lib/typescript/fabric/tabs/TabsScreenIOSNativeComponent.d.ts +2 -2
  454. package/lib/typescript/fabric/tabs/TabsScreenIOSNativeComponent.d.ts.map +1 -1
  455. package/lib/typescript/flags.d.ts +13 -0
  456. package/lib/typescript/flags.d.ts.map +1 -1
  457. package/lib/typescript/legacy/TransitionProgressContext.d.ts +1 -1
  458. package/lib/typescript/legacy/TransitionProgressContext.d.ts.map +1 -1
  459. package/lib/typescript/legacy/components/Screen.d.ts +5 -3
  460. package/lib/typescript/legacy/components/Screen.d.ts.map +1 -1
  461. package/lib/typescript/legacy/components/Screen.web.d.ts +10 -2
  462. package/lib/typescript/legacy/components/Screen.web.d.ts.map +1 -1
  463. package/lib/typescript/legacy/components/ScreenContainer.web.d.ts +5 -2
  464. package/lib/typescript/legacy/components/ScreenContainer.web.d.ts.map +1 -1
  465. package/lib/typescript/legacy/components/ScreenContentWrapper.web.d.ts +5 -2
  466. package/lib/typescript/legacy/components/ScreenContentWrapper.web.d.ts.map +1 -1
  467. package/lib/typescript/legacy/components/ScreenContentWrapper.windows.d.ts +5 -2
  468. package/lib/typescript/legacy/components/ScreenContentWrapper.windows.d.ts.map +1 -1
  469. package/lib/typescript/legacy/components/ScreenFooter.web.d.ts +10 -3
  470. package/lib/typescript/legacy/components/ScreenFooter.web.d.ts.map +1 -1
  471. package/lib/typescript/legacy/components/ScreenFooter.windows.d.ts +10 -3
  472. package/lib/typescript/legacy/components/ScreenFooter.windows.d.ts.map +1 -1
  473. package/lib/typescript/legacy/components/ScreenStack.web.d.ts +5 -2
  474. package/lib/typescript/legacy/components/ScreenStack.web.d.ts.map +1 -1
  475. package/lib/typescript/legacy/components/ScreenStackHeaderConfig.d.ts +3 -1
  476. package/lib/typescript/legacy/components/ScreenStackHeaderConfig.d.ts.map +1 -1
  477. package/lib/typescript/legacy/components/ScreenStackItem.d.ts +3 -2
  478. package/lib/typescript/legacy/components/ScreenStackItem.d.ts.map +1 -1
  479. package/lib/typescript/legacy/components/SearchBar.d.ts +3 -3
  480. package/lib/typescript/legacy/components/SearchBar.d.ts.map +1 -1
  481. package/lib/typescript/legacy/components/SearchBar.web.d.ts +5 -2
  482. package/lib/typescript/legacy/components/SearchBar.web.d.ts.map +1 -1
  483. package/lib/typescript/legacy/components/helpers/prepareHeaderBarButtonItems.d.ts +15 -12
  484. package/lib/typescript/legacy/components/helpers/prepareHeaderBarButtonItems.d.ts.map +1 -1
  485. package/lib/typescript/legacy/gesture-handler/fabricUtils.d.ts +3 -2
  486. package/lib/typescript/legacy/gesture-handler/fabricUtils.d.ts.map +1 -1
  487. package/lib/typescript/legacy/types.d.ts +25 -5
  488. package/lib/typescript/legacy/types.d.ts.map +1 -1
  489. package/lib/typescript/legacy/useTransitionProgress.d.ts +2 -5
  490. package/lib/typescript/legacy/useTransitionProgress.d.ts.map +1 -1
  491. package/lib/typescript/private/hooks/useRenderDebugInfo.d.ts +2 -2
  492. package/lib/typescript/private/hooks/useRenderDebugInfo.d.ts.map +1 -1
  493. package/package.json +18 -17
  494. package/react-native.config.js +3 -0
  495. package/src/components/modals/form-sheet/FormSheet.types.ts +3 -3
  496. package/src/components/scroll-to-top-guard/ScrollToTopGuard.ios.tsx +17 -0
  497. package/src/components/scroll-to-top-guard/ScrollToTopGuard.tsx +18 -0
  498. package/src/components/scroll-to-top-guard/index.ts +1 -0
  499. package/src/components/stack/header/StackHeaderConfig.android.tsx +48 -23
  500. package/src/components/stack/header/StackHeaderConfig.android.types.ts +660 -20
  501. package/src/components/stack/header/StackHeaderConfig.ios.tsx +77 -23
  502. package/src/components/stack/header/StackHeaderConfig.ios.types.ts +251 -2
  503. package/src/components/stack/header/StackHeaderConfig.types.ts +2 -2
  504. package/src/components/stack/header/ios/StackHeaderItem.ios.tsx +1 -23
  505. package/src/components/stack/header/ios/StackHeaderItem.ios.types.ts +2 -0
  506. package/src/components/stack/header/ios/iconUtils.ios.ts +38 -2
  507. package/src/components/stack/header/utils.ts +6 -11
  508. package/src/components/stack/host/StackHost.tsx +4 -2
  509. package/src/components/stack/host/StackHost.types.ts +28 -4
  510. package/src/components/stack/index.ts +6 -1
  511. package/src/components/tabs/host/TabsHost.ios.tsx +1 -0
  512. package/src/components/tabs/host/TabsHost.ios.types.ts +16 -0
  513. package/src/components/tabs/host/TabsHost.types.ts +3 -0
  514. package/src/components/tabs/screen/TabsScreen.types.ts +7 -3
  515. package/src/experimental/index.ts +1 -0
  516. package/src/fabric/ScrollViewMarkerNativeComponent.ts +8 -2
  517. package/src/fabric/legacy/FullWindowOverlayNativeComponent.ts +6 -2
  518. package/src/fabric/legacy/ModalScreenNativeComponent.ts +8 -2
  519. package/src/fabric/legacy/ScreenContainerNativeComponent.ts +5 -2
  520. package/src/fabric/legacy/ScreenContentWrapperNativeComponent.ts +2 -2
  521. package/src/fabric/legacy/ScreenFooterNativeComponent.ts +5 -2
  522. package/src/fabric/legacy/ScreenNativeComponent.ts +8 -2
  523. package/src/fabric/legacy/ScreenNavigationContainerNativeComponent.ts +2 -2
  524. package/src/fabric/legacy/ScreenStackHeaderConfigNativeComponent.ts +8 -3
  525. package/src/fabric/legacy/ScreenStackHeaderSubviewNativeComponent.ts +6 -2
  526. package/src/fabric/legacy/ScreenStackNativeComponent.ts +10 -2
  527. package/src/fabric/legacy/SearchBarNativeComponent.ts +10 -7
  528. package/src/fabric/modals/form-sheet/FormSheetContentWrapperNativeComponent.ts +2 -2
  529. package/src/fabric/modals/form-sheet/FormSheetHostNativeComponent.ts +7 -2
  530. package/src/fabric/safe-area/SafeAreaViewNativeComponent.ts +6 -2
  531. package/src/fabric/scroll-to-top-guard/ScrollToTopGuardNativeComponent.ts +10 -0
  532. package/src/fabric/split/SplitHostNativeComponent.ts +5 -2
  533. package/src/fabric/split/SplitScreenNativeComponent.ts +6 -2
  534. package/src/fabric/stack/StackHeaderConfigAndroidNativeComponent.ts +81 -1
  535. package/src/fabric/stack/StackHeaderConfigIOSNativeComponent.ts +39 -2
  536. package/src/fabric/stack/StackHeaderItemIOSNativeComponent.ts +4 -1
  537. package/src/fabric/stack/StackHeaderItemSpacerIOSNativeComponent.ts +6 -2
  538. package/src/fabric/stack/StackHeaderSubviewAndroidNativeComponent.ts +6 -2
  539. package/src/fabric/stack/StackHostNativeComponent.ts +15 -3
  540. package/src/fabric/stack/StackScreenNativeComponent.ts +6 -2
  541. package/src/fabric/tabs/TabsBottomAccessoryContentNativeComponent.ts +6 -2
  542. package/src/fabric/tabs/TabsBottomAccessoryNativeComponent.ts +6 -2
  543. package/src/fabric/tabs/TabsHostAndroidNativeComponent.ts +7 -2
  544. package/src/fabric/tabs/TabsHostIOSNativeComponent.ts +8 -2
  545. package/src/fabric/tabs/TabsScreenAndroidNativeComponent.ts +2 -1
  546. package/src/fabric/tabs/TabsScreenIOSNativeComponent.ts +2 -1
  547. package/src/flags.ts +26 -0
  548. package/src/legacy/TransitionProgressContext.tsx +1 -1
  549. package/src/legacy/components/Screen.tsx +14 -6
  550. package/src/legacy/components/ScreenStackHeaderConfig.tsx +7 -1
  551. package/src/legacy/components/ScreenStackItem.tsx +3 -4
  552. package/src/legacy/components/SearchBar.tsx +34 -44
  553. package/src/legacy/components/helpers/prepareHeaderBarButtonItems.ts +7 -1
  554. package/src/legacy/gesture-handler/fabricUtils.ts +5 -2
  555. package/src/legacy/types.ts +28 -5
  556. package/src/legacy/useTransitionProgress.tsx +4 -2
  557. package/src/private/hooks/useRenderDebugInfo.tsx +2 -2
  558. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingView.kt +0 -83
  559. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewManager.kt +0 -89
  560. package/android/src/main/java/com/swmansion/rnscreens/modals/dimmingview/DimmingViewPointerEvents.kt +0 -18
  561. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetDetents.kt +0 -106
  562. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetDialog.kt +0 -60
  563. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetDialogManager.kt +0 -138
  564. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetDimensionsCoordinator.kt +0 -131
  565. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetNativeDismissCoordinator.kt +0 -25
  566. package/android/src/main/java/com/swmansion/rnscreens/modals/formsheet/FormSheetPresentationManager.kt +0 -207
  567. package/android/src/main/java/com/swmansion/rnscreens/stack/header/StackHeaderAppBarLayout.kt +0 -113
  568. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuConfig.kt +0 -60
  569. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuElementOptions.kt +0 -32
  570. package/android/src/main/java/com/swmansion/rnscreens/stack/header/toolbar/StackHeaderToolbarMenuGroupMetadata.kt +0 -16
  571. package/ios/ReactMountingTransactionObserving.swift +0 -7
  572. package/ios/bridging/Swift-Bridging.h +0 -7
  573. package/ios/conversion/RNSConversions-Stack.h +0 -32
  574. package/ios/conversion/RNSConversions-Stack.mm +0 -41
  575. package/ios/conversion/always_false.h +0 -31
  576. package/ios/orientation/RNSOrientationProviding.swift +0 -6
  577. package/ios/orientation/RNSOrientationSwift.swift +0 -14
  578. package/ios/split/RNSSplitAppearanceApplicator.swift +0 -199
  579. package/ios/split/RNSSplitAppearanceCoordinator.swift +0 -26
  580. package/ios/split/RNSSplitAppearanceUpdateFlags.swift +0 -11
  581. package/ios/split/RNSSplitHostController.swift +0 -570
  582. package/ios/split/RNSSplitNavigationController.swift +0 -46
  583. package/ios/split/RNSSplitScreenController.swift +0 -133
  584. package/ios/utils/RNSLog.swift +0 -6
  585. /package/ios/{conversion → scroll-view-marker/conversion}/RNSConversions-ScrollViewMarker.h +0 -0
@@ -0,0 +1,195 @@
1
+ package com.swmansion.rnscreens.stack.header.toolbar
2
+
3
+ import android.content.res.ColorStateList
4
+ import android.graphics.drawable.Drawable
5
+ import android.os.Build
6
+ import android.util.Log
7
+ import android.view.Menu
8
+ import android.view.MenuItem
9
+ import androidx.core.view.MenuItemCompat
10
+ import com.google.android.material.appbar.MaterialToolbar
11
+ import com.swmansion.rnscreens.stack.header.getResizedDrawable
12
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuConfig
13
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuElementConfig
14
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuGroupConfig
15
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuModel
16
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarFieldUpdate
17
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuElementOptions
18
+ import com.swmansion.rnscreens.stack.header.toolbar.update.valueOrNull
19
+
20
+ /**
21
+ * Writes onto the android Menu: builds the toolbar menu from its model and
22
+ * applies in-place element updates (options, checkability, icon tint).
23
+ */
24
+ internal object StackHeaderToolbarMenuApplicator {
25
+ // region Menu build
26
+
27
+ internal fun rebuildToolbarMenu(
28
+ toolbar: MaterialToolbar,
29
+ model: StackHeaderToolbarMenuModel,
30
+ groupDividerEnabled: Boolean,
31
+ optionsForItem: (id: String) -> StackHeaderToolbarMenuElementOptions,
32
+ onItemClicked: (id: String) -> Unit,
33
+ ) {
34
+ toolbar.menu.clear()
35
+ addElements(toolbar, toolbar.menu, model.config, model.forwardIdMap, model.forwardGroupIdMap, optionsForItem)
36
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
37
+ toolbar.menu.setGroupDividerEnabled(groupDividerEnabled)
38
+ }
39
+ toolbar.setOnMenuItemClickListener { menuItem ->
40
+ model.reverseIdMap[menuItem.itemId]?.let(onItemClicked)
41
+ true
42
+ }
43
+ }
44
+
45
+ private fun addElements(
46
+ toolbar: MaterialToolbar,
47
+ menu: Menu,
48
+ menuConfig: StackHeaderToolbarMenuConfig,
49
+ forwardIdMap: Map<String, Int>,
50
+ forwardGroupIdMap: Map<String, Int>,
51
+ optionsForItem: (id: String) -> StackHeaderToolbarMenuElementOptions,
52
+ ) {
53
+ menuConfig.children.forEachIndexed { index, element ->
54
+ val itemId =
55
+ requireNotNull(forwardIdMap[element.item.id]) {
56
+ "[RNScreens] Invalid forwardIdMap received. Missing item: ${element.item}."
57
+ }
58
+ val groupIntId =
59
+ element.item.groupId
60
+ ?.let { forwardGroupIdMap[it] ?: Menu.NONE }
61
+ ?: Menu.NONE
62
+ when (element) {
63
+ is StackHeaderToolbarMenuElementConfig.MenuItem -> {
64
+ val menuItem = menu.add(groupIntId, itemId, index, null)
65
+ applyMenuElementOptions(toolbar, menuItem, optionsForItem(element.item.id))
66
+ }
67
+ is StackHeaderToolbarMenuElementConfig.Submenu -> {
68
+ val subMenu = menu.addSubMenu(groupIntId, itemId, index, null)
69
+ applyMenuElementOptions(toolbar, subMenu.item, optionsForItem(element.item.id))
70
+ addElements(toolbar, subMenu, element.menu, forwardIdMap, forwardGroupIdMap, optionsForItem)
71
+ }
72
+ }
73
+ }
74
+ configureGroupCheckability(menu, menuConfig.groups, forwardGroupIdMap)
75
+ }
76
+
77
+ // Group membership is the only source of checkability (configs are validated
78
+ // up front, see StackHeaderToolbarMenuModel); checked state belongs to the
79
+ // controller, which projects it right after the rebuild.
80
+ private fun configureGroupCheckability(
81
+ menu: Menu,
82
+ groups: List<StackHeaderToolbarMenuGroupConfig>,
83
+ forwardGroupIdMap: Map<String, Int>,
84
+ ) {
85
+ for (group in groups) {
86
+ val groupIntId = forwardGroupIdMap[group.groupId] ?: continue
87
+ menu.setGroupCheckable(groupIntId, true, group.singleSelection)
88
+ }
89
+ }
90
+
91
+ // endregion
92
+
93
+ // region Element updates
94
+
95
+ internal fun updateToolbarMenuElement(
96
+ toolbar: MaterialToolbar,
97
+ forwardIdMap: Map<String, Int>,
98
+ id: String,
99
+ options: StackHeaderToolbarMenuElementOptions,
100
+ ) {
101
+ val item =
102
+ forwardIdMap[id]?.let { toolbar.menu.findItem(it) } ?: run {
103
+ Log.e(TAG, "[RNScreens] Unable to find menu element with id '$id'.")
104
+ return
105
+ }
106
+ applyMenuElementOptions(toolbar, item, options)
107
+ }
108
+
109
+ private fun applyMenuElementOptions(
110
+ toolbar: MaterialToolbar,
111
+ menuItem: MenuItem,
112
+ options: StackHeaderToolbarMenuElementOptions,
113
+ ) {
114
+ options.title?.let { menuItem.title = it.valueOrNull() }
115
+ options.titleCondensed?.let { menuItem.titleCondensed = it.valueOrNull() }
116
+ options.tooltipText?.let { MenuItemCompat.setTooltipText(menuItem, it.valueOrNull()) }
117
+ options.accessibilityLabel?.let {
118
+ // Setting `null` will restore Android's default (`title` for items
119
+ // in toolbar, `null` otherwise).
120
+ MenuItemCompat.setContentDescription(menuItem, it.valueOrNull())
121
+ }
122
+ options.hidden?.let { menuItem.isVisible = !it }
123
+ options.disabled?.let { menuItem.isEnabled = !it }
124
+
125
+ options.icon?.let {
126
+ when (it) {
127
+ StackHeaderToolbarFieldUpdate.Reset -> menuItem.icon = null
128
+ is StackHeaderToolbarFieldUpdate.Set<Drawable> ->
129
+ menuItem.icon = getResizedDrawable(toolbar, it.value)
130
+ }
131
+ }
132
+
133
+ // The tint list is built absolutely from the given fields, so whenever
134
+ // this branch runs the caller must pass all four tint slots resolved
135
+ // (Set/Reset) — see StackHeaderToolbarMenuController.effectiveOptions.
136
+ if (options.requiresIconTintColorUpdate || options.icon != null) {
137
+ MenuItemCompat.setIconTintList(menuItem, buildIconTintList(options))
138
+ }
139
+
140
+ options.menuTitle?.let { update ->
141
+ val subMenu = menuItem.subMenu
142
+ if (subMenu != null) {
143
+ // In order to match native behavior, we need to clear the header first and then use
144
+ // regular title if menuTitle is not provided. If title is also null, there will be
145
+ // no submenu header at all.
146
+ subMenu.clearHeader()
147
+ subMenu.setHeaderTitle(update.valueOrNull() ?: menuItem.title)
148
+ } else {
149
+ Log.w(TAG, "[RNScreens] menuTitle ignored: target is not a submenu.")
150
+ }
151
+ }
152
+
153
+ // Apply showAsAction property after icon is set to ensure correct overflow behavior.
154
+ options.showAsAction?.let { menuItem.setShowAsAction(it.toNativeShowAsAction()) }
155
+ }
156
+
157
+ // endregion
158
+
159
+ // region Icon tint
160
+
161
+ private fun buildIconTintList(options: StackHeaderToolbarMenuElementOptions): ColorStateList? {
162
+ val states = mutableListOf<IntArray>()
163
+ val colors = mutableListOf<Int>()
164
+
165
+ options.iconTintColorDisabled?.valueOrNull()?.let {
166
+ states.add(intArrayOf(-android.R.attr.state_enabled))
167
+ colors.add(it)
168
+ }
169
+
170
+ options.iconTintColorPressed?.valueOrNull()?.let {
171
+ states.add(intArrayOf(android.R.attr.state_pressed))
172
+ colors.add(it)
173
+ }
174
+
175
+ options.iconTintColorFocused?.valueOrNull()?.let {
176
+ states.add(intArrayOf(android.R.attr.state_focused))
177
+ colors.add(it)
178
+ }
179
+
180
+ options.iconTintColorNormal?.valueOrNull()?.let {
181
+ states.add(intArrayOf())
182
+ colors.add(it)
183
+ }
184
+
185
+ return if (states.isNotEmpty()) {
186
+ ColorStateList(states.toTypedArray(), colors.toIntArray())
187
+ } else {
188
+ null
189
+ }
190
+ }
191
+
192
+ // endregion
193
+
194
+ private const val TAG = "StackHeaderToolbarMenuApplicator"
195
+ }
@@ -0,0 +1,448 @@
1
+ package com.swmansion.rnscreens.stack.header.toolbar
2
+
3
+ import android.graphics.drawable.Drawable
4
+ import android.util.Log
5
+ import android.view.MenuItem
6
+ import com.google.android.material.appbar.MaterialToolbar
7
+ import com.swmansion.rnscreens.helpers.IconResolution
8
+ import com.swmansion.rnscreens.helpers.PropIconResolver
9
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuConfig
10
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuElementConfig
11
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuItemIconSource
12
+ import com.swmansion.rnscreens.stack.header.toolbar.model.StackHeaderToolbarMenuModel
13
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarFieldUpdate
14
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuElementOptions
15
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuElementRawUpdate
16
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuElementUpdate
17
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuIconResolver
18
+ import com.swmansion.rnscreens.stack.header.toolbar.update.StackHeaderToolbarMenuUpdateQueue
19
+ import com.swmansion.rnscreens.stack.header.toolbar.update.toOptions
20
+ import java.lang.ref.WeakReference
21
+
22
+ /**
23
+ * Owns the toolbar menu: the parsed model and the runtime state accumulated on
24
+ * top of it (imperative element updates, group selections, resolved prop
25
+ * icons). The state is the source of truth and lives as long as this
26
+ * controller; an attached toolbar is merely a projection of it, rebuilt from
27
+ * scratch at every [attach]. Checked-state semantics run on the state, so
28
+ * updates behave identically whether a toolbar is attached or not.
29
+ */
30
+ internal class StackHeaderToolbarMenuController(
31
+ private val iconResolver: StackHeaderToolbarMenuIconResolver,
32
+ ) {
33
+ internal var delegate: WeakReference<StackHeaderToolbarMenuDelegate>? = null
34
+
35
+ // region Model
36
+
37
+ private var model = StackHeaderToolbarMenuModel.EMPTY
38
+ private var groupDividerEnabled = false
39
+
40
+ // Set by a menu change and cleared by [attach]: until then a live toolbar
41
+ // still shows the previous menu (with previous int ids), so in-place
42
+ // application is suspended and updates are recorded only.
43
+ private var modelDirty = false
44
+
45
+ /**
46
+ * Replaces the menu configuration. Returns `true` when it actually
47
+ * changed; icon sources are part of the config, so an icon-source-only
48
+ * prop change counts. A real change validates the new menu, resets all
49
+ * runtime state, re-initializes group selections from
50
+ * `initialToggleState` and drops pending command batches. Application to
51
+ * the toolbar is the caller's responsibility (via [attach]).
52
+ */
53
+ internal fun setMenu(menu: StackHeaderToolbarMenuConfig): Boolean {
54
+ if (menu == model.config) {
55
+ return false
56
+ }
57
+
58
+ // Throws on an invalid menu before any mutation, so the previous,
59
+ // valid model stays intact.
60
+ model = StackHeaderToolbarMenuModel.from(menu)
61
+
62
+ commandOverrides.clear()
63
+ propIcons.keys.retainAll(model.elementById.keys)
64
+ propIconResolvers.keys.retainAll(model.elementById.keys)
65
+ groupSelections =
66
+ model.groupMetadata.groupMemberItems
67
+ .mapValues { (_, members) ->
68
+ members.filterTo(mutableSetOf()) {
69
+ model.elementById
70
+ .getValue(it)
71
+ .item.initialToggleState
72
+ }
73
+ }.toMutableMap()
74
+
75
+ // Commands sent against the previous menu must not touch the new one,
76
+ // even those still waiting for an icon.
77
+ updateQueue.clearPending()
78
+
79
+ modelDirty = true
80
+ resolvePropIcons()
81
+ return true
82
+ }
83
+
84
+ /** Returns `true` when the value changed and the menu needs a rebuild. */
85
+ internal fun setGroupDividerEnabled(enabled: Boolean): Boolean {
86
+ if (groupDividerEnabled == enabled) {
87
+ return false
88
+ }
89
+ groupDividerEnabled = enabled
90
+ return true
91
+ }
92
+
93
+ // endregion
94
+
95
+ // region State
96
+
97
+ // Resolved icons of prop-declared items, and the stateful per-item
98
+ // resolvers behind them; both pruned in [setMenu].
99
+ private val propIcons = mutableMapOf<String, Drawable>()
100
+ private val propIconResolvers = mutableMapOf<String, PropIconResolver>()
101
+
102
+ // Accumulated imperative element updates, merged field-wise (newer
103
+ // non-null wins). `checked` never reaches here — it travels on the update
104
+ // envelope and group selections are its single home.
105
+ private val commandOverrides = mutableMapOf<String, StackHeaderToolbarMenuElementOptions>()
106
+
107
+ // Fully materialized selection per group. Initialized from
108
+ // `initialToggleState` at [setMenu], mutated by taps and command `checked`.
109
+ private var groupSelections = mutableMapOf<String, MutableSet<String>>()
110
+
111
+ // endregion
112
+
113
+ // region Imperative updates
114
+
115
+ // Serial, batch-atomic command ingestion; owned here so a menu change can
116
+ // drop stale batches locally (see setMenu).
117
+ private val updateQueue =
118
+ StackHeaderToolbarMenuUpdateQueue(iconResolver) { applyElementUpdates(it) }
119
+
120
+ /**
121
+ * Enqueues an `updateToolbarMenuElements` batch. Batches apply serially
122
+ * and atomically, once every icon in the batch has resolved — see
123
+ * [StackHeaderToolbarMenuUpdateQueue].
124
+ */
125
+ internal fun enqueueElementUpdates(batch: List<StackHeaderToolbarMenuElementRawUpdate>) {
126
+ updateQueue.enqueue(batch)
127
+ }
128
+
129
+ /**
130
+ * Applies a fully resolved `updateToolbarMenuElements` batch: records it,
131
+ * runs checked-state transitions on the state, projects onto the live
132
+ * toolbar when one is attached, and emits one coalesced selection event per
133
+ * changed group — identically whether attached or not.
134
+ */
135
+ private fun applyElementUpdates(updates: List<StackHeaderToolbarMenuElementUpdate>) {
136
+ val changedGroups = LinkedHashSet<String>()
137
+ val toolbar = liveToolbar()
138
+
139
+ for (update in updates) {
140
+ val id = update.id
141
+ if (id !in model.elementById) {
142
+ Log.w(TAG, "[RNScreens] Ignoring toolbar menu update for unknown item id '$id'.")
143
+ continue
144
+ }
145
+
146
+ val options = applicableOptions(id, update.options)
147
+
148
+ if (!options.isEmpty) {
149
+ commandOverrides[id] = commandOverrides[id]?.mergedWith(options) ?: options
150
+ }
151
+
152
+ update.checked?.let { checked ->
153
+ applyCheckedInState(id, checked)?.let(changedGroups::add)
154
+ }
155
+
156
+ if (toolbar != null && !options.isEmpty) {
157
+ StackHeaderToolbarMenuApplicator.updateToolbarMenuElement(
158
+ toolbar,
159
+ model.forwardIdMap,
160
+ id,
161
+ widenWithCoupledFields(id, options),
162
+ )
163
+ }
164
+ }
165
+
166
+ if (toolbar != null) {
167
+ changedGroups.forEach { applySelectionToToolbar(toolbar, it) }
168
+ }
169
+ changedGroups.forEach(::emitGroupSelection)
170
+ }
171
+
172
+ /**
173
+ * Drops options the target element cannot accept. They would otherwise be
174
+ * recorded in [commandOverrides], which outlive every rebuild, and be
175
+ * re-applied — and re-warned about — by each of them.
176
+ */
177
+ private fun applicableOptions(
178
+ id: String,
179
+ options: StackHeaderToolbarMenuElementOptions,
180
+ ): StackHeaderToolbarMenuElementOptions {
181
+ val targetsSubmenu = model.elementById[id] is StackHeaderToolbarMenuElementConfig.Submenu
182
+ if (options.menuTitle == null || targetsSubmenu) {
183
+ return options
184
+ }
185
+ Log.w(TAG, "[RNScreens] Ignoring menuTitle of '$id': the target is not a submenu.")
186
+ return options.copy(menuTitle = null)
187
+ }
188
+
189
+ // endregion
190
+
191
+ // region Prop icons
192
+
193
+ /**
194
+ * Re-resolves every prop-declared icon source; called on a menu change —
195
+ * the only time sources can change. Results flow through [setItemIcon]:
196
+ * while the menu is dirty (until the next [attach]) they land in state
197
+ * only, later async ones also apply to the live toolbar in place.
198
+ */
199
+ private fun resolvePropIcons() {
200
+ model.elementById.forEach { (id, element) ->
201
+ val source = element.item.iconSource
202
+ // An escaping exception would leave the menu dirty forever, with
203
+ // in-place application suspended until the next [attach].
204
+ try {
205
+ propIconResolvers
206
+ .getOrPut(id) {
207
+ PropIconResolver { name, uri, onComplete ->
208
+ iconResolver.resolve(
209
+ StackHeaderToolbarMenuItemIconSource(name, uri),
210
+ onComplete,
211
+ )
212
+ }
213
+ }.resolve(source.drawableIconResourceName, source.imageIconUri) { result ->
214
+ when (result) {
215
+ IconResolution.Unchanged -> Unit
216
+ is IconResolution.Resolved -> setItemIcon(id, source, result.drawable)
217
+ }
218
+ }
219
+ } catch (e: Exception) {
220
+ Log.e(TAG, "[RNScreens] Failed to resolve the icon of toolbar menu item '$id'.", e)
221
+ }
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Sets or clears the resolved icon of a prop-declared item, in place —
227
+ * never rebuilds the menu and never touches command state. An icon set via
228
+ * a view command takes precedence until the next real menu change.
229
+ */
230
+ private fun setItemIcon(
231
+ id: String,
232
+ source: StackHeaderToolbarMenuItemIconSource,
233
+ icon: Drawable?,
234
+ ) {
235
+ // Pruning a resolver in [setMenu] does not cancel its in-flight load,
236
+ // and the orphan's latest-wins guard still matches the source it was
237
+ // asked for, so a result must be matched against the current model.
238
+ if (model.elementById[id]?.item?.iconSource != source) {
239
+ return
240
+ }
241
+ val previous = if (icon != null) propIcons.put(id, icon) else propIcons.remove(id)
242
+ if (previous === icon || commandOverrides[id]?.icon != null) {
243
+ return
244
+ }
245
+ val toolbar = liveToolbar() ?: return
246
+ val effective = effectiveOptions(id)
247
+ StackHeaderToolbarMenuApplicator.updateToolbarMenuElement(
248
+ toolbar,
249
+ model.forwardIdMap,
250
+ id,
251
+ StackHeaderToolbarMenuElementOptions(
252
+ // Action-item classification runs when showAsAction is set and
253
+ // setting an icon alone does not re-run it, so it must
254
+ // accompany the icon.
255
+ showAsAction = effective.showAsAction,
256
+ icon = effective.icon,
257
+ iconTintColorNormal = effective.iconTintColorNormal,
258
+ iconTintColorPressed = effective.iconTintColorPressed,
259
+ iconTintColorFocused = effective.iconTintColorFocused,
260
+ iconTintColorDisabled = effective.iconTintColorDisabled,
261
+ ),
262
+ )
263
+ }
264
+
265
+ // endregion
266
+
267
+ // region Attachment & projection
268
+
269
+ private var attachedToolbar: WeakReference<MaterialToolbar>? = null
270
+
271
+ /**
272
+ * Projects the menu (model ⊕ prop icons ⊕ command overrides ⊕ selections)
273
+ * onto [toolbar] and starts applying subsequent updates to it in place.
274
+ * Emits no events — the projection is semantically a no-change.
275
+ */
276
+ internal fun attach(toolbar: MaterialToolbar) {
277
+ attachedToolbar = WeakReference(toolbar)
278
+ modelDirty = false
279
+ StackHeaderToolbarMenuApplicator.rebuildToolbarMenu(
280
+ toolbar,
281
+ model,
282
+ groupDividerEnabled,
283
+ optionsForItem = ::effectiveOptions,
284
+ onItemClicked = ::handleItemClick,
285
+ )
286
+ model.groupMetadata.groupMemberItems.keys
287
+ .forEach { applySelectionToToolbar(toolbar, it) }
288
+ }
289
+
290
+ internal fun detach() {
291
+ attachedToolbar = null
292
+ }
293
+
294
+ internal fun tearDown() {
295
+ updateQueue.tearDown()
296
+ detach()
297
+ }
298
+
299
+ private fun liveToolbar(): MaterialToolbar? = if (modelDirty) null else attachedToolbar?.get()
300
+
301
+ private fun applySelectionToToolbar(
302
+ toolbar: MaterialToolbar,
303
+ groupId: String,
304
+ ) {
305
+ val selected = groupSelections[groupId].orEmpty()
306
+
307
+ // setChecked(false) on an item of an exclusive group checks it instead
308
+ // of clearing it, so only the selected member is written and the native
309
+ // sibling-uncheck does the rest. Such a group is never cleared.
310
+ if (model.groupMetadata.groupSingleSelection[groupId] == true) {
311
+ val selectedId = selected.singleOrNull() ?: return
312
+ menuItemFor(toolbar, selectedId)?.isChecked = true
313
+ return
314
+ }
315
+
316
+ for (memberId in model.groupMetadata.groupMemberItems[groupId].orEmpty()) {
317
+ val item = menuItemFor(toolbar, memberId) ?: continue
318
+ val shouldBeChecked = memberId in selected
319
+ if (item.isChecked != shouldBeChecked) {
320
+ item.isChecked = shouldBeChecked
321
+ }
322
+ }
323
+ }
324
+
325
+ private fun menuItemFor(
326
+ toolbar: MaterialToolbar,
327
+ id: String,
328
+ ): MenuItem? = model.forwardIdMap[id]?.let { toolbar.menu.findItem(it) }
329
+
330
+ // endregion
331
+
332
+ // region Checked-state semantics
333
+
334
+ /**
335
+ * Mutates the selection of [itemId]'s group and returns the group id when
336
+ * it actually changed. [explicitCheckedValue] `null` means a user toggle.
337
+ */
338
+ private fun applyCheckedInState(
339
+ itemId: String,
340
+ explicitCheckedValue: Boolean?,
341
+ ): String? {
342
+ val groupId = model.groupMetadata.itemGroupMap[itemId] ?: return null
343
+ val singleSelection = model.groupMetadata.groupSingleSelection[groupId] ?: return null
344
+ val selection = groupSelections.getOrPut(groupId) { mutableSetOf() }
345
+
346
+ if (singleSelection) {
347
+ if (explicitCheckedValue == false) {
348
+ Log.w(
349
+ TAG,
350
+ "[RNScreens] Cannot uncheck item '$itemId' in single-selection group '$groupId'. " +
351
+ "Check a different item instead.",
352
+ )
353
+ return null
354
+ }
355
+ if (selection.singleOrNull() == itemId) {
356
+ return null
357
+ }
358
+ selection.clear()
359
+ selection.add(itemId)
360
+ return groupId
361
+ }
362
+
363
+ val newChecked = explicitCheckedValue ?: (itemId !in selection)
364
+ val changed = if (newChecked) selection.add(itemId) else selection.remove(itemId)
365
+ return groupId.takeIf { changed }
366
+ }
367
+
368
+ private fun handleItemClick(id: String) {
369
+ if (!isCheckable(id)) {
370
+ delegate?.get()?.onMenuItemClicked(id)
371
+ return
372
+ }
373
+ val changedGroup = applyCheckedInState(id, explicitCheckedValue = null) ?: return
374
+ liveToolbar()?.let { applySelectionToToolbar(it, changedGroup) }
375
+ emitGroupSelection(changedGroup)
376
+ }
377
+
378
+ private fun emitGroupSelection(groupId: String) {
379
+ val selection = groupSelections[groupId].orEmpty()
380
+ val selectedIds =
381
+ model.groupMetadata.groupMemberItems[groupId]
382
+ .orEmpty()
383
+ .filter { it in selection }
384
+ delegate?.get()?.onGroupSelectionChanged(groupId, selectedIds)
385
+ }
386
+
387
+ // Validation guarantees only plain menu items carry a groupId, so
388
+ // checkability reduces to group membership.
389
+ private fun isCheckable(id: String): Boolean = model.elementById[id]?.item?.groupId != null
390
+
391
+ // endregion
392
+
393
+ // region Effective values
394
+
395
+ private fun effectiveOptions(id: String): StackHeaderToolbarMenuElementOptions {
396
+ val base = model.elementById.getValue(id).toOptions()
397
+ val withPropIcon =
398
+ propIcons[id]?.let { base.copy(icon = StackHeaderToolbarFieldUpdate.Set(it)) } ?: base
399
+ return commandOverrides[id]?.let(withPropIcon::mergedWith) ?: withPropIcon
400
+ }
401
+
402
+ /**
403
+ * The live item already reflects effective state, so applying the delta
404
+ * keeps it there. Three fields need widening: tint colors resolve as one
405
+ * complete ColorStateList, so touching any tint slot (or the icon, whose
406
+ * application re-tints) requires all four; `showAsAction` must accompany a
407
+ * new icon, because action-item classification runs when it is set and
408
+ * setting an icon alone does not re-run it; and a submenu header must be
409
+ * re-asserted on every title change, because `MenuItem.setTitle`
410
+ * propagates into it and would leave it following the title until the
411
+ * next rebuild projected the effective `menuTitle` back.
412
+ */
413
+ private fun widenWithCoupledFields(
414
+ id: String,
415
+ delta: StackHeaderToolbarMenuElementOptions,
416
+ ): StackHeaderToolbarMenuElementOptions {
417
+ val effective = effectiveOptions(id)
418
+ var resolved = delta
419
+
420
+ if (delta.icon != null || delta.requiresIconTintColorUpdate) {
421
+ resolved =
422
+ resolved.copy(
423
+ iconTintColorNormal = effective.iconTintColorNormal,
424
+ iconTintColorPressed = effective.iconTintColorPressed,
425
+ iconTintColorFocused = effective.iconTintColorFocused,
426
+ iconTintColorDisabled = effective.iconTintColorDisabled,
427
+ )
428
+ if (delta.icon != null) {
429
+ resolved = resolved.copy(showAsAction = effective.showAsAction)
430
+ }
431
+ }
432
+
433
+ if (delta.title != null &&
434
+ delta.menuTitle == null &&
435
+ model.elementById[id] is StackHeaderToolbarMenuElementConfig.Submenu
436
+ ) {
437
+ resolved = resolved.copy(menuTitle = effective.menuTitle)
438
+ }
439
+
440
+ return resolved
441
+ }
442
+
443
+ // endregion
444
+
445
+ companion object {
446
+ private const val TAG = "StackHeaderToolbarMenuController"
447
+ }
448
+ }
@@ -0,0 +1,10 @@
1
+ package com.swmansion.rnscreens.stack.header.toolbar
2
+
3
+ internal interface StackHeaderToolbarMenuDelegate {
4
+ fun onMenuItemClicked(id: String)
5
+
6
+ fun onGroupSelectionChanged(
7
+ groupId: String,
8
+ selectedIds: List<String>,
9
+ )
10
+ }