@apexnative/navigation 1.0.0-alpha.5 → 1.0.0-alpha.7

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 (358) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +32 -0
  3. package/README.md +1 -1
  4. package/android/CLAUDE.md +31 -20
  5. package/android/CORE.md +12 -8
  6. package/android/consumer-rules.pro +6 -0
  7. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +36 -5
  8. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  9. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  10. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
  11. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  12. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  13. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  14. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  15. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  16. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  18. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  19. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  20. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  21. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +7 -3
  22. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
  23. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
  24. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +0 -2
  25. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  26. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +12 -49
  27. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  28. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +6 -6
  29. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
  30. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
  31. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  32. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  33. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  34. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +9 -7
  35. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  36. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +13 -10
  37. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  38. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  39. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +7 -8
  40. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  41. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  42. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +20 -2
  43. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +443 -58
  44. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +33 -5
  45. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  46. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
  47. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +4 -0
  48. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +3 -6
  49. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
  50. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
  51. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  52. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +2 -2
  53. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +50 -7
  54. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
  55. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +10 -4
  56. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  57. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
  58. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
  59. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  60. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  61. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +36 -38
  62. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  63. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  64. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  65. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  66. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  67. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +129 -179
  68. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
  69. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  70. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +67 -3
  71. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  72. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  73. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -42
  74. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  75. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  76. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  77. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  78. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
  79. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
  80. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  81. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  82. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  83. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
  84. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  85. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  86. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  87. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  88. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  89. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  90. package/android/src/main/res/values/styles.xml +1 -1
  91. package/android/src/main/res/values-night/styles.xml +1 -1
  92. package/cli/doctor/checks/app.js +16 -1
  93. package/cli/project.js +4 -0
  94. package/cli/setup/index.js +5 -0
  95. package/cli/setup/steps/metro.js +46 -0
  96. package/docs-md/architecture/native-screens.md +4 -0
  97. package/docs-md/architecture/theme-and-context.md +131 -12
  98. package/docs-md/architecture/transitions.md +46 -5
  99. package/docs-md/containers/modals.md +2 -0
  100. package/docs-md/containers/overlays.md +1 -1
  101. package/docs-md/containers/side-menu.md +1 -1
  102. package/docs-md/containers/tabs.md +2 -0
  103. package/docs-md/flows/bottom-sheets.md +4 -2
  104. package/docs-md/fundamentals/screens-and-props.md +9 -1
  105. package/docs-md/fundamentals/starting-the-app.md +1 -1
  106. package/docs-md/guides/cli.md +3 -1
  107. package/docs-md/help/glossary.md +2 -2
  108. package/docs-md/help/troubleshooting.md +22 -1
  109. package/docs-md/index.json +41 -1
  110. package/docs-md/migration/from-expo-router.md +1 -1
  111. package/docs-md/migration/from-react-native-navigation.md +1 -1
  112. package/docs-md/migration/from-react-navigation.md +2 -2
  113. package/docs-md/screen-ui/back-and-gestures.md +17 -1
  114. package/docs-md/screen-ui/bar-buttons.md +5 -5
  115. package/docs-md/screen-ui/search.md +1 -1
  116. package/docs-md/screen-ui/system-ui.md +16 -11
  117. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  118. package/docs-md/screen-ui/top-bar.md +8 -4
  119. package/docs-md/start/installation.md +16 -1
  120. package/ios/Animations/ANNFrameDriver.h +55 -15
  121. package/ios/Animations/ANNFrameDriver.mm +216 -60
  122. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  123. package/ios/Animations/ANNTransitionAnimator.mm +49 -3
  124. package/ios/Animations/ANNTransitionPlan.h +2 -2
  125. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  126. package/ios/Animations/Elements/ANNElementFinder.h +2 -2
  127. package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
  128. package/ios/Animations/Elements/ANNElementTransition.h +3 -3
  129. package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
  130. package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
  131. package/ios/Animations/Elements/ANNSharedElementFlight.mm +249 -45
  132. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  133. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  134. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  135. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  136. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  137. package/ios/CLAUDE.md +32 -22
  138. package/ios/CORE.md +25 -21
  139. package/ios/Contract/ANNCommandRunner.h +8 -7
  140. package/ios/Contract/ANNCommandRunner.mm +21 -27
  141. package/ios/Contract/ANNLayoutNode.h +3 -3
  142. package/ios/Contract/ANNLayoutReader.h +3 -3
  143. package/ios/Core/ANNAppDelegate.mm +0 -2
  144. package/ios/Core/ANNDeepLinkQueue.h +6 -5
  145. package/ios/Core/ANNDeepLinkQueue.mm +22 -10
  146. package/ios/Core/ANNJavaScriptCalls.h +11 -12
  147. package/ios/Core/ANNJavaScriptCalls.mm +7 -16
  148. package/ios/Core/ANNReloadCoordinator.mm +4 -8
  149. package/ios/Core/ANNSceneDelegate.mm +2 -2
  150. package/ios/Core/ApexNavigation+Internal.h +1 -1
  151. package/ios/Core/ApexNavigation.mm +6 -2
  152. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  153. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  154. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +4 -4
  155. package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
  156. package/ios/Layouts/Screen/ANNComponentViewController.h +2 -2
  157. package/ios/Layouts/Screen/ANNComponentViewController.mm +13 -23
  158. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  159. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  160. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  161. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  162. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  163. package/ios/Layouts/Screen/ANNScreenRegions.mm +0 -38
  164. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  165. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  166. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  167. package/ios/Layouts/Stack/ANNPreviewPush.mm +57 -5
  168. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  169. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  170. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  171. package/ios/Layouts/Stack/ANNStackController.mm +153 -11
  172. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  173. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  174. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  175. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  176. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  177. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +2 -1
  178. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  179. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +4 -0
  180. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +123 -36
  181. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  182. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  183. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  184. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  185. package/ios/Options/ANNAnimationOptions.h +2 -1
  186. package/ios/Options/ANNAnimationOptions.mm +1 -1
  187. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  188. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  189. package/ios/Options/ANNOptions.h +25 -0
  190. package/ios/Options/ANNOptions.mm +157 -1
  191. package/ios/Options/ANNOptionsReader.mm +108 -0
  192. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  193. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  194. package/ios/Options/Params/ANNParam.h +15 -0
  195. package/ios/Options/Params/ANNParam.mm +61 -0
  196. package/ios/Options/Params/Color.h +3 -0
  197. package/ios/Options/Params/Color.mm +21 -0
  198. package/ios/Options/Params/ColorParser.h +4 -3
  199. package/ios/Options/Params/ColorParser.mm +22 -4
  200. package/ios/Options/Params/Image.h +4 -0
  201. package/ios/Options/Params/Image.mm +20 -0
  202. package/ios/React/ANNReactView.mm +6 -25
  203. package/ios/React/ANNSafeAreaViewComponentView.mm +26 -15
  204. package/ios/React/ANNSurfaceHostingView.h +14 -0
  205. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  206. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  207. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  208. package/ios/TopBar/ANNBarAppearance.h +2 -1
  209. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  210. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  211. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  212. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  213. package/ios/TopBar/ANNBarButtons.h +5 -3
  214. package/ios/TopBar/ANNBarButtons.mm +186 -17
  215. package/ios/TopBar/ANNLargeTitlePresenter.mm +24 -4
  216. package/ios/TopBar/ANNMainList.h +3 -0
  217. package/ios/TopBar/ANNMainList.mm +4 -0
  218. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  219. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  220. package/ios/TopBar/ANNSearchPresenter.mm +2 -2
  221. package/ios/TopBar/ANNSearchResultsViewController.mm +5 -5
  222. package/ios/TopBar/ANNTopBarPresenter.h +3 -2
  223. package/ios/TopBar/ANNTopBarPresenter.mm +95 -22
  224. package/ios/TurboModules/ANNTurboModule.mm +66 -16
  225. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  226. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  227. package/lib/module/ARCHITECTURE.md +17 -7
  228. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  229. package/lib/module/api/app/AppRegistry.js +14 -2
  230. package/lib/module/api/app/AppRegistry.js.map +1 -1
  231. package/lib/module/api/app/createNavigation.js +188 -66
  232. package/lib/module/api/app/createNavigation.js.map +1 -1
  233. package/lib/module/api/events/navigationEvents.js +6 -2
  234. package/lib/module/api/events/navigationEvents.js.map +1 -1
  235. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  236. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  237. package/lib/module/api/linking/linking.js +11 -0
  238. package/lib/module/api/linking/linking.js.map +1 -1
  239. package/lib/module/api/options/OptionsChain.js +2 -2
  240. package/lib/module/api/screens/defineScreen.js +45 -3
  241. package/lib/module/api/screens/defineScreen.js.map +1 -1
  242. package/lib/module/api/screens/nativeScreens.js +31 -6
  243. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  244. package/lib/module/api/screens/registerScreens.js +172 -35
  245. package/lib/module/api/screens/registerScreens.js.map +1 -1
  246. package/lib/module/api/theme/theme.js +5 -0
  247. package/lib/module/api/theme/theme.js.map +1 -1
  248. package/lib/module/engine/commands.js +42 -2
  249. package/lib/module/engine/commands.js.map +1 -1
  250. package/lib/module/engine/layout.js +7 -2
  251. package/lib/module/engine/layout.js.map +1 -1
  252. package/lib/module/engine/nativeScreens.js +9 -0
  253. package/lib/module/engine/nativeScreens.js.map +1 -1
  254. package/lib/module/engine/options.js +5 -4
  255. package/lib/module/engine/options.js.map +1 -1
  256. package/lib/module/engine/optionsChange.js +102 -0
  257. package/lib/module/engine/optionsChange.js.map +1 -0
  258. package/lib/module/engine/refresh.js +85 -0
  259. package/lib/module/engine/refresh.js.map +1 -0
  260. package/lib/module/engine/rememberedOptions.js +60 -0
  261. package/lib/module/engine/rememberedOptions.js.map +1 -1
  262. package/lib/module/engine/screens.js +55 -4
  263. package/lib/module/engine/screens.js.map +1 -1
  264. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
  265. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  266. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  267. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  268. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  269. package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
  270. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  271. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  272. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  273. package/lib/typescript/api/index.d.ts +1 -1
  274. package/lib/typescript/api/index.d.ts.map +1 -1
  275. package/lib/typescript/api/linking/linking.d.ts +8 -0
  276. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  277. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  278. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  279. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  280. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  281. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  282. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  283. package/lib/typescript/api/theme/theme.d.ts +2 -0
  284. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  285. package/lib/typescript/engine/commands.d.ts +5 -0
  286. package/lib/typescript/engine/commands.d.ts.map +1 -1
  287. package/lib/typescript/engine/layout.d.ts.map +1 -1
  288. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  289. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  290. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  291. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  292. package/lib/typescript/engine/refresh.d.ts +35 -0
  293. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  294. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  295. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  296. package/lib/typescript/engine/screens.d.ts +27 -6
  297. package/lib/typescript/engine/screens.d.ts.map +1 -1
  298. package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
  299. package/lib/typescript/interfaces/options/animations.d.ts +44 -14
  300. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  301. package/lib/typescript/interfaces/options/bottomTabs.d.ts +19 -6
  302. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  303. package/lib/typescript/interfaces/options/buttons.d.ts +10 -10
  304. package/lib/typescript/interfaces/options/modals.d.ts +6 -7
  305. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  306. package/lib/typescript/interfaces/options/stack.d.ts +8 -3
  307. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  308. package/lib/typescript/interfaces/options/system.d.ts +8 -5
  309. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  310. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  311. package/lib/typescript/interfaces/options/topBar.d.ts +46 -29
  312. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  313. package/metro/acceptPlugin.js +57 -0
  314. package/metro/babelTransformer.js +45 -0
  315. package/metro/index.js +36 -0
  316. package/package.json +3 -1
  317. package/src/ARCHITECTURE.md +17 -7
  318. package/src/adapters/NativeANNTurboModule.ts +7 -0
  319. package/src/api/app/AppRegistry.ts +16 -2
  320. package/src/api/app/createNavigation.ts +201 -69
  321. package/src/api/events/navigationEvents.ts +9 -3
  322. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  323. package/src/api/index.ts +1 -0
  324. package/src/api/linking/linking.ts +22 -1
  325. package/src/api/options/OptionsChain.ts +2 -2
  326. package/src/api/screens/defineScreen.ts +49 -5
  327. package/src/api/screens/nativeScreens.ts +40 -4
  328. package/src/api/screens/registerScreens.tsx +170 -42
  329. package/src/api/theme/theme.ts +5 -0
  330. package/src/engine/commands.ts +51 -6
  331. package/src/engine/layout.ts +11 -2
  332. package/src/engine/nativeScreens.ts +10 -1
  333. package/src/engine/options.ts +6 -8
  334. package/src/engine/optionsChange.ts +107 -0
  335. package/src/engine/refresh.ts +97 -0
  336. package/src/engine/rememberedOptions.ts +70 -0
  337. package/src/engine/screens.tsx +53 -8
  338. package/src/interfaces/ComponentEvents.ts +2 -2
  339. package/src/interfaces/options/animations.ts +44 -14
  340. package/src/interfaces/options/bottomTabs.ts +19 -6
  341. package/src/interfaces/options/buttons.ts +10 -10
  342. package/src/interfaces/options/modals.ts +6 -7
  343. package/src/interfaces/options/stack.ts +8 -3
  344. package/src/interfaces/options/system.ts +8 -5
  345. package/src/interfaces/options/toolbar.ts +2 -2
  346. package/src/interfaces/options/topBar.ts +46 -29
  347. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -42
  348. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -70
  349. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  350. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  351. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -136
  352. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -86
  353. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  354. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -64
  355. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -177
  356. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -137
  357. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  358. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -70
