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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +32 -0
  3. package/README.md +1 -1
  4. package/android/CLAUDE.md +31 -20
  5. package/android/CORE.md +12 -8
  6. package/android/consumer-rules.pro +6 -0
  7. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +36 -5
  8. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  9. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  10. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +1 -1
  11. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  12. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  13. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  14. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  15. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  16. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  18. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  19. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  20. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  21. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +7 -3
  22. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +41 -3
  23. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +16 -1
  24. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +0 -2
  25. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  26. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +12 -49
  27. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  28. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +6 -6
  29. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +27 -7
  30. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +12 -1
  31. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  32. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  33. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  34. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +9 -7
  35. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  36. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +13 -10
  37. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  38. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  39. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +7 -8
  40. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  41. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  42. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +20 -2
  43. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +443 -58
  44. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +33 -5
  45. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  46. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +60 -2
  47. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +4 -0
  48. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +3 -6
  49. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +8 -2
  50. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +32 -4
  51. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  52. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +2 -2
  53. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +50 -7
  54. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +15 -3
  55. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +10 -4
  56. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  57. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +215 -43
  58. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +25 -26
  59. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  60. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  61. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +36 -38
  62. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  63. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  64. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  65. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  66. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  67. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +129 -179
  68. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +8 -1
  69. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  70. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +67 -3
  71. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  72. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  73. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +55 -42
  74. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  75. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  76. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  77. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  78. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -24
  79. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +51 -34
  80. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  81. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  82. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  83. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +121 -175
  84. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  85. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  86. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  87. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  88. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  89. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  90. package/android/src/main/res/values/styles.xml +1 -1
  91. package/android/src/main/res/values-night/styles.xml +1 -1
  92. package/cli/doctor/checks/app.js +16 -1
  93. package/cli/project.js +4 -0
  94. package/cli/setup/index.js +5 -0
  95. package/cli/setup/steps/metro.js +46 -0
  96. package/docs-md/architecture/native-screens.md +4 -0
  97. package/docs-md/architecture/theme-and-context.md +131 -12
  98. package/docs-md/architecture/transitions.md +46 -5
  99. package/docs-md/containers/modals.md +2 -0
  100. package/docs-md/containers/overlays.md +1 -1
  101. package/docs-md/containers/side-menu.md +1 -1
  102. package/docs-md/containers/tabs.md +2 -0
  103. package/docs-md/flows/bottom-sheets.md +4 -2
  104. package/docs-md/fundamentals/screens-and-props.md +9 -1
  105. package/docs-md/fundamentals/starting-the-app.md +1 -1
  106. package/docs-md/guides/cli.md +3 -1
  107. package/docs-md/help/glossary.md +2 -2
  108. package/docs-md/help/troubleshooting.md +22 -1
  109. package/docs-md/index.json +41 -1
  110. package/docs-md/migration/from-expo-router.md +1 -1
  111. package/docs-md/migration/from-react-native-navigation.md +1 -1
  112. package/docs-md/migration/from-react-navigation.md +2 -2
  113. package/docs-md/screen-ui/back-and-gestures.md +17 -1
  114. package/docs-md/screen-ui/bar-buttons.md +5 -5
  115. package/docs-md/screen-ui/search.md +1 -1
  116. package/docs-md/screen-ui/system-ui.md +16 -11
  117. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  118. package/docs-md/screen-ui/top-bar.md +8 -4
  119. package/docs-md/start/installation.md +16 -1
  120. package/ios/Animations/ANNFrameDriver.h +55 -15
  121. package/ios/Animations/ANNFrameDriver.mm +216 -60
  122. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  123. package/ios/Animations/ANNTransitionAnimator.mm +49 -3
  124. package/ios/Animations/ANNTransitionPlan.h +2 -2
  125. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  126. package/ios/Animations/Elements/ANNElementFinder.h +2 -2
  127. package/ios/Animations/Elements/ANNElementFinder.mm +2 -2
  128. package/ios/Animations/Elements/ANNElementTransition.h +3 -3
  129. package/ios/Animations/Elements/ANNElementTransition.mm +2 -2
  130. package/ios/Animations/Elements/ANNSharedElementFlight.h +3 -3
  131. package/ios/Animations/Elements/ANNSharedElementFlight.mm +249 -45
  132. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  133. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  134. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  135. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  136. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  137. package/ios/CLAUDE.md +32 -22
  138. package/ios/CORE.md +25 -21
  139. package/ios/Contract/ANNCommandRunner.h +8 -7
  140. package/ios/Contract/ANNCommandRunner.mm +21 -27
  141. package/ios/Contract/ANNLayoutNode.h +3 -3
  142. package/ios/Contract/ANNLayoutReader.h +3 -3
  143. package/ios/Core/ANNAppDelegate.mm +0 -2
  144. package/ios/Core/ANNDeepLinkQueue.h +6 -5
  145. package/ios/Core/ANNDeepLinkQueue.mm +22 -10
  146. package/ios/Core/ANNJavaScriptCalls.h +11 -12
  147. package/ios/Core/ANNJavaScriptCalls.mm +7 -16
  148. package/ios/Core/ANNReloadCoordinator.mm +4 -8
  149. package/ios/Core/ANNSceneDelegate.mm +2 -2
  150. package/ios/Core/ApexNavigation+Internal.h +1 -1
  151. package/ios/Core/ApexNavigation.mm +6 -2
  152. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  153. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  154. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +4 -4
  155. package/ios/Layouts/Root/ANNRootCoordinator.mm +45 -15
  156. package/ios/Layouts/Screen/ANNComponentViewController.h +2 -2
  157. package/ios/Layouts/Screen/ANNComponentViewController.mm +13 -23
  158. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  159. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  160. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  161. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  162. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  163. package/ios/Layouts/Screen/ANNScreenRegions.mm +0 -38
  164. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  165. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  166. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  167. package/ios/Layouts/Stack/ANNPreviewPush.mm +57 -5
  168. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  169. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  170. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  171. package/ios/Layouts/Stack/ANNStackController.mm +153 -11
  172. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  173. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  174. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  175. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  176. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  177. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +2 -1
  178. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  179. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +4 -0
  180. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +123 -36
  181. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  182. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  183. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  184. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  185. package/ios/Options/ANNAnimationOptions.h +2 -1
  186. package/ios/Options/ANNAnimationOptions.mm +1 -1
  187. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  188. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  189. package/ios/Options/ANNOptions.h +25 -0
  190. package/ios/Options/ANNOptions.mm +157 -1
  191. package/ios/Options/ANNOptionsReader.mm +108 -0
  192. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  193. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  194. package/ios/Options/Params/ANNParam.h +15 -0
  195. package/ios/Options/Params/ANNParam.mm +61 -0
  196. package/ios/Options/Params/Color.h +3 -0
  197. package/ios/Options/Params/Color.mm +21 -0
  198. package/ios/Options/Params/ColorParser.h +4 -3
  199. package/ios/Options/Params/ColorParser.mm +22 -4
  200. package/ios/Options/Params/Image.h +4 -0
  201. package/ios/Options/Params/Image.mm +20 -0
  202. package/ios/React/ANNReactView.mm +6 -25
  203. package/ios/React/ANNSafeAreaViewComponentView.mm +26 -15
  204. package/ios/React/ANNSurfaceHostingView.h +14 -0
  205. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  206. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  207. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  208. package/ios/TopBar/ANNBarAppearance.h +2 -1
  209. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  210. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  211. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  212. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  213. package/ios/TopBar/ANNBarButtons.h +5 -3
  214. package/ios/TopBar/ANNBarButtons.mm +186 -17
  215. package/ios/TopBar/ANNLargeTitlePresenter.mm +24 -4
  216. package/ios/TopBar/ANNMainList.h +3 -0
  217. package/ios/TopBar/ANNMainList.mm +4 -0
  218. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  219. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  220. package/ios/TopBar/ANNSearchPresenter.mm +2 -2
  221. package/ios/TopBar/ANNSearchResultsViewController.mm +5 -5
  222. package/ios/TopBar/ANNTopBarPresenter.h +3 -2
  223. package/ios/TopBar/ANNTopBarPresenter.mm +95 -22
  224. package/ios/TurboModules/ANNTurboModule.mm +66 -16
  225. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  226. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  227. package/lib/module/ARCHITECTURE.md +17 -7
  228. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  229. package/lib/module/api/app/AppRegistry.js +14 -2
  230. package/lib/module/api/app/AppRegistry.js.map +1 -1
  231. package/lib/module/api/app/createNavigation.js +188 -66
  232. package/lib/module/api/app/createNavigation.js.map +1 -1
  233. package/lib/module/api/events/navigationEvents.js +6 -2
  234. package/lib/module/api/events/navigationEvents.js.map +1 -1
  235. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  236. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  237. package/lib/module/api/linking/linking.js +11 -0
  238. package/lib/module/api/linking/linking.js.map +1 -1
  239. package/lib/module/api/options/OptionsChain.js +2 -2
  240. package/lib/module/api/screens/defineScreen.js +45 -3
  241. package/lib/module/api/screens/defineScreen.js.map +1 -1
  242. package/lib/module/api/screens/nativeScreens.js +31 -6
  243. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  244. package/lib/module/api/screens/registerScreens.js +172 -35
  245. package/lib/module/api/screens/registerScreens.js.map +1 -1
  246. package/lib/module/api/theme/theme.js +5 -0
  247. package/lib/module/api/theme/theme.js.map +1 -1
  248. package/lib/module/engine/commands.js +42 -2
  249. package/lib/module/engine/commands.js.map +1 -1
  250. package/lib/module/engine/layout.js +7 -2
  251. package/lib/module/engine/layout.js.map +1 -1
  252. package/lib/module/engine/nativeScreens.js +9 -0
  253. package/lib/module/engine/nativeScreens.js.map +1 -1
  254. package/lib/module/engine/options.js +5 -4
  255. package/lib/module/engine/options.js.map +1 -1
  256. package/lib/module/engine/optionsChange.js +102 -0
  257. package/lib/module/engine/optionsChange.js.map +1 -0
  258. package/lib/module/engine/refresh.js +85 -0
  259. package/lib/module/engine/refresh.js.map +1 -0
  260. package/lib/module/engine/rememberedOptions.js +60 -0
  261. package/lib/module/engine/rememberedOptions.js.map +1 -1
  262. package/lib/module/engine/screens.js +55 -4
  263. package/lib/module/engine/screens.js.map +1 -1
  264. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +7 -0
  265. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  266. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  267. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  268. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  269. package/lib/typescript/api/events/navigationEvents.d.ts +2 -2
  270. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  271. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  272. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  273. package/lib/typescript/api/index.d.ts +1 -1
  274. package/lib/typescript/api/index.d.ts.map +1 -1
  275. package/lib/typescript/api/linking/linking.d.ts +8 -0
  276. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  277. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  278. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  279. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  280. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  281. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  282. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  283. package/lib/typescript/api/theme/theme.d.ts +2 -0
  284. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  285. package/lib/typescript/engine/commands.d.ts +5 -0
  286. package/lib/typescript/engine/commands.d.ts.map +1 -1
  287. package/lib/typescript/engine/layout.d.ts.map +1 -1
  288. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  289. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  290. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  291. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  292. package/lib/typescript/engine/refresh.d.ts +35 -0
  293. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  294. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  295. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  296. package/lib/typescript/engine/screens.d.ts +27 -6
  297. package/lib/typescript/engine/screens.d.ts.map +1 -1
  298. package/lib/typescript/interfaces/ComponentEvents.d.ts +2 -2
  299. package/lib/typescript/interfaces/options/animations.d.ts +44 -14
  300. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  301. package/lib/typescript/interfaces/options/bottomTabs.d.ts +19 -6
  302. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  303. package/lib/typescript/interfaces/options/buttons.d.ts +10 -10
  304. package/lib/typescript/interfaces/options/modals.d.ts +6 -7
  305. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  306. package/lib/typescript/interfaces/options/stack.d.ts +8 -3
  307. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  308. package/lib/typescript/interfaces/options/system.d.ts +8 -5
  309. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  310. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  311. package/lib/typescript/interfaces/options/topBar.d.ts +46 -29
  312. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  313. package/metro/acceptPlugin.js +57 -0
  314. package/metro/babelTransformer.js +45 -0
  315. package/metro/index.js +36 -0
  316. package/package.json +3 -1
  317. package/src/ARCHITECTURE.md +17 -7
  318. package/src/adapters/NativeANNTurboModule.ts +7 -0
  319. package/src/api/app/AppRegistry.ts +16 -2
  320. package/src/api/app/createNavigation.ts +201 -69
  321. package/src/api/events/navigationEvents.ts +9 -3
  322. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  323. package/src/api/index.ts +1 -0
  324. package/src/api/linking/linking.ts +22 -1
  325. package/src/api/options/OptionsChain.ts +2 -2
  326. package/src/api/screens/defineScreen.ts +49 -5
  327. package/src/api/screens/nativeScreens.ts +40 -4
  328. package/src/api/screens/registerScreens.tsx +170 -42
  329. package/src/api/theme/theme.ts +5 -0
  330. package/src/engine/commands.ts +51 -6
  331. package/src/engine/layout.ts +11 -2
  332. package/src/engine/nativeScreens.ts +10 -1
  333. package/src/engine/options.ts +6 -8
  334. package/src/engine/optionsChange.ts +107 -0
  335. package/src/engine/refresh.ts +97 -0
  336. package/src/engine/rememberedOptions.ts +70 -0
  337. package/src/engine/screens.tsx +53 -8
  338. package/src/interfaces/ComponentEvents.ts +2 -2
  339. package/src/interfaces/options/animations.ts +44 -14
  340. package/src/interfaces/options/bottomTabs.ts +19 -6
  341. package/src/interfaces/options/buttons.ts +10 -10
  342. package/src/interfaces/options/modals.ts +6 -7
  343. package/src/interfaces/options/stack.ts +8 -3
  344. package/src/interfaces/options/system.ts +8 -5
  345. package/src/interfaces/options/toolbar.ts +2 -2
  346. package/src/interfaces/options/topBar.ts +46 -29
  347. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -42
  348. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -70
  349. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  350. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  351. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -136
  352. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -86
  353. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  354. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -64
  355. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -177
  356. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -137
  357. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  358. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -70
