@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
@@ -63,7 +63,8 @@ form of `src/api/events/navigationEvents.ts`. Everything in `src/engine` is inte
63
63
  `LinkParams`, `PendingLink`, …). `linkPaths.ts`: a URL into its path and query (`parseLink`), the patterns ordered
64
64
  (`compileRoutes`) and matched (`matchLink`). `linking.ts`: the links of the app — the launch link, the `url` events
65
65
  of React Native's `Linking`, the routes run, the pending link opened after `setContext`. `pendingLinks.ts`: the one
66
- waiting link and its listeners, which `navigation` and `usePendingLink` read.
66
+ waiting link and its listeners, which `navigation` and `usePendingLink` read. `dispatchedLinks.ts` (iOS): hands
67
+ `Linking` the links of `ANN.DeepLinkDispatched`.
67
68
  - `events/` — `navigationEvents.ts`: the events by name, the native event behind each, `onNavigationEvent`,
68
69
  `listeners`. `screenLifecycle.ts`: what goes when a screen unmounts, `whenScreenUnmounts`. `tabPresses.ts`: the
69
70
  handlers of `useTabPress`.
@@ -84,24 +85,26 @@ form of `src/api/events/navigationEvents.ts`. Everything in `src/engine` is inte
84
85
 
85
86
  ## `src/engine` — the engine
86
87
 