@@ -64,8 +64,8 @@ The look and the state of a button:
64
64
  | --- | --- |
65
65
  | `color` | The color of this button. |
66
66
  | `enabled: false` | Dimmed; a press does nothing. |
67
- | `style: 'prominent'` | (iOS) The main action, such as Done or Send. On iOS 26 a filled capsule in the button's `color`; before, a bold title. |
68
- | `group` | (iOS) 26: buttons with the same group share one glass capsule; each other button has a capsule of its own. |
67
+ | `style: 'prominent'` | (iOS) The main action, such as Done or Send. With the glass design a filled capsule in the button's `color`; without it, a bold title. See [the glass design](./top-bar#glass-design). |
68
+ | `group` | (iOS) Glass design: buttons with the same group share one glass capsule; each other button has a capsule of its own. |
69
69
  | `badge` | (iOS) 26: a number, a short text, or `true` for a dot. |
70
70
  | `toggle`, `selected` | (iOS) A button that switches on and off at each tap; the press carries the new state as `selected`. |
71
71
 
@@ -148,7 +148,7 @@ useNavigationButton('sort-name', () => setSort('name'));
148
148
  | Platform | The menu |
149
149
  | --- | --- |
150
150
  | (iOS) | The system menu, with SF Symbols, submenus and a check on the picked item. |