@@ -71,19 +71,19 @@ static ANNLaunchLinkCompletion ANNWaitingLaunchLinkCompletion;
71
71
  selector:@selector(applicationDidBecomeActive:)
72
72
  name:UIApplicationDidBecomeActiveNotification
73
73
  object:nil];
74
+ // Started once the app is active (an app that starts React Native later, on demand), the queue missed the scene's
75
+ // connection and the notification: the links that launched the app went elsewhere, and none waits for them.
76
+ if (UIApplication.sharedApplication.applicationState == UIApplicationStateActive) {
77
+ [self launchLinksKnown];
78
+ }
74
79
  }
75
80
 
76
81
  + (void)dispatchURL:(NSURL *)url {
77
- ANNAssertMainQueue();
78
82
  // The URL of the scene's link keeps its context; one the app delegate changed is a URL of its own.
79
83
  ANNDeepLink *link = [ANNForwardedSceneLink.url isEqual:url]
80
84
  ? ANNForwardedSceneLink
81
85
  : [[ANNDeepLink alloc] initWithURL:url context:nil activity:nil scene:nil];
82
- if (ANNReactContentAppeared && ANNWaitingLaunchLinkCompletion == nil) {
83
- [self openLink:link];
84
- return;
85
- }
86
- [ANNPendingDeepLinks addObject:link];
86
+ [self dispatchLink:link];
87
87
  }
