@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (581) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +132 -0
  3. package/README.md +147 -51
  4. package/android/CLAUDE.md +78 -25
  5. package/android/CORE.md +49 -25
  6. package/android/RECIPES.md +13 -6
  7. package/android/consumer-rules.pro +6 -0
  8. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
  9. package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
  10. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
  11. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
  12. package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
  13. package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
  14. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  15. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  16. package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
  18. package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
  19. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  20. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  21. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  22. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  23. package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
  24. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  25. package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
  26. package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
  27. package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
  28. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  29. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  30. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  31. package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
  32. package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
  33. package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
  34. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  35. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  36. package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
  37. package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
  38. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
  39. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
  40. package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
  41. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
  42. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
  43. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  44. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
  45. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  46. package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
  47. package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
  48. package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
  49. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
  50. package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
  51. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
  52. package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
  53. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
  54. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
  55. package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
  56. package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
  57. package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
  58. package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
  59. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  60. package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
  61. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  62. package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
  63. package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
  64. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  65. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
  66. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementDefinition.kt +9 -3
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  123. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  124. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  127. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  130. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  131. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  142. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  143. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  156. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  157. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  158. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  159. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  160. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  161. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  162. package/android/src/main/res/values/styles.xml +1 -1
  163. package/android/src/main/res/values-night/styles.xml +1 -1
  164. package/cli/app.js +1 -1
  165. package/cli/doctor/checks/app.js +77 -14
  166. package/cli/doctor/checks/splash.js +4 -22
  167. package/cli/migrate/native.js +18 -0
  168. package/cli/project.js +10 -2
  169. package/cli/setup/index.js +18 -0
  170. package/cli/setup/source.js +2 -1
  171. package/cli/setup/steps/appDelegate.js +66 -11
  172. package/cli/setup/steps/mainApplication.js +134 -19
  173. package/cli/setup/steps/metro.js +46 -0
  174. package/cli/setup/steps/sceneDelegate.js +108 -0
  175. package/cli/splash/index.js +3 -1
  176. package/docs-md/architecture/native-screens.md +4 -0
  177. package/docs-md/architecture/theme-and-context.md +131 -12
  178. package/docs-md/architecture/transitions.md +58 -12
  179. package/docs-md/containers/arrangement.md +17 -1
  180. package/docs-md/containers/modals.md +8 -4
  181. package/docs-md/containers/overlays.md +3 -1
  182. package/docs-md/containers/side-menu.md +19 -2
  183. package/docs-md/containers/tabs.md +5 -1
  184. package/docs-md/flows/bottom-sheets.md +4 -2
  185. package/docs-md/flows/forms-in-a-modal.md +1 -1
  186. package/docs-md/fundamentals/screens-and-props.md +9 -1
  187. package/docs-md/fundamentals/starting-the-app.md +1 -1
  188. package/docs-md/guides/cli.md +4 -3
  189. package/docs-md/guides/deep-links.md +15 -33
  190. package/docs-md/help/glossary.md +4 -4
  191. package/docs-md/help/troubleshooting.md +44 -6
  192. package/docs-md/index.json +61 -1
  193. package/docs-md/migration/from-expo-router.md +1 -1
  194. package/docs-md/migration/from-react-native-navigation.md +9 -3
  195. package/docs-md/migration/from-react-navigation.md +2 -2
  196. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  197. package/docs-md/screen-ui/bar-buttons.md +5 -5
  198. package/docs-md/screen-ui/search.md +1 -1
  199. package/docs-md/screen-ui/system-ui.md +17 -12
  200. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  201. package/docs-md/screen-ui/top-bar.md +8 -4
  202. package/docs-md/start/installation.md +21 -3
  203. package/ios/Animations/ANNFrameDriver.h +55 -15
  204. package/ios/Animations/ANNFrameDriver.mm +216 -60
  205. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  206. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  207. package/ios/Animations/ANNTransitionPlan.h +2 -2
  208. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  209. package/ios/Animations/ANNTransitionWait.mm +6 -7
  210. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  211. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  212. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  213. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  214. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  215. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  216. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  217. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  218. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  219. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  220. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  221. package/ios/CLAUDE.md +60 -24
  222. package/ios/CORE.md +44 -34
  223. package/ios/Contract/ANNCommandAnswer.h +13 -5
  224. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  225. package/ios/Contract/ANNCommandContract.h +15 -0
  226. package/ios/Contract/ANNCommandContract.mm +78 -0
  227. package/ios/Contract/ANNCommandRunner.h +10 -9
  228. package/ios/Contract/ANNCommandRunner.mm +22 -28
  229. package/ios/Contract/ANNErrorTexts.h +6 -2
  230. package/ios/Contract/ANNErrorTexts.mm +18 -10
  231. package/ios/Contract/ANNLayoutNode.h +3 -3
  232. package/ios/Contract/ANNLayoutReader.h +3 -3
  233. package/ios/Core/ANNAppDelegate.mm +0 -2
  234. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  235. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  236. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  237. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  238. package/ios/Core/ANNErrorHandler.h +9 -4
  239. package/ios/Core/ANNErrorHandler.mm +20 -2
  240. package/ios/Core/ANNEventContract.h +246 -0
  241. package/ios/Core/ANNEventContract.mm +225 -0
  242. package/ios/Core/ANNEventEmitter.h +6 -2
  243. package/ios/Core/ANNEventEmitter.mm +117 -80
  244. package/ios/Core/ANNHinge.h +6 -0
  245. package/ios/Core/ANNHinge.mm +15 -4
  246. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  247. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  248. package/ios/Core/ANNLayoutProtocol.h +5 -5
  249. package/ios/Core/ANNNavigationState.h +7 -5
  250. package/ios/Core/ANNNavigationState.mm +8 -7
  251. package/ios/Core/ANNNodeHelper.h +32 -12
  252. package/ios/Core/ANNNodeHelper.mm +100 -3
  253. package/ios/Core/ANNParking.h +5 -4
  254. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  255. package/ios/Core/ANNRenderWait.h +20 -6
  256. package/ios/Core/ANNRenderWait.mm +143 -56
  257. package/ios/Core/ANNSceneDelegate.mm +25 -15
  258. package/ios/Core/ANNSystemUI.h +3 -2
  259. package/ios/Core/ANNSystemUI.mm +7 -0
  260. package/ios/Core/ANNUtils.h +7 -0
  261. package/ios/Core/ANNUtils.mm +10 -0
  262. package/ios/Core/ApexNavigation+Internal.h +1 -1
  263. package/ios/Core/ApexNavigation.mm +7 -6
  264. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  265. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  266. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  267. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  268. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +195 -21
  269. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  270. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  271. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  272. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  273. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  274. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  275. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  276. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  277. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  278. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  279. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  280. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  281. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  282. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  283. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  284. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  285. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  286. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  287. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  288. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  289. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  290. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  291. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  292. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  293. package/ios/Layouts/Screen/ANNScreenSettling.h +34 -0
  294. package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -0
  295. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  296. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  297. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  298. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  299. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  300. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  301. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  302. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  303. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  304. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  305. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  306. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  307. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  308. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  309. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  310. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  311. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  312. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  313. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  314. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  315. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  317. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  318. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  319. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  320. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  321. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  322. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  323. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  324. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  325. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  326. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  327. package/ios/Options/ANNAnimationOptions.h +2 -1
  328. package/ios/Options/ANNAnimationOptions.mm +1 -1
  329. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  330. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  331. package/ios/Options/ANNOptions.h +25 -0
  332. package/ios/Options/ANNOptions.mm +157 -1
  333. package/ios/Options/ANNOptionsCache.h +7 -6
  334. package/ios/Options/ANNOptionsReader.mm +108 -0
  335. package/ios/Options/ANNSearchBarOptions.h +4 -3
  336. package/ios/Options/ANNSheetOptions.h +4 -1
  337. package/ios/Options/ANNSideMenuOptions.h +2 -0
  338. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  339. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  340. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  341. package/ios/Options/ANNUserChoice.h +57 -0
  342. package/ios/Options/ANNUserChoice.mm +44 -0
  343. package/ios/Options/Params/ANNImageSource.h +61 -0
  344. package/ios/Options/Params/ANNImageSource.mm +101 -0
  345. package/ios/Options/Params/ANNOptionImages.h +37 -0
  346. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  347. package/ios/Options/Params/ANNParam.h +15 -0
  348. package/ios/Options/Params/ANNParam.mm +61 -0
  349. package/ios/Options/Params/Color.h +3 -0
  350. package/ios/Options/Params/Color.mm +21 -0
  351. package/ios/Options/Params/ColorParser.h +4 -3
  352. package/ios/Options/Params/ColorParser.mm +22 -4
  353. package/ios/Options/Params/Image.h +15 -2
  354. package/ios/Options/Params/Image.mm +35 -2
  355. package/ios/Options/Params/ImageParser.h +5 -5
  356. package/ios/Options/Params/ImageParser.mm +28 -46
  357. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  358. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  359. package/ios/RECIPES.md +13 -6
  360. package/ios/React/ANNReactView.mm +6 -25
  361. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  362. package/ios/React/ANNSurfaceHostingView.h +14 -0
  363. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  364. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  365. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  366. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  367. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  368. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  369. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  370. package/ios/TopBar/ANNBarAppearance.h +2 -1
  371. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  372. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  373. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  374. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  375. package/ios/TopBar/ANNBarButtons.h +14 -8
  376. package/ios/TopBar/ANNBarButtons.mm +397 -80
  377. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  378. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  379. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  380. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  381. package/ios/TopBar/ANNMainList.h +3 -0
  382. package/ios/TopBar/ANNMainList.mm +4 -0
  383. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  384. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  385. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  386. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  387. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  388. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  389. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  390. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  391. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  392. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  393. package/lib/module/ARCHITECTURE.md +40 -27
  394. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  395. package/lib/module/api/app/AppRegistry.js +14 -2
  396. package/lib/module/api/app/AppRegistry.js.map +1 -1
  397. package/lib/module/api/app/createNavigation.js +190 -66
  398. package/lib/module/api/app/createNavigation.js.map +1 -1
  399. package/lib/module/api/commands/commands.js +54 -6
  400. package/lib/module/api/commands/commands.js.map +1 -1
  401. package/lib/module/api/events/navigationEvents.js +6 -2
  402. package/lib/module/api/events/navigationEvents.js.map +1 -1
  403. package/lib/module/api/hooks/useNavigation.js +8 -3
  404. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  405. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  406. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  407. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  408. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  409. package/lib/module/api/linking/linking.js +11 -0
  410. package/lib/module/api/linking/linking.js.map +1 -1
  411. package/lib/module/api/navigation.js.map +1 -1
  412. package/lib/module/api/options/OptionsChain.js +2 -2
  413. package/lib/module/api/screens/arrangement.js +5 -2
  414. package/lib/module/api/screens/arrangement.js.map +1 -1
  415. package/lib/module/api/screens/defineScreen.js +45 -3
  416. package/lib/module/api/screens/defineScreen.js.map +1 -1
  417. package/lib/module/api/screens/nativeScreens.js +31 -6
  418. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  419. package/lib/module/api/screens/registerScreens.js +193 -35
  420. package/lib/module/api/screens/registerScreens.js.map +1 -1
  421. package/lib/module/api/theme/theme.js +5 -0
  422. package/lib/module/api/theme/theme.js.map +1 -1
  423. package/lib/module/engine/commands.js +51 -9
  424. package/lib/module/engine/commands.js.map +1 -1
  425. package/lib/module/engine/layout.js +20 -11
  426. package/lib/module/engine/layout.js.map +1 -1
  427. package/lib/module/engine/nativeScreens.js +9 -0
  428. package/lib/module/engine/nativeScreens.js.map +1 -1
  429. package/lib/module/engine/options.js +49 -15
  430. package/lib/module/engine/options.js.map +1 -1
  431. package/lib/module/engine/optionsChange.js +102 -0
  432. package/lib/module/engine/optionsChange.js.map +1 -0
  433. package/lib/module/engine/places.js +52 -7
  434. package/lib/module/engine/places.js.map +1 -1
  435. package/lib/module/engine/props.js +30 -1
  436. package/lib/module/engine/props.js.map +1 -1
  437. package/lib/module/engine/refresh.js +85 -0
  438. package/lib/module/engine/refresh.js.map +1 -0
  439. package/lib/module/engine/rememberedOptions.js +61 -1
  440. package/lib/module/engine/rememberedOptions.js.map +1 -1
  441. package/lib/module/engine/screens.js +77 -16
  442. package/lib/module/engine/screens.js.map +1 -1
  443. package/lib/module/interfaces/contract/commands.json +101 -0
  444. package/lib/module/interfaces/contract/errors.json +275 -0
  445. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  446. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  447. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  448. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  449. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  450. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  451. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  452. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  453. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  454. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  455. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  456. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  457. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  458. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  459. package/lib/typescript/api/index.d.ts +1 -1
  460. package/lib/typescript/api/index.d.ts.map +1 -1
  461. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  462. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  463. package/lib/typescript/api/linking/linking.d.ts +8 -0
  464. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  465. package/lib/typescript/api/navigation.d.ts +4 -1
  466. package/lib/typescript/api/navigation.d.ts.map +1 -1
  467. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  468. package/lib/typescript/api/screens/arrangement.d.ts +12 -2
  469. package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
  470. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  471. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  472. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  473. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  474. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  475. package/lib/typescript/api/theme/theme.d.ts +2 -0
  476. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  477. package/lib/typescript/engine/commands.d.ts +5 -0
  478. package/lib/typescript/engine/commands.d.ts.map +1 -1
  479. package/lib/typescript/engine/layout.d.ts.map +1 -1
  480. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  481. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  482. package/lib/typescript/engine/options.d.ts +5 -2
  483. package/lib/typescript/engine/options.d.ts.map +1 -1
  484. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  485. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  486. package/lib/typescript/engine/places.d.ts +7 -2
  487. package/lib/typescript/engine/places.d.ts.map +1 -1
  488. package/lib/typescript/engine/props.d.ts +8 -1
  489. package/lib/typescript/engine/props.d.ts.map +1 -1
  490. package/lib/typescript/engine/refresh.d.ts +35 -0
  491. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  492. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  493. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  494. package/lib/typescript/engine/screens.d.ts +27 -6
  495. package/lib/typescript/engine/screens.d.ts.map +1 -1
  496. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  497. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  498. package/lib/typescript/interfaces/Events.d.ts +28 -10
  499. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  500. package/lib/typescript/interfaces/Options.d.ts +1 -1
  501. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  502. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  503. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  504. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  505. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  506. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  507. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  508. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  509. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  510. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  511. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  512. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  513. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  514. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  515. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  516. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  517. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  518. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  519. package/metro/acceptPlugin.js +57 -0
  520. package/metro/babelTransformer.js +45 -0
  521. package/metro/index.js +36 -0
  522. package/package.json +3 -1
  523. package/src/ARCHITECTURE.md +40 -27
  524. package/src/adapters/NativeANNTurboModule.ts +12 -2
  525. package/src/api/app/AppRegistry.ts +16 -2
  526. package/src/api/app/createNavigation.ts +203 -69
  527. package/src/api/commands/commands.ts +48 -7
  528. package/src/api/commands/presentation.ts +4 -3
  529. package/src/api/events/navigationEvents.ts +10 -4
  530. package/src/api/hooks/useNavigation.ts +9 -4
  531. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  532. package/src/api/index.ts +1 -0
  533. package/src/api/linking/dispatchedLinks.ts +18 -0
  534. package/src/api/linking/linking.ts +22 -1
  535. package/src/api/navigation.ts +4 -1
  536. package/src/api/options/OptionsChain.ts +2 -2
  537. package/src/api/screens/arrangement.ts +17 -4
  538. package/src/api/screens/defineScreen.ts +49 -5
  539. package/src/api/screens/nativeScreens.ts +40 -4
  540. package/src/api/screens/registerScreens.tsx +185 -42
  541. package/src/api/theme/theme.ts +5 -0
  542. package/src/engine/commands.ts +70 -13
  543. package/src/engine/layout.ts +27 -11
  544. package/src/engine/nativeScreens.ts +10 -1
  545. package/src/engine/options.ts +45 -19
  546. package/src/engine/optionsChange.ts +107 -0
  547. package/src/engine/places.ts +65 -7
  548. package/src/engine/props.ts +30 -1
  549. package/src/engine/refresh.ts +97 -0
  550. package/src/engine/rememberedOptions.ts +74 -1
  551. package/src/engine/screens.tsx +76 -21
  552. package/src/interfaces/ComponentEvents.ts +4 -4
  553. package/src/interfaces/Events.ts +29 -10
  554. package/src/interfaces/Options.ts +1 -0
  555. package/src/interfaces/contract/commands.json +101 -0
  556. package/src/interfaces/contract/errors.json +275 -0
  557. package/src/interfaces/options/animations.ts +81 -22
  558. package/src/interfaces/options/bottomTabs.ts +21 -7
  559. package/src/interfaces/options/buttons.ts +23 -15
  560. package/src/interfaces/options/modals.ts +34 -26
  561. package/src/interfaces/options/sideMenu.ts +24 -6
  562. package/src/interfaces/options/stack.ts +17 -3
  563. package/src/interfaces/options/system.ts +18 -11
  564. package/src/interfaces/options/toolbar.ts +2 -2
  565. package/src/interfaces/options/topBar.ts +68 -38
  566. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  567. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  568. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  569. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  570. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  571. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  572. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  573. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  574. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  575. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  576. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  577. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  578. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  579. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  580. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  581. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -1,6 +1,7 @@