151
- | (Android) | The Material popup menu under the button, with the same items, without the `title` of the menu. |
151
+ | (Android) | The Material popup menu under the button, with the same items, without the `title` of the menu. `topBar.menuBackgroundColor` and `topBar.menuTextColor` color it and "⋮"; without them it takes the bar's color and the title's color, in light and dark mode. |
152
152
 
153
153
  ## The overflow menu
154
154
 
@@ -248,7 +248,7 @@ s.rightButtons({
248
248
  });
249
249
  ```
250
250
 
251
- The bar sends no press for it: the component's own `onPress` is the press. On (iOS) 26 it has no glass capsule; `hideSharedBackground: false` puts it on one. On (Android) `component.width` and `height` size it.
251
+ The bar sends no press for it: the component's own `onPress` is the press. On (iOS) with the glass design it has no glass capsule; `hideSharedBackground: false` puts it on one. On (Android) `component.width` and `height` size it.
252
252
 
253
253
  ## Buttons that change
254
254
 
@@ -273,7 +273,7 @@ function NewNote() {
273
273
 
274
274
  The options are built on each render and applied before the screen paints when they changed, so the bar never lags behind the state. `onPress` sees the state of the same render. A full form in a modal, with Cancel and Save, is walked through in [Forms in a modal](../flows/forms-in-a-modal).
275
275
 
276
- On (iOS) `animateRightButtons` and `animateLeftButtons` fade the new buttons in. On iOS 26 buttons that share a capsule (several with one `group`) change at once: UIKit has no animation for groups of buttons.
276
+ On (iOS) `animateRightButtons` and `animateLeftButtons` fade the new buttons in. With the glass design buttons that share a capsule (several with one `group`) change at once: UIKit has no animation for groups of buttons.
277
277
 
278
278
  ## Buttons on iPhone Duo
279
279
 
@@ -171,7 +171,7 @@ The component gets the search events itself, with `useSearchBar`, as a screen of
171
171
 
172
172
  | Platform | The results screen |
173
173
  | --- | --- |
174
- | (iOS) | Covers the whole screen, under the search field and to the bottom edge, so its background fills it. It keeps its content clear of the bar itself: a list with `contentInsetAdjustmentBehavior="automatic"`, other content with `useSafeAreaInsets`. |
174
+ | (iOS) | Covers the whole screen, under the search field and to the bottom edge, so its background fills it. It keeps its content clear of the bar itself: a list with `contentInsetAdjustmentBehavior="automatic"`, other content with `useSafeAreaInsets`. The results screen has no padding of its own. |
175
175
  | (Android) | The search opens over the whole screen, the field at the top and the component under it. |
176
176
 
177
177
  ## In the toolbar
@@ -29,12 +29,12 @@ The status bar sits at the top, with the camera cutout in it; the home indicator
29
29
 
30
30
  ## The safe area
31
31
 
32
- The safe area is where nothing covers the content: not the bars of the navigation, not the status bar, not the cutout, not the home indicator. **The navigation keeps every screen in it by default**, so a screen doesn't need its own padding:
32
+ The safe area is where nothing covers the content: not the bars of the navigation, not the status bar, not the cutout, not the home indicator. **The navigation keeps every screen's top and sides in it by default**, so a screen doesn't need its own padding there. The bottom is not padded: the content goes down to the edge, under the home indicator, the navigation bar and a tab bar or toolbar, and a list adds `useSafeAreaInsets().bottom` to its own padding, as with `react-native-safe-area-context`.
33
33
 
34
34
  | Platform | By default |
35
35
  | --- | --- |
36
- | (iOS) | Every edge, except one under a bar that shows: a list goes under the top bar and keeps its rows clear itself, so the bar's glass shows the content scrolling under it. A screen with a large title leaves the top out too, and on iPhone Duo the side of the [vertical bar](#vertical-bar). |
37
- | (Android) | All four edges: under the status bar, out of the cutout, above the navigation bar. |
36
+ | (iOS) | The top and the sides, but not the top under a top bar that shows: a list goes under the bar and keeps its rows clear itself, so the bar's glass shows the content scrolling under it. A screen with a large title leaves the top out too, and on iPhone Duo the side of the [vertical bar](#vertical-bar). The bottom goes under the home indicator and under a tab bar or toolbar. |
37
+ | (Android) | The top and the sides: under the status bar, out of the cutout. The top is free under a top bar that hides on scroll and under a large title. The bottom goes under the navigation bar, when the screen draws under it (not with an opaque bar), and under the tabs only with `bottomTabs.drawBehind` or `hideOnScroll`. |
38
38
 
39
39
  > **Tip**
40
40
  >
@@ -47,6 +47,12 @@ A screen that should go under the system, such as a photo or a map, says which e
47
47
  ```ts