88
88
 
89
89
  + (void)forwardURLContext:(UIOpenURLContext *)context
@@ -104,15 +104,18 @@ static ANNLaunchLinkCompletion ANNWaitingLaunchLinkCompletion;
104
104
  through:forward];
105
105
  }
106
106
 
107
- + (void)openURLContext:(UIOpenURLContext *)context ofScene:(UIScene *)scene {
108
- [self openLink:[[ANNDeepLink alloc] initWithURL:context.URL context:context activity:nil scene:scene]];
107
+ + (void)dispatchURLContext:(UIOpenURLContext *)context ofScene:(UIScene *)scene {
108
+ [self dispatchLink:[[ANNDeepLink alloc] initWithURL:context.URL context:context activity:nil scene:scene]];
109
109
  }
110
110
 
111
- + (void)openUserActivity:(NSUserActivity *)activity ofScene:(UIScene *)scene {
111
+ + (void)dispatchUserActivity:(NSUserActivity *)activity ofScene:(UIScene *)scene {
112
112
  if (activity.webpageURL == nil) {
113
113
  return;
114
114
  }
115
- [self openLink:[[ANNDeepLink alloc] initWithURL:activity.webpageURL context:nil activity:activity scene:scene]];
115
+ [self dispatchLink:[[ANNDeepLink alloc] initWithURL:activity.webpageURL
116
+ context:nil
117
+ activity:activity
118
+ scene:scene]];
116
119
  }
117
120
 
118
121
  + (void)windowSceneDidConnect {
@@ -191,6 +194,15 @@ static ANNLaunchLinkCompletion ANNWaitingLaunchLinkCompletion;
191
194
  completion(url);
192
195
  }
193
196
 
197
+ + (void)dispatchLink:(ANNDeepLink *)link {
198
+ ANNAssertMainQueue();
199
+ if (ANNReactContentAppeared && ANNWaitingLaunchLinkCompletion == nil) {
200
+ [self openLink:link];
201
+ return;
202
+ }
203
+ [ANNPendingDeepLinks addObject:link];
204
+ }
205
+
194
206
  + (void)forwardLink:(ANNDeepLink *)link through:(NS_NOESCAPE dispatch_block_t)forward {
195
207
  ANNAssertMainQueue();
196
208
  ANNDeepLink *outer = ANNForwardedSceneLink;
@@ -5,28 +5,27 @@
5
5
  NS_ASSUME_NONNULL_BEGIN
6
6
 
7
7
  /// The way of the calls JavaScript makes to `ANNTurboModule`, for a step that must come after them. A call without an
8
- /// answer (`mergeOptions`) leaves the JavaScript thread as it is made, goes to the module's queue (React Native's
9
- /// `ModuleNativeMethodCallInvoker`, a `dispatch_async` to it) and from there to the main queue (`ANNCommandRunner`):
10
- /// a step that takes the same three hops after them comes after them on the main queue, as each of the three runs its
11
- /// work in order. The module tells its call invoker and its queue when React Native made it, and that it went when
12
- /// React Native invalidates it (a reload). Any thread, except `afterCallsMadeSoFar:`.
8
+ /// answer (`mergeOptions`) leaves the JavaScript thread as it is made, as a task on the main queue, the module's queue
9
+ /// (React Native's `ModuleNativeMethodCallInvoker`, a `dispatch_async` to it), and runs whole in that task
10
+ /// (`ANNCommandRunner`). A step sent from the JavaScript thread to the main queue after them comes after them: the
11
+ /// JavaScript thread runs its tasks in order, and the main queue runs what it is given in the order it was given. The
12
+ /// module tells its call invoker when React Native made it, and that it went when React Native invalidates it (a
13
+ /// reload). Any thread, except `afterCallsMadeSoFar:`.
13
14
  @interface ANNJavaScriptCalls : NSObject
14
15
 
15
16
  - (instancetype)init NS_UNAVAILABLE;
16
17
  + (instancetype)new NS_UNAVAILABLE;
17
18
 
18
- /// The module of the JavaScript that runs now, its call invoker (the JavaScript thread) and its queue.
19
- + (void)setCallInvoker:(nullable RCTCallInvoker *)callInvoker
20
- methodQueue:(nullable dispatch_queue_t)methodQueue
21
- ofModule:(id)module;
19
+ /// The module of the JavaScript that runs now and its call invoker (the JavaScript thread).
20
+ + (void)setCallInvoker:(nullable RCTCallInvoker *)callInvoker ofModule:(id)module;
22
21
 
23
22
  /// The module went: with no newer module told since, no JavaScript runs to wait for.
24
23
  + (void)moduleWent:(id)module;
25
24
 
26
25
  /// `block` runs on the main queue once every call JavaScript made to the module before the next task of its thread is
27
- /// applied on the main queue: a task on the JavaScript thread, from there one on the module's queue, from there one on
28
- /// the main queue. With no JavaScript to ask (none yet, a reload), at once. Main queue. A JavaScript thread that never
29
- /// runs the task again (its runtime went) never runs `block`: a caller that can't wait for long has a limit of its own.
26
+ /// applied: a task on the JavaScript thread, from there one on the main queue. With no JavaScript to ask (none yet, a
27
+ /// reload), at once. Main queue. A JavaScript thread that never runs the task again (its runtime went) never runs
28
+ /// `block`: a caller that can't wait for long has a limit of its own.
30
29
  + (void)afterCallsMadeSoFar:(dispatch_block_t)block;
31
30
 
32
31
  @end
@@ -1,23 +1,18 @@
1
1
  #import "ANNJavaScriptCalls.h"
2
2
  #import "ANNAssert.h"
3
3
  #import <React/RCTCallInvoker.h>
4
- #import <React/RCTUtils.h>
5
4
  #import <ReactCommon/CallInvoker.h>
6
5
 
7
- // The module told last, weakly: a module that went takes its invoker and its queue with it.
6
+ // The module told last, weakly: a module that went takes its invoker with it.
8
7
  static __weak id ANNCallsModule;
9
8
  static RCTCallInvoker *ANNCallsInvoker;
10
- static dispatch_queue_t ANNCallsQueue;
11
9
 
12
10
  @implementation ANNJavaScriptCalls
13
11
 
14
- + (void)setCallInvoker:(RCTCallInvoker *)callInvoker
15
- methodQueue:(dispatch_queue_t)methodQueue
16
- ofModule:(id)module {
12
+ + (void)setCallInvoker:(RCTCallInvoker *)callInvoker ofModule:(id)module {
17
13
  @synchronized(self) {
18
14
  ANNCallsModule = module;
19
15
  ANNCallsInvoker = callInvoker;
20
- ANNCallsQueue = methodQueue;
21
16
  }
22
17
  }
23
18
 
@@ -28,33 +23,29 @@ static dispatch_queue_t ANNCallsQueue;
28
23
  }
29
24
  ANNCallsModule = nil;
30
25
  ANNCallsInvoker = nil;
31
- ANNCallsQueue = nil;
32
26
  }
33
27
  }
34
28
 
35
29
  + (void)afterCallsMadeSoFar:(dispatch_block_t)block {
36
30
  ANNAssertMainQueue();
37
31
  RCTCallInvoker *callInvoker = nil;
38
- dispatch_queue_t queue = nil;
39
32
  @synchronized(self) {
40
33
  if (ANNCallsModule) {
41
34
  callInvoker = ANNCallsInvoker;
42
- queue = ANNCallsQueue;
43
35
  }
44
36
  }
45
37
  std::shared_ptr<facebook::react::CallInvoker> invoker =
46
38
  callInvoker ? callInvoker.callInvoker : nullptr;
47
- if (!invoker || !queue) {
39
+ if (!invoker) {
48
40
  block();
49
41
  return;
50
42
  }
51
43
  dispatch_block_t done = [block copy];
52
44
  // The JavaScript thread runs the task after the one it runs now, which made the calls of this moment (a commit of
53
- // React and its layout effects); the module's queue then has those calls before this hop, and the main queue too.
54
- invoker->invokeAsync([queue, done](facebook::jsi::Runtime &) {
55
- dispatch_async(queue, ^{
56
- RCTExecuteOnMainQueue(done);
57
- });
45
+ // React and its layout effects). Each of those calls went to the main queue as it was made, so this hop, sent from
46
+ // the same thread later, reaches the main queue behind them (a serial queue, in the order it was given).
47
+ invoker->invokeAsync([done](facebook::jsi::Runtime &) {
48
+ dispatch_async(dispatch_get_main_queue(), done);
58
49
  });
59
50
  }
60
51
 
@@ -1,5 +1,4 @@
1
1
  #import "ANNReloadCoordinator.h"
2
- #import "ANNArrangementState.h"
3
2
  #import "ANNAssert.h"
4
3
  #import "ANNErrorTexts.h"
5
4
  #import "ANNHinge.h"
@@ -12,9 +11,8 @@
12
11
  #import "ANNPreviewInteraction.h"
13
12
  #import "ANNPreviewPush.h"
14
13
  #import "ANNRootCoordinator.h"
15
- #import "ANNScreenInsets.h"
14
+ #import "ANNScreenEnvironment.h"
16
15
  #import "ANNScreenReadiness.h"
17
- #import "ANNScreenRegions.h"
18
16
  #import "ANNSplashViewController.h"
19
17
  #import "ANNSplitViewCommands.h"
20
18
  #import "ANNTabsPreloadWindow.h"
@@ -154,12 +152,10 @@ static BOOL ANNWatchingBundles;
154
152
  [oldScreens addObjectsFromArray:[ANNSplitViewCommands takeAllForReload]];
155
153
  // The new JavaScript counts its ids anew: nothing the safe area views of the old screens said stays ready for a new
156
154
  // screen with the same id. The old surfaces are stopped or silent. The same for what the old screens kept for
157
- // JavaScript: their insets and padding, regions and arrangement states (an old screen still in a window writes no
158
- // insets or regions again: its emitter is not current).
155
+ // JavaScript, their environment: insets and padding, regions and arrangements (an old screen still in a window
156
+ // writes no insets or regions again: its emitter is not current).
159
157
  [ANNScreenReadiness reset];
160
- [ANNScreenInsets removeAll];
161
- [ANNScreenRegions removeAll];
162
- [ANNArrangementState removeAll];
158
+ [ANNScreenEnvironment removeAll];
163
159
  // 6. The window shows the blank screen, which counts as the splash: a reload is not a launch. The
164
160
  // reset runs from the second bundle of the process on.
165
161
  if (window) {
@@ -77,7 +77,7 @@
77
77
  [appDelegate application:application openURL:context.URL options:options];
78
78
  }];
79
79
  } else {
80
- [ANNDeepLinkQueue openURLContext:context ofScene:scene];
80
+ [ANNDeepLinkQueue dispatchURLContext:context ofScene:scene];
81
81
  }
82
82
  }
83
83
 
@@ -95,7 +95,7 @@
95
95
  }];