1
1
  #import "ANNSheetPresenter.h"
2
2
  #import "ANNModalSizePresenter.h"
3
3
  #import "ANNReactView.h"
4
+ #import "ANNUtils.h"
4
5
  #import "UIViewController+LayoutProtocol.h"
5
6
  #import <React/RCTLog.h>
6
7
  #import <objc/runtime.h>
@@ -53,7 +54,7 @@ static NSString *const ANNContentDetent = @"content";
53
54
  + (void)applyOptions:(ANNSheetOptions *)options toSheet:(UISheetPresentationController *)sheet {
54
55
  if (options.detents) {
55
56
  NSMutableArray<UISheetPresentationControllerDetent *> *detents = [NSMutableArray new];
56
- for (id value in options.detents) {
57
+ for (id value in [self sortedDetents:options.detents ofSheet:sheet]) {
57
58
  UISheetPresentationControllerDetent *detent = [self detentFor:value ofSheet:sheet];
58
59
  if (detent) {
59
60
  [detents addObject:detent];
@@ -81,6 +82,85 @@ static NSString *const ANNContentDetent = @"content";
81
82
  }
82
83
  }
83
84
 
85
+ // UIKit wants the detents once each, from the lowest to the highest: it takes the last for the largest and closes the
86
+ // sheet on a drag down from the first. The options may give them in any order and more than once; the first of a
87
+ // repeat stays, and detents of the same height keep their order.
88
+ + (NSArray *)sortedDetents:(NSArray *)values ofSheet:(UISheetPresentationController *)sheet {
89
+ NSMutableArray *detents = [NSMutableArray new];
90
+ NSMutableSet<NSString *> *identifiers = [NSMutableSet new];
91
+ for (id value in values) {
92
+ NSString *identifier = [self identifierFor:value];
93
+ if (identifier && ![identifiers containsObject:identifier]) {
94
+ [identifiers addObject:identifier];
95
+ [detents addObject:value];
96
+ }
97
+ }
98
+ CGFloat maximum = [self maximumDetentHeightOf:sheet];
99
+ return [detents sortedArrayWithOptions:NSSortStable
100
+ usingComparator:^NSComparisonResult(id a, id b) {
101
+ return [self compareHeightOf:a
102
+ with:b
103
+ maximum:maximum
104
+ ofSheet:sheet];
105
+ }];
106
+ }
107
+
108
+ // The content of a sheet sized to it changed its height, and with it maybe its place among the other detents.
109
+ + (void)sortDetentsOfSheet:(UISheetPresentationController *)sheet API_AVAILABLE(ios(16.0)) {
110
+ CGFloat maximum = [self maximumDetentHeightOf:sheet];
111
+ NSArray<UISheetPresentationControllerDetent *> *detents = sheet.detents;
112
+ NSArray<UISheetPresentationControllerDetent *> *sorted = [detents
113
+ sortedArrayWithOptions:NSSortStable
114
+ usingComparator:^NSComparisonResult(UISheetPresentationControllerDetent *a,
115
+ UISheetPresentationControllerDetent *b) {
116
+ return [self compareHeightOf:[self detentForIdentifier:a.identifier]
117
+ with:[self detentForIdentifier:b.identifier]
118
+ maximum:maximum
119
+ ofSheet:sheet];
120
+ }];
121
+ if (![sorted isEqualToArray:detents]) {
122
+ sheet.detents = sorted;
123
+ }
124
+ }
125
+
126
+ + (NSComparisonResult)compareHeightOf:(id)a
127
+ with:(id)b
128
+ maximum:(CGFloat)maximum
129
+ ofSheet:(UISheetPresentationController *)sheet {
130
+ CGFloat heightA = [self heightOf:a maximum:maximum ofSheet:sheet];
131
+ CGFloat heightB = [self heightOf:b maximum:maximum ofSheet:sheet];
132
+ return heightA < heightB ? NSOrderedAscending
133
+ : heightA > heightB ? NSOrderedDescending : NSOrderedSame;
134
+ }
135
+
136
+ // The height a detent of the options stands at, to sort them, as its resolver gives it: 'medium' half of the largest
137
+ // height (UIKit's is about half), 'large' all of it, a height capped at it, 'content' the content's height now, all of
138
+ // it while the content isn't measured.
139
+ + (CGFloat)heightOf:(id)value
140
+ maximum:(CGFloat)maximum
141
+ ofSheet:(UISheetPresentationController *)sheet {
142
+ if ([value isEqual:@"medium"]) {
143
+ return maximum / 2;
144
+ }
145
+ if ([value isKindOfClass:NSNumber.class]) {
146
+ return MIN([value doubleValue], maximum);
147
+ }
148
+ if ([value isEqual:ANNContentDetent]) {
149
+ CGFloat height = [self contentHeightOf:sheet.presentedViewController];
150
+ return height > 0 ? MIN(height, maximum) : maximum;
151
+ }
152
+ return maximum;
153
+ }
154
+
155
+ // About the largest height of a sheet: its container, or the window before it is shown, below the top safe area.
156
+ + (CGFloat)maximumDetentHeightOf:(UISheetPresentationController *)sheet {
157
+ UIView *view = sheet.containerView ?: ANNUtils.mainWindow;
158
+ if (!view) {
159
+ return ANNUtils.mainScreen.bounds.size.height;
160
+ }
161
+ return view.bounds.size.height - view.safeAreaInsets.top;
162
+ }
163
+
84
164
  + (UISheetPresentationControllerDetent *)detentFor:(id)value
85
165
  ofSheet:(UISheetPresentationController *)sheet {
86
166
  if ([value isEqual:@"medium"]) {
@@ -180,6 +260,7 @@ static NSString *const ANNContentDetent = @"content";
180
260
  }
181
261
  height = newHeight;
182
262
  [strongSheet animateChanges:^{
263
+ [self sortDetentsOfSheet:strongSheet];
183
264
  [strongSheet invalidateDetents];
184
265
  }];
185
266
  }
@@ -201,6 +282,7 @@ static NSString *const ANNContentDetent = @"content";
201
282
  // The new screen's content mounts may come later: its mounts resolve the detents again too.
202
283
  [self followContentOfSheet:sheet when:YES];
203
284
  [sheet animateChanges:^{
285
+ [self sortDetentsOfSheet:sheet];
204
286
  [sheet invalidateDetents];
205
287
  }];
206
288
  }
@@ -179,7 +179,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
179
179
  limit:ANNOverlayRenderLimit
180
180
  bar:ANNRenderWaitBarWithContent
181
181
  barLimits:withContent];
182
- wait.mountLimit = ANNOverlayRenderLimit;
182
+ wait.unseenLimit = ANNOverlayRenderLimit;
183
183
  wait.protect = ^(dispatch_block_t step) {
184
184
  [ANNOverlayCoordinator protectWaitOf:weakOverlay step:step];
185
185
  };
@@ -238,13 +238,7 @@ static NSMutableArray<ANNOverlay *> *ANNOverlays;
238
238
  [self dismiss:shown answer:nil];
239
239
  }
