@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
@@ -0,0 +1,32 @@
1
+ #import <UIKit/UIKit.h>
2
+
3
+ NS_ASSUME_NONNULL_BEGIN
4
+
5
+ /// Posted on the main queue when the screens' geometry has settled: each screen sends its insets, padding and regions
6
+ /// once.
7
+ extern NSNotificationName const ANNScreenSettlingDidEndNotification;
8
+
9
+ /// iPhone Duo (iOS 27.1) folds and unfolds in steps: around the size transition, UIKit gives the views safe areas and a
10
+ /// vertical bar edge that are neither the old nor the new ones (the bar on the other side, insets on both sides,
11
+ /// twice its width) and tells of the bar's edge and of the safe area at other moments. While the geometry settles the
12
+ /// screens lay out as always but send nothing to JavaScript: the settling ends once the transition is over and the
13
+ /// values of the screens have stood still for a short while, and the screens send what they have then. Only on a
14
+ /// device with a hinge: elsewhere a rotation gives the new safe area at once, and it goes at once. Main queue.
15
+ @interface ANNScreenSettling : NSObject
16
+
17
+ /// A size transition starts: the settling runs at least until it ends.
18
+ + (void)beginWithTransition:(id<UIViewControllerTransitionCoordinator>)coordinator;
19
+
20
+ /// The vertical bar's edge changed: the size transition, when one follows, comes a little later. The hinge's moves
21
+ /// begin the settling too (`ANNHingeDidMoveNotification`): UIKit may give a new safe area before either.
22
+ + (void)beginForTraitChange;
23
+
24
+ /// Whether the screens hold their insets now.
25
+ + (BOOL)isSettling;
26
+
27
+ /// A screen's values changed while settling: the quiet time starts again.
28
+ + (void)valuesDidChange;
29
+
30
+ @end
31
+
32
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,137 @@
1
+ #import "ANNScreenSettling.h"
2
+ #import "ANNEventContract.h"
3
+ #import "ANNHinge.h"
4
+ #import <QuartzCore/QuartzCore.h>
5
+
6
+ NSNotificationName const ANNScreenSettlingDidEndNotification = @"ANNScreenSettlingDidEnd";
7
+
8
+ // How long the values of the screens stand still before the settling ends. On iPhone Duo UIKit's last step of a fold
9
+ // comes some 30 ms after the size transition's end, and the size transition some 50 ms after the bar's new edge.
10
+ static const CFTimeInterval ANNScreenSettlingQuietTime = 0.15;
11
+ // The settling holds the insets no longer than this after its last start, whatever keeps changing.
12
+ static const CFTimeInterval ANNScreenSettlingLongest = 1.0;
13
+ // The degrees the hinge turns before it counts as a move: a device held half open trembles a little.
14
+ static const double ANNScreenSettlingHingeStep = 2;
15
+
16
+ static BOOL ANNSettling;
17
+ // The size transitions that began and haven't ended: each screen counts its own call of the same transition.
18
+ static NSInteger ANNSettlingTransitions;
19
+ static CFTimeInterval ANNSettlingStart;
20
+ static CFTimeInterval ANNSettlingLastChange;
21
+ // Only the check scheduled last runs.
22
+ static NSUInteger ANNSettlingCheckGeneration;
23
+ // One more at each end: a transition that began before it no longer counts.
24
+ static NSUInteger ANNSettlingEpoch;
25
+ // The hinge's state and angle at its first value and at its last move that counted; none without a hinge.
26
+ static id ANNSettlingHingeState;
27
+ static NSNumber *ANNSettlingHingeAngle;
28
+
29
+ @implementation ANNScreenSettling
30
+
31
+ // The screens ask `isSettling` from their first layout on, before any fold.
32
+ + (void)initialize {
33
+ if (self == ANNScreenSettling.class) {
34
+ [NSNotificationCenter.defaultCenter addObserver:self
35
+ selector:@selector(hingeDidMove:)
36
+ name:ANNHingeDidMoveNotification
37
+ object:nil];
38
+ }
39
+ }
40
+
41
+ // A fold starts with the hinge, and the display it shows on changes as it moves.
42
+ + (void)hingeDidMove:(NSNotification *)notification {
43
+ NSDictionary<NSString *, id> *value = [ANNHinge lastValue];
44
+ const auto &keys = ANNEventContract.HingeChanged;
45
+ id state = value[keys.state];
46
+ NSNumber *angle = value[keys.angle];
47
+ // The first value, and the hinge's coming or going, are no move.
48
+ if (!state || !ANNSettlingHingeState) {
49
+ ANNSettlingHingeState = state;
50
+ ANNSettlingHingeAngle = angle;
51
+ return;
52
+ }
53
+ double turned = fabs(angle.doubleValue - ANNSettlingHingeAngle.doubleValue);
54
+ BOOL moved = ![state isEqual:ANNSettlingHingeState] || !angle || !ANNSettlingHingeAngle ||
55
+ turned >= ANNScreenSettlingHingeStep;
56
+ if (!moved) {
57
+ return;
58
+ }
59
+ ANNSettlingHingeState = state;
60
+ ANNSettlingHingeAngle = angle;
61
+ [self beginForTraitChange];
62
+ }
63
+
64
+ + (void)beginWithTransition:(id<UIViewControllerTransitionCoordinator>)coordinator {
65
+ if (![ANNHinge isPresent]) {
66
+ return;
67
+ }
68
+ [self begin];
69
+ ANNSettlingTransitions += 1;
70
+ NSUInteger epoch = ANNSettlingEpoch;
71
+ void (^ended)(id<UIViewControllerTransitionCoordinatorContext>) =
72
+ ^(id<UIViewControllerTransitionCoordinatorContext> context) {
73
+ if (epoch != ANNSettlingEpoch) {
74
+ return;
75
+ }
76
+ ANNSettlingTransitions = MAX(0, ANNSettlingTransitions - 1);
77
+ [ANNScreenSettling valuesDidChange];
78
+ [ANNScreenSettling checkAfter:ANNScreenSettlingQuietTime];
79
+ };
80
+ [coordinator animateAlongsideTransition:nil completion:ended];
81
+ // The longest still holds should the transition's end never come.
82
+ [self checkAfter:ANNScreenSettlingLongest];
83
+ }
84
+
85
+ // Only iPhone Duo has a vertical bar: no need to ask for the hinge.
86
+ + (void)beginForTraitChange {
87
+ [self begin];
88
+ [self checkAfter:ANNScreenSettlingQuietTime];
89
+ }
90
+
91
+ + (void)begin {
92
+ CFTimeInterval now = CACurrentMediaTime();
93
+ ANNSettling = YES;
94
+ ANNSettlingStart = now;
95
+ ANNSettlingLastChange = now;
96
+ }
97
+
98
+ + (BOOL)isSettling {
99
+ return ANNSettling;
100
+ }
101
+
102
+ + (void)valuesDidChange {
103
+ ANNSettlingLastChange = CACurrentMediaTime();
104
+ }
105
+
106
+ + (void)checkAfter:(CFTimeInterval)delay {
107
+ NSUInteger generation = ++ANNSettlingCheckGeneration;
108
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)),
109
+ dispatch_get_main_queue(), ^{
110
+ if (generation == ANNSettlingCheckGeneration) {
111
+ [ANNScreenSettling check];
112
+ }
113
+ });
114
+ }
115
+
116
+ // Ends once no transition runs and the values stood still for the quiet time, or at the longest; else looks again
117
+ // when that can be the case. A change since the check was scheduled moves the end on.
118
+ + (void)check {
119
+ if (!ANNSettling) {
120
+ return;
121
+ }
122
+ CFTimeInterval now = CACurrentMediaTime();
123
+ CFTimeInterval longest = ANNSettlingStart + ANNScreenSettlingLongest;
124
+ CFTimeInterval quiet = ANNSettlingLastChange + ANNScreenSettlingQuietTime;
125
+ if (now >= longest || (ANNSettlingTransitions == 0 && now >= quiet)) {
126
+ ANNSettling = NO;
127
+ ANNSettlingTransitions = 0;
128
+ ANNSettlingEpoch += 1;
129
+ [NSNotificationCenter.defaultCenter postNotificationName:ANNScreenSettlingDidEndNotification
130
+ object:nil];
131
+ return;
132
+ }
133
+ CFTimeInterval next = ANNSettlingTransitions > 0 ? longest : MIN(quiet, longest);
134
+ [self checkAfter:next - now];
135
+ }
136
+
137
+ @end
@@ -12,6 +12,14 @@ typedef NS_ENUM(NSInteger, ANNSideMenuOpenMode) {
12
12
  ANNSideMenuOpenModeAboveContent,
13
13
  };
