@apexnative/navigation 1.0.0-alpha.0 → 1.0.0-alpha.10

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 (574) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +128 -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/SecondaryScreenPresenter.kt +13 -5
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  123. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  124. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  127. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  130. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  131. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  142. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  143. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  156. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  157. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  158. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  159. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  160. package/android/src/main/res/values/styles.xml +1 -1
  161. package/android/src/main/res/values-night/styles.xml +1 -1
  162. package/cli/app.js +1 -1
  163. package/cli/doctor/checks/app.js +77 -14
  164. package/cli/doctor/checks/splash.js +4 -22
  165. package/cli/migrate/native.js +18 -0
  166. package/cli/project.js +10 -2
  167. package/cli/setup/index.js +18 -0
  168. package/cli/setup/source.js +2 -1
  169. package/cli/setup/steps/appDelegate.js +66 -11
  170. package/cli/setup/steps/mainApplication.js +134 -19
  171. package/cli/setup/steps/metro.js +46 -0
  172. package/cli/setup/steps/sceneDelegate.js +108 -0
  173. package/cli/splash/index.js +3 -1
  174. package/cli/upgrade/changelog.js +2 -2
  175. package/docs-md/architecture/native-screens.md +4 -0
  176. package/docs-md/architecture/theme-and-context.md +131 -12
  177. package/docs-md/architecture/transitions.md +58 -12
  178. package/docs-md/containers/modals.md +8 -4
  179. package/docs-md/containers/overlays.md +3 -1
  180. package/docs-md/containers/side-menu.md +19 -2
  181. package/docs-md/containers/tabs.md +5 -1
  182. package/docs-md/flows/bottom-sheets.md +4 -2
  183. package/docs-md/flows/forms-in-a-modal.md +1 -1
  184. package/docs-md/fundamentals/screens-and-props.md +9 -1
  185. package/docs-md/fundamentals/starting-the-app.md +1 -1
  186. package/docs-md/guides/cli.md +4 -3
  187. package/docs-md/guides/deep-links.md +15 -33
  188. package/docs-md/help/glossary.md +4 -4
  189. package/docs-md/help/troubleshooting.md +44 -6
  190. package/docs-md/index.json +57 -1
  191. package/docs-md/migration/from-expo-router.md +1 -1
  192. package/docs-md/migration/from-react-native-navigation.md +9 -3
  193. package/docs-md/migration/from-react-navigation.md +2 -2
  194. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  195. package/docs-md/screen-ui/bar-buttons.md +5 -5
  196. package/docs-md/screen-ui/search.md +1 -1
  197. package/docs-md/screen-ui/system-ui.md +17 -12
  198. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  199. package/docs-md/screen-ui/top-bar.md +8 -4
  200. package/docs-md/start/installation.md +21 -3
  201. package/ios/Animations/ANNFrameDriver.h +55 -15
  202. package/ios/Animations/ANNFrameDriver.mm +216 -60
  203. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  204. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  205. package/ios/Animations/ANNTransitionPlan.h +2 -2
  206. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  207. package/ios/Animations/ANNTransitionWait.mm +6 -7
  208. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  209. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  210. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  211. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  212. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  213. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  214. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  215. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  216. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  217. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  218. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  219. package/ios/CLAUDE.md +60 -24
  220. package/ios/CORE.md +44 -34
  221. package/ios/Contract/ANNCommandAnswer.h +13 -5
  222. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  223. package/ios/Contract/ANNCommandContract.h +15 -0
  224. package/ios/Contract/ANNCommandContract.mm +78 -0
  225. package/ios/Contract/ANNCommandRunner.h +10 -9
  226. package/ios/Contract/ANNCommandRunner.mm +22 -28
  227. package/ios/Contract/ANNErrorTexts.h +6 -2
  228. package/ios/Contract/ANNErrorTexts.mm +18 -10
  229. package/ios/Contract/ANNLayoutNode.h +3 -3
  230. package/ios/Contract/ANNLayoutReader.h +3 -3
  231. package/ios/Core/ANNAppDelegate.mm +0 -2
  232. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  233. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  234. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  235. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  236. package/ios/Core/ANNErrorHandler.h +9 -4
  237. package/ios/Core/ANNErrorHandler.mm +20 -2
  238. package/ios/Core/ANNEventContract.h +246 -0
  239. package/ios/Core/ANNEventContract.mm +225 -0
  240. package/ios/Core/ANNEventEmitter.h +6 -2
  241. package/ios/Core/ANNEventEmitter.mm +117 -80
  242. package/ios/Core/ANNHinge.h +6 -0
  243. package/ios/Core/ANNHinge.mm +15 -4
  244. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  245. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  246. package/ios/Core/ANNLayoutProtocol.h +5 -5
  247. package/ios/Core/ANNNavigationState.h +7 -5
  248. package/ios/Core/ANNNavigationState.mm +8 -7
  249. package/ios/Core/ANNNodeHelper.h +32 -12
  250. package/ios/Core/ANNNodeHelper.mm +100 -3
  251. package/ios/Core/ANNParking.h +5 -4
  252. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  253. package/ios/Core/ANNRenderWait.h +20 -6
  254. package/ios/Core/ANNRenderWait.mm +143 -56
  255. package/ios/Core/ANNSceneDelegate.mm +25 -15
  256. package/ios/Core/ANNSystemUI.h +3 -2
  257. package/ios/Core/ANNSystemUI.mm +7 -0
  258. package/ios/Core/ANNUtils.h +7 -0
  259. package/ios/Core/ANNUtils.mm +10 -0
  260. package/ios/Core/ApexNavigation+Internal.h +1 -1
  261. package/ios/Core/ApexNavigation.mm +7 -6
  262. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  263. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  264. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  265. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  266. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
  267. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  268. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  269. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  270. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  271. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  272. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  273. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  274. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  275. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  276. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  277. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  278. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  279. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  280. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  281. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  282. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  283. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  284. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  285. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  286. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  287. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  288. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  289. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  290. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  291. package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
  292. package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
  293. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  294. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  295. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  296. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  297. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  298. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  299. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  300. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  301. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  302. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  303. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  304. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  305. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  306. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  307. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  308. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  309. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  310. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  311. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  312. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  313. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  314. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  315. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  317. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  318. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  319. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  320. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  321. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  322. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  323. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  324. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  325. package/ios/Options/ANNAnimationOptions.h +2 -1
  326. package/ios/Options/ANNAnimationOptions.mm +1 -1
  327. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  328. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  329. package/ios/Options/ANNOptions.h +25 -0
  330. package/ios/Options/ANNOptions.mm +157 -1
  331. package/ios/Options/ANNOptionsCache.h +7 -6
  332. package/ios/Options/ANNOptionsReader.mm +108 -0
  333. package/ios/Options/ANNSearchBarOptions.h +4 -3
  334. package/ios/Options/ANNSheetOptions.h +4 -1
  335. package/ios/Options/ANNSideMenuOptions.h +2 -0
  336. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  337. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  338. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  339. package/ios/Options/ANNUserChoice.h +57 -0
  340. package/ios/Options/ANNUserChoice.mm +44 -0
  341. package/ios/Options/Params/ANNImageSource.h +61 -0
  342. package/ios/Options/Params/ANNImageSource.mm +101 -0
  343. package/ios/Options/Params/ANNOptionImages.h +37 -0
  344. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  345. package/ios/Options/Params/ANNParam.h +15 -0
  346. package/ios/Options/Params/ANNParam.mm +61 -0
  347. package/ios/Options/Params/Color.h +3 -0
  348. package/ios/Options/Params/Color.mm +21 -0
  349. package/ios/Options/Params/ColorParser.h +4 -3
  350. package/ios/Options/Params/ColorParser.mm +22 -4
  351. package/ios/Options/Params/Image.h +15 -2
  352. package/ios/Options/Params/Image.mm +35 -2
  353. package/ios/Options/Params/ImageParser.h +5 -5
  354. package/ios/Options/Params/ImageParser.mm +28 -46
  355. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  356. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  357. package/ios/RECIPES.md +13 -6
  358. package/ios/React/ANNReactView.mm +6 -25
  359. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  360. package/ios/React/ANNSurfaceHostingView.h +14 -0
  361. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  362. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  363. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  364. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  365. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  366. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  367. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  368. package/ios/TopBar/ANNBarAppearance.h +2 -1
  369. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  370. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  371. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  372. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  373. package/ios/TopBar/ANNBarButtons.h +14 -8
  374. package/ios/TopBar/ANNBarButtons.mm +397 -80
  375. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  376. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  377. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  378. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  379. package/ios/TopBar/ANNMainList.h +3 -0
  380. package/ios/TopBar/ANNMainList.mm +4 -0
  381. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  382. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  383. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  384. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  385. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  386. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  387. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  388. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  389. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  390. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  391. package/lib/module/ARCHITECTURE.md +40 -27
  392. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  393. package/lib/module/api/app/AppRegistry.js +14 -2
  394. package/lib/module/api/app/AppRegistry.js.map +1 -1
  395. package/lib/module/api/app/createNavigation.js +190 -66
  396. package/lib/module/api/app/createNavigation.js.map +1 -1
  397. package/lib/module/api/commands/commands.js +54 -6
  398. package/lib/module/api/commands/commands.js.map +1 -1
  399. package/lib/module/api/events/navigationEvents.js +6 -2
  400. package/lib/module/api/events/navigationEvents.js.map +1 -1
  401. package/lib/module/api/hooks/useNavigation.js +8 -3
  402. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  403. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  404. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  405. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  406. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  407. package/lib/module/api/linking/linking.js +11 -0
  408. package/lib/module/api/linking/linking.js.map +1 -1
  409. package/lib/module/api/navigation.js.map +1 -1
  410. package/lib/module/api/options/OptionsChain.js +2 -2
  411. package/lib/module/api/screens/defineScreen.js +45 -3
  412. package/lib/module/api/screens/defineScreen.js.map +1 -1
  413. package/lib/module/api/screens/nativeScreens.js +31 -6
  414. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  415. package/lib/module/api/screens/registerScreens.js +193 -35
  416. package/lib/module/api/screens/registerScreens.js.map +1 -1
  417. package/lib/module/api/theme/theme.js +5 -0
  418. package/lib/module/api/theme/theme.js.map +1 -1
  419. package/lib/module/engine/commands.js +51 -9
  420. package/lib/module/engine/commands.js.map +1 -1
  421. package/lib/module/engine/layout.js +20 -11
  422. package/lib/module/engine/layout.js.map +1 -1
  423. package/lib/module/engine/nativeScreens.js +9 -0
  424. package/lib/module/engine/nativeScreens.js.map +1 -1
  425. package/lib/module/engine/options.js +49 -15
  426. package/lib/module/engine/options.js.map +1 -1
  427. package/lib/module/engine/optionsChange.js +102 -0
  428. package/lib/module/engine/optionsChange.js.map +1 -0
  429. package/lib/module/engine/places.js +52 -7
  430. package/lib/module/engine/places.js.map +1 -1
  431. package/lib/module/engine/props.js +30 -1
  432. package/lib/module/engine/props.js.map +1 -1
  433. package/lib/module/engine/refresh.js +85 -0
  434. package/lib/module/engine/refresh.js.map +1 -0
  435. package/lib/module/engine/rememberedOptions.js +61 -1
  436. package/lib/module/engine/rememberedOptions.js.map +1 -1
  437. package/lib/module/engine/screens.js +77 -16
  438. package/lib/module/engine/screens.js.map +1 -1
  439. package/lib/module/interfaces/contract/commands.json +101 -0
  440. package/lib/module/interfaces/contract/errors.json +275 -0
  441. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  442. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  443. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  444. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  445. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  446. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  447. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  448. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  449. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  450. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  451. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  452. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  453. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  454. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  455. package/lib/typescript/api/index.d.ts +1 -1
  456. package/lib/typescript/api/index.d.ts.map +1 -1
  457. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  458. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  459. package/lib/typescript/api/linking/linking.d.ts +8 -0
  460. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  461. package/lib/typescript/api/navigation.d.ts +4 -1
  462. package/lib/typescript/api/navigation.d.ts.map +1 -1
  463. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  464. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  465. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  466. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  467. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  468. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  469. package/lib/typescript/api/theme/theme.d.ts +2 -0
  470. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  471. package/lib/typescript/engine/commands.d.ts +5 -0
  472. package/lib/typescript/engine/commands.d.ts.map +1 -1
  473. package/lib/typescript/engine/layout.d.ts.map +1 -1
  474. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  475. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  476. package/lib/typescript/engine/options.d.ts +5 -2
  477. package/lib/typescript/engine/options.d.ts.map +1 -1
  478. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  479. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  480. package/lib/typescript/engine/places.d.ts +7 -2
  481. package/lib/typescript/engine/places.d.ts.map +1 -1
  482. package/lib/typescript/engine/props.d.ts +8 -1
  483. package/lib/typescript/engine/props.d.ts.map +1 -1
  484. package/lib/typescript/engine/refresh.d.ts +35 -0
  485. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  486. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  487. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  488. package/lib/typescript/engine/screens.d.ts +27 -6
  489. package/lib/typescript/engine/screens.d.ts.map +1 -1
  490. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  491. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  492. package/lib/typescript/interfaces/Events.d.ts +28 -10
  493. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  494. package/lib/typescript/interfaces/Options.d.ts +1 -1
  495. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  496. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  497. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  498. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  499. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  500. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  501. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  502. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  503. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  504. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  505. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  506. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  507. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  508. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  509. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  510. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  511. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  512. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  513. package/metro/acceptPlugin.js +57 -0
  514. package/metro/babelTransformer.js +45 -0
  515. package/metro/index.js +36 -0
  516. package/package.json +4 -25
  517. package/src/ARCHITECTURE.md +40 -27
  518. package/src/adapters/NativeANNTurboModule.ts +12 -2
  519. package/src/api/app/AppRegistry.ts +16 -2
  520. package/src/api/app/createNavigation.ts +203 -69
  521. package/src/api/commands/commands.ts +48 -7
  522. package/src/api/commands/presentation.ts +4 -3
  523. package/src/api/events/navigationEvents.ts +10 -4
  524. package/src/api/hooks/useNavigation.ts +9 -4
  525. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  526. package/src/api/index.ts +1 -0
  527. package/src/api/linking/dispatchedLinks.ts +18 -0
  528. package/src/api/linking/linking.ts +22 -1
  529. package/src/api/navigation.ts +4 -1
  530. package/src/api/options/OptionsChain.ts +2 -2
  531. package/src/api/screens/defineScreen.ts +49 -5
  532. package/src/api/screens/nativeScreens.ts +40 -4
  533. package/src/api/screens/registerScreens.tsx +185 -42
  534. package/src/api/theme/theme.ts +5 -0
  535. package/src/engine/commands.ts +70 -13
  536. package/src/engine/layout.ts +27 -11
  537. package/src/engine/nativeScreens.ts +10 -1
  538. package/src/engine/options.ts +45 -19
  539. package/src/engine/optionsChange.ts +107 -0
  540. package/src/engine/places.ts +65 -7
  541. package/src/engine/props.ts +30 -1
  542. package/src/engine/refresh.ts +97 -0
  543. package/src/engine/rememberedOptions.ts +74 -1
  544. package/src/engine/screens.tsx +76 -21
  545. package/src/interfaces/ComponentEvents.ts +4 -4
  546. package/src/interfaces/Events.ts +29 -10
  547. package/src/interfaces/Options.ts +1 -0
  548. package/src/interfaces/contract/commands.json +101 -0
  549. package/src/interfaces/contract/errors.json +275 -0
  550. package/src/interfaces/options/animations.ts +81 -22
  551. package/src/interfaces/options/bottomTabs.ts +21 -7
  552. package/src/interfaces/options/buttons.ts +23 -15
  553. package/src/interfaces/options/modals.ts +34 -26
  554. package/src/interfaces/options/sideMenu.ts +24 -6
  555. package/src/interfaces/options/stack.ts +17 -3
  556. package/src/interfaces/options/system.ts +18 -11
  557. package/src/interfaces/options/toolbar.ts +2 -2
  558. package/src/interfaces/options/topBar.ts +68 -38
  559. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  560. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  561. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  562. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  563. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  564. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  565. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  566. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  567. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  568. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  569. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  570. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  571. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  572. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  573. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  574. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -15,11 +15,13 @@ import dev.apexnative.navigation.viewcontrollers.component.Readiness