48
48
  s.safeArea('bottom'); // only the bottom: the photo goes under the top
49
49
  s.safeArea(); // no edge: the content goes everywhere
50
+ s.safeArea('top', 'left', 'right', 'bottom'); // all four: a form above the home indicator
51
+
52
+ // listed edges replace the default: this one loses
53
+ // the sides; under a large title the top stays free,
54
+ // because the list keeps clear of the bar itself
55
+ s.safeArea('top', 'bottom');
50
56
  ```
51
57
 
52
58
  The edges for every screen of the app go in `createNavigation`, and a screen's own `safeArea` wins over them:
@@ -54,11 +60,11 @@ The edges for every screen of the app go in `createNavigation`, and a screen's o
54
60
  ```ts
55
61
  export const Navigation = createNavigation({
56
62
  // …
57
- safeArea: { edges: ['top', 'bottom'] },
63
+ safeArea: { edges: ['top', 'left', 'right', 'bottom'] },
58
64
  });
59
65
  ```
60
66
 
61
- Content that keeps clear of the system itself, such as a list that scrolls under the home indicator, reads what still covers it with `useSafeAreaInsets()`. The insets are **what is left after the screen's own padding**: 0 on an edge the screen keeps, all of what covers it on an edge its content goes under. So the content adds them to its own padding, and no edge is padded twice. Here the screen keeps the top only, and the list pads its own bottom:
67
+ Content that keeps clear of the system itself, such as a list that scrolls under the home indicator, reads what still covers it with `useSafeAreaInsets()`. The insets are **what is left after the screen's own padding**: 0 on an edge the screen keeps, all of what covers it on an edge its content goes under. So the content adds them to its own padding, and no edge is padded twice. Here the screen keeps the top and the sides by default, and the list pads its own bottom:
62
68
 
63
69
  ```tsx