87
- | Module | What it does |
88
- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
89
- | `native.ts` | `commands`: the TurboModule (`src/adapters/NativeANNTurboModule.ts`). `onNativeEvent(name, listener)`: one native event, `ANN.<name>`. iOS sends events through `ANNTurboEventEmitter`; Android without a module. `getLaunchLink()`: the URL that launched the native side, null without the native side (Jest). `getStartInfo()`: `{ coldStart, splashLogo, arrangements }`, asked once; without the native side a cold start without a logo and without arrangements. |
90
- | `layout.ts` | `toNativeLayout(layout)`: a `LayoutNode`, `{ id, type, data: { name, options, passProps?, functions?, key?, columns? }, children }`. For a screen, in this order: a name that shows a pair becomes an `Arrangement` node (see Pairs, regions and the hinge), an unknown name fails, its id, its own options under those of the show, the press handlers of its buttons taken out; then a native screen goes as an external component (`showNativeScreen`), a React screen with its `key`, its props kept here, as a slot in one tree. |
91
- | `options.ts` | `toNativeOptions(options)`: colors (iOS: a number, `DynamicColorIOS` or `'NoColor'`; Android: `{ light, dark }`), images (`require` resolved), components in options (`componentId`, their props kept here), the props of buttons with a component, the roots of the bar buttons' components (`*Buttons`, the toolbar's `buttons`) remembered. Options come in their own form only. |
92
- | `commands.ts` | `setRoot`, `push`, `pop`, `popTo`, `popToRoot`, `setStackRoot`, `showInColumn`, `setColumnShown`, `showModal`, `dismissModal`, `dismissAllModals`, `showOverlay`, `dismissOverlay`, `dismissAllOverlays`, `mergeOptions`, `setDefaultOptions`. One that shows screens waits for lazy ones (`afterLoading`), checks the ids (`checkIds`), notes the places and waits for the hooks of native screens (`whenNativeScreensReady`). On Android, in one tree, a push goes through `preparePush` first (see One command). |
93
- | `screens.tsx` | The screens by name: a React component with its options, `key`, `load` (a lazy screen) and `arrangement` (its pair, if it has a secondary), a native screen (`nativeName`, the controller of its `useProps`, `arrangement`), or a pair entry of `defineArrangement` (`pair`). `arrangementOf(name)`: the pair a name shows; `checkArrangements` at registration, `checkArrangement` when a lazy screen's pair shows. `loadScreens`/`afterLoading`: a command goes once its lazy screens loaded, at once when none waits. A React screen is registered with `AppRegistry` as a root (`screenRoot`) that renders it with the props left for its id. After a JavaScript reload React Native starts the old roots again under the new screens' ids: the root with the newest root tag owns the screen, and an older one that unmounts leaves it alone. |
94
- | `nativeScreens.ts` | The native screens shown, by id. Data props go as JSON (`passProps`); functions stay here, their names in `data.functions`, and the native side calls them (`ANN.NativeScreenCall`, answered with `resolveNativeScreenCall`). With `useProps`: the hidden host runs the hook (`startHost`, 5 s to start), the command waits for its first result, later changes go with `updateNativeScreenProps`. `ANN.NativeScreenReleased` forgets one. |
95
- | `props.ts` | The props of screens and of components in options, by id: a command puts them here before the native side creates the view; React Native passes a root only its id. Also which roots are the components of bar buttons (`isButtonRoot`): on iOS their wrapper centers the content in the slot. |
96
- | `events.ts` | `toScreenEvent(event)`: an event of a screen as `listeners`, `navigation.on`, the screen hooks and `onPress` get it: the screen as `screen: { id, name }`, without the fields of the native side. |
97
- | `places.ts` | Where each screen is, noted as the commands build their layouts: the root, a modal or an overlay, its stack and its index there, its side menu, its pair (`arrangement`: the pair's id and its placement; `alone` for a primary shown without one, `noteAlone`). The column of a split view each stack shows (`columnOf`, `stackOfColumn`), and whether a split view's columns show as one stack (`ANN.SplitViewColumnsStacked`, `listenToSplitViews`): `showInColumn` notes its screen first in the column's stack, or over the screen that asks in the compact column, and the first screen of a column over the one before it can pop (`coversColumn`). `canPop`, `canDismiss`, `dismiss` and `placeFor` read it at once; `isGone` knows the last screens that went. |
98
- | `buttons.ts` | The `onPress` handlers of the buttons of each screen and of their menu items, called on `NavigationButtonPressed`; the API gives the event its form (`setPressEvent`). |
99
- | `tabs.ts` | The press handlers of `Tab().onPress()`: they come with the tabs' layout, stay under the id the tabs are shown with, and go once every React screen shown in the tabs (pushed ones too) unmounted. |
100
- | `slots.ts` | One tree (`appProvider`): `slotName` sends a React screen as `slot:<name>`, the native side gives it an empty container, and the slot with its id in `SlotHost` renders it. `withSlots` takes back the slots of a failed command; `ANN.SlotDestroyed` removes one. For a push on Android: `holdSlot` (nothing renders until the native side laid the screen out), `showSlot` (at its `SlotFrame`; resolves once React committed it, `slotCommitted`), `preparedPadding` (the first padding of its safe area view). |
101
- | `launchState.ts` | The last root and default options: Android destroys the activity while JavaScript lives on and sends `AppLaunched` again; the app sets them again. |
102
- | `backListeners.ts` | Android: wraps `BackHandler.addEventListener` at the launch to count the listeners, and tells the native side whether there is one (`setBackListeners`): the navigation takes the back button only while it can go back or JavaScript listens. A listener added before the launch isn't counted. |
103
- | `reactMeasures.ts` | Development only: every command that shows or closes screens drops React's `performance.measure` entries of component renders (named after the component with U+200B in front). React Native keeps them without a limit, and a long session ran out of memory; the app's own measures stay. |
104
- | `ids.ts`, `mergeOptions.ts` | `nextId` and the merge of options; see Ids and Options in layers. |
88
+ | Module | What it does |
89
+ | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90
+ | `native.ts` | `commands`: the TurboModule (`src/adapters/NativeANNTurboModule.ts`). `onNativeEvent(name, listener)`: one native event, `ANN.<name>`. iOS sends events through `ANNTurboEventEmitter`; Android without a module. `getLaunchLink()`: the URL that launched the native side, null without the native side (Jest). `getStartInfo()`: `{ coldStart, splashLogo, arrangements }`, asked once; without the native side a cold start without a logo and without arrangements. |
91
+ | `layout.ts` | `toNativeLayout(layout)`: a `LayoutNode`, `{ id, type, data: { name, options, passProps?, functions?, key?, columns? }, children }`. For a screen, in this order: a name that shows a pair becomes an `Arrangement` node (see Pairs, regions and the hinge), an unknown name fails, its id, its own options under those of the show, the press handlers of its buttons taken out; then a native screen goes as an external component (`showNativeScreen`), a React screen with its `key`, its props kept here, as a slot in one tree. |
92
+ | `options.ts` | `toNativeOptions(options, owner)`: colors (iOS: a number, `{ light, dark }` or `'NoColor'`; Android: always `{ light, dark }`), images (`require` resolved), components in options (`componentId`, their props kept here; without an `id` of their own, `<owner>/<place>/<name>`, e.g. `Component12/topBar.title/Clock`, a list item by its id where it has one (`topBar.rightButtons[Save]`), the same on every `mergeOptions` of the node, so the native side keeps the mounted root), the props of buttons with a component, the roots of the bar buttons' components (`*Buttons`, the toolbar's `buttons`) remembered. Options come in their own form only. |
93
+ | `commands.ts` | `setRoot`, `push`, `pop`, `popTo`, `popToRoot`, `setStackRoot`, `showInColumn`, `setColumnShown`, `showModal`, `dismissModal`, `dismissAllModals`, `showOverlay`, `dismissOverlay`, `dismissAllOverlays`, `mergeOptions`, `clearOptions` (Fast Refresh, development), `setDefaultOptions`. One that shows screens waits for lazy ones (`afterLoading`), checks the ids (`checkIds`), notes the places and waits for the hooks of native screens (`whenNativeScreensReady`). On Android, in one tree, a push goes through `preparePush` first (see One command). |
94
+ | `screens.tsx` | The screens by name: a React component with its options, `key`, `load` (a lazy screen) and `arrangement` (its pair, if it has a secondary), a native screen (`nativeName`, the controller of its `useProps`, `arrangement`), or a pair entry of `defineArrangement` (`pair`). `arrangementOf(name)`: the pair a name shows; `checkArrangements` at registration, `checkArrangement` when a lazy screen's pair shows. `loadScreens`/`afterLoading`: a command goes once its lazy screens loaded, at once when none waits. A React screen is registered with `AppRegistry` as a root (`screenRoot`) that renders it with the props left for its id. After a JavaScript reload React Native starts the old roots again under the new screens' ids: a root that unmounts while another root of the id is mounted leaves the screen alone. The props of a component the library named in options go with its node, not with a root (several roots may show one default). |
95
+ | `nativeScreens.ts` | The native screens shown, by id. Data props go as JSON (`passProps`); functions stay here, their names in `data.functions`, and the native side calls them (`ANN.NativeScreenCall`, answered with `resolveNativeScreenCall`). With `useProps`: the hidden host runs the hook (`startHost`, 5 s to start), the command waits for its first result, later changes go with `updateNativeScreenProps`. `ANN.NativeScreenReleased` forgets one. |
96
+ | `props.ts` | The props of screens and of components in options, by id: a command puts them here before the native side creates the view; React Native passes a root only its id. Also which roots are the components of bar buttons (`isButtonRoot`): on iOS their wrapper centers the content in the slot. |
97
+ | `events.ts` | `toScreenEvent(event)`: an event of a screen as `listeners`, `navigation.on`, the screen hooks and `onPress` get it: the screen as `screen: { id, name }`, without the fields of the native side. |
98
+ | `places.ts` | Where each screen is, noted as the commands build their layouts: the root, a modal or an overlay, its stack and its index there, its side menu, its pair (`arrangement`: the pair's id and its placement; `alone` for a primary shown without one, `noteAlone`). The column of a split view each stack shows (`columnOf`, `stackOfColumn`), and whether a split view's columns show as one stack (`ANN.SplitViewColumnsStacked`, `listenToSplitViews`): `showInColumn` notes its screen first in the column's stack, or over the screen that asks in the compact column, and the first screen of a column over the one before it can pop (`coversColumn`). `canPop`, `canDismiss`, `dismiss` and `placeFor` read it at once; `isGone` knows the last screens that went. It also notes the layouts each screen shows in (`layoutsOf`): a layout whose last screen went is gone, and so are the props of the components named in its options. |
99
+ | `buttons.ts` | The `onPress` handlers of the buttons of each screen and of their menu items, called on `NavigationButtonPressed`; the API gives the event its form (`setPressEvent`). |
100
+ | `tabs.ts` | The press handlers of `Tab().onPress()`: they come with the tabs' layout, stay under the id the tabs are shown with, and go once every React screen shown in the tabs (pushed ones too) unmounted. |
101
+ | `slots.ts` | One tree (`appProvider`): `slotName` sends a React screen as `slot:<name>`, the native side gives it an empty container, and the slot with its id in `SlotHost` renders it. `withSlots` takes back the slots of a failed command; `ANN.SlotDestroyed` removes one. For a push on Android: `holdSlot` (nothing renders until the native side laid the screen out), `showSlot` (at its `SlotFrame`; resolves once React committed it, `slotCommitted`), `preparedPadding` (the first padding of its safe area view). |
102
+ | `refresh.ts` | Development only. Fast Refresh runs an edited module again and every export is a new function; `familyOf` and the newest-version lookup read React Refresh's family of a component (Metro registers each export under its module and name), so what the library keeps of a screen (options, `key`, `arrangement`) follows an edit without a reload. Nothing in a release build. |
103
+ | `optionsChange.ts` | `optionsChange(previous, next)`: what an edit of a screen's options changes: the options to merge (objects compare key by key, arrays and other values as a whole, functions by source) and the paths taken out, which go to the native `clearOptions`. |
104
+ | `launchState.ts` | The last root and default options: Android destroys the activity while JavaScript lives on and sends `AppLaunched` again; the app sets them again. |
105
+ | `backListeners.ts` | Android: wraps `BackHandler.addEventListener` at the launch to count the listeners, and tells the native side whether there is one (`setBackListeners`): the navigation takes the back button only while it can go back or JavaScript listens. A listener added before the launch isn't counted. |
106
+ | `reactMeasures.ts` | Development only: every command that shows or closes screens drops React's `performance.measure` entries of component renders (named after the component with U+200B in front). React Native keeps them without a limit, and a long session ran out of memory; the app's own measures stay. |
107
+ | `ids.ts`, `mergeOptions.ts` | `nextId` and the merge of options; see Ids and Options in layers. |
105
108
 
106
109
  ## The start of the app
107
110
 
@@ -135,6 +138,10 @@ form of `src/api/events/navigationEvents.ts`. Everything in `src/engine` is inte
135
138
  `launchState.root`, as it was passed (functions in props included), is set again. Then, with `linking`, the new
136
139
  activity's link runs as in a running app (`linksRelaunched`).
137
140
 
141
+ ## Hot update
142
+
143
+ `@apexnative/navigation/metro` (`withApexNavigation`) wraps the Metro config: it applies React Refresh's Babel plugin that React Native 0.87's transformer skips, and makes the module that imports `createNavigation` accept hot updates. When that module runs again, `createNavigation` meets a running navigation and updates it instead of starting: the screens (`registerScreens` again; a defined screen's options through `optionsChange` become `mergeOptions` and `clearOptions` on the screens that show; `key` and `arrangement` apply from the next show), the default options when `theme` or `options` changed, the roots, the listeners and the link routes. What only the start reads (the first root, `willMount`, the splash, the context) isn't run again. `defineScreen` returns the component, so a file that exports only screens is a Fast Refresh boundary; a native screen's component runs its `useProps`, and a change of its native name or of having `useProps` restarts the app.
144
+
138
145
  ## Links
139
146
 
140
147
  `linking` of `createNavigation` (`src/api/linking/`) turns URLs into commands; the native side keeps no routes.
@@ -247,15 +254,19 @@ name and on one id for two screens.
247
254
 
248
255
  `usePreview(nativeID, { screen, props, actions })` works on iOS only. It arms a `pushPreview` from its screen: a push
249
256
  with an id of its own (`Preview14`) and a `preview` option (`nativeID`, `commit`, the menu without its handlers, a
250
- size). The native side builds the screen and gives the view with that `nativeID` a context menu that previews it. A tap
251
- on the preview pushes the screen, the push resolves, and the hook arms the next one. A press of a menu item comes as
252
- `buttonPressed` of the preview's id, and the hook calls its `onPress`. A preview that goes without being shown rejects
253
- its push, which the hook ignores.
257
+ size). The native side makes the screen's node at once and gives the view with that `nativeID` a context menu that
258
+ previews it; a React screen gets its own root and renders when a press starts (the menu's configuration call, about
259
+ 0.5 s before the preview), so a hundred previews hold no rendered screens until one is pressed. A screen of the one
260
+ tree (`appProvider`) and a native screen render at once. A tap on the preview pushes the screen, the push resolves, and
261
+ the hook arms the next one. A press of a menu item comes as `buttonPressed` of the preview's id, and the hook calls its
262
+ `onPress`. A preview that goes without being shown rejects its push, which the hook ignores. One that goes before its
263
+ first press never mounted a root, so the engine forgets what the push noted for it (`forgetUnmountedPreview` in
264
+ `src/engine/commands.ts`, after 1 s, unless a root of it mounted by then).
254
265
 
255
266
  ## The native side's contract
256
267
 
257
268
  - Commands: the methods of `ANNTurboModule` (`src/adapters/NativeANNTurboModule.ts`), with the JSON above: those of
258
- `commands.ts`, each but `mergeOptions` and `setDefaultOptions` with a command id and a promise. A command that changed
269
+ `commands.ts`, each but `mergeOptions`, `clearOptions` and `setDefaultOptions` with a command id and a promise. A command that changed
259
270
  what the user sees sends `ANN.NavigationStateChanged` right before its promise resolves, so `getState()` after
260
271
  `await` shows its result and the next command acts from there. Besides them: `setBackListeners` (Android: whether
261
272
  JavaScript has `BackHandler` listeners; iOS does nothing), `preparePush` and `cancelPreparedPush` (Android, one
@@ -268,7 +279,9 @@ its push, which the hook ignores.
268
279
  given once; JS asks only with `linking`) and `getStartInfo` (synchronous: `coldStart`, true for the whole life of
269
280
  the first JavaScript runtime of the process, and `splashLogo`, the size of the native splash's logo the CLI wrote,
270
281
  or null; `arrangements`, whether it shows pairs). The links that come while the app runs reach JS through React Native's
271
- `Linking`, not through `ANN.*` events.
282
+ `Linking`, not through `ANN.*` events. One exception, iOS only: a link the app dispatched (`dispatchDeepLinkURL`) that
283
+ `Linking` doesn't take from the native side (React Native 0.88 and newer, with a scene delegate) comes as
284
+ `ANN.DeepLinkDispatched`, and `src/api/linking/dispatchedLinks.ts` hands it to `Linking` as a `url` event.
272
285
  - Events: `ANN.AppLaunched`, `ANN.ComponentWillAppear`, `ANN.ComponentDidAppear`, `ANN.ComponentDidDisappear`,
273
286
  `ANN.NavigationButtonPressed`, `ANN.BottomTabSelected`, `ANN.BottomTabPressed`, `ANN.BottomTabLongPressed`,
274
287
  `ANN.ModalDismissed`, `ANN.ModalAttemptedToDismiss`, `ANN.ScreenPopped`, `ANN.SearchBarUpdated`,
@@ -276,8 +289,8 @@ its push, which the hook ignores.
276
289
  `ANN.NavigationStateChanged`, `ANN.SlotDestroyed`, `ANN.ScreenInsetsChanged`, `ANN.TitleRenamed`,
277
290
  `ANN.BottomAccessoryPlacementChanged`, `ANN.SheetDetentChanged`, `ANN.SplitViewDisplayModeChanged`,
278
291
  `ANN.KeyCommandPressed`, `ANN.NativeScreenCall`, `ANN.NativeScreenReleased`, `ANN.ScreenRegionsChanged`,
279
- `ANN.ArrangementChanged`, `ANN.HingeChanged`, `ANN.SplitViewColumnsStacked`. Their payloads are typed in
280
- `src/interfaces/ComponentEvents.ts` and `Events.ts`. Both platforms also send `ANN.CommandCompleted`
292
+ `ANN.ArrangementChanged`, `ANN.HingeChanged`, `ANN.SplitViewColumnsStacked`, `ANN.DeepLinkDispatched` (iOS). Their
293
+ payloads are typed in `src/interfaces/ComponentEvents.ts` and `Events.ts`. Both platforms also send `ANN.CommandCompleted`
281
294
  (`CommandCompletedEvent`), which nothing in JS listens to.
282
295
  - Native components: `ANNSlot` (`src/api/slots`) and `ANNSafeAreaView` (`src/api/safeArea`), with C++ of their own in
283
296
  `ios/cpp`, which Android builds too (their states hold a size and a padding; the first one comes from the props
@@ -14,7 +14,14 @@ export interface Spec extends TurboModule {
14
14
  setDefaultOptions(options: CodegenTypes.UnsafeObject): void;
15
15
  /** Merges options into the layout with the id and applies them to what shows; an unknown id does nothing. */
16
16
  mergeOptions(componentId: string, options: CodegenTypes.UnsafeObject): void;
17
- /** Pushes a layout over the screen in its stack; resolves with the id of the screen that shows. */
17
+ /**
18
+ * (Development) Takes the options at the paths (`topBar.subtitle`, a group's path for the whole group) out of the own
19
+ * options of the layout with the id, so it shows what the layouts around it and the defaults give there, and applies
20
+ * the result to what shows as `setDefaultOptions` does. An unknown id or path does nothing. Fast Refresh sends it
21
+ * for the options an edit took out of a screen that shows.
22
+ */
23
+ clearOptions(componentId: string, paths: ReadonlyArray<string>): void;
24
+ /** Pushes a layout over the screen in its stack; resolves with the id of the screen that shows (of a pair: its id). */
18
25
  push(commandId: string, componentId: string, layout: CodegenTypes.UnsafeObject): Promise<string>;
19
26
  /**
20
27
  * (Android, one React tree) Lays the screen of a coming push out in its stack before React renders it, and resolves
@@ -67,7 +74,10 @@ export interface Spec extends TurboModule {
67
74
  column: string,
68
75
  layout: CodegenTypes.UnsafeObject
69
76
  ): Promise<string>;
70
- /** Shows or hides a column of the screen's split view; resolves once the columns stopped moving. */
77
+ /**
78
+ * Shows or hides a column of the screen's split view; resolves once the columns stopped moving, with nothing (on
79
+ * Android `null`).
80
+ */
71
81
  setColumnShown(
72
82
  commandId: string,
73
83
  componentId: string,
@@ -1,8 +1,14 @@
1
1
  import { AppRegistry as ReactNativeAppRegistry } from 'react-native';
2
2
  import { onNativeEvent } from '../../engine/native';
3
+ import { familyOf } from '../../engine/refresh';
3
4
  import { SLOT_HOST_MODULE } from '../../engine/slots';
4
5
  import { SlotHost } from '../slots/SlotHost';
5
- import { isNavigationApp, type NavigationApp, startApp } from './createNavigation';
6
+ import {
7
+ isNavigationApp,
8
+ type NavigationApp,
9
+ noteReplacingApp,
10
+ startApp,
11
+ } from './createNavigation';
6
12
 
7
13
  type NavigationAppProvider = () => NavigationApp<any, any>;
8
14
 
@@ -35,7 +41,15 @@ function registerComponent(
35
41
  navigation: NavigationApp<any, any> | NavigationAppProvider
36
42
  ): string {
37
43
  if (__DEV__ && registered) {
38
- console.warn(`[navigation] '${key}' replaces the app registered as '${appKey}'`);
44
+ // The entry file running again after an edit (Fast Refresh) registers its new version of the same app under the
45
+ // same name; Metro puts one it exports in the family of the old one once the file ran.
46
+ if (key === appKey) noteReplacingApp(navigation);
47
+ const before = { key: appKey, app: registered };
48
+ Promise.resolve().then(() => {
49
+ const family = familyOf(before.app);
50
+ if (key === before.key || (family && family === familyOf(navigation))) return;
51
+ console.warn(`[navigation] '${key}' replaces the app registered as '${before.key}'`);
52
+ });
39
53
  }
40
54
  appKey = key;
41
55
  registered = navigation;
@@ -1,7 +1,10 @@
1
1
  import type { ComponentType } from 'react';
2
+ import { DevSettings } from 'react-native';
2
3
  import { setDefaultOptions, setRoot } from '../../engine/commands';
3
4
  import { type AppProvider, enableSlots, withSlots } from '../../engine/slots';
4
5
  import { listenToNativeScreens, startHost } from '../../engine/nativeScreens';
6
+ import { sameValue } from '../../engine/optionsChange';
7
+ import { familyOf, keepStateOf, refreshRuns } from '../../engine/refresh';
5
8
  import { listenToSplitViews } from '../../engine/places';
6
9
  import { hasNativeScreenHooks } from '../../engine/screens';
7
10
  import type { LayoutRoot } from '../../interfaces/Layout';
@@ -24,7 +27,10 @@ import type { ErrorFallbackProps } from '../screens/ScreenBoundary';
24
27
  import { getAppContext, setAppContext } from '../context/appContext';
25
28
  import {
26
29
  type AppOptionsInput,
30
+ getDirection,
31
+ getTheme,
27
32
  initTheme,
33
+ setTheme,
28
34
  type NavigationDirection,
29
35
  type NavigationTheme,
30
36
  themedDefaultOptions,
@@ -43,6 +49,7 @@ import {
43
49
  import { launchState } from '../../engine/launchState';
44
50
  import { watchBackListeners } from '../../engine/backListeners';
45
51
  import { resolveRoot, type RootsMap, type RootTarget, type UsesOfRootValue } from './roots';
52
+ import { listenToDispatchedLinks } from '../linking/dispatchedLinks';
46
53
  import {
47
54
  launchLink,
48
55
  launchRoot,
@@ -50,6 +57,7 @@ import {
50
57
  linksStarted,
51
58
  reportLink,
52
59
  setupLinking,
60
+ updateLinking,
53
61
  } from '../linking/linking';
54
62
  import type { LinkMatch } from '../linking/linkPaths';
55
63
  import type { LinkingConfig } from '../linking/types';
@@ -85,6 +93,9 @@ const starts = new WeakMap<NavigationApp<any, any>, () => Promise<void>>();
85
93
 
86
94
  /** Starts the app, or brings back its root when the native side launches again. */
87
95
  export function startApp(app: NavigationApp<any, any>): Promise<void> {
96
+ // An app made after another launched knows once its module ran whether it is that app's next version.
97
+ const waiting = pending.get(app);
98
+ if (waiting) return waiting.then(() => startApp(app));
88
99
  const start = starts.get(app);
89
100
  if (!start) throw new Error('[navigation] Not an app made by createNavigation');
90
101
  return start();
@@ -150,9 +161,9 @@ interface BaseConfig<
150
161
  /** The look of the navigation: colors of the bars, tabs and backgrounds; `navigation.setTheme` changes it. */
151
162
  theme?: NavigationTheme;
152
163
  /**
153
- * The edges on which every screen keeps its content out of its safe area. Without it: all four on Android; on iOS
154
- * every edge but those where the content goes under a bar that shows. A screen gives its own with `safeArea(...)`
155
- * in its options.
164
+ * The edges on which every screen keeps its content out of its safe area. Without it: the top and the sides, but
165
+ * those where the content goes under a bar (`layout.safeAreaEdges`); the bottom is free and a list keeps clear of it
166
+ * with `useSafeAreaInsets()`. A screen gives its own with `safeArea(...)` in its options.
156
167
  */
157
168
  safeArea?: { edges: SafeAreaEdge[] };
158
169
  /** (iOS) The app's window, behind the screens: seen around a modal as it comes in. */
@@ -239,7 +250,11 @@ type CheckedRoots<Root, Roots, AppScreens> = {
239
250
  };
240
251
 
241
252
  export function isNavigationApp(value: unknown): value is NavigationApp {
242
- return typeof value === 'object' && value !== null && starts.has(value as NavigationApp);
253
+ return (
254
+ typeof value === 'object' &&
255
+ value !== null &&
256
+ (starts.has(value as NavigationApp) || pending.has(value as NavigationApp))
257
+ );
243
258
  }
244
259
 
245
260
  /**
@@ -276,14 +291,18 @@ export function createNavigation<
276
291
  > &
277
292
  NoInfer<CheckedRoots<FirstLayout, Roots, AllScreens<AppScreens, Groups>>>
278
293
  ): NavigationApp<Roots, AllScreens<AppScreens, Groups>> {
294
+ // The app that launched before, when this call may be its module running again after an edit (Fast Refresh): what
295
+ // the call starts waits until that is known.
296
+ const launched = __DEV__ ? hotCandidate() : undefined;
279
297
  // Counted from here: a "back again to leave" listener of the app's entry file comes after this call.
280
- watchBackListeners();
298
+ if (!launched) watchBackListeners();
281
299
  // idle: not started yet, or the last start failed. mounting: the first root is on its way. mounted: it is shown.
282
300
  let phase: 'idle' | 'mounting' | 'mounted' = 'idle';
283
301
  let screensRegistered = false;
284
302
  // The splash shows at the first start of this runtime only: a start that failed and runs again goes without it.
285
303
  let splashChecked = false;
286
304
  let listening = false;
305
+ let removeListeners: (() => void) | undefined;
287
306
  let prepared: Promise<void> | undefined;
288
307
  let markMounted!: () => void;
289
308
  // A new activity came while the first root was on its way (Android): its link is taken once that root is shown.
@@ -324,6 +343,62 @@ export function createNavigation<
324
343
  return buildRoot(typeof root === 'function' ? root(context) : root);
325
344
  }
326
345
 
346
+ // The screens of the app, its groups, the screen of a failed start and the splash, with what wraps each of them.
347
+ function registerAppScreens() {
348
+ const wrapper = {
349
+ errorFallback: config.errorFallback,
350
+ loadingFallback: config.loadingFallback,
351
+ onError:
352
+ config.onError &&
353
+ ((error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) =>
354
+ config.onError?.(error, { type: 'screen', screen, componentStack })),
355
+ };
356
+ registerScreens(
357
+ [
358
+ { source: 'screens', screens: config.screens ?? {} },
359
+ ...Object.entries(config.groups ?? {}).map(([group, { screens, options }]) => ({
360
+ source: `the group '${group}'`,
361
+ screens,
362
+ options,
363
+ })),
364
+ ...(config.errorFallback
365
+ ? [
366
+ {
367
+ source: 'the start',
368
+ screens: { [START_FAILURE_SCREEN]: startFailureScreen(config.errorFallback) },
369
+ },
370
+ ]
371
+ : []),
372
+ ],
373
+ { ...wrapper, provider: config.screenProvider }
374
+ );
375
+ // The splash renders before willMount ends: a root of its own, without the app's providers, which may need what
376
+ // willMount prepares.
377
+ if (config.splash) {
378
+ registerScreens(
379
+ [
380
+ {
381
+ source: 'the splash',
382
+ screens: { [SPLASH_SCREEN]: config.splash.component },
383
+ ownRoot: true,
384
+ },
385
+ ],
386
+ {
387
+ ...wrapper,
388
+ // A splash that failed to render can't call hide(): the start goes on without waiting for it.
389
+ onError: (
390
+ error: unknown,
391
+ screen: ScreenInfo,
392
+ componentStack: string | null | undefined
393
+ ) => {
394
+ releaseSplash();
395
+ wrapper.onError?.(error, screen, componentStack);
396
+ },
397
+ }
398
+ );
399
+ }
400
+ }
401
+
327
402
  async function mount() {
328
403
  phase = 'mounting';
329
404
  // The state before the first root: the links wait for a newer one, which tells the screen they act from.
@@ -332,54 +407,7 @@ export function createNavigation<
332
407
  let linkHandled = false;
333
408
  try {
334
409
  if (!screensRegistered) {
335
- const wrapper = {
336
- errorFallback: config.errorFallback,
337
- loadingFallback: config.loadingFallback,
338
- onError:
339
- config.onError &&
340
- ((error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) =>
341
- config.onError?.(error, { type: 'screen', screen, componentStack })),
342
- };
343
- registerScreens(
344
- [
345
- { source: 'screens', screens: config.screens ?? {} },
346
- ...Object.entries(config.groups ?? {}).map(([group, { screens, options }]) => ({
347
- source: `the group '${group}'`,
348
- screens,
349
- options,
350
- })),
351
- ...(config.errorFallback
352
- ? [
353
- {
354
- source: 'the start',
355
- screens: { [START_FAILURE_SCREEN]: startFailureScreen(config.errorFallback) },
356
- },
357
- ]
358
- : []),
359
- ],
360
- { ...wrapper, provider: config.screenProvider }
361
- );
362
- // The splash renders before willMount ends: a root of its own, without the app's providers, which may need what
363
- // willMount prepares.
364
- if (config.splash) {
365
- registerScreens(
366
- [
367
- {
368
- source: 'the splash',
369
- screens: { [SPLASH_SCREEN]: config.splash.component },
370
- ownRoot: true,
371
- },
372
- ],
373
- {
374
- ...wrapper,
375
- // A splash that failed to render can't call hide(): the start goes on without waiting for it.
376
- onError: (error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) => {
377
- releaseSplash();
378
- wrapper.onError?.(error, screen, componentStack);
379
- },
380
- }
381
- );
382
- }
410
+ registerAppScreens();
383
411
  screensRegistered = true;
384
412
  }
385
413
  // The link that launched the app is asked for first: on iOS the first React content to appear (the host below,
@@ -484,28 +512,22 @@ export function createNavigation<
484
512
  }
485
513
 
486
514
  async function launch() {
515
+ if (__DEV__) launchedApp = app;
487
516
  setActiveApp({ roots: config.roots, presentation: config.presentation, mounted });
488
517
  if (!listening) {
489
518
  listening = true;
490
519
  // The edges of `safeArea` go under the app's options; the window's color goes with them, as the native side
491
520
  // takes it from the default options.
492
- initTheme(
493
- config.theme,
494
- {
495
- under: config.safeArea && { layout: { safeAreaEdges: config.safeArea.edges } },
496
- options: config.options,
497
- over: config.window && { window: config.window },
498
- },
499
- config.direction
500
- );
521
+ initTheme(config.theme, appDefaults(), config.direction);
501
522
  if (config.context !== undefined) setAppContext(config.context);
502
523
  if (config.appProvider) enableSlots(config.appProvider);
503
524
  listenToNavigationState();
525
+ listenToDispatchedLinks();
504
526
  watchSideMenus();
505
527
  listenToNativeScreens();
506
528
  listenToSplitViews();
507
529
  listenToNativeScreenCalls();
508
- if (config.listeners) addNavigationListeners(config.listeners);
530
+ if (config.listeners) removeListeners = addNavigationListeners(config.listeners);
509
531
  }
510
532
  launchState.launch++;
511
533
  // A new activity has no default options: the last ones set come back, else the theme's and the app's.
@@ -526,19 +548,131 @@ export function createNavigation<
526
548
  relaunchWaiters.splice(0).forEach((resume) => resume());
527
549
  }
528
550
 
529
- // The links listen from now on: one that comes before the native side launches waits for the first root.
530
- if (config.linking) {
531
- setupLinking(config.linking, {
551
+ // The routes of the links, the roots they name and where their errors go.
552
+ function linkingOptions() {
553
+ return {
532
554
  roots: config.roots,
533
- onError: config.onError && ((error, url) => config.onError?.(error, { type: 'link', url })),
534
- });
555
+ onError:
556
+ config.onError &&
557
+ ((error: unknown, url: string) => config.onError?.(error, { type: 'link', url })),
558
+ };
559
+ }
560
+
561
+ // Fast Refresh ran the module that makes the app again (development): its new config takes the place of the old.
562
+ // What only the start reads (the first root, willMount, the splash, the context) has done its part; the screens, the
563
+ // default options, the roots, the listeners and the links take the new one. A theme the same as before leaves the one
564
+ // the app set since. The providers and fallbacks are in the families of the ones before (`keepStateOf`): React
565
+ // Refresh puts the new ones in place, with the state of what they wrap.
566
+ function update(next: typeof config) {
567
+ const before = config;
568
+ // The app's one tree is set up at the start, or not: a provider added or taken out starts the app again.
569
+ if (!before.appProvider !== !next.appProvider) {
570
+ DevSettings.reload('[navigation] appProvider was added or taken out');
571
+ return;
572
+ }
573
+ config = next;
574
+ if (screensRegistered) registerAppScreens();
575
+ setActiveApp({ roots: config.roots, presentation: config.presentation, mounted });
576
+ // A direction the app set since stays too, unless the edit changes the config's.
577
+ const defaultsBefore = themedDefaultOptions();
578
+ const direction = sameValue(before.direction, next.direction) ? getDirection() : next.direction;
579
+ initTheme(getTheme(), appDefaults(), direction);
580
+ if (!sameValue(before.theme, next.theme)) {
581
+ setTheme(next.theme ?? {});
582
+ } else {
583
+ const defaults = themedDefaultOptions();
584
+ if (!sameValue(defaultsBefore, defaults)) setDefaultOptions(defaults ?? {});
585
+ }
586
+ if (listening) {
587
+ removeListeners?.();
588
+ removeListeners = config.listeners && addNavigationListeners(config.listeners);
589
+ }
590
+ if (config.linking && linkingStarted) updateLinking(config.linking, linkingOptions());
591
+ else startLinking();
592
+ }
593
+
594
+ // The default options of the app, under and over the theme's.
595
+ function appDefaults() {
596
+ return {
597
+ under: config.safeArea && { layout: { safeAreaEdges: config.safeArea.edges } },
598
+ options: config.options,
599
+ over: config.window && { window: config.window },
600
+ };
601
+ }
602
+
603
+ // The links listen from now on: one that comes before the native side launches waits for the first root.
604
+ let linkingStarted = false;
605
+ function startLinking() {
606
+ if (!config.linking || linkingStarted) return;
607
+ linkingStarted = true;
608
+ setupLinking(config.linking, linkingOptions());
609
+ }
610
+
611
+ // The components of the app keep their state across Fast Refresh, as the screens' do.
612
+ function keepComponentsState() {
613
+ if (!__DEV__) return;
614
+ keepStateOf(app, config.appProvider, 'appProvider');
615
+ keepStateOf(app, config.screenProvider, 'screenProvider');
616
+ keepStateOf(app, config.errorFallback, 'errorFallback');
617
+ keepStateOf(app, config.loadingFallback, 'loadingFallback');
618
+ keepStateOf(app, config.splash?.component, 'splash');
535
619
  }
536
620
 
537
621
  const app: NavigationApp<Roots, AllScreens<AppScreens, Groups>> = { [NAVIGATION_APP]: true };
538
- starts.set(app, () => reportStart(launch));
622
+ keepComponentsState();
623
+ const start = () => {
624
+ startLinking();
625
+ starts.set(app, () => reportStart(launch));
626
+ if (__DEV__) updates.set(app, update as (config: unknown) => void);
627
+ };
628
+ if (!launched) {
629
+ start();
630
+ return app;
631
+ }
632
+ // Once the module ran, Metro has put its exports in the families of the ones of its run before: the same family as
633
+ // the app that launched, or the app's entry registering it under the app's name again (an app it doesn't export),
634
+ // means this is its module again, and the app that runs takes the new config.
635
+ pending.set(
636
+ app,
637
+ Promise.resolve().then(() => {
638
+ pending.delete(app);
639
+ const family = familyOf(app);
640
+ if ((family && family === familyOf(launched)) || replacing.delete(app)) {
641
+ updates.get(launched)?.(config);
642
+ starts.set(app, starts.get(launched)!);
643
+ updates.set(app, updates.get(launched)!);
644
+ return;
645
+ }
646
+ watchBackListeners();
647
+ start();
648
+ })
649
+ );
539
650
  return app;
540
651
  }
541
652
 
653
+ // The app that launched in this runtime, and what takes the config of its module when it runs again (development).
654
+ let launchedApp: NavigationApp<any, any> | undefined;
655
+ const updates = new WeakMap<NavigationApp<any, any>, (config: unknown) => void>();
656
+ // The apps made after the launch until their module ran, and those the app's entry registered again under its name.
657
+ const pending = new WeakMap<NavigationApp<any, any>, Promise<void>>();
658
+ const replacing = new WeakSet<NavigationApp<any, any>>();
659
+
660
+ /**
661
+ * Notes an app the entry file registers under the name of the app that launched: the entry ran again after an edit
662
+ * (development), and the new app is the old one's next version.
663
+ */
664
+ export function noteReplacingApp(app: unknown): void {
665
+ if (__DEV__ && launchedApp && typeof app === 'object' && app !== null && NAVIGATION_APP in app) {
666
+ replacing.add(app as NavigationApp<any, any>);
667
+ }
668
+ }
669
+
670
+ // The app that launched, when React Refresh runs and a new app may be its module running again: one its module
671
+ // exports (Metro gives it a family), or one the entry registers again under the app's name.
672
+ function hotCandidate(): NavigationApp<any, any> | undefined {
673
+ return launchedApp && refreshRuns() ? launchedApp : undefined;
674
+ }
675
+
542
676
  // A willMount that never ends keeps the splash screen for good: in development the app hears of it.
543
677
  function warnIfLong(willMount: Promise<void>) {
544
678
  const timer = setTimeout(