240
240
  }
241
- UIWindow *mainWindow = ApexNavigation.mainWindow;
242
- UIWindowScene *scene = mainWindow.windowScene;
243
- // `initWithFrame:` is deprecated from iOS 26 on and warns only with a deployment target from 26: a window
244
- // without a scene is made so, and joins the scene as the main window gets it.
245
- ANNOverlayWindow *window =
246
- scene ? [[ANNOverlayWindow alloc] initWithWindowScene:scene]
247
- : [[ANNOverlayWindow alloc] initWithFrame:ANNUtils.mainScreen.bounds];
241
+ ANNOverlayWindow *window = [ANNUtils makeWindowOfClass:ANNOverlayWindow.class];
248
242
  window.windowLevel = UIWindowLevelNormal;
249
243
  window.backgroundColor = UIColor.clearColor;
250
244
  window.previousWindow = [self keyWindow];
@@ -69,7 +69,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
69
69
  // The nodes whose appearance the transition reports itself (`driveAppearanceOf:`), while `driving`.
70
70
  @property(nonatomic, copy) NSArray<UIViewController *> *driven;
71
71
  @property(nonatomic) BOOL driving;
72
+ // The snapshot of the window as it was: it dissolves over the new root (`dissolves`), plays its `exit` (`custom`), or
73
+ // only covers the old root's modals while they go, and leaves as the new root is the window's.
72
74
  @property(nonatomic, strong, nullable) UIView *snapshot;