64
70
  import { ScrollView } from 'react-native';
@@ -71,7 +77,7 @@ function Inbox() {
71
77
  const insets = useSafeAreaInsets();
72
78
  return (
73
79
  <ScrollView
74
- contentContainerStyle={{ paddingBottom: insets.bottom }}
80
+ contentContainerStyle={{ paddingBottom: 16 + insets.bottom }}
75
81
  >
76
82
  {/* the rows scroll under the home indicator,
77
83
  and the last one ends above it */}
@@ -80,12 +86,11 @@ function Inbox() {
80
86
  }
81
87
 
82
88
  export const InboxScreen = defineScreen({
83
- component: Inbox,
84
- options: (s) => s.safeArea('top'),
89
+ component: Inbox, // the default edges: the top and the sides
85
90
  });
86
91
  ```
87
92
 
88
- On a screen that keeps the bottom edge, the default on Android and on iOS without a bar at the bottom, `insets.bottom` is 0, so the same code works there: the content is already above the home indicator. Below a top bar the top inset is 0; on a screen drawn behind the bars it is their height. On (iOS) a scroll view with `contentInsetAdjustmentBehavior="automatic"` keeps clear of the bars by itself: leave the inset out on those edges. More: [The insets and the safe area of the screen](/api/system-ui/useSafeAreaInsets#safe-area).
93
+ On a screen that lists `'bottom'` in its edges, `insets.bottom` is 0, so the same code works there: the content is already above the home indicator. Below a top bar the top inset is 0; on a screen drawn behind the bars it is their height. On (iOS) a scroll view with `contentInsetAdjustmentBehavior="automatic"` keeps clear of the bars by itself: leave the inset out on those edges. More: [The insets and the safe area of the screen](/api/system-ui/useSafeAreaInsets#safe-area).
89
94
 
90
95
  ### The vertical bar of iPhone Duo
91
96
 
@@ -231,7 +236,7 @@ export const PhotoScreen = defineScreen({
231
236
  | Platform | The bottom |
232
237
  | --- | --- |
233
238
  | (iOS) | The home indicator. `layout.autoHideHomeIndicator` fades it out while the screen isn't touched, as in a video. `layout.deferSystemGestures` makes the first swipe on those edges go to the app, for a game or a drawing; the second swipe goes home. |
234
- | (Android) | The navigation bar: a handle, or three buttons. The screen goes under it, and its safe area keeps the content above it. `navigationBar` sets its `backgroundColor`, hides it with `visible: false`, or puts the screen above it with `drawBehind: false`. |
239
+ | (Android) | The navigation bar: a handle, or three buttons. The screen goes under it, and by default so does the content; a list adds `insets.bottom`. With an opaque bar or `drawBehind: false` the screen ends above it. `navigationBar` sets its `backgroundColor`, hides it with `visible: false`, or puts the screen above it with `drawBehind: false`. |
235
240
 
236
241
  (Android) The screen goes edge to edge as the platform says: always on Android 16+ for apps targeting SDK 36, on Android 15 for SDK 35, and on every version with `edgeToEdgeEnabled=true` in `android/gradle.properties`, the default of new React Native apps.
237
242
 
@@ -274,7 +279,7 @@ export const Navigation = createNavigation({
274
279
  s.scrollEdgeEffect({ top: { style: 'hard' } });
275
280
  ```
276
281
 
277
- The effect belongs to the scroll views of the screen, so a list that mounts after the screen shows gets it the next time the screen appears. Render the list at once, and fill it when the data comes.
282
+ The effect applies to the vertical lists and text views of the screen when it shows, so a list that mounts after the screen shows gets it the next time the screen appears. A list nested very deep in the screen's views may not get it. A list inside another vertical list, like a horizontal carousel in a feed, gets none: UIKit draws no edge effect there. Render the list at once, and fill it when the data comes.
278
283
 
279
284
  ## Keyboard shortcuts
280
285
 
@@ -46,10 +46,10 @@ Filter sits at the leading edge and Compose at the trailing one. The buttons are
46
46
  | Item | What it does |
47
47
  | --- | --- |
48
48
  | `{ systemItem: 'flexibleSpace' }` | Takes the free width, and pushes the next buttons to the far side. |
49
- | `{ systemItem: 'fixedSpace' }` | A gap. On iOS 26 it also starts a new glass capsule. |
49
+ | `{ systemItem: 'fixedSpace' }` | A gap. With the glass design it also starts a new glass capsule. |
50
50
  | `{ systemItem: 'searchField' }` | iOS 26: the search field of the screen, between the buttons. See [Search](./search#toolbar). |
51
51
 
52
- On iOS 26 icons next to each other share one glass capsule; a text button has one of its own, and a `badge` doesn't show in the toolbar. `visible: false` hides the toolbar with its buttons.
52
+ With the glass design ([what it is](./top-bar#glass-design)) icons next to each other share one glass capsule; a text button has one of its own, and a `badge` doesn't show in the toolbar. `visible: false` hides the toolbar with its buttons.
53
53
 
54
54
  On iPhone with iOS 26 the floating tab bar takes the same place at the bottom. A screen with a toolbar inside [tabs](../containers/tabs) hides the tab bar with `hideBottomTabs()`.
55
55
 
@@ -75,6 +75,8 @@ A round button with a pencil floats at the bottom right; a press opens Compose.
75
75
  | `backgroundColor`, `iconColor` | Its colors. Without them, the colors of the app's Material 3 theme. |
76
76
  | `visible: false` | Hides it. |
77
77
 
78
+ The FAB belongs to its screen. A push brings the new screen's FAB in with it and takes the old one out with the screen it covers; a pop does the same the other way, and the back gesture shows the FAB of the screen under the top with that screen. Two screens with the same `id` share one button: it stays in place while the screens move.
79
+
78
80
  ### Actions
79
81
 
80
82
  A FAB with `actions` opens them above it on a press, each a small FAB with its own press:
@@ -31,6 +31,10 @@ The top bar belongs to **the stack, not to a screen**: one bar for all the scree
31
31
 
32
32
  The platform draws the bar: `UINavigationBar` on (iOS), with Liquid Glass on iOS 26, and the Material 3 top app bar on (Android). Its colors come from the [theme](../architecture/theme-and-context) until a screen sets its own.
33
33
 
34
+ ## The glass design and the compatibility mode
35
+
36
+ On (iOS) the look of iOS 26 (Liquid Glass) is *the glass design*, and this page and [the bar buttons](./bar-buttons) call it that. An app in the compatibility mode (`UIDesignRequiresCompatibility = YES` in Info.plist) doesn't get it: the mode applies on iOS 26, and on iOS 27 only to an app built with an SDK before iOS 27. There the bar looks and behaves as before iOS 26: a title with a subtitle as two lines only when no large title can show (with a large title the subtitle shows nowhere), no capsules (`title.glass`, `hideSharedBackground` and `group` do nothing), `style: 'prominent'` is a bold Done button, the back button shows the title of the screen below, `background.color` gives an opaque bar, and a large title is drawn in the bar. [The bottom tabs](../containers/tabs) follow the same mode.
37
+
34
38
  ## The title
35
39
 
36
40
  The title is the name of the screen. The subtitle is a second line under it, such as a status or a count. Both can come from the props of the screen:
@@ -84,20 +88,20 @@ s.title('Details').largeTitle({ displayMode: 'never' });
84
88
 
85
89
  ## The background and the border
86
90
 
87
- On iOS 26 the bar is Liquid Glass, and the content shows through it as it scrolls under. **A color takes the glass away**, so set one only when the design needs it:
91
+ With the glass design the bar is Liquid Glass, and the content shows through it as it scrolls under. **A color takes the glass away**, so set one only when the design needs it:
88
92
 
89
93
  ```ts
90
94
  s.topBar({ background: { color: '#F3E9D2' }, noBorder: true });
91
95
  ```
92
96
 
93
- `background.color` colors the bar on both platforms. With a large title on iOS 26 the color goes behind the title in the list, and fills the bar once the title collapses. Under a bar with a color the list has no edge effect at the top: see [The edge of the scroll](./system-ui#scroll-edge).
97
+ `background.color` colors the bar on both platforms. With a large title and the glass design the color goes behind the title in the list, and fills the bar once the title collapses. Under a bar with a color the list has no edge effect at the top: see [The edge of the scroll](./system-ui#scroll-edge).
94
98
 
95
99
  The other keys of the background are rarer:
96
100
 
97
101
  | Option | What it does |
98
102
  | --- | --- |
99
103
  | `background.component` | A component of `screens` drawn behind the bar, such as a gradient. It is registered as the [title component](#title-component) is. |
100
- | `background.translucent` | (iOS) `true`: the content shows through; Liquid Glass on iOS 26, where it is the default. `false`: a solid bar, white in the light theme and black in the dark one. |
104
+ | `background.translucent` | (iOS) `true`: the content shows through; Liquid Glass with the glass design, where it is the default. `false`: a solid bar, white in the light theme and black in the dark one. |
101
105
  | `background.blur` | (iOS) The system's frosted blur, plainer than the glass. A `color` wins over it, and it wins over `translucent`. |
102
106
  | `scrollEdgeAppearance` | (iOS) The look of the bar while the content is at its top, with `active: true`. The bar takes its usual look once the content scrolls under it. |
103
107
 
@@ -132,7 +136,7 @@ The bar can also hide and show by itself:
132
136
  | `hideOnKeyboard` | (iOS) Hides while the keyboard shows. |
133
137
  | `animate` | `false`: hides and shows at once, without the animation. |
134
138
 
135
- With `hideOnScroll` the screen goes under the bar, so its rows show where the bar was. Its list keeps its first rows clear: on (iOS) with `contentInsetAdjustmentBehavior="automatic"`, on (Android) with `paddingTop: useSafeAreaInsets().top`.
139
+ With `hideOnScroll` the screen goes under the bar, so its rows show where the bar was. Its list keeps its first rows clear: on (iOS) with `contentInsetAdjustmentBehavior="automatic"`, on (Android) with `paddingTop: useSafeAreaInsets().top`. The bottom edge is not padded by default, so the list also adds `useSafeAreaInsets().bottom` to its bottom padding (an iOS list with `contentInsetAdjustmentBehavior="automatic"` does it itself).
136
140
 
137
141
  `drawBehind: true` keeps the bar and puts the content under it, as a map or a photo under a glass bar.
138
142
 
@@ -129,7 +129,7 @@ In an app as the React Native template makes it, the window shows **one React vi
129
129
  | `MainApplication.kt` | Extends `NavigationApplication`; keeps the template's `loadReactNative(this)` in `onCreate`, or adds it. | It keeps one React host for all screens, made after `loadReactNative(this)` loaded React Native. Native screens made by `codegen` are registered there, before JS opens them. |
130
130
  | `MainActivity.kt` | Extends `NavigationActivity`. | The activity holds the containers of the navigation instead of one React view. It gets the back press, edge-to-edge and configuration changes first. |
131
131
  | `AndroidManifest.xml` | Adds `android:enableOnBackInvokedCallback="true"` to `<application>`. | On the first screen the system plays its own animation back to the home screen as the user swipes back (predictive back). Android 16 turns it on for apps that target API 36; an app that targets less opts in here. A value the app set itself stays. See [Back to the home screen](../screen-ui/back-and-gestures#system-animation). |
132
- | `styles.xml` | `AppTheme` inherits `Theme.ApexNavigation`. | The bars, tabs and search are Material 3 views and take their colors from the app's theme. This one is Material 3 in neutral grays, light and dark; change any color in the same file. A theme of the app's own stays as it is. See [Android's colors](../architecture/theme-and-context#android). |
132
+ | `styles.xml` | `AppTheme` inherits `Theme.ApexNavigation`. | The bars, tabs and search are Material 3 views and take their colors from the app's theme. This one is Material 3 in neutral grays, light and dark; change any color in the same file. A theme of the app's own stays as it is. See [Android's theme](../architecture/theme-and-context#android). |
133
133
 
134
134
  The main activity keeps the template's `android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"`. Without `orientation`, `screenSize`, `smallestScreenSize`, `screenLayout` or `uiMode` Android recreates the activity on a rotation, a resize, a fold or a light/dark switch, and every screen goes with it; `doctor` warns about it under Config changes.
135
135
 
@@ -150,8 +150,23 @@ These files are the same on both platforms.
150
150
  | `index.js` | Starts the app through the navigation. | `AppRegistry` of the package starts `createNavigation` instead of mounting one root component. |
151
151
  | `Navigation.ts` | New: shows `App` as the first screen. | The app keeps working as it was, now as the first screen of a stack. |
152
152
  | `App.tsx` | Takes out the template's ``. | React Native's `StatusBar` logs an error on iOS once the screens set the status bar. |
153
+ | `metro.config.js` | Wraps the exported config in `withApexNavigation`. | Fast Refresh: an edit of a screen updates the running app in place, with its state, instead of reloading it. See [Fast Refresh](#fast-refresh). |
153
154
  | `navigation-env.d.ts` | New: ties the commands to the screens of `Navigation.ts`. | The commands come from the package and can't see the app's screens. This declaration links them, so names and props are checked. See [Typed commands](#typed-commands). |
154
155
 
156
+ ### Fast Refresh
157
+
158
+ `setup` wraps your `metro.config.js` in `withApexNavigation`; in a new app `init` has done it. By hand:
159
+
160
+ ```js
161
+ const { withApexNavigation } = require('@apexnative/navigation/metro');
162
+
163
+ module.exports = withApexNavigation(mergeConfig(getDefaultConfig(__dirname), config));
164
+ ```
165
+
166
+ It does two things. React Native 0.87's transformer doesn't apply React Refresh's Babel plugin (Metro no longer passes it `hot`), and without the plugin a component that its module doesn't export loses its state at every edit. And it makes the module that imports `createNavigation` accept hot updates, so an edit of the `screens` map or of the app's config updates the running app without a reload: the screens, the default options (when `theme` or `options` changed), the roots, the listeners and the link routes. What only the start reads isn't run again: the first root, `willMount`, the splash and the context. The app's module itself runs again, as a component's module does in Fast Refresh: code at its top level (an SDK's `init`, a listener added there) runs again too, so keep such code in a module of its own that doesn't change, or make it safe to run twice. The same holds for a module the app's module imports that isn't a component, such as a store: its edit runs it and the app's module again instead of reloading the app, so a store made at the top of that module is made anew while the screens that didn't run again keep the old one. Reload the app (R) after such an edit.
167
+
168
+ `doctor` warns under Fast Refresh when the Metro config doesn't use it. What to write in a screen file so that its edits update in place: [Fast Refresh](../fundamentals/screens-and-props#fast-refresh).
169
+
155
170
  ### Typed commands
156
171
 
157
172
  `navigation.push('Details', { props })` comes from the package, and the package doesn't know the screens of your app. One declaration links them: `setup` and `init` write it in `navigation-env.d.ts` at the root of the app.
@@ -1,27 +1,47 @@
1
+ #import <QuartzCore/QuartzCore.h>
1
2
  #import <UIKit/UIKit.h>
2
3
 
3
4
  NS_ASSUME_NONNULL_BEGIN
4
5
 
5
- /// What a frame driver moves: a view's properties (`ANNViewTracks`), an element, a shared element's copy. Each frame it
6
- /// writes its values at the time from the transition's start; past its end it holds its end values.
6
+ /// What a frame driver moves: a view's properties (`ANNViewTracks`), an element, a shared element's copy. It gives its
7
+ /// values for the whole transition at once, as Core Animation's animations on its layers (`ANNKeyframes`); past its end
8
+ /// they hold its end values.
7
9
  @protocol ANNFrameClient <NSObject>
8
10
 
9
- /// The values at `time`, in seconds from the start of the transition.
10
- - (void)applyAtTime:(NSTimeInterval)time;
11
+ /// The client's animations for a transition of `length` seconds go onto its layers, all inside the driver's
12
+ /// transaction, so they start together.
13
+ - (void)addAnimationsWithLength:(NSTimeInterval)length;
11
14
 
12
15
  /// The time from which the client holds its end values.
13
16
  @property(nonatomic, readonly) NSTimeInterval endTime;
14
17
 
15
- /// Every value the client wrote goes back as it was read before the transition (also at a cancel); a client that made
16
- /// views of its own removes them. Once; later calls do nothing.
18
+ /// The client's animations go, every value it wrote goes back as it was read before the transition (also at a
19
+ /// cancel), and a client that made views of its own removes them. Once; later calls do nothing.
17
20
  - (void)restore;
18
21
 
19
22
  @end
20
23
 
21
- /// The frames of one running transition: one `CADisplayLink` in the common modes of the run loop, so frames go on while
22
- /// a finger drags a scroll view; the time is the link's `targetTimestamp` from the start (monotonic host time). Each
23
- /// frame every client writes its values; once the time reached `length` and every client its end, the clients write
24
- /// their ends, the link stops and `done` runs once. No `CATransaction` waits. Main queue.
24
+ /// The times a client samples its values at, in seconds from the start: 0, every 1/120 s up to `end` (wider apart for
25
+ /// a transition over 20 s, 2400 samples at most), each of `marks` within it (a track's start and end, a swap's), `end`
26
+ /// and `length`; ascending, without repeats. The values between two samples are linear, so a kink of a track falls on
27
+ /// a sample.
28
+ FOUNDATION_EXPORT NSArray<NSNumber *> *ANNSampleTimes(NSTimeInterval end, NSTimeInterval length,
29
+ NSArray<NSNumber *> *marks);
30
+
31
+ /// The animation of `keyPath` through `values` at `times` (from `ANNSampleTimes`) over `length` seconds: linear
32
+ /// between them, holding the first value before and the last after (until it is removed). Nil for no length, and for
33
+ /// values and times that don't pair up.
34
+ FOUNDATION_EXPORT CAKeyframeAnimation *_Nullable ANNKeyframes(NSString *keyPath, NSArray *values,
35
+ NSArray<NSNumber *> *times,
36
+ NSTimeInterval length);
37
+
38
+ /// The key of the core's animation of `keyPath` on a layer, for its `restore`.
39
+ FOUNDATION_EXPORT NSString *ANNAnimationKey(NSString *keyPath);
40
+
41
+ /// The frames of one running transition, in Core Animation: every client adds its animations in one transaction, which
42
+ /// starts them together at its commit; the render server plays them, so a busy main queue no longer stops the
43
+ /// transition. Once every animation ended (or was removed) and `length` passed, `done` runs once on the main queue.
44
+ /// Main queue.
25
45
  @interface ANNFrameDriver : NSObject
26
46
 
27
47
  - (instancetype)initWithClients:(NSArray<id<ANNFrameClient>> *)clients
@@ -30,17 +50,37 @@ NS_ASSUME_NONNULL_BEGIN
30
50
  - (instancetype)init NS_UNAVAILABLE;
31
51
  + (instancetype)new NS_UNAVAILABLE;
32
52
 
33
- /// The clients write their values of time 0 now (the first frame shows the start values), and the frames start. `done`
34
- /// comes on a later frame, never inside this call.
53
+ /// The clients add their animations, which start at the commit of the current transaction (the first frame shows the
54
+ /// start values). `done` comes later, never inside this call.
35
55
  - (void)startWithDone:(dispatch_block_t)done;
36
56
 
37
- /// The transition stops where it is (a destroy, a reload, a newer `setRoot`): the clients write their end values, the
38
- /// link stops, `done` never runs. The caller restores the clients.
57
+ /// The start of a transition that follows a gesture: the clients add their animations as `startWithDone:` does, under
58
+ /// the time of `clock` (the transition's container), which stops. `setProgress:` shows them at a part of the length;
59
+ /// `finishWithSpeed:` plays the rest and `rewindWithSpeed:` plays them back to the start, both in Core Animation. The
60
+ /// other animations under `clock` stop with it. Before `done`, which comes once after either of them (never inside a
61
+ /// call) with whether the transition finished, `clock` gets its time back; the caller restores the clients inside
62
+ /// `done` (one commit with it), or they would show at the clock's time for a frame.
63
+ - (void)startPausedOn:(CALayer *)clock done:(void (^)(BOOL finished))done;
64
+
65
+ /// The animations show at `progress` (0 to 1) of the length. Nothing once the end plays.
66
+ - (void)setProgress:(CGFloat)progress;
67
+
68
+ /// The rest of the animations plays from where they show, `speed` times as fast as they would (1 or more).
69
+ - (void)finishWithSpeed:(CGFloat)speed;
70
+
71
+ /// The animations play back to their start, `speed` times as fast as they would (1 or more).
72
+ - (void)rewindWithSpeed:(CGFloat)speed;
73
+
74
+ /// The transition stops (a destroy, a reload, a newer `setRoot`): `done` never runs, and a stopped `clock` gets its
75
+ /// time back. The caller restores the clients, which removes their animations, in the same commit.
39
76
  - (void)cancel;
40
77
 
41
- /// The frames run.
78
+ /// The animations run.
42
79
  @property(nonatomic, readonly) BOOL isRunning;
43
80
 
81
+ /// The seconds from the start to the end of the last client, the transition's own length at least.
82
+ @property(nonatomic, readonly) NSTimeInterval length;
83
+
44
84
  @end
45
85
 
46
86
  NS_ASSUME_NONNULL_END