96
96
  }];
97
97
  } else if ([activity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
98
- [ANNDeepLinkQueue openUserActivity:activity ofScene:scene];
98
+ [ANNDeepLinkQueue dispatchUserActivity:activity ofScene:scene];
99
99
  }
100
100
  }
101
101
 
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
18
18
  + (nullable ANNNativeScreenCreator)nativeScreenCreatorForName:(NSString *)name;
19
19
 
20
20
  /// Whether a native screen is registered under the name by `registerNativeScreen:creator:` (the registration of 8.x is
21
- /// gone). Any thread: the layout of a command is checked on the module's queue.
21
+ /// gone). Any thread (the layout check of a command reads it on the main queue).
22
22
  + (BOOL)hasNativeScreenNamed:(NSString *)name;
23
23
 
24
24
  @end
@@ -45,8 +45,9 @@ static UIWindowScene *ANNConnectedWindowScene(void) {
45
45
  }
46
46
  }
47
47
 
48
- // Once, on the main queue: the generated native screens before any other part, then the core's parts, the `<Modal>`
49
- // replacement before any React content, the window with the copy of the launch screen, and the watch of the bundles.
48
+ // Once, on the main queue: the generated native screens before any other part, then the core's parts, the queue of the
49
+ // links, the `<Modal>` replacement before any React content, the window with the copy of the launch screen, and the
50
+ // watch of the bundles.
50
51
  + (void)bootstrapWithHost:(RCTHost *)host {
51
52
  ANNAssertMainQueue();
52
53
  if (ANNBootstrapped) {
@@ -55,6 +56,9 @@ static UIWindowScene *ANNConnectedWindowScene(void) {
55
56
  ANNBootstrapped = YES;
56
57
  [self registerGeneratedScreens];
57
58
  ANNHost = host;
59
+ // The links that come before React content wait for it; the launch link waits for the scene. Here, not in
60
+ // `ANNAppDelegate`, so an app delegate of the app's own keeps its launch link.
61
+ [ANNDeepLinkQueue start];
58
62
  // React Native lets a class with the descriptor of `ModalHostView` stand in for its own.
59
63
  [ANNModalHostViewComponentView registerForModalHostView];
60
64
  [self makeMainWindowInScene:nil];
@@ -1,30 +1,15 @@
1
- #import "ANNEventEmitter.h"
2
1
  #import <UIKit/UIKit.h>
3
2
 
4
3
  NS_ASSUME_NONNULL_BEGIN
5
4
 
6
- /// The state of each screen of an arrangement (`useArrangement`): `{ placement, layout, front, hidden }`, which view of
7
- /// the pair it is and how the pair lies. The native side keeps it on the main queue; JavaScript reads it from its own
8
- /// thread for a screen's first render, and gets every change as `ANN.ArrangementChanged`.
5
+ /// Whether the app can show pairs at all. The state of each screen of a pair (`useArrangement`) is kept for JavaScript
6
+ /// by `ANNScreenEnvironment`.
9
7
  @interface ANNArrangementState : NSObject
10
8
 
11
9
  /// Whether the app shows arrangements (`getStartInfo().arrangements`): built with the iOS 27.1 SDK and running on
12
10
  /// iOS 27.1 or later. Without them JavaScript sends only the primary, as a screen. Any thread.
13
11
  + (BOOL)canShowArrangements;
14
12
 
15
- /// Keeps the screen's state and tells when it changed; nothing goes without an emitter. Main queue.
16
- + (void)setState:(NSDictionary<NSString *, id> *)state
17
- forScreenId:(NSString *)screenId
18
- eventEmitter:(nullable ANNEventEmitter *)eventEmitter;
19
-
20
- /// The screen's state, or nil for a screen outside a pair. Any thread.
21
- + (nullable NSDictionary<NSString *, id> *)stateForScreenId:(NSString *)screenId;
22
-
23
- + (void)removeScreenId:(NSString *)screenId;
24
-
25
- /// Forgets every screen: after a reload the new JavaScript counts its ids anew. Main queue.
26
- + (void)removeAll;
27
-
28
13
  @end
29
14
 
30
15
  NS_ASSUME_NONNULL_END
@@ -1,16 +1,8 @@
1
1
  #import "ANNArrangementState.h"
2
2
  #import "ANNArrangementViewController.h"
3
3
 
4
- static NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *ANNArrangementStateById;
5
-
6
4
  @implementation ANNArrangementState
7
5
 
8
- + (void)initialize {
9
- if (self == ANNArrangementState.class) {
10
- ANNArrangementStateById = [NSMutableDictionary new];
11
- }
12
- }
13
-
14
6
  + (BOOL)canShowArrangements {
15
7
  #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
16
8
  if (@available(iOS 27.1, *)) {
@@ -20,34 +12,4 @@ static NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *ANNArran
20
12
  return NO;
21
13
  }
22
14
 
23
- + (void)setState:(NSDictionary<NSString *, id> *)state
24
- forScreenId:(NSString *)screenId
25
- eventEmitter:(ANNEventEmitter *)eventEmitter {
26
- @synchronized(ANNArrangementStateById) {
27
- if ([ANNArrangementStateById[screenId] isEqualToDictionary:state]) {
28
- return;
29
- }
30
- ANNArrangementStateById[screenId] = state;
31
- }
32
- [eventEmitter sendArrangementChanged:screenId state:state];
33
- }
34
-
35
- + (NSDictionary<NSString *, id> *)stateForScreenId:(NSString *)screenId {
36
- @synchronized(ANNArrangementStateById) {
37
- return ANNArrangementStateById[screenId];
38
- }
39
- }
40
-
41
- + (void)removeScreenId:(NSString *)screenId {
42
- @synchronized(ANNArrangementStateById) {
43
- [ANNArrangementStateById removeObjectForKey:screenId];
44
- }
45
- }
46
-
47
- + (void)removeAll {
48
- @synchronized(ANNArrangementStateById) {
49
- [ANNArrangementStateById removeAllObjects];
50
- }
51
- }
52
-
53
15
  @end
@@ -2,10 +2,10 @@
2
2
 
3
3
  #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
4
4
 
5
- #import "ANNArrangementState.h"
6
5
  #import "ANNComponentViewController.h"
7
6
  #import "ANNEventContract.h"
8
7
  #import "ANNExternalViewController.h"
8
+ #import "ANNScreenEnvironment.h"
9
9
  #import "ANNShownScreens.h"
10
10
  #import "ANNUtils.h"
11
11
 
@@ -298,9 +298,9 @@ static BOOL ANNIsShown(UIViewController *screen, UIArrangementViewState *state,
298
298
  ofScreen:(UIViewController *)screen
299
299
  eventEmitter:(ANNEventEmitter *)eventEmitter {
300
300
  if (ANNKeepsState(screen)) {
301
- [ANNArrangementState setState:state
302
- forScreenId:screen.layoutInfo.componentId
303
- eventEmitter:eventEmitter];
301
+ [ANNScreenEnvironment setArrangement:state
302
+ forScreenId:screen.layoutInfo.componentId
303
+ eventEmitter:eventEmitter];
304
304
  }
305
305
  }
306
306
 
@@ -83,6 +83,10 @@ typedef NS_ENUM(NSInteger, ANNRootShowState) {
83
83
  @property(nonatomic, strong, nullable) ANNFrameDriver *driver;
84
84
  @property(nonatomic, copy, nullable) NSArray<ANNViewTracks *> *tracks;
85
85
  @property(nonatomic) BOOL animating;
86
+ // The new root's view takes no touches while it animates, and whether it took them before: Core Animation draws it
87
+ // elsewhere than where it is (the view itself stays in place), so a tap on the old screen would reach it.
88
+ @property(nonatomic, weak, nullable) UIView *untouchableRoot;
89
+ @property(nonatomic) BOOL rootTouchesBefore;
86
90
  @property(nonatomic) BOOL layersShown;
87
91
  @end
88
92
 
@@ -533,20 +537,43 @@ static __weak ANNRootShow *ANNAnimatingShow;
533
537
  NSMutableArray<ANNViewTracks *> *tracks = [NSMutableArray new];
534
538
  ANNViewAnimationOptions *enter = [ANNAnimationRules playingSide:animation.enter];
535
539
  ANNViewAnimationOptions *exit = [ANNAnimationRules playingSide:animation.exit];
536
- if (enter && rootView) {
537
- [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
538
- side:enter
539
- alphaBefore:rootView.alpha]];
540
- }
541
- if (exit && snapshot) {
542
- [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
543
- side:exit
544
- alphaBefore:snapshot.alpha]];
545
- }
546
540
  NSTimeInterval length =
547
541
  MAX([ANNAnimationRules lengthOfSide:enter], [ANNAnimationRules lengthOfSide:exit]);
542
+ if (UIAccessibilityIsReduceMotionEnabled() && length > 0) {
543
+ // With the system's Reduce Motion on, nothing moves: the new root fades in over the snapshot in the same
544
+ // length, or the snapshot fades out without a new root's view.
545
+ if (rootView) {
546
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
547
+ fadeFrom:0
548
+ to:rootView.alpha
549
+ duration:length
550
+ alphaBefore:rootView.alpha]];
551
+ } else if (snapshot) {
552
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
553
+ fadeFrom:snapshot.alpha
554
+ to:0
555
+ duration:length
556
+ alphaBefore:snapshot.alpha]];
557
+ }
558
+ } else {
559
+ if (enter && rootView) {
560
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:rootView
561
+ side:enter
562
+ alphaBefore:rootView.alpha]];
563
+ }
564
+ if (exit && snapshot) {
565
+ [tracks addObject:[[ANNViewTracks alloc] initWithView:snapshot
566
+ side:exit
567
+ alphaBefore:snapshot.alpha]];
568
+ }
569
+ }
548
570
  show.tracks = tracks;