75
+ @property(nonatomic) BOOL dissolves;
73
76
  // The root is the window's root: the old root's modals went before it (`startTransitionOf:done:`).
74
77
  @property(nonatomic) BOOL installed;
75
78
  // The root's view waits in the window under the current root (`park:`).
@@ -80,6 +83,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
80
83
  @property(nonatomic, strong, nullable) ANNFrameDriver *driver;
81
84
  @property(nonatomic, copy, nullable) NSArray<ANNViewTracks *> *tracks;
82
85
  @property(nonatomic) BOOL animating;
86
+ // The new root's view takes no touches while it animates, and whether it took them before: Core Animation draws it
87
+ // elsewhere than where it is (the view itself stays in place), so a tap on the old screen would reach it.
88
+ @property(nonatomic, weak, nullable) UIView *untouchableRoot;
89
+ @property(nonatomic) BOOL rootTouchesBefore;
83
90
  @property(nonatomic) BOOL layersShown;
84
91
  @end
85
92
 
@@ -293,7 +300,7 @@ static __weak ANNRootShow *ANNAnimatingShow;
293
300
  barLimits:contentFirst ? ownPhase : withContent];
294
301
  // A screen the user won't see at once (an unselected tab's) never holds the root longer than the limit, also with
295
302
  // `waitForRender: true`.