15
15
  import dev.apexnative.navigation.viewcontrollers.component.RenderWait
16
16
  import dev.apexnative.navigation.viewcontrollers.parent.OptionsScreen
17
17
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.BarMotion
18
+ import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.BarTravel
18
19
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.BarVisibility
19
20
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.Custom
20
21
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.Elements
21
22
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.Fade
22
23
  import dev.apexnative.navigation.viewcontrollers.stack.StackDisplay.Motion
24
+ import dev.apexnative.navigation.viewcontrollers.stack.fab.FabMotion
23
25
  import dev.apexnative.navigation.viewcontrollers.viewcontroller.ViewController
24
26
  import dev.apexnative.navigation.views.animations.AnimationRules
25
27
  import java.util.WeakHashMap
@@ -51,9 +53,13 @@ private typealias Node = ViewController<*>
51
53
  *
52
54
  * Its waits for a screen to render are the core's one wait ([RenderWait]), on the screen it pushes or sets as the top;
53
55
  * the readiness signals reach it through [deliver] (the stack posts them to the next turn of the main loop: a signal
54
- * that comes inside a layout pass or a view's attach moves no view of the container there). A push or a
55
- * `setStackRoot` with elements waits for its targets after that, a wait like the others: a cut or a replace during it
56
- * interrupts the push, which moves no view into a layer.
56
+ * that comes inside a layout pass or a view's attach moves no view of the container there). A push of a screen with
57
+ * React content waits for its first mount: [PUSH_WAIT_MILLIS] at most without `waitForRender`, as long as it takes
58
+ * with `true`, not at all with `false`; its signal reaches the wait through [afterCalls], behind the calls JavaScript
59
+ * made in the commit of that mount (its `mergeOptions`), so the transition starts with the options of that commit —
60
+ * content mounted already goes that way too. A push or a `setStackRoot` with elements waits for its targets after
61
+ * that, a wait like the others, within what is left of its limit without `waitForRender`: a cut or a replace during it
62
+ * interrupts the push, which starts no element.
57
63
  *
58
64
  * The transition is the screens' own when the options say so (`AnimationRules.stackIsOwn`): the display plays each
59
65
  * screen's side ([StackDisplay.animateCustom]) with the same owners as the default transitions; the bar's row then
@@ -65,18 +71,31 @@ internal class StackQueue(
65
71
  private val scheduler: AppearanceDispatcher.Scheduler,
66
72
  private val host: Host,
67
73
  private val deliver: (() -> Unit) -> Unit = { it() },
74
+ /**
75
+ * How the mount of a pushed screen reaches the push's wait: on the main thread behind every call JavaScript made
76
+ * before it (the stack: `PendingCalls`, on a later turn of the main loop); at once by default.
77
+ */
78
+ private val afterCalls: (() -> Unit) -> Unit = { it() },
68
79
  ) {
69
80
  /** What the queue tells the stack. */
70
81
  interface Host {
71
82
  /** The current child (the top of [shown]) changed: a transition started, or an operation ran at once. */
72
83
  fun currentChildChanged()
73
84
 
85
+ /** An operation was accepted: a back gesture's preview that shows ends, the stack as it was. */
86
+ fun operationAccepted() = Unit
87
+
74
88
  /**
75
89
  * The current child is about to change, right before [currentChildChanged]: [motion] is the default transition
76
90
  * the bar's row goes with, none when the change comes at once or with an animation of its own; [visibility] is
77
- * how the bar shows or hides when the new top wants it otherwise.
91
+ * how the bar shows or hides when the new top wants it otherwise; [travel]: the bar goes with the screens of an
92
+ * animation of its own without elements.
78
93
  */
79
- fun barTransition(motion: StackDisplay.BarMotion?, visibility: BarVisibility) = Unit
94
+ fun barTransition(
95
+ motion: StackDisplay.BarMotion?,
96
+ visibility: BarVisibility,
97
+ travel: StackDisplay.BarTravel? = null,
98
+ ) = Unit
80
99
 
81
100
  /**
82
101
  * The current child is about to change, right before [barTransition]: [move] is how the transition goes, which
@@ -85,6 +104,12 @@ internal class StackQueue(
85
104
  */
86
105
  fun tabBarTransition(move: TabBarMotion.Move, side: BottomTabsEnterExitAnimationOptions?) = Unit
87
106
 
107
+ /**
108
+ * The current child is about to change, right after [barTransition]: [move] is how the FAB goes, the new top's
109
+ * arriving with its screen and the old one's leaving with its own from the start of the transition.
110
+ */
111
+ fun fabTransition(move: FabMotion.Move) = Unit
112
+
88
113
  /** [node] was accepted to show as the top (a push, the new top of a replace). */
89
114
  fun willShow(node: Node) = Unit
90
115
 
@@ -95,10 +120,10 @@ internal class StackQueue(
95
120
  fun operationEnded(topSettled: Boolean)
96
121
 
97
122
  /**
98
- * Whether [node] is a React screen with a root of its own, which a push prepares when its switch is on
99
- * ([StackSwitches.preparesOwnRootPushes]).
123
+ * Whether [node] shows React content whose first mount its push waits for: a React screen (a root of its own or
124
+ * a slot), or an entry that shows one. A native screen has none: its push starts at once.
100
125
  */
101
- fun isOwnRootScreen(node: Node): Boolean = false
126
+ fun hasReactContent(node: Node): Boolean = false
102
127
 
103
128
  /** One line for the log: a failure that has no command to answer. */
104
129
  fun log(text: String) = Unit
@@ -140,6 +165,9 @@ internal class StackQueue(
140
165
  private var takenOver = false
141
166
  private var destroyed = false
142
167
 
168
+ /** [node]'s content is made and nothing waits for it to render as a lower screen. */
169
+ fun isRendered(node: Node): Boolean = node !in unrendered && node !in lowerWaits
170
+
143
171
  /** The stack as JavaScript sees it, bottom to top. */
144
172
  val entries: List<Node>
145
173
  get() = entryList
@@ -199,7 +227,9 @@ internal class StackQueue(
199
227
 
200
228
  /**
201
229
  * A cut to [target], an entry that becomes the top: every entry above it leaves. [answer] gets [value]; a back of
202
- * the user has none. [silent]: no animation and no appearance events (`popToRootOnBlur`).
230
+ * the user has none. [silent]: no animation and no appearance events (`popToRootOnBlur`). [gesture]: the release of
231
+ * a back gesture whose preview shows the pop already (`StackDisplay.finishBackGesture` ends it, the bar shows the
232
+ * target at once).
203
233
  */
204
234
  fun cut(
205
235
  target: Node,
@@ -208,6 +238,7 @@ internal class StackQueue(
208
238
  what: String,
209
239
  value: String?,
210
240
  silent: Boolean = false,
241
+ gesture: Boolean = false,
211
242
  ) {
212
243
  val index = entryList.indexOf(target)
213
244
  if (destroyed || index < 0) return refuse(answer, null, componentId, emptyList())
@@ -219,7 +250,7 @@ internal class StackQueue(
219
250
  (waiting as? ReplaceOp)?.let(::completeAtOnce)
220
251
  val showsAbove = target in shownList && shownList.last() !== target
221
252
  val op = if (showsAbove) {
222
- CutOp(seq, answer, componentId, what, target, value, silent)
253
+ CutOp(seq, answer, componentId, what, target, value, silent, gesture)
223
254
  } else {
224
255
  // A cut that moves nothing more: its answer at its turn.
225
256
  NoneOp(seq, answer, null, componentId, what, value, null)
@@ -341,6 +372,8 @@ internal class StackQueue(
341
372
  // The table.
342
373
 
343
374
  private fun enqueue(op: Op) {
375
+ // Anything but the release of a back gesture ends its preview first.
376
+ if (!(op is CutOp && op.gesture)) host.operationAccepted()
344
377
  queued.addLast(op)
345
378
  drain()
346
379
  }
@@ -410,11 +443,12 @@ internal class StackQueue(
410
443
  val node = op.node
411
444
  val push = resolved(node).animations.push
412
445
  op.awaitsTargets = awaitsTargets(push, !push.enabled.isFalse)
446
+ // A prepared screen rendered before its push; `false`, and a node without React content, start at once.
413
447
  val wait = when {
414
448
  op.prepared -> Wait.Prepared
415
449
  push.waitForRender.isTrue -> Wait.Content
416
- StackSwitches.preparesOwnRootPushes && host.isOwnRootScreen(node) -> Wait.Limited
417
- else -> Wait.None
450
+ push.waitForRender.isFalse || !host.hasReactContent(node) -> Wait.None
451
+ else -> Wait.Limited
418
452
  }
419
453
  if (wait == Wait.None) return if (op.awaitsTargets) awaitTargets(op) else beginPush(op)
420
454
  waiting = op
@@ -422,18 +456,37 @@ internal class StackQueue(
422
456
  Wait.Prepared -> awaitPrepared(op)
423
457
  Wait.Content -> {
424
458
  // Then the components of the bar drawn in advance, 0.5 s at most after the content (a title or a
425
- // background with its own `waitForRender: false` not).
459
+ // background with its own `waitForRender: false` not). React content mounted already goes behind the
460
+ // calls too; a native screen starts at once.
426
461
  display.placeWaiting(node)
427
- awaitContent(op, node, limit = null, bar = RenderWait.Bar.AfterContent)
462
+ awaitContent(
463
+ op,
464
+ node,
465
+ limit = null,
466
+ bar = RenderWait.Bar.AfterContent,
467
+ deliver = afterCalls,
468
+ deliversReady = host.hasReactContent(node),
469
+ )
428
470
  }
429
471
  else -> {
472
+ // The screen renders hidden under the top, its signal (or its content mounted already) behind the
473
+ // calls; the bar's components don't count. The 0.5 s hold for the content and the targets together.
430
474
  display.placeWaiting(node)
431
- awaitContent(op, node, limit = OWN_ROOT_WAIT_MILLIS, bar = RenderWait.Bar.None)
475
+ op.cancelLimit = scheduler.schedule(PUSH_WAIT_MILLIS) { op.overLimit = true }
476
+ awaitContent(
477
+ op,
478
+ node,
479
+ limit = PUSH_WAIT_MILLIS,
480
+ bar = RenderWait.Bar.None,
481
+ deliver = afterCalls,
482
+ deliversReady = true,
483
+ )
432
484
  }
433
485
  }
434
486
  }
435
487
 
436
488
  private fun beginPush(op: PushOp) {
489
+ op.cancelLimit?.invoke()
437
490
  val node = op.node
438
491
  val covered = shownList.lastOrNull()
439
492
  // The views first: a failure here leaves the lists as they were.
@@ -450,7 +503,7 @@ internal class StackQueue(
450
503
  val elements = own && AnimationRules.hasElements(push)
451
504
  // The bar's row goes with the default transition only; with an animation of its own it changes at once. The tab
452
505
  // bar moves with its screens or by its own side.
453
- tellBars(animated, own, elements, push, TabBarMotion.Move.WithPush, BarMotion.Push)
506
+ tellBars(animated, own, elements, push, TabBarMotion.Move.WithPush, BarMotion.Push, BarTravel.Forward)
454
507
  host.currentChildChanged()
455
508
  finishTakenOver(ended)
456
509
  running += op
@@ -488,6 +541,7 @@ internal class StackQueue(
488
541
 
489
542
  // Off screen or without a view: at once, without a transition; the top appears when the stack shows.
490
543
  private fun pushAtOnce(op: PushOp) {
544
+ op.cancelLimit?.invoke()
491
545
  val node = op.node
492
546
  val covered = shownList.lastOrNull()
493
547
  if (display.hasView) {
@@ -499,6 +553,7 @@ internal class StackQueue(
499
553
  val ended = takeOver(listOfNotNull(covered, node), op)
500
554
  host.tabBarTransition(TabBarMotion.Move.AtOnce, null)
501
555
  host.barTransition(null, BarVisibility.AT_ONCE)
556
+ host.fabTransition(FabMotion.Move.AtOnce)
502
557
  host.currentChildChanged()
503
558
  finishTakenOver(ended)
504
559
  if (display.hasView && covered != null) display.detach(covered)
@@ -516,6 +571,7 @@ internal class StackQueue(
516
571
  if (op.done) return
517
572
  op.done = true
518
573
  if (waiting === op) stopWaiting(op)
574
+ op.cancelLimit?.invoke()
519
575
  queued.remove(op)
520
576
  val node = op.node
521
577
  entryList.remove(node)
@@ -581,7 +637,9 @@ internal class StackQueue(
581
637
  val animated = !atOnce && !op.silent && display.canAnimate && !pop.enabled.isFalse
582
638
  val own = animated && AnimationRules.stackIsOwn(pop)
583
639
  val elements = own && AnimationRules.hasElements(pop)
584
- tellBars(animated, own, elements, pop, TabBarMotion.Move.WithPop, BarMotion.Pop)
640
+ // A back gesture's preview shows the target and its bar already: the bar stays as it is.
641
+ val gesture = op.gesture && animated && !own && leaving.size == 1 && display.hasBackPreview(top, target)
642
+ tellBars(animated, own, elements, pop, TabBarMotion.Move.WithPop, BarMotion.Pop, BarTravel.Back, gesture)
585
643
  host.currentChildChanged()
586
644
  finishTakenOver(ended)
587
645
  if (display.hasView) target.onViewBroughtToFront()
@@ -592,6 +650,17 @@ internal class StackQueue(
592
650
  // The screens between the top and the target leave without animation.
593
651
  leaving.drop(1).forEach(display::hide)
594
652
  if (!animated) return finishCut(op)
653
+ if (gesture) {
654
+ op.animating += top
655
+ op.animating += target
656
+ display.finishBackGesture(
657
+ top,
658
+ target,
659
+ { step(op) { screenDone(op, top) } },
660
+ { step(op) { screenDone(op, target) } },
661
+ )
662
+ return
663
+ }
595
664
  // Its own: no wait on a pop; the leaving screen starts from where it is.
596
665
  if (own) return animate(op, backMoves(top, target, pop, elements, moving))
597
666
  animate(op, listOf(Move(top, Motion.PopOut, true), Move(target, Motion.PopReveal, moving)))
@@ -657,7 +726,7 @@ internal class StackQueue(
657
726
  val elements = own && !op.asPush && AnimationRules.hasElements(played)
658
727
  val motion = if (op.asPush) BarMotion.Push else BarMotion.FadeThrough
659
728
  val system = if (op.asPush) TabBarMotion.Move.WithPush else TabBarMotion.Move.Slide
660
- tellBars(animated, own, elements, played, system, motion)
729
+ tellBars(animated, own, elements, played, system, motion, BarTravel.Forward)
661
730
  host.currentChildChanged()
662
731
  finishTakenOver(ended)
663
732
  op.owned += moved
@@ -724,6 +793,7 @@ internal class StackQueue(
724
793
  val ended = takeOver(old + top, op)
725
794
  host.tabBarTransition(TabBarMotion.Move.AtOnce, null)
726
795
  host.barTransition(null, BarVisibility.AT_ONCE)
796
+ host.fabTransition(FabMotion.Move.AtOnce)
727
797
  host.currentChildChanged()
728
798
  finishTakenOver(ended)
729
799
  op.done = true
@@ -769,8 +839,16 @@ internal class StackQueue(
769
839
 
770
840
  // The one wait (RenderWait) for [screen], the node the operation brings: at [limit] the content not ready counts
771
841
  // as mounted; without one, `waitForRender: true` waits as long as it takes, except for content the readiness store
772
- // knows nothing of after 1 s, which counts as ready (the same rule as iOS).
773
- private fun awaitContent(op: Op, screen: Node, limit: Long?, bar: RenderWait.Bar) {
842
+ // knows nothing of after 1 s, which counts as ready (the same rule as iOS). A push's signals come through
843
+ // [afterCalls] ([deliver]); with [deliversReady], so does content ready at the start.
844
+ private fun awaitContent(
845
+ op: Op,
846
+ screen: Node,
847
+ limit: Long?,
848
+ bar: RenderWait.Bar,
849
+ deliver: (() -> Unit) -> Unit = this.deliver,
850
+ deliversReady: Boolean = false,
851
+ ) {
774
852
  val wait = RenderWait(
775
853
  readiness = readiness,
776
854
  scheduler = scheduler,
@@ -778,6 +856,7 @@ internal class StackQueue(
778
856
  bar = bar,
779
857
  countsUnknownContent = true,
780
858
  deliver = deliver,
859
+ deliversReadyContent = deliversReady,
781
860
  step = { work -> step(op) { work() } },
782
861
  onEnd = { endWait(op) },
783
862
  )
@@ -798,15 +877,32 @@ internal class StackQueue(
798
877
  step(op) { wait.retake(RenderWait.waitedScreens(node)) }
799
878
  }
800
879
 
880
+ // The prepared screen's slot mounts (or the display's limit passes), then its transition starts behind the calls
881
+ // JavaScript made before ([afterCalls]): a commit that came after the push (its JavaScript's own limit) brings its
882
+ // `mergeOptions` first. The same 0.5 s from the start hold for both: the transition starts then anyway.
801
883
  private fun awaitPrepared(op: PushOp) {
802
884
  val token = Any()
803
885
  op.waitToken = token
804
886
  val node = op.node
887
+ val still = { !destroyed && !op.done && op.waitToken === token && waiting === op && op.isCurrent() }
888
+ var mounted = false
889
+ val markMounted = {
890
+ if (!mounted && !readiness.isReady(node)) readiness.markReady(node)
891
+ mounted = true
892
+ }
893
+ val start = { step(op) { if (still()) endWait(op) } }
894
+ op.cancelCap = scheduler.schedule(PUSH_WAIT_MILLIS) {
895
+ step(op) {
896
+ if (!still()) return@step
897
+ markMounted()
898
+ endWait(op)
899
+ }
900
+ }
805
901
  display.awaitPrepared(
806
902
  node,
807
- waiting = { !destroyed && !op.done && op.waitToken === token && waiting === op && op.isCurrent() },
808
- mounted = { step(op) { if (!readiness.isReady(node)) readiness.markReady(node) } },
809
- start = { step(op) { if (waiting === op) endWait(op) } },
903
+ waiting = still,
904
+ mounted = { step(op) { markMounted() } },
905
+ start = { afterCalls(start) },
810
906
  )
811
907
  }
812
908
 
@@ -835,7 +931,8 @@ internal class StackQueue(
835
931
  val token = Any()
836
932
  op.waitToken = token
837
933
  val still = { !destroyed && !op.done && op.waitToken === token && waiting === op && op.isCurrent() }
838
- // Without `waitForRender` a `setStackRoot`'s 0.5 s holds for its content and its targets together.
934
+ // Without `waitForRender` the 0.5 s of a `setStackRoot` and of a push of React content hold for the content
935
+ // and the targets together.
839
936
  val from = currentChild
840
937
  op.stopTargets = display.awaitTargets(animation, from, to, { still() && !op.overLimit }) {
841
938
  step(op) { if (still()) endWait(op) }
@@ -844,6 +941,8 @@ internal class StackQueue(
844
941
 
845
942
  private fun stopWaiting(op: Op) {
846
943
  if (waiting === op) waiting = null
944
+ op.cancelCap?.invoke()
945
+ op.cancelCap = null
847
946
  op.waitToken = null
848
947
  op.wait?.cancel()
849
948
  op.wait = null
@@ -1034,6 +1133,7 @@ internal class StackQueue(
1034
1133
  reject(op, text)
1035
1134
  host.tabBarTransition(TabBarMotion.Move.AtOnce, null)
1036
1135
  host.barTransition(null, BarVisibility.AT_ONCE)
1136
+ host.fabTransition(FabMotion.Move.AtOnce)
1037
1137
  host.currentChildChanged()
1038
1138
  settled()
1039
1139
  drain()
@@ -1081,9 +1181,10 @@ internal class StackQueue(
1081
1181
  private fun awaitsTargets(animation: StackAnimationOptions, enabled: Boolean): Boolean = enabled &&
1082
1182
  display.canAnimate && !animation.waitForRender.isFalse && AnimationRules.hasElements(animation)
1083
1183
 
1084
- // The bars with a change of the current child. The row goes with the default transition only; the tab bar rides
1085
- // with the system's [system] move, slides with an animation of its own or a side of its own, and is where the new
1086
- // top wants it at once without animation; with elements every bar changes at once.
1184
+ // The bars with a change of the current child. The row goes with the default transition; with an animation of its
1185
+ // own the top bar goes with the screens ([travel]). The tab bar rides with the system's [system] move, slides with an
1186
+ // animation of its own or a side of its own, and is where the new top wants it at once without animation; with
1187
+ // elements every bar changes at once. The FAB goes with its screen, by Material's swap with an animation of its own.
1087
1188
  private fun tellBars(
1088
1189
  animated: Boolean,
1089
1190
  own: Boolean,
@@ -1091,6 +1192,10 @@ internal class StackQueue(
1091
1192
  animation: StackAnimationOptions,
1092
1193
  system: TabBarMotion.Move,
1093
1194
  row: BarMotion,
1195
+ travel: BarTravel,
1196
+ // The top bar and the FAB show the new top already (a back gesture's preview): they change at once, the tab bar
1197
+ // still moves.
1198
+ barAtOnce: Boolean = false,
1094
1199
  ) {
1095
1200
  val tabs = animation.bottomTabs
1096
1201
  val tabsSide = AnimationRules.barSideGiven(tabs.enter) || AnimationRules.barSideGiven(tabs.exit)
@@ -1100,7 +1205,13 @@ internal class StackQueue(
1100
1205
  else -> system
1101
1206
  }
1102
1207
  host.tabBarTransition(move, tabs.takeIf { move == TabBarMotion.Move.Slide })
1103
- host.barTransition(if (animated && !own) row else null, barVisibility(animated && !elements, animation.topBar))
1208
+ val barMoves = animated && !barAtOnce
1209
+ host.barTransition(
1210
+ if (barMoves && !own) row else null,
1211
+ barVisibility(barMoves && !elements, animation.topBar),
1212
+ travel.takeIf { barMoves && own && !elements },
1213
+ )
1214
+ host.fabTransition(FabMotion.moveOf(animated, own, row, shown = barAtOnce))
1104
1215
  }
1105
1216
 
1106
1217
  private fun barVisibility(animated: Boolean, side: TopBarEnterExitAnimationOptions): BarVisibility =
@@ -1179,9 +1290,12 @@ internal class StackQueue(
1179
1290
  // It waits for its elements' targets after its content; what stops that wait.
1180
1291
  var awaitsTargets = false
1181
1292
  var stopTargets: (() -> Unit)? = null
1182
- // The limit of a `setStackRoot` without `waitForRender` passed: its targets get nothing of it any more.
1293
+ // The limit of a `setStackRoot` or a push without `waitForRender` passed: its targets get nothing of it any
1294
+ // more.
1183
1295
  var overLimit = false
1184
1296
  var cancelLimit: (() -> Unit)? = null
1297
+ // The limit of a prepared push's wait, which ends with the wait.
1298
+ var cancelCap: (() -> Unit)? = null
1185
1299
  // Its screen came by an animation of its own: it stays at that animation's end values.
1186
1300
  var keepsEnd = false
1187
1301
  // The listener of a module heard its answer: it hears one only.
@@ -1209,6 +1323,7 @@ internal class StackQueue(
1209
1323
  val target: Node,
1210
1324
  val value: String?,
1211
1325
  val silent: Boolean,
1326
+ val gesture: Boolean,
1212
1327
  ) : Op(seq, answer, null, componentId, what) {
1213
1328
  var leaving: List<Node> = emptyList()
1214
1329
  }
@@ -1255,20 +1370,13 @@ internal class StackQueue(
1255
1370
  /** How long a lower screen stays placed in the container to make its content, at most. */
1256
1371
  const val LOWER_SCREEN_MILLIS = 500L
1257
1372
 
1258
- /** How long the push of a screen with its own root waits for its content, with the switch on. */
1259
- const val OWN_ROOT_WAIT_MILLIS = 500L
1373
+ /**
1374
+ * How long a push waits for its screen's first mount without `waitForRender`, and a prepared push for its slot
1375
+ * and the calls before it.
1376
+ */
1377
+ const val PUSH_WAIT_MILLIS = 500L
1260
1378
 
1261
1379
  // The alpha an arriving screen shows with: its own at rest, never the 0 of its wait.
1262
1380
  private const val ARRIVING_ALPHA = 1f
1263
1381
  }
1264
1382
  }
1265
-
1266
- /**
1267
- * The internal switches of the stack. [preparesOwnRootPushes]: the push of a React screen with a root of its own starts
1268
- * its surface hidden in the stack at its size and insets, and starts its transition once the content rendered, 0.5 s at
1269
- * most. Off by default («б»: the push starts at once); it is measured at the end on a phone.
1270
- */
1271
- internal object StackSwitches {
1272
- @Volatile
1273
- var preparesOwnRootPushes = false
1274
- }
@@ -16,11 +16,15 @@ import dev.apexnative.navigation.views.animations.SystemTransition
16
16
  * system's transition between activities (`SystemTransition`: 96 dp along the axis in 450 ms on
17
17
  * `fast_out_extra_slow_in`, mirrored right to left), `setStackRoot` is Material's fade through (`FadeThrough`). What
18
18
  * leaves starts from where it is; what comes in on a push is hidden explicitly until it fades in, as a delay doesn't
19
- * apply an animator's first value. Main thread only.
19
+ * apply an animator's first value. The system's windows also extend their edge by the distance they move
20
+ * ([extendsStart], `StackLayout.extendEdge`). Main thread only.
20
21
  */
21
22
  internal object StackTransitions {
22
- /** The animator of [view] for [motion]; [fromCurrent] for a screen taken over from a transition still running. */
23
- fun animator(view: View, motion: Motion, fromCurrent: Boolean): Animator {
23
+ /**
24
+ * The animator of [view] for [motion]; [fromCurrent] for a screen taken over from a transition still running.
25
+ * [onSlide] runs at each frame of its slide.
26
+ */
27
+ fun animator(view: View, motion: Motion, fromCurrent: Boolean, onSlide: () -> Unit = {}): Animator {
24
28
  val distance = SystemTransition.DISTANCE_DP * view.resources.displayMetrics.density
25
29
  // Forward is to the end of the line: right to left, the screens move the other way. The stack's view inherits
26
30
  // the app's direction, which `layout.direction` sets on the activity's content (`AppDirection`).
@@ -30,24 +34,37 @@ internal object StackTransitions {
30
34
  view.translationX = forward
31
35
  view.alpha = 0f
32
36
  together(
33
- slide(view, 0f),
37
+ slide(view, 0f, onSlide),
34
38
  fade(view, 1f, SystemTransition.PUSH_FADE_DELAY),
35
39
  )
36
40
  }
37
- Motion.PushCover -> slide(view, -forward)
41
+ Motion.PushCover -> slide(view, -forward, onSlide)
38
42
  Motion.PopOut -> together(
39
- slide(view, forward),
43
+ slide(view, forward, onSlide),
40
44
  fade(view, 0f, SystemTransition.POP_FADE_DELAY),
41
45
  )
42
46
  Motion.PopReveal -> {
43
47
  if (!fromCurrent) view.translationX = -forward
44
- if (view.alpha < 1f) together(slide(view, 0f), fade(view, 1f, 0L)) else slide(view, 0f)
48
+ if (view.alpha < 1f) together(slide(view, 0f, onSlide), fade(view, 1f, 0L)) else slide(view, 0f, onSlide)
45
49
  }
46
50
  Motion.FadeIn -> FadeThrough.enter(view)
47
51
  Motion.FadeOut -> FadeThrough.exit(view)
48
52
  }
49
53
  }
50
54
 
55
+ /**
56
+ * Whether a screen moving by [motion] extends its start edge (the side it moves away from on a push in and a pop
57
+ * out), its end edge (a push cover, a pop reveal), or none (a fade through: null), as the system's windows do.
58
+ */
59
+ fun extendsStart(motion: Motion): Boolean? = when (motion) {
60
+ Motion.PushIn, Motion.PopOut -> true
61
+ Motion.PushCover, Motion.PopReveal -> false
62
+ Motion.FadeIn, Motion.FadeOut -> null
63
+ }
64
+
65
+ /** Whether [motion] animates the screen's alpha: it draws through a hardware layer meanwhile. */
66
+ fun fades(motion: Motion): Boolean = motion != Motion.PushCover && motion != Motion.PopReveal
67
+
51
68
  /**
52
69
  * The fade of a screen around elements: in from 0 to 1, out from where it is to 0, linearly in
53
70
  * [AnimationRules.SCREEN_FADE]; none for [Fade.None].
@@ -65,10 +82,11 @@ internal object StackTransitions {
65
82
  }
66
83
  }
67
84
 
68
- private fun slide(view: View, to: Float): Animator =
85
+ private fun slide(view: View, to: Float, onFrame: () -> Unit): Animator =
69
86
  ObjectAnimator.ofFloat(view, View.TRANSLATION_X, view.translationX, to).apply {
70
87
  duration = SystemTransition.DURATION
71
88
  interpolator = SystemTransition.CURVE
89
+ addUpdateListener { onFrame() }
72
90
  }
73
91
 
74
92
  private fun fade(view: View, to: Float, delay: Long): Animator =