549
571
  show.animating = YES;
572
+ if (rootView) {
573
+ show.untouchableRoot = rootView;
574
+ show.rootTouchesBefore = rootView.userInteractionEnabled;
575
+ rootView.userInteractionEnabled = NO;
576
+ }
550
577
  ANNAnimatingShow = show;
551
578
  show.driver = [[ANNFrameDriver alloc] initWithClients:tracks length:length];
552
579
  // The layers' state from here on: the chain may start and a newer `setRoot` stops it.
@@ -583,8 +610,8 @@ static __weak ANNRootShow *ANNAnimatingShow;
583
610
  [self finishLayersOf:show];
584
611
  }
585
612
 
586
- // The animation stops at its end state (its end, a newer `setRoot`, a reload, a failure): the views get back what they
587
- // had and the snapshot goes.
613
+ // The animation stops (its end, a newer `setRoot`, a reload, a failure): its animations go, the views get back what
614
+ // they had and the snapshot goes.
588
615
  + (void)stopAnimationOf:(ANNRootShow *)show {
589
616
  if (!show.animating) {
590
617
  return;
@@ -592,13 +619,16 @@ static __weak ANNRootShow *ANNAnimatingShow;
592
619
  show.animating = NO;
593
620
  [show.driver cancel];
594
621
  show.driver = nil;
622
+ show.untouchableRoot.userInteractionEnabled = show.rootTouchesBefore;
623
+ show.untouchableRoot = nil;
595
624
  for (ANNViewTracks *tracks in show.tracks) {
596
625
  [tracks restore];
597
626
  }
598
627
  show.tracks = nil;
599
- // UIKit works out the safe area of the window's root view from where the view is drawn: moved away from the top
600
- // edge by `enter` (from the bottom, scaled down) it has no top inset, and putting the transform back doesn't make
601
- // UIKit work it out again. A layout now gives the root, its bars and its screens the window's safe area back.
628
+ // UIKit works out the safe area of the window's root view from where the view is: moved away from the top edge by
629
+ // a transform it has no top inset, and putting the transform back doesn't make UIKit work it out again. `enter`
630
+ // moves only what Core Animation draws now; the layout stays, so the root, its bars and its screens end with the
631
+ // window's safe area whatever moved them.
602
632
  UIView *rootView = show.root.viewIfLoaded;
603
633
  [rootView setNeedsLayout];
604
634
  [rootView layoutIfNeeded];
@@ -11,8 +11,8 @@ NS_ASSUME_NONNULL_BEGIN
11
11
  ///
12
12
  /// Its view has the size of the screen of the navigation window's scene; the content sits in the root frame, by the one
13
13
  /// "under bars" rule (`ANNScreenBars`). Every recompute of the frame (a layout, a change of the safe area or the
14
- /// traits, `mergeOptions`, an appearance) gives the modules the screen's insets, padding and regions
15
- /// (`ANNScreenInsets`, `ANNScreenRegions`). Its presenter is an `ANNComponentPresenter`.
14
+ /// traits, `mergeOptions`, an appearance) gives the store the screen's insets, padding and regions
15
+ /// (`ANNScreenEnvironment`). Its presenter is an `ANNComponentPresenter`.
16
16
  ///
17
17
  /// The screen answers UIKit's questions about the system UI (native screens too): the status bar's style and visibility
18
18
  /// (never animated), the orientations, the home indicator, the deferred edges and the vertical bars, from its resolved
@@ -1,9 +1,7 @@
1
1
  #import "ANNComponentViewController.h"
2
2
  #import "ANNAppearanceDispatcher.h"
3
- #import "ANNArrangementState.h"
4
3
  #import "ANNBottomTabsController.h"
5
4
  #import "ANNComponentPresenter.h"
6
- #import "ANNEventContract.h"
7
5
  #import "ANNHinge.h"
8
6
  #import "ANNKeyCommands.h"
9
7
  #import "ANNNodeRegistry.h"
@@ -11,11 +9,12 @@
11
9
  #import "ANNPendingLayers.h"
12
10
  #import "ANNPreviewPush.h"
13
11
  #import "ANNScreenBars.h"
14
- #import "ANNScreenInsets.h"
12
+ #import "ANNScreenEnvironment.h"
15
13
  #import "ANNScreenReadiness.h"
16
14
  #import "ANNScreenRegions.h"
17
15
  #import "ANNScreenSafeArea.h"
18
16
  #import "ANNStackController.h"
17
+ #import "ANNSurfaceHostingView.h"
19
18
  #import "ANNSystemUI.h"
20
19
  #import "ANNTopBarPresenter.h"
21
20
  #import "ANNUtils.h"
@@ -105,10 +104,12 @@
105
104
  }
106
105
 
107
106
  // UIKit names the size transition as the moment the status bar's frame changes (a rotation, a new window size): the
108
- // blur follows it along the animation and takes the final frame at its end.
107
+ // blur follows it along the animation and takes the final frame at its end. The React content takes its new size
108
+ // without animation meanwhile, or what it draws itself is stretched along the animation (`ANNSurfaceHostingView`).
109
109
  - (void)viewWillTransitionToSize:(CGSize)size
110
110
  withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
111
111
  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
112
+ [ANNSurfaceHostingView followSizeTransition:coordinator];
112
113
  __weak ANNComponentViewController *weakSelf = self;
113
114
  [coordinator
114
115
  animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
@@ -432,7 +433,7 @@
432
433
  return UIRectEdgeNone;
433
434
  }
434
435
 
435
- // The insets and the padding of a React screen or a slot screen go to the module, which keeps them, gives JavaScript
436
+ // The insets and the padding of a React screen or a slot screen go to the store, which keeps them, gives JavaScript
436
437
  // what still covers the content and tells only of changes; the regions in the same pass. Only in a window and with an
437
438
  // id; never after the destroy, which removed them (a late layout would bring them back), nor for the JavaScript that
438
439
  // went (an old screen held after a reload: the new JavaScript may give its id to a new screen).
@@ -453,22 +454,18 @@
453
454
  UINavigationController *stack = [self shownNavigation];
454
455
  ANNScreenPaddingContext context = {
455
456
  .inStack = stack != nil,
456
- // The stack's toolbar, by the rule the stack shows it with: one that `topBar.hideOnScroll`
457
- // hid with the bar still counts.
458
- .stackShowsToolbar = stack != nil && options.toolbar.shouldShow,
459
- .windowBottomSafeArea = window.safeAreaInsets.bottom,
460
457
  .verticalBarSide = [self verticalBarSide],
461
458
  };
462
459
  UIEdgeInsets padding = ANNScreenPadding(insets, options, context);
463
- [ANNScreenInsets setInsets:insets
464
- padding:padding
465
- forScreenId:componentId
466
- eventEmitter:eventEmitter];
460
+ [ANNScreenEnvironment setInsets:insets
461
+ padding:padding
462
+ forScreenId:componentId
463
+ eventEmitter:eventEmitter];
467
464
  [self updateRegions];
468
465
  }