296
- wait.mountLimit = ANNRootRenderLimit;
303
+ wait.unseenLimit = ANNRootRenderLimit;
297
304
  wait.protect = ^(dispatch_block_t step) {
298
305
  [ANNRootCoordinator protect:weakShow step:step];
299
306
  };
@@ -415,9 +422,14 @@ static __weak ANNRootShow *ANNAnimatingShow;
415
422
  BOOL seen = !window.hidden && scene != nil &&
416
423
  scene.activationState != UISceneActivationStateBackground;
417
424
  BOOL dissolves = !overSplash && !enterDisabled && !custom && seen;
425
+ show.dissolves = dissolves;
418
426
  show.custom = custom && seen;
419
- UIView *snapshot =
420
- dissolves || show.custom ? [window snapshotViewAfterScreenUpdates:NO] : nil;
427
+ // UIKit draws the dismissal of the old root's modals, without animation too (a sheet's dim goes a frame before
428
+ // its card): with nothing to dissolve, the snapshot covers them until the new root is in place.
429
+ BOOL covers = seen && old.presentedViewController != nil;
430
+ UIView *snapshot = dissolves || show.custom || covers
431
+ ? [window snapshotViewAfterScreenUpdates:NO]
432
+ : nil;
421
433
 
422
434
  show.state = ANNRootShowStateTransition;
423
435
  // It shows from here: a stack in it counts as on screen.
@@ -480,7 +492,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
480
492
  [self endTransitionOf:show];
481
493
  return;
482
494
  }
483
- if (!snapshot) {
495
+ // A snapshot that only covered the old root's modals leaves in this turn, with the new root in place under it.
496
+ if (!snapshot || !show.dissolves) {
484
497
  [self endTransitionOf:show];
485
498
  return;
486
499
  }
@@ -524,20 +537,43 @@ static __weak ANNRootShow *ANNAnimatingShow;
524
537
  NSMutableArray<ANNViewTracks *> *tracks = [NSMutableArray new];
525
538
  ANNViewAnimationOptions *enter = [ANNAnimationRules playingSide:animation.enter];
526
539
  ANNViewAnimationOptions *exit = [ANNAnimationRules playingSide:animation.exit];
527
- if (enter && rootView) {
528
- [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
529
- side:enter
530
- alphaBefore:rootView.alpha]];
531
- }
532
- if (exit && snapshot) {
533
- [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
534
- side:exit
535
- alphaBefore:snapshot.alpha]];
536
- }
537
540
  NSTimeInterval length =
538
541
  MAX([ANNAnimationRules lengthOfSide:enter], [ANNAnimationRules lengthOfSide:exit]);
542
+ if (UIAccessibilityIsReduceMotionEnabled() && length > 0) {
543
+ // With the system's Reduce Motion on, nothing moves: the new root fades in over the snapshot in the same
544
+ // length, or the snapshot fades out without a new root's view.
545
+ if (rootView) {
546
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
547
+ fadeFrom:0
548
+ to:rootView.alpha
549
+ duration:length
550
+ alphaBefore:rootView.alpha]];
551
+ } else if (snapshot) {
552
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
553
+ fadeFrom:snapshot.alpha
554
+ to:0
555
+ duration:length
556
+ alphaBefore:snapshot.alpha]];
557
+ }
558
+ } else {
559
+ if (enter && rootView) {
560
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
561
+ side:enter
562
+ alphaBefore:rootView.alpha]];
563
+ }
564
+ if (exit && snapshot) {
565
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
566
+ side:exit
567
+ alphaBefore:snapshot.alpha]];
568
+ }
569
+ }
539
570
  show.tracks = tracks;
540
571
  show.animating = YES;
572
+ if (rootView) {
573
+ show.untouchableRoot = rootView;
574
+ show.rootTouchesBefore = rootView.userInteractionEnabled;
575
+ rootView.userInteractionEnabled = NO;
576
+ }
541
577
  ANNAnimatingShow = show;
542
578
  show.driver = [[ANNFrameDriver alloc] initWithClients:tracks length:length];
543
579
  // The layers' state from here on: the chain may start and a newer `setRoot` stops it.
@@ -574,8 +610,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
574
610
  [self finishLayersOf:show];
575
611
  }
576
612
 