14
14
 
15
+ /** `sideMenu.menusAttachMode`: when the screens of the menus are made, with the side menu, after its first
16
+ * appearance, or each as it first starts to open. */
17
+ typedef NS_ENUM(NSInteger, ANNSideMenuAttachMode) {
18
+ ANNSideMenuAttachModeTogether,
19
+ ANNSideMenuAttachModeAfterCenter,
20
+ ANNSideMenuAttachModeOnOpen,
21
+ };
22
+
15
23
  /** `sideMenu.openGestureMode`: a pan from anywhere on the center, or from its edges only. */
16
24
  typedef NS_ENUM(NSInteger, ANNSideMenuOpenGestureMode) {
17
25
  ANNSideMenuOpenGestureModeEntireScreen,
@@ -12,6 +12,24 @@ static const CGFloat ANNSideMenuDimAlpha = 0.5;
12
12
  static const CGFloat ANNSideMenuMaxStretch = 1.1;
13
13
  static const NSTimeInterval ANNSideMenuMinimumDuration = 0.1;
14
14
 
15
+ // `sideMenu.menusAttachMode` of the side menu's own options, else of the defaults; any other value, and none, is
16
+ // `together`.
17
+ static ANNSideMenuAttachMode ANNSideMenuAttachModeOf(ANNNavigationOptions *options,
18
+ ANNNavigationOptions *defaultOptions) {
19
+ Text *value = options.sideMenu.menusAttachMode;
20
+ if (!value.hasValue) {
21
+ value = defaultOptions.sideMenu.menusAttachMode;
22
+ }
23
+ NSString *mode = [value withDefault:nil];
24
+ if ([mode isEqualToString:@"afterCenter"]) {
25
+ return ANNSideMenuAttachModeAfterCenter;
26
+ }
27
+ if ([mode isEqualToString:@"onOpen"]) {
28
+ return ANNSideMenuAttachModeOnOpen;
29
+ }
30
+ return ANNSideMenuAttachModeTogether;
31
+ }
32
+
15
33
  static UINavigationController *ANNStackOfResponder(UIResponder *responder) {
16
34
  for (; responder; responder = responder.nextResponder) {
17
35
  if ([responder isKindOfClass:UINavigationController.class]) {
@@ -65,6 +83,8 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
65
83
  @property(nonatomic) BOOL glass;
66
84
  @property(nonatomic) ANNSideMenuAppearance appearance;
67
85
  @property(nonatomic, copy) NSString *scrimTestID;
86
+ // The menu's part is in its container and renders (`menusAttachMode`).
87
+ @property(nonatomic) BOOL attached;
68
88
  @end
69
89
 
70
90
  @implementation ANNSideMenuSideState
@@ -95,6 +115,8 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
95
115
  ANNSideMenuSideState *_leftState;
96
116
  ANNSideMenuSideState *_rightState;
97
117
  ANNSideMenuOpenGestureMode _openGestureMode;
118
+ ANNSideMenuAttachMode _attachMode;
119
+ BOOL _firstAppeared;
98
120
  NSString *_animationType;
99
121
  UIView *_centerContainer;
100
122
  UIView *_leftContainer;
@@ -132,6 +154,7 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
132
154
  _leftState = [ANNSideMenuSideState new];
133
155
  _rightState = [ANNSideMenuSideState new];
134
156
  _openGestureMode = ANNSideMenuOpenGestureModeBezel;
157
+ _attachMode = ANNSideMenuAttachModeOf(options, defaultOptions);
135
158
  [self setSideMenuChildren:childViewControllers];
136
159
 
137
160
  self.presenter = presenter;
@@ -181,10 +204,15 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
181
204
 
182
205
  - (void)viewDidLoad {
183
206
  [super viewDidLoad];
184
- _leftContainer = [self containerForChild:self.left];
185
- _rightContainer = [self containerForChild:self.right];
186
- _centerContainer = [self containerForChild:self.center];
207
+ _leftContainer = [self makeContainer];
208
+ _rightContainer = [self makeContainer];
209
+ _centerContainer = [self makeContainer];
210
+ [self putChild:self.center into:_centerContainer];
187
211
  _centerContainer.hidden = NO;
212
+ if (_attachMode == ANNSideMenuAttachModeTogether) {
213
+ [self attachMenu:ANNSideMenuSideLeft];
214
+ [self attachMenu:ANNSideMenuSideRight];
215
+ }
188
216
  [self applyGlassOf:ANNSideMenuSideLeft];
189
217
  [self applyGlassOf:ANNSideMenuSideRight];
190
218
 
@@ -200,32 +228,65 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
200
228
  [self.view addGestureRecognizer:_pan];
201
229
  }
202
230
 
203
- // A child in a view of its own, which the menu moves; a menu's container is hidden while closed.
204
- - (UIView *)containerForChild:(UIViewController *)child {
231
+ // The view of a part, which the menu moves; a menu's container is hidden while closed.
232
+ - (UIView *)makeContainer {
205
233
  UIView *container = [[UIView alloc] initWithFrame:self.view.bounds];
206
234
  container.hidden = YES;
207
235
  [self.view addSubview:container];
208
- if (child) {
209
- [self addChildViewController:child];
210
- child.view.frame = container.bounds;
211
- child.view.autoresizingMask =
212
- UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
213
- [container addSubview:child.view];
214
- [child didMoveToParentViewController:self];
215
- }
216
236
  return container;
217
237
  }
218
238
 
239
+ // A part in its container, over the container's glass. Loading the part's view loads its node's, which renders.
240
+ - (void)putChild:(UIViewController *)child into:(UIView *)container {
241
+ if (!child) {
242
+ return;
243
+ }
244
+ [self addChildViewController:child];
245
+ child.view.frame = container.bounds;
246
+ child.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
247
+ [container addSubview:child.view];
248
+ [child didMoveToParentViewController:self];
249
+ }
250
+
251
+ // The menu's part goes into its container and renders, once: with the side menu's view (`together`), after its first
252
+ // appearance (`afterCenter`), or as the menu first starts to open (`onOpen`, and any mode for a menu that opens
253
+ // earlier). A menu not attached yet keeps its node and options; only its view and content wait.
254
+ - (void)attachMenu:(ANNSideMenuSide)side {
255
+ ANNSideMenuChildViewController *menu = [self menuOf:side];
256
+ if (!menu || [self stateOf:side].attached || self.nodeHelper.destroyed) {
257
+ return;
258
+ }
259
+ [self loadViewIfNeeded];
260
+ ANNSideMenuSideState *state = [self stateOf:side];
261
+ if (state.attached) {
262
+ return;
263
+ }
264
+ state.attached = YES;
265
+ [self putChild:menu into:[self containerOf:side]];
266
+ [menu render];
267
+ }
268
+
269
+ // The current part renders, and every other part that is attached or will be with the side menu's view.
219
270
  - (void)render {
220
271
  [self.nodeHelper render];
221
272
  UIViewController *currentChild = self.getCurrentChild;
222
273
  for (UIViewController *vc in _sideMenuChildren) {
223
- if (vc != currentChild) {
274
+ if (vc != currentChild && [self rendersPart:vc]) {
224
275
  [vc render];
225
276
  }
226
277
  }
227
278
  }
228
279
 
280
+ - (BOOL)rendersPart:(UIViewController *)part {
281
+ if (part == self.left) {
282
+ return _attachMode == ANNSideMenuAttachModeTogether || _leftState.attached;
283
+ }
284
+ if (part == self.right) {
285
+ return _attachMode == ANNSideMenuAttachModeTogether || _rightState.attached;
286
+ }
287
+ return YES;
288
+ }
289
+
229
290
  #pragma mark - Options
230
291
 
231
292
  - (ANNSideMenuSideState *)stateOf:(ANNSideMenuSide)side {
@@ -380,6 +441,7 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
380
441
 
381
442
  // The menu on screen in its place under or over the center, its screens about to appear.
382
443
  - (void)show:(ANNSideMenuSide)side {
444
+ [self attachMenu:side];
383
445
  _side = side;
384
446
  [self orderSide:side];
385
447
  [self containerOf:side].hidden = NO;
@@ -586,6 +648,13 @@ typedef NS_ENUM(NSInteger, ANNSideMenuAppearance) {
586
648
  if (_side != ANNSideMenuSideNone) {
587
649
  [self side:_side transitionEnded:YES];
588
650
  }
651
+ if (!_firstAppeared) {
652
+ _firstAppeared = YES;
653
+ if (_attachMode == ANNSideMenuAttachModeAfterCenter) {
654
+ [self attachMenu:ANNSideMenuSideLeft];
655
+ [self attachMenu:ANNSideMenuSideRight];
656
+ }
657
+ }
589
658
  }
590
659
 
591
660
  - (void)viewWillDisappear:(BOOL)animated {
@@ -15,8 +15,9 @@ NS_ASSUME_NONNULL_BEGIN
15
15
  /// `showInColumn`: the push's checks of the layout (the options of the tree, what the core makes), then the screen is
16
16
  /// made and waits by the push's rules. Once it is ready, by the state then: the source in a split view not collapsed
17
17
  /// into its compact layout — the split view shows the screen in `column`, unless a later request of that column began
18
- /// meanwhile (the last one wins); else the source in a stack — a push over it; else a rejection. The answer is the
19
- /// shown screen's id; every rejection destroys the screen.
18
+ /// meanwhile (the last one wins; the superseded one answers when the last one does, with its own screen's id whatever
19
+ /// the last one's outcome, as on Android); else the source in a stack — a push over it; else a rejection. The answer
20
+ /// is the shown screen's id; every rejection destroys the screen.
20
21
  + (void)showInColumn:(NSString *)column
21
22
  layout:(ANNLayoutNode *)layout
22
23
  componentId:(NSString *)componentId
@@ -15,14 +15,19 @@
15
15
  #import "ANNRenderWait.h"
16
16
  #import "ANNShownScreens.h"
17
17
  #import "ANNStackCommands.h"
18
+ #import "ANNStackController.h"
18
19
  #import "ANNStackQueue.h"
19
20
  #import "ApexNavigation+Internal.h"
20
21
  #import "UIViewController+LayoutProtocol.h"
21
22
  #import <React/RCTLog.h>
22
23
 
23
- // The limits of the bar components of a push: title and background 1 s, buttons 0.5 s.
24
+ // The limits of the bar components of a push: title and background 1 s, buttons 0.5 s. With `waitForRender` unset they
25
+ // count from the wait's start, as a stack's push; with `true`, from the content's end.
24
26
  static const ANNBarWaitLimits ANNColumnBarLimits = {1, 0.5};
25
27
 
28
+ // How long the push's wait waits for the screen's first content when `waitForRender` is not set, as a stack's push.
29
+ static const NSTimeInterval ANNColumnRenderLimit = 0.5;
30
+
26
31
  // The split view of `node`: the node itself or the nearest of its layout parents that has columns.
27
32
  static UIViewController *ANNSplitViewOf(UIViewController *node) {
28
33
  for (UIViewController *parent = node; parent; parent = parent.layoutParent) {
@@ -45,17 +50,26 @@ static BOOL ANNIsOnScreen(UIViewController *node) {
45
50
 
46
51
  @class ANNColumnRequest;
47
52
 
53
+ // A request the newest of its column superseded: its answer and the id it resolves with, its own screen's (each
54
+ // `showInColumn` answers its own screen, as on Android).
55
+ @interface ANNSupersededRequest : NSObject
56
+ @property(nonatomic, strong) ANNCommandAnswer *answer;
57
+ @property(nonatomic, copy) NSString *value;
58
+ @end
59
+
60
+ @implementation ANNSupersededRequest
61
+ @end
62
+
48
63
  // "The last request of a column" (`showInColumn` step 2): one per split view and column. The newest request decides
49
- // what the requests it superseded answer: its id, or its rejection.
64
+ // when the requests it superseded answer; each of them resolves with its own screen's id whatever the newest one's
65
+ // outcome, as on Android.
50
66
  @interface ANNColumnRecord : NSObject
51
67
  @property(nonatomic, weak, nullable) UIViewController *splitView;
52
68
  @property(nonatomic, copy) NSString *column;
53
69
  // Weakly: what runs the newest request holds it (the waiting requests, the split view's call, the push).
54
70
  @property(nonatomic, weak, nullable) ANNColumnRequest *newest;
55
- @property(nonatomic, strong) NSMutableArray<ANNCommandAnswer *> *superseded;
71
+ @property(nonatomic, strong) NSMutableArray<ANNSupersededRequest *> *superseded;
56
72
  @property(nonatomic) BOOL ended;
57
- @property(nonatomic, copy, nullable) NSString *value;
58
- @property(nonatomic, copy, nullable) NSString *rejection;
59
73
  @end
60
74
 
61
75
  @implementation ANNColumnRecord
@@ -184,10 +198,11 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
184
198
  return record;
185
199
  }
186
200
 
187
- // Step 1, the push's wait: `waitForRender` unset waits for the bar components only, `true` for the content as long as
188
- // it takes (with the rule for content nobody knows of), then the bar components; `false` for nothing; nothing either
189
- // while the source's place isn't seen. Read from the screen's own options over the defaults: it has no place yet. With
190
- // content, the screen waits unseen in the source's window, as a layer that waits to show.
201
+ // Step 1, the push's wait, as a stack's push: `waitForRender` unset waits for the content at most 0.5 s, `true` as long
202
+ // as it takes (with the rule for content nobody knows of), then the bar components; `false` for nothing; nothing either
203
+ // while the source's place isn't seen. The content's end waits for the calls JavaScript made by then, so that the
204
+ // options of the screen's first commit are applied before it shows. Read from the screen's own options over the
205
+ // defaults: it has no place yet. The screen waits unseen in the source's window, as a layer that waits to show.
191
206
  + (void)startWaitOf:(ANNColumnRequest *)request {
192
207
  UIViewController *screen = request.screen;
193
208
  Bool *waitForRender = [screen resolveOptionsWithDefault].animations.push.waitForRender;
@@ -198,20 +213,22 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
198
213
  [self readyOnNextTurnOf:request];
199
214
  return;
200
215
  }
201
- BOOL content = waitForRender.hasValue;
216
+ BOOL bounded = !waitForRender.hasValue;
202
217
  __weak UIViewController *weakScreen = screen;
203
218
  NSArray<UIViewController *> * (^screens)(void) = ^NSArray<UIViewController *> * {
204
219
  UIViewController *waited = weakScreen;
205
220
  return waited ? waited.waitedComponentViewControllers : @[];
206
221
  };
207
- ANNRenderWaitContent waited = content ? ANNRenderWaitContentNode : ANNRenderWaitContentNone;
208
- ANNRenderWait *wait = [[ANNRenderWait alloc] initWithContent:waited
209
- node:content ? screen : nil
210
- screens:screens
211
- limit:0
212
- bar:ANNRenderWaitBarAfterContent
213
- barLimits:ANNColumnBarLimits];
214
- wait.unknownContentRule = content;
222
+ ANNRenderWait *wait =
223
+ [[ANNRenderWait alloc] initWithContent:ANNRenderWaitContentNode
224
+ node:screen
225
+ screens:screens
226
+ limit:bounded ? ANNColumnRenderLimit : 0
227
+ bar:ANNRenderWaitBarAfterContent
228
+ barLimits:ANNColumnBarLimits];
229
+ wait.unknownContentRule = !bounded;
230
+ wait.settlesThroughJavaScript = YES;
231
+ wait.barLimitsFromStart = bounded;
215
232
  __weak ANNColumnRequest *weakRequest = request;
216
233
  wait.canEnd = ^BOOL {
217
234
  ANNColumnRequest *waiting = weakRequest;
@@ -225,7 +242,7 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
225
242
  if (!ready) {
226
243
  return;
227
244
  }
228
- // Without content the screen makes it right before it shows (as a push does).
245
+ // A screen that didn't render while parked makes its content right before it shows (as a push does).
229
246
  [ANNSplitViewCommands render:ready];
230
247
  if (ready.starting) {
231
248
  [ANNSplitViewCommands readyOnNextTurnOf:ready];
@@ -233,14 +250,12 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
233
250
  [ANNSplitViewCommands readyOf:ready];
234
251
  }
235
252
  };
236
- if (content) {
237
- wait.setUp = ^{
238
- ANNColumnRequest *waiting = weakRequest;
239
- if (waiting) {
240
- [ANNSplitViewCommands park:waiting];
241
- }
242
- };
243
- }
253
+ wait.setUp = ^{
254
+ ANNColumnRequest *waiting = weakRequest;
255
+ if (waiting) {
256
+ [ANNSplitViewCommands park:waiting];
257
+ }
258
+ };
244
259
  request.wait = wait;
245
260
  request.starting = YES;
246
261
  @try {
@@ -281,6 +296,13 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
281
296
  [screen setWaitForRender:YES];
282
297
  }
283
298
  if (window) {
299
+ __weak ANNColumnRequest *placed = request;
300
+ ANNScreenPlace * (^place)(void) = ^ANNScreenPlace * {
301
+ return [ANNSplitViewCommands placeOf:placed];
302
+ };
303
+ for (ANNComponentViewController *each in ANNStackScreensOfEntry(screen)) {
304
+ each.placeWhileParked = place;
305
+ }
284
306
  request.parking = [ANNParking new];
285
307
  [request.parking park:screen inView:window];
286
308
  }
@@ -304,6 +326,34 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
304
326
  }
305
327
  }
306
328
 
329
+ // Where the parked screen will show, as far as it is known now: the column's stack (whose screens it replaces), the
330
+ // navigation controller UIKit keeps a column that is a screen alone in, or the source's stack while the split view
331
+ // shows as one stack. Nil without one: the screen lays out with its view's own safe area.
332
+ + (nullable ANNScreenPlace *)placeOf:(ANNColumnRequest *)request {
333
+ UIViewController *screen = request.screen;
334
+ UIViewController *source = request.source;
335
+ if (!screen || !source) {
336
+ return nil;
337
+ }
338
+ UIViewController *splitView = ANNSplitViewOf(source);
339
+ UINavigationController *stack = nil;
340
+ if (splitView && !ANNIsCollapsedIntoCompact(splitView)) {
341
+ UIViewController *columnNode =
342
+ [(id<ANNLayoutProtocol>)splitView viewControllerOfColumn:request.column];
343
+ stack = [columnNode isKindOfClass:UINavigationController.class]
344
+ ? (UINavigationController *)columnNode
345
+ : columnNode.navigationController;
346
+ } else {
347
+ stack = [ANNStackCommands stackOf:source].shownNavigationController;
348
+ }
349
+ if (!stack) {
350
+ return nil;
351
+ }
352
+ return [ANNScreenPlace placeOfEntry:screen
353
+ inStack:stack
354
+ options:[ANNStackOptionsScreen(screen) resolveOptionsWithDefault]];
355
+ }
356
+
307
357
  // The screen leaves its place and the waiting requests; UIKit ends its departure from the window here (it shows in
308
358
  // this turn, or goes).
309
359
  + (void)leaveWaitingPlace:(ANNColumnRequest *)request {
@@ -353,18 +403,23 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
353
403
  [self request:request endedWithValue:nil rejection:text];
354
404
  }
355
405
 
356
- // Superseded at its readiness: its screen goes without having shown (no events), and its answer is the newest
357
- // request's, at once when that answered.
406
+ // Superseded at its readiness: its screen goes without having shown (no events). It answers when the newest request
407
+ // does, at once when that answered, with its own screen's id: the newest one's rejection (a container for a stack
408
+ // column, a split view that went) is about that request only.
358
409
  + (void)supersede:(ANNColumnRequest *)request {
359
410
  [self leaveWaitingPlace:request];
360
411
  request.done = YES;
412
+ NSString *value = ANNStackAnswerIdOf(request.screen, ANNStackAnswerCommandShowInColumn);
361
413
  [request.screen destroy];
362
414
  ANNColumnRecord *record = request.record;
363
415
  if (record.ended) {
364
- [self answer:request.answer value:record.value rejection:record.rejection];
416
+ [request.answer resolve:value];
365
417
  return;
366
418
  }
367
- [record.superseded addObject:request.answer];
419
+ ANNSupersededRequest *superseded = [ANNSupersededRequest new];
420
+ superseded.answer = request.answer;
421
+ superseded.value = value;
422
+ [record.superseded addObject:superseded];
368
423
  }
369
424
 
370
425
  // (a) The split view shows the screen in the column: a stack column's screens are replaced without an animation and
@@ -373,14 +428,26 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
373
428
  // `DidDisappear` of the screens that left, `DidAppear` of the new one, the state, then the answer.
374
429
  + (void)show:(ANNColumnRequest *)request inSplitView:(UIViewController *)splitView {
375
430
  UIViewController *screen = request.screen;
431
+ UIViewController *columnNode =
432
+ [(id<ANNLayoutProtocol>)splitView viewControllerOfColumn:request.column];
433
+ // A stack column takes what a stack takes, a screen or a pair; any other layout rejects `columnIsStack`, as on
434
+ // Android. A column that is a screen alone takes any layout in its place.
435
+ if ([columnNode isKindOfClass:UINavigationController.class] &&
436
+ [ANNLayoutValidator checkStackChild:request.layout
437
+ stackId:columnNode.layoutInfo.componentId ?: @""]) {
438
+ [self leaveWaitingPlace:request];
439
+ [screen destroy];
440
+ [self request:request
441
+ endedWithValue:nil
442
+ rejection:[ANNErrorTexts columnIsStack:request.componentId column:request.column]];
443
+ return;
444
+ }
376
445
  // Before the parking lets go of it, so that UIKit's calls stay silent until the end.
377
446
  [ANNAppearanceDispatcher driveAppearanceOf:@[ screen ]];
378
447
  request.driven = YES;
379
448
  [self leaveWaitingPlace:request];
380
449
  // A screen alone in a column has the split view as its parent by the layout (UIKit puts it into a navigation
381
450
  // controller of its own); a stack column's stack is its parent.
382
- UIViewController *columnNode =
383
- [(id<ANNLayoutProtocol>)splitView viewControllerOfColumn:request.column];
384
451
  if (columnNode && ![columnNode isKindOfClass:UINavigationController.class]) {
385
452
  [screen setExplicitLayoutParent:splitView];
386
453
  }
@@ -485,7 +552,8 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
485
552
 
486
553
  #pragma mark - The answers
487
554
 
488
- // The request answers once; when it is the newest of its column, the requests it superseded answer the same.
555
+ // The request answers once; when it is the newest of its column, the requests it superseded answer then, each with its
556
+ // own screen's id.
489
557
  + (void)request:(ANNColumnRequest *)request
490
558
  endedWithValue:(NSString *)value
491
559
  rejection:(NSString *)rejection {
@@ -499,13 +567,11 @@ static NSMapTable<UIViewController *, ANNColumnRecordsOfSplitView *> *ANNColumnR
499
567
  return;
500
568
  }
501
569
  record.ended = YES;
502
- record.value = value;
503
- record.rejection = rejection;
504
570
  record.newest = nil;
505
- NSArray<ANNCommandAnswer *> *superseded = [record.superseded copy];
571
+ NSArray<ANNSupersededRequest *> *superseded = [record.superseded copy];
506
572
  [record.superseded removeAllObjects];
507
- for (ANNCommandAnswer *answer in superseded) {
508
- [self answer:answer value:value rejection:rejection];
573
+ for (ANNSupersededRequest *each in superseded) {
574
+ [each.answer resolve:each.value];
509
575
  }
510
576
  // A request that begins from now on starts a record of its own.
511
577
  UIViewController *splitView = record.splitView;
@@ -1,5 +1,6 @@
1
1
  #import "ANNSplitViewController.h"
2
2
  #import "ANNErrorHandler.h"
3
+ #import "ANNErrorTexts.h"
3
4
  #import "ANNShownScreens.h"
4
5
  #import "UISplitViewController+ANNOptions.h"
5
6
  #import "UIViewController+LayoutProtocol.h"
@@ -213,23 +214,21 @@ static UISplitViewControllerColumn ANNSplitViewColumn(NSString *name) {
213
214
  completion:(ANNTransitionCompletionBlock)completion
214
215
  rejection:(ANNTransitionRejectionBlock)rejection {
215
216
  UIViewController *previous = _columns[column];
217
+ NSString *fromId = fromViewController.layoutInfo.componentId ?: @"";
216
218
  if (!previous) {
217
- rejection([NSString stringWithFormat:@"the split view of the screen '%@' has no '%@' column",
218
- fromViewController.layoutInfo.componentId, column],
219
- nil);
219
+ rejection([ANNErrorTexts noSuchColumn:fromId column:column], nil);
220
220
  return;
221
221
  }
222
222
  if ([previous isKindOfClass:UINavigationController.class]) {
223
- // UIKit does not take a navigation controller among the screens of another.
223
+ // UIKit does not take a navigation controller among the screens of another. The core rejects every layout a
224
+ // stack doesn't take before it asks; this guards the module's own call.
224
225
  if ([screen isKindOfClass:UINavigationController.class]) {
225
- rejection([NSString stringWithFormat:@"the '%@' column of the split view of the screen '%@' is a "
226
- @"stack: it takes a screen, not a stack",
227
- column, fromViewController.layoutInfo.componentId],
228
- nil);
226
+ rejection([ANNErrorTexts columnIsStack:fromId column:column], nil);
229
227
  return;
230
228
  }
231
229
  // In place, as a column of UIKit apps changes; UIKit animates a column it brings on top.
232
230
  [(UINavigationController *)previous setStackChildren:@[ screen ]
231
+ inColumn:column
233
232
  fromViewController:fromViewController
234
233
  animated:NO
235
234
  completion:^{