469
466
 
470
467
  // The regions in the same pass, and on the next turn after a change of the hinge's state (`hingeDidChange:`). Nil
471
- // before iOS 27.1: nothing to keep. An empty first result is not sent.
468
+ // before iOS 27.1: nothing to keep. The store neither keeps nor sends an empty first result.
472
469
  - (void)updateRegions {
473
470
  UIView<ANNComponentProtocol> *content = _reactView;
474
471
  NSString *componentId = self.layoutInfo.componentId;
@@ -483,12 +480,7 @@
483
480
  if (!regions) {
484
481
  return;
485
482
  }
486
- const auto &keys = ANNEventContract.ScreenRegionsChanged;
487
- BOOL empty = [regions[keys.division] count] == 0 && [regions[keys.occlusion] count] == 0;
488
- if (empty && ![ANNScreenRegions regionsForScreenId:componentId]) {
489
- return;
490
- }
491
- [ANNScreenRegions setRegions:regions forScreenId:componentId eventEmitter:eventEmitter];
483
+ [ANNScreenEnvironment setRegions:regions forScreenId:componentId eventEmitter:eventEmitter];
492
484
  }
493
485
 
494
486
  - (void)hingeDidChange:(NSNotification *)notification {
@@ -690,9 +682,7 @@
690
682
  // its destroy, as at a reload) keeps it.
691
683
  NSString *componentId = self.layoutInfo.componentId;
692
684
  if (componentId && ![ANNNodeRegistry nodeForComponentId:componentId]) {
693
- [ANNScreenInsets removeScreenId:componentId];
694
- [ANNScreenRegions removeScreenId:componentId];
695
- [ANNArrangementState removeScreenId:componentId];
685
+ [ANNScreenEnvironment removeScreenId:componentId];
696
686
  [ANNScreenReadiness removeScreenId:componentId];
697
687
  }
698
688
  }