577
- // The animation stops at its end state (its end, a newer `setRoot`, a reload, a failure): the views get back what they
578
- // had and the snapshot goes.
613
+ // The animation stops (its end, a newer `setRoot`, a reload, a failure): its animations go, the views get back what
614
+ // they had and the snapshot goes.
579
615
  + (void)stopAnimationOf:(ANNRootShow *)show {
580
616
  if (!show.animating) {
581
617
  return;
@@ -583,13 +619,16 @@ static __weak ANNRootShow *ANNAnimatingShow;
583
619
  show.animating = NO;
584
620
  [show.driver cancel];
585
621
  show.driver = nil;
622
+ show.untouchableRoot.userInteractionEnabled = show.rootTouchesBefore;
623
+ show.untouchableRoot = nil;
586
624
  for (ANNViewTracks *tracks in show.tracks) {
587
625
  [tracks restore];
588
626
  }
589
627
  show.tracks = nil;
590
- // UIKit works out the safe area of the window's root view from where the view is drawn: moved away from the top
591
- // edge by `enter` (from the bottom, scaled down) it has no top inset, and putting the transform back doesn't make
592
- // UIKit work it out again. A layout now gives the root, its bars and its screens the window's safe area back.
628
+ // UIKit works out the safe area of the window's root view from where the view is: moved away from the top edge by
629
+ // a transform it has no top inset, and putting the transform back doesn't make UIKit work it out again. `enter`
630
+ // moves only what Core Animation draws now; the layout stays, so the root, its bars and its screens end with the
631
+ // window's safe area whatever moved them.
593
632
  UIView *rootView = show.root.viewIfLoaded;
594
633
  [rootView setNeedsLayout];
595
634
  [rootView layoutIfNeeded];
@@ -7,9 +7,11 @@ NS_ASSUME_NONNULL_BEGIN
7
7
  /// either at once. The status bar follows the Info.plist keys `UIStatusBarStyle` and `UIStatusBarHidden`. Main queue.
8
8
  @interface ANNSplashViewController : UIViewController
9
9
 
10
- /// The copy of the launch screen: the initial view controller of `UILaunchStoryboardName` as a child (a storyboard
11
- /// that doesn't load: the first view of the nib of that name), else the legacy launch images, full screen. Nil when the
12
- /// app has none of these: the window then has no root view controller until the first root.
10
+ /// The copy of the launch screen. When iOS builds it from the Info.plist (`UILaunchScreen`, or the default of
11
+ /// `UILaunchScreens`), the same color, image and bars as plain views; else the initial view controller of
12
+ /// `UILaunchStoryboardName` as a child (a storyboard that doesn't load: the first view of the nib of that name), else
13
+ /// the legacy launch images, full screen. Nil when the app has none of these: the window then has no root view
14
+ /// controller until the first root.
13
15
  + (nullable instancetype)launchScreenCopyWithBounds:(CGRect)bounds;
14
16
 
15
17
  /// The blank screen after a reload: clear when the default options give the window a color (`window.backgroundColor`),
@@ -34,9 +34,63 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
34
34
  return names;
35
35
  }
36
36
 
37
+ static NSDictionary *ANNDictionaryOrNil(id value) {
38
+ return [value isKindOfClass:NSDictionary.class] ? value : nil;
39
+ }
40
+
41
+ static NSString *ANNStringOrNil(id value) {
42
+ return [value isKindOfClass:NSString.class] && [value length] > 0 ? value : nil;
43
+ }
44
+
45
+ // The definition that a plural key (`UILaunchScreens`, `UILaunchStoryboards`) marks as its default.
46
+ static NSDictionary *ANNDefaultDefinition(id plural, NSString *definitionsKey,
47
+ NSString *identifierKey, NSString *defaultKey) {
48
+ NSDictionary *dictionary = ANNDictionaryOrNil(plural);
49
+ NSArray *definitions = dictionary[definitionsKey];
50
+ NSString *defaultIdentifier = ANNStringOrNil(dictionary[defaultKey]);
51
+ if (![definitions isKindOfClass:NSArray.class] || !defaultIdentifier) {
52
+ return nil;
53
+ }
54
+ for (id definition in definitions) {
55
+ NSDictionary *entry = ANNDictionaryOrNil(definition);
56
+ if ([entry[identifierKey] isEqual:defaultIdentifier]) {
57
+ return entry;
58
+ }
59
+ }
60
+ return nil;
61
+ }
62
+
63
+ // The launch screen that iOS builds from the Info.plist without a storyboard, or nil when it shows a storyboard. Of
64
+ // `UILaunchStoryboardName`, `UILaunchScreen`, the default of `UILaunchStoryboards` and the default of
65
+ // `UILaunchScreens`, the last one present wins (SplashBoard's `XBApplicationLaunchCompatibilityInfo`). A launch by a
66
+ // link that `UILaunchScreens` maps to a screen of its own still gets the default here.
67
+ static NSDictionary *ANNLaunchScreenConfiguration(NSBundle *bundle) {
68
+ NSDictionary *screen =
69
+ ANNDefaultDefinition([bundle objectForInfoDictionaryKey:@"UILaunchScreens"],
70
+ @"UILaunchScreenDefinitions", @"UILaunchScreenIdentifier",
71
+ @"UIDefaultLaunchScreen");
72
+ if (screen) {
73
+ return screen;
74
+ }
75
+ if (ANNDefaultDefinition([bundle objectForInfoDictionaryKey:@"UILaunchStoryboards"],
76
+ @"UILaunchStoryboardDefinitions", @"UILaunchStoryboardIdentifier",
77
+ @"UIDefaultLaunchStoryboard")) {
78
+ return nil;
79
+ }
80
+ return ANNDictionaryOrNil([bundle objectForInfoDictionaryKey:@"UILaunchScreen"]);
81
+ }
82
+
37
83
  @implementation ANNSplashViewController {
38
84
  UIViewController *_content;
39
85
  UIView *_contentView;
86
+ NSDictionary *_launchScreen;
87
+ // The parts of a launch screen built from `UILaunchScreen`, laid out once the safe area is known.
88
+ UIImageView *_imageView;
89
+ BOOL _imageRespectsSafeArea;
90
+ UINavigationBar *_navigationBar;
91
+ UIImageView *_navigationBarImageView;
92
+ UIView *_bottomBar;
93
+ UIImageView *_bottomBarImageView;
40
94
  }
41
95
 
42
96
  - (instancetype)initWithContent:(UIViewController *)content
@@ -52,6 +106,12 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
52
106
 
53
107
  + (instancetype)launchScreenCopyWithBounds:(CGRect)bounds {
54
108
  NSBundle *bundle = NSBundle.mainBundle;
109
+ NSDictionary *launchScreen = ANNLaunchScreenConfiguration(bundle);
110
+ if (launchScreen) {
111
+ ANNSplashViewController *copy = [[self alloc] initWithContent:nil contentView:nil blank:NO];
112
+ copy->_launchScreen = launchScreen;
113
+ return copy;
114
+ }
55
115
  NSString *storyboardName = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
56
116
  if ([storyboardName isKindOfClass:NSString.class] && storyboardName.length > 0) {
57
117
  UIViewController *initial = nil;
@@ -97,6 +157,10 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
97
157
  view.backgroundColor = windowHasColor ? UIColor.clearColor : UIColor.systemBackgroundColor;
98
158
  return;
99
159
  }
160
+ if (_launchScreen) {
161
+ [self buildLaunchScreen];
162
+ return;
163
+ }
100
164
  UIView *contentView = _contentView;
101
165
  if (_content) {
102
166
  [self addChildViewController:_content];
@@ -109,6 +173,89 @@ static NSArray<NSString *> *ANNLegacyLaunchImageNames(CGFloat height) {
109
173
  [_content didMoveToParentViewController:self];
110
174
  }
111
175
 
176
+ #pragma mark - The launch screen of `UILaunchScreen`
177
+
178
+ // Built as SplashBoard builds it: the named color over the whole screen, else the system background; the named image
179
+ // at its own size in the middle of the screen or of its safe area, stretched instead when the asset has slicing; a tab
180
+ // bar or a toolbar at the bottom and a navigation bar at the top, the system's own bars, or the bar's named image
181
+ // stretched over the bar's place. A name the asset catalog doesn't have leaves its part out, as iOS does.
182
+ - (void)buildLaunchScreen {
183
+ UIView *view = self.view;
184
+ NSString *colorName = ANNStringOrNil(_launchScreen[@"UIColorName"]);
185
+ UIColor *color = colorName ? [UIColor colorNamed:colorName] : nil;
186
+ view.backgroundColor = color ?: UIColor.systemBackgroundColor;
187
+
188
+ NSString *imageName = ANNStringOrNil(_launchScreen[@"UIImageName"]);
189
+ UIImage *image = imageName ? [UIImage imageNamed:imageName] : nil;
190
+ if (image) {
191
+ _imageView = [[UIImageView alloc] initWithImage:image];
192
+ _imageView.contentMode = UIEdgeInsetsEqualToEdgeInsets(image.capInsets, UIEdgeInsetsZero)
193
+ ? UIViewContentModeCenter
194
+ : UIViewContentModeScaleToFill;
195
+ id respects = _launchScreen[@"UIImageRespectsSafeAreaInsets"];
196
+ _imageRespectsSafeArea = [respects respondsToSelector:@selector(boolValue)] &&
197
+ [respects boolValue];
198
+ [view addSubview:_imageView];
199
+ }
200
+
201
+ // A toolbar takes the bottom before a tab bar; a navigation bar comes on top of either.
202
+ id toolbar = _launchScreen[@"UIToolbar"];
203
+ id tabBar = _launchScreen[@"UITabBar"];
204
+ if (toolbar || tabBar) {
205
+ _bottomBar = toolbar ? [UIToolbar new] : [UITabBar new];
206
+ _bottomBarImageView = [self addBar:_bottomBar configuration:toolbar ?: tabBar];
207
+ }
208
+ id navigationBar = _launchScreen[@"UINavigationBar"];
209
+ if (navigationBar) {
210
+ _navigationBar = [UINavigationBar new];
211
+ _navigationBarImageView = [self addBar:_navigationBar configuration:navigationBar];
212
+ }
213
+ }
214
+
215
+ // Adds the bar, or its image in its place when its configuration names one that loads.
216
+ - (UIImageView *)addBar:(UIView *)bar configuration:(id)configuration {
217
+ NSString *name = ANNStringOrNil(ANNDictionaryOrNil(configuration)[@"UIImageName"]);
218
+ UIImage *image = name ? [UIImage imageNamed:name] : nil;
219
+ UIImageView *imageView = image ? [[UIImageView alloc] initWithImage:image] : nil;
220
+ bar.hidden = imageView != nil;
221
+ [self.view addSubview:bar];
222
+ if (imageView) {
223
+ [self.view addSubview:imageView];
224
+ }
225
+ return imageView;
226
+ }
227
+
228
+ // The safe area is known only in the window, so the parts are laid out here, after every change of it.
229
+ - (void)viewDidLayoutSubviews {
230
+ [super viewDidLayoutSubviews];
231
+ if (!_launchScreen) {
232
+ return;
233
+ }
234
+ CGRect bounds = self.view.bounds;
235
+ UIEdgeInsets safeArea = self.view.safeAreaInsets;
236
+ _imageView.frame =
237
+ _imageRespectsSafeArea ? UIEdgeInsetsInsetRect(bounds, safeArea) : bounds;
238
+ [self layOutBar:_bottomBar imageView:_bottomBarImageView atBottom:YES];
239
+ [self layOutBar:_navigationBar imageView:_navigationBarImageView atBottom:NO];
240
+ }
241
+
242
+ // A bar is as tall as UIKit makes it, plus the safe area on its edge of the screen, and as wide as the screen.
243
+ - (void)layOutBar:(UIView *)bar
244
+ imageView:(UIImageView *)imageView
245
+ atBottom:(BOOL)atBottom {
246
+ if (!bar) {
247
+ return;
248
+ }
249
+ CGRect bounds = self.view.bounds;
250
+ UIEdgeInsets safeArea = self.view.safeAreaInsets;
251
+ CGFloat height = [bar sizeThatFits:bounds.size].height +
252
+ (atBottom ? safeArea.bottom : safeArea.top);
253
+ CGFloat y = atBottom ? CGRectGetMaxY(bounds) - height : CGRectGetMinY(bounds);
254
+ CGRect frame = CGRectMake(CGRectGetMinX(bounds), y, CGRectGetWidth(bounds), height);
255
+ bar.frame = frame;
256
+ imageView.frame = frame;
257
+ }
258
+
112
259
  #pragma mark - The status bar, as the launch screen had it
113
260
 
114
261
  - (UIStatusBarStyle)preferredStatusBarStyle {
@@ -19,11 +19,19 @@ NS_ASSUME_NONNULL_BEGIN
19
19
  /// it. Nothing before the screen's view is loaded.
20
20
  - (void)applyBackground:(ANNNavigationOptions *)resolvedOptions;
21
21
 
22
- /// `statusBar.blur` (iOS): UIKit's regular blur over the screen's own view in the frame of the scene's status bar at
23
- /// this moment (x 0, the view's width; it doesn't follow a rotation); `false` or none removes it. At each appearance
24
- /// and at a merge that names it; nothing before the screen's view is loaded.
22
+ /// `statusBar.blur` (iOS): UIKit's regular blur over the screen's own view in the frame of the scene's status bar (x 0,
23
+ /// the view's width), laid out at once; `false` or none removes it. At each appearance and at a merge that names it;
24
+ /// nothing before the screen's view is loaded.
25
25
  - (void)applyStatusBarBlur:(ANNNavigationOptions *)resolvedOptions;
26
26
 
27
+ /// The blur takes the status bar's frame as it is now; nothing without a blur. The single place of its frame: the blur
28
+ /// as it is applied, the screen's view laid out (a rotation, a new window size, a new safe area), a size transition
29
+ /// along its animation and at its end, the turn after new traits, and `statusBarDidChange`.
30
+ - (void)layOutStatusBarBlur;
31
+
32
+ /// The status bar was asked again (hidden or shown, a new style): every blur takes its frame.
33
+ + (void)statusBarDidChange;
34
+
27
35
  /// The blur stays the last subview of the screen's view: the content added after it goes under it.
28
36
  - (void)keepStatusBarBlurOnTop;
29
37
 
@@ -5,6 +5,10 @@
5
5
  #import "ANNTopBarPresenter.h"
6
6
  #import "ANNUtils.h"
7
7
 
8
+ // The presenters whose screen shows `statusBar.blur`: the status bar hidden or shown lays out no view, so they hear of
9
+ // it from the system UI (`statusBarDidChange`).
10
+ static NSHashTable<ANNComponentPresenter *> *ANNBlurringPresenters;
11
+
8
12
  @implementation ANNComponentPresenter {
9
13
  // `statusBar.blur` while it is on.
10
14
  UIVisualEffectView *_statusBarBlur;
@@ -95,9 +99,7 @@
95
99
 
96
100
  #pragma mark - The status bar's blur (`statusBar.blur`)
97
101
 
98
- // Over the screen's own view, never over a React view; no touches, nothing for VoiceOver. The frame is the scene's
99
- // status bar's as it is now, in the view's own coordinates without a conversion: a pushed screen's view may still be
100
- // out of place while it appears.
102
+ // Over the screen's own view, never over a React view; no touches, nothing for VoiceOver.
101
103
  - (void)applyStatusBarBlur:(ANNNavigationOptions *)resolvedOptions {
102
104
  ANNComponentViewController *screen = self.screen;
103
105
  if (!screen.isViewLoaded) {
@@ -106,6 +108,7 @@
106
108
  if (![resolvedOptions.statusBar.blur withDefault:NO]) {
107
109
  [_statusBarBlur removeFromSuperview];
108
110
  _statusBarBlur = nil;
111
+ [ANNBlurringPresenters removeObject:self];
109
112
  return;
110
113
  }
111
114
  UIView *view = screen.view;
@@ -115,15 +118,40 @@
115
118
  _statusBarBlur.userInteractionEnabled = NO;
116
119
  _statusBarBlur.isAccessibilityElement = NO;
117
120
  _statusBarBlur.accessibilityElementsHidden = YES;
121
+ if (!ANNBlurringPresenters) {
122
+ ANNBlurringPresenters = [NSHashTable weakObjectsHashTable];
123
+ }
124
+ [ANNBlurringPresenters addObject:self];
118
125
  }
119
- CGRect statusBar = ANNUtils.statusBarFrame;
120
- _statusBarBlur.frame = CGRectMake(0, CGRectGetMinY(statusBar), CGRectGetWidth(view.bounds),
121
- CGRectGetHeight(statusBar));
122
126
  if (_statusBarBlur.superview != view) {
123
127
  [view addSubview:_statusBarBlur];
124
128
  } else {
125
129
  [view bringSubviewToFront:_statusBarBlur];
126
130
  }
131
+ [self layOutStatusBarBlur];
132
+ }
133
+
134
+ // The status bar's frame in the scene of the screen's window (the main window's before the screen is in one), in the
135
+ // view's own coordinates without a conversion: a pushed screen's view may still be out of place while it appears. A
136
+ // hidden status bar has no frame, and the blur no height.
137
+ - (void)layOutStatusBarBlur {
138
+ UIView *view = _statusBarBlur.superview;
139
+ if (!view) {
140
+ return;
141
+ }
142
+ UIWindowScene *scene = view.window.windowScene;
143
+ CGRect statusBar = scene ? scene.statusBarManager.statusBarFrame : ANNUtils.statusBarFrame;
144
+ CGRect frame = CGRectMake(0, CGRectGetMinY(statusBar), CGRectGetWidth(view.bounds),
145
+ CGRectGetHeight(statusBar));
146
+ if (!CGRectEqualToRect(_statusBarBlur.frame, frame)) {
147
+ _statusBarBlur.frame = frame;
148
+ }
149
+ }
150
+
151
+ + (void)statusBarDidChange {
152
+ for (ANNComponentPresenter *presenter in ANNBlurringPresenters.allObjects) {
153
+ [presenter layOutStatusBarBlur];
154
+ }
127
155
  }
128
156
 
129
157
  - (void)keepStatusBarBlurOnTop {
@@ -1,6 +1,7 @@
1
1
  #import "ANNArrangementScreenDelegate.h"
2
2
  #import "ANNLayoutProtocol.h"
3
3
  #import "ANNScreenAppearance.h"
4
+ #import "ANNScreenPlace.h"
4
5
  #import "UIViewController+LayoutProtocol.h"
5
6
  #import <UIKit/UIKit.h>
6
7
 
@@ -10,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
10
11
  ///
11
12
  /// Its view has the size of the screen of the navigation window's scene; the content sits in the root frame, by the one
12
13
  /// "under bars" rule (`ANNScreenBars`). Every recompute of the frame (a layout, a change of the safe area or the
13
- /// traits, `mergeOptions`, an appearance) gives the modules the screen's insets, padding and regions
14
- /// (`ANNScreenInsets`, `ANNScreenRegions`). Its presenter is an `ANNComponentPresenter`.
14
+ /// traits, `mergeOptions`, an appearance) gives the store the screen's insets, padding and regions
15
+ /// (`ANNScreenEnvironment`). Its presenter is an `ANNComponentPresenter`.
15
16
  ///
16
17
  /// The screen answers UIKit's questions about the system UI (native screens too): the status bar's style and visibility
17
18
  /// (never animated), the orientations, the home indicator, the deferred edges and the vertical bars, from its resolved
@@ -42,21 +43,22 @@ NS_ASSUME_NONNULL_BEGIN
42
43
  /// nobody rendered gets its content when UIKit first loads its view.
43
44
  - (void)render;
44
45
 
46
+ /// Where the screen will show while it waits for its content out of it (parked by a stack's or `showInColumn`'s wait,
47
+ /// or in a tab rendered before it shows, `ANNParking`): it lays out with that place's safe area and bars
48
+ /// (`ANNScreenPlace`), as it will once it shows there. Asked at each layout, and kept past the parking until UIKit
49
+ /// gives the screen a safe area of its own in a parent (the push lays it out once before that, with none), or as it
50
+ /// appears. Nil: its view's own. Set by the one that parks the screen.
51
+ @property(nonatomic, copy, nullable) ANNScreenPlace *_Nullable (^placeWhileParked)(void);
52
+
53
+ /// The place is kept until the screen appears, not only until UIKit gives it a safe area: a tab's screen rendered
54
+ /// before the tab shows gets a part of it first (the bar without the status bar) as UIKit lays the tab out. Set with
55
+ /// `placeWhileParked`, and goes with it.
56
+ @property(nonatomic) BOOL placeKeptUntilAppearance;
57
+
45
58
  /// Applies the "under bars" rule to the root frame again, then gives the modules the insets, the padding and the
46
59
  /// regions of the screen. Nothing before the view loaded; the safe area only in a window.
47
60
  - (void)updateRootLayout;
48
61
 
49
- /// The content view (only the core's React view, never the screen's own view) mounts unseen in `host` (the tabs'
50
- /// preload window) at the frame it has, while the screen's tab isn't shown. NO when there is nothing to lend: no React
51
- /// view of its own, in a window already, lent already, or the screen went.
52
- - (BOOL)lendContentTo:(UIView *)host;
53
-
54
- /// The lent content comes back into the screen's view at its root frame; also as the screen first appears.
55
- - (void)takeContentBack;
56
-
57
- /// The content is lent (`lendContentTo:`): `updateRootLayout` leaves its frame alone meanwhile.
58
- @property(nonatomic, readonly) BOOL contentIsLent;
59
-
60
62
  /// The transition that removes the screen starts (before its destroy): with `blurOnUnmount` in its resolved options,
61
63
  /// the editing inside its view ends and the keyboard goes (`blurOnUnmount`).
62
64
  - (void)screenWillLeave;