@@ -9,15 +9,18 @@
9
9
 
10
10
  /**
11
11
  * Previews `preview` from `view`, the component view with the tag `reactTag`, and replaces an earlier
12
- * preview of the view. `commit` runs on a tap on the preview and returns whether it showed the
13
- * screen; the preview goes then, as the push it stands for is done. `dismissed` runs once when the
14
- * preview goes without being shown as a screen: replaced by another preview of the view, after
15
- * Fabric gave the view to another component, or when `source`, the screen of the view, goes.
12
+ * preview of the view. `prepare` runs as each press starts, before the menu shows the preview: it
13
+ * renders the screen if it hasn't yet, and returns NO when the preview went instead (no menu shows
14
+ * then). `commit` runs on a tap on the preview and returns whether it showed the screen; the
15
+ * preview goes then, as the push it stands for is done. `dismissed` runs once when the preview
16
+ * goes without being shown as a screen: replaced by another preview of the view, after Fabric gave
17
+ * the view to another component, or when `source`, the screen of the view, goes.
16
18
  */
17
19
  + (void)attachPreview:(UIViewController *)preview
18
20
  toView:(UIView *)view
19
21
  reactTag:(NSInteger)reactTag
20
22
  source:(UIViewController *)source
23
+ prepare:(BOOL (^)(void))prepare
21
24
  commit:(BOOL (^)(void))commit
22
25
  dismissed:(void (^)(void))dismissed;
23
26