@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
@@ -1,6 +1,5 @@
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
5
  #import "ANNHinge.h"
@@ -10,18 +9,22 @@
10
9
  #import "ANNPendingLayers.h"
11
10
  #import "ANNPreviewPush.h"
12
11
  #import "ANNScreenBars.h"
13
- #import "ANNScreenInsets.h"
12
+ #import "ANNScreenEnvironment.h"
14
13
  #import "ANNScreenReadiness.h"
15
14
  #import "ANNScreenRegions.h"
16
15
  #import "ANNScreenSafeArea.h"
16
+ #import "ANNScreenSettling.h"
17
17
  #import "ANNStackController.h"
18
+ #import "ANNSurfaceHostingView.h"
18
19
  #import "ANNSystemUI.h"
19
20
  #import "ANNTopBarPresenter.h"
20
21
  #import "ANNUtils.h"
21
22
 
22
23
  @implementation ANNComponentViewController {
23
- // Where the content is lent while it mounts unseen (the tabs' preload window).
24
- __weak UIView *_contentLentTo;
24
+ // What the screen would send while the geometry settles (`ANNScreenSettling`), and whether it still owes it.
25
+ UIEdgeInsets _settlingInsets;
26
+ UIEdgeInsets _settlingPadding;
27
+ BOOL _settlingHeld;
25
28
  }
26
29
 
27
30
  - (instancetype)initWithLayoutInfo:(ANNLayoutInfo *)layoutInfo
@@ -46,8 +49,8 @@
46
49
  defaultOptions:defaultOptions
47
50
  presenter:presenter
48
51
  eventEmitter:eventEmitter];
49
- // While the screen lives (removed at its destroy): the end of an edit gives the key commands back, and a change of
50
- // the hinge's state moves the regions without a change of size or traits.
52
+ // While the screen lives (removed at its destroy): the end of an edit gives the key commands back, a change of the
53
+ // hinge's state moves the regions without a change of size or traits, and the end of a fold sends the insets.
51
54
  NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
52
55
  [center addObserver:self
53
56
  selector:@selector(textDidEndEditing:)
@@ -61,11 +64,21 @@
61
64
  selector:@selector(hingeDidChange:)
62
65
  name:ANNHingeDidChangeNotification
63
66
  object:nil];
67
+ [center addObserver:self
68
+ selector:@selector(screenSettlingDidEnd:)
69
+ name:ANNScreenSettlingDidEndNotification
70
+ object:nil];
64
71
  return self;
65
72
  }
66
73
 
67
74
  #pragma mark - The view
68
75
 
76
+ - (nullable ANNComponentPresenter *)componentPresenter {
77
+ ANNNodePresenter *presenter = self.presenter;
78
+ return [presenter isKindOfClass:ANNComponentPresenter.class] ? (ANNComponentPresenter *)presenter
79
+ : nil;
80
+ }
81
+
69
82
  // The size of the screen of the navigation window's scene, not the deprecated main screen: a surface made before the
70
83
  // screen is in a window starts with the width it will have.
71
84
  - (void)loadView {
@@ -94,6 +107,26 @@
94
107
  }
95
108
  // The pair the screen is in may lie otherwise now.
96
109
  [self.arrangement screenDidChangeLayout:self];
110
+ [self.componentPresenter layOutStatusBarBlur];
111
+ }
112
+
113
+ // UIKit names the size transition as the moment the status bar's frame changes (a rotation, a new window size): the
114
+ // blur follows it along the animation and takes the final frame at its end. The React content takes its new size
115
+ // without animation meanwhile, or what it draws itself is stretched along the animation (`ANNSurfaceHostingView`). On
116
+ // a device with a hinge the insets wait until the geometry settles.
117
+ - (void)viewWillTransitionToSize:(CGSize)size
118
+ withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
119
+ [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
120
+ [ANNScreenSettling beginWithTransition:coordinator];
121
+ [ANNSurfaceHostingView followSizeTransition:coordinator];
122
+ __weak ANNComponentViewController *weakSelf = self;
123
+ [coordinator
124
+ animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
125
+ [weakSelf.componentPresenter layOutStatusBarBlur];
126
+ }
127
+ completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
128
+ [weakSelf.componentPresenter layOutStatusBarBlur];
129
+ }];
97
130
  }
98
131
 
99
132
  - (void)viewSafeAreaInsetsDidChange {
@@ -102,14 +135,26 @@
102
135
  }
103
136
 
104
137
  // The regions UIKit reserves are still the old ones while it tells of new traits: they are read again on the next turn
105
- // of the main queue. A fold changes the traits, not always the size.
138
+ // of the main queue. A fold changes the traits, not always the size; a new edge of the vertical bar comes before the
139
+ // safe area that goes with it, so the insets wait until the geometry settles.
106
140
  - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
107
141
  [super traitCollectionDidChange:previousTraitCollection];
142
+ #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 270100
143
+ if (@available(iOS 27.1, *)) {
144
+ // A screen that comes into the window gets the bar's edge from none: that is no fold.
145
+ UIVerticalBarEdge before = previousTraitCollection.verticalBarEdge;
146
+ if (self.viewIfLoaded.window && before != UIVerticalBarEdgeUnspecified &&
147
+ before != self.traitCollection.verticalBarEdge) {
148
+ [ANNScreenSettling beginForTraitChange];
149
+ }
150
+ }
151
+ #endif
108
152
  [self updateRootLayout];
109
153
  [self.arrangement screenDidChangeLayout:self];
110
154
  __weak ANNComponentViewController *weakSelf = self;
111
155
  dispatch_async(dispatch_get_main_queue(), ^{
112
156
  [weakSelf updateRootLayout];
157
+ [weakSelf.componentPresenter layOutStatusBarBlur];
113
158
  });
114
159
  }
115
160
 
@@ -119,10 +164,17 @@
119
164
  // hide. They are the screen's report as a container gives it; the dispatcher keeps it to one per appearance. While a
120
165
  // command drives the appearance (a window's root replaced), UIKit's calls come at its own moments and would break the
121
166
  // command's order: the command reports instead.
167
+ // A screen that left the window while the geometry settled sends what it held as it comes back: the end of the settling
168
+ // found it out of the window.
169
+ - (void)viewIsAppearing:(BOOL)animated {
170
+ [super viewIsAppearing:animated];
171
+ if (_settlingHeld && !ANNScreenSettling.isSettling) {
172
+ [self updateRootLayout];
173
+ }
174
+ }
175
+
122
176
  - (void)viewWillAppear:(BOOL)animated {
123
177
  [super viewWillAppear:animated];
124
- // A tab shows for the first time while its content still mounts in the preload window.
125
- [self takeContentBack];
126
178
  // A preview screen that UIKit's menu takes leaves its unseen place first, so that the menu reports it.
127
179
  [ANNPreviewPush screenWillAppear:self];
128
180
  if (![ANNAppearanceDispatcher isAppearanceDriven:self]) {
@@ -138,6 +190,12 @@
138
190
  [ANNSystemUI setNeedsUpdate];
139
191
  [self.arrangement screenDidChangeLayout:self];
140
192
  [ANNHinge watchForScreens];
193
+ // A parked screen whose place gave it no safe area at all lays out with its view's own from now on.
194
+ if (self.placeWhileParked && ![ANNParking isUnseen:self]) {
195
+ self.placeWhileParked = nil;
196
+ self.placeKeptUntilAppearance = NO;
197
+ [self updateRootLayout];
198
+ }
141
199
  // Once JavaScript heard the appearance (a driven one ends later, with its command).
142
200
  __weak ANNComponentViewController *weakSelf = self;
143
201
  [ANNAppearanceDispatcher afterDidAppearOf:self.appearance
@@ -200,9 +258,7 @@
200
258
  #pragma mark - The root frame and the safe area
201
259
 
202
260
  - (void)applyBackground {
203
- if ([self.presenter isKindOfClass:ANNComponentPresenter.class]) {
204
- [(ANNComponentPresenter *)self.presenter applyBackground:[self resolveOptionsWithDefault]];
205
- }
261
+ [self.componentPresenter applyBackground:[self resolveOptionsWithDefault]];
206
262
  }
207
263
 
208
264
  // The navigation controller that shows the screen's stack: the stack, or UIKit's More navigation while a tab of More
@@ -341,11 +397,32 @@
341
397
  }
342
398
  #endif
343
399
 
400
+ // The place the screen waits to show in, while it is parked out of it and until UIKit gives it a safe area of its
401
+ // own there: the push lays the screen out once before that, with none, and a list laid out then at the screen's top
402
+ // would stay the list the bar follows. A place that shows with no safe area at all hands over as the screen appears.
403
+ - (nullable ANNScreenPlace *)parkedPlace {
404
+ ANNScreenPlace * (^place)(void) = self.placeWhileParked;
405
+ if (!place) {
406
+ return nil;
407
+ }
408
+ if (!self.placeKeptUntilAppearance && ![ANNParking isUnseen:self] &&
409
+ self.parentViewController &&
410
+ !UIEdgeInsetsEqualToEdgeInsets(self.view.safeAreaInsets, UIEdgeInsetsZero)) {
411
+ self.placeWhileParked = nil;
412
+ return nil;
413
+ }
414
+ return place();
415
+ }
416
+
344
417
  - (CGRect)rootFrameForOptions:(ANNNavigationOptions *)options {
345
418
  UIView *view = self.view;
346
- BOOL fromTop = ANNScreenIsUnderTopBar(options) || ![self hasShownTopBar];
347
- BOOL toBottom = ANNScreenIsUnderTabBar(options) || ![self hasShownTabBar];
348
- return ANNScreenRootFrame(view.bounds, view.safeAreaInsets, fromTop, toBottom);
419
+ ANNScreenPlace *place = [self parkedPlace];
420
+ BOOL topBarShown = place ? place.showsTopBar : [self hasShownTopBar];
421
+ BOOL tabBarShown = place ? place.showsTabBar : [self hasShownTabBar];
422
+ BOOL fromTop = ANNScreenIsUnderTopBar(options) || !topBarShown;
423
+ BOOL toBottom = ANNScreenIsUnderTabBar(options) || !tabBarShown;
424
+ UIEdgeInsets safeArea = place ? place.safeArea : view.safeAreaInsets;
425
+ return ANNScreenRootFrame(view.bounds, safeArea, fromTop, toBottom);
349
426
  }
350
427
 
351
428
  - (void)updateRootLayout {
@@ -354,7 +431,7 @@
354
431
  }
355
432
  ANNNavigationOptions *options = [self resolveOptionsWithDefault];
356
433
  UIView<ANNComponentProtocol> *content = _reactView;
357
- if (content && !self.contentIsLent) {
434
+ if (content) {
358
435
  CGRect frame = [self rootFrameForOptions:options];
359
436
  if (!CGRectEqualToRect(content.frame, frame)) {
360
437
  content.frame = frame;
@@ -385,10 +462,12 @@
385
462
  return UIRectEdgeNone;
386
463
  }
387
464
 
388
- // The insets and the padding of a React screen or a slot screen go to the module, which keeps them, gives JavaScript
465
+ // The insets and the padding of a React screen or a slot screen go to the store, which keeps them, gives JavaScript
389
466
  // what still covers the content and tells only of changes; the regions in the same pass. Only in a window and with an
390
467
  // id; never after the destroy, which removed them (a late layout would bring them back), nor for the JavaScript that
391
- // went (an old screen held after a reload: the new JavaScript may give its id to a new screen).
468
+ // went (an old screen held after a reload: the new JavaScript may give its id to a new screen). While the geometry
469
+ // settles they are only noted, the steps of a fold would reach JavaScript one by one; but a screen's first values go at
470
+ // once, since JavaScript reads them as it renders the screen.
392
471
  - (void)updateSafeAreaWithOptions:(ANNNavigationOptions *)options {
393
472
  UIView<ANNComponentProtocol> *content = _reactView;
394
473
  NSString *componentId = self.layoutInfo.componentId;
@@ -399,28 +478,41 @@
399
478
  self.nodeHelper.destroyed) {
400
479
  return;
401
480
  }
402
- UIEdgeInsets insets =
403
- ANNScreenInsetsOverRoot(content.frame, view.bounds.size, view.safeAreaInsets);
481
+ // A parked screen has no safe area of its own: it takes its place's.
482
+ ANNScreenPlace *place = [self parkedPlace];
483
+ UIEdgeInsets safeArea = place ? place.safeArea : view.safeAreaInsets;
484
+ UIEdgeInsets insets = ANNScreenInsetsOverRoot(content.frame, view.bounds.size, safeArea);
404
485
  UINavigationController *stack = [self shownNavigation];
405
486
  ANNScreenPaddingContext context = {
406
487
  .inStack = stack != nil,
407
- // The stack's toolbar, by the rule the stack shows it with: one that `topBar.hideOnScroll`
408
- // hid with the bar still counts.
409
- .stackShowsToolbar = stack != nil && options.toolbar.shouldShow,
410
- .windowBottomSafeArea = window.safeAreaInsets.bottom,
411
488
  .verticalBarSide = [self verticalBarSide],
412
489
  };
413
490
  UIEdgeInsets padding = ANNScreenPadding(insets, options, context);
414
- [ANNScreenInsets setInsets:insets
415
- padding:padding
416
- forScreenId:componentId
417
- eventEmitter:eventEmitter];
491
+ if (ANNScreenSettling.isSettling && [ANNScreenEnvironment insetsForScreenId:componentId]) {
492
+ if (!UIEdgeInsetsEqualToEdgeInsets(insets, _settlingInsets) ||
493
+ !UIEdgeInsetsEqualToEdgeInsets(padding, _settlingPadding)) {
494
+ _settlingInsets = insets;
495
+ _settlingPadding = padding;
496
+ [ANNScreenSettling valuesDidChange];
497
+ }
498
+ _settlingHeld = YES;
499
+ return;
500
+ }
501
+ _settlingHeld = NO;
502
+ [ANNScreenEnvironment setInsets:insets
503
+ padding:padding
504
+ forScreenId:componentId
505
+ eventEmitter:eventEmitter];
418
506
  [self updateRegions];
419
507
  }
420
508
 
421
- // The regions in the same pass, and on the next turn after a change of the hinge's state (`hingeDidChange:`). Nil
422
- // before iOS 27.1: nothing to keep. An empty first result is not sent.
509
+ // The regions in the same pass, and on the next turn after a change of the hinge's state (`hingeDidChange:`); not while
510
+ // the geometry settles, whose end sends them with the insets. Nil before iOS 27.1: nothing to keep. The store neither
511
+ // keeps nor sends an empty first result.
423
512
  - (void)updateRegions {
513
+ if (ANNScreenSettling.isSettling) {
514
+ return;
515
+ }
424
516
  UIView<ANNComponentProtocol> *content = _reactView;
425
517
  NSString *componentId = self.layoutInfo.componentId;
426
518
  ANNEventEmitter *eventEmitter = self.eventEmitter;
@@ -434,11 +526,11 @@
434
526
  if (!regions) {
435
527
  return;
436
528
  }
437
- BOOL empty = [regions[@"division"] count] == 0 && [regions[@"occlusion"] count] == 0;
438
- if (empty && ![ANNScreenRegions regionsForScreenId:componentId]) {
439
- return;
440
- }
441
- [ANNScreenRegions setRegions:regions forScreenId:componentId eventEmitter:eventEmitter];
529
+ [ANNScreenEnvironment setRegions:regions forScreenId:componentId eventEmitter:eventEmitter];
530
+ }
531
+
532
+ - (void)screenSettlingDidEnd:(NSNotification *)notification {
533
+ [self updateRootLayout];
442
534
  }
443
535
 
444
536
  - (void)hingeDidChange:(NSNotification *)notification {
@@ -511,37 +603,6 @@
511
603
  });
512
604
  }
513
605
 
514
- #pragma mark - The preload window
515
-
516
- - (BOOL)contentIsLent {
517
- return _contentLentTo != nil;
518
- }
519
-
520
- - (BOOL)lendContentTo:(UIView *)host {
521
- UIView<ANNComponentProtocol> *content = _reactView;
522
- if (!content || _contentLentTo || content.window || self.nodeHelper.destroyed ||
523
- ![content isKindOfClass:ANNReactView.class]) {
524
- return NO;
525
- }
526
- _contentLentTo = host;
527
- [host addSubview:content];
528
- return YES;
529
- }
530
-
531
- - (void)takeContentBack {
532
- if (!_contentLentTo) {
533
- return;
534
- }
535
- _contentLentTo = nil;
536
- UIView<ANNComponentProtocol> *content = _reactView;
537
- if (!content || self.nodeHelper.destroyed) {
538
- [content removeFromSuperview];
539
- return;
540
- }
541
- [self.view insertSubview:content atIndex:0];
542
- [self updateRootLayout];
543
- }
544
-
545
606
  #pragma mark - Leaving
546
607
 
547
608
  - (void)screenWillLeave {
@@ -606,9 +667,7 @@
606
667
  content.autoresizingMask = UIViewAutoresizingNone;
607
668
  content.frame = [self rootFrameForOptions:[self resolveOptionsWithDefault]];
608
669
  [view addSubview:content];
609
- if ([self.presenter isKindOfClass:ANNComponentPresenter.class]) {
610
- [(ANNComponentPresenter *)self.presenter keepStatusBarBlurOnTop];
611
- }
670
+ [self.componentPresenter keepStatusBarBlurOnTop];
612
671
  [self applyBackground];
613
672
  [self updateRootLayout];
614
673
  }
@@ -634,17 +693,13 @@
634
693
  [topBar releaseLists];
635
694
  [topBar stopComponents];
636
695
  [self destroyReactView];
637
- // The stop holds the hosting view until the surface stopped: the screen lets go of its content view now, wherever
638
- // it is (a preload window too).
639
- _contentLentTo = nil;
696
+ // The stop holds the hosting view until the surface stopped: the screen lets go of its content view now.
640
697
  [_reactView removeFromSuperview];
641
698
  // The data is kept by id: a node that holds the id now (a new JavaScript reused it while this screen waited for
642
699
  // its destroy, as at a reload) keeps it.
643
700
  NSString *componentId = self.layoutInfo.componentId;
644
701
  if (componentId && ![ANNNodeRegistry nodeForComponentId:componentId]) {
645
- [ANNScreenInsets removeScreenId:componentId];
646
- [ANNScreenRegions removeScreenId:componentId];
647
- [ANNArrangementState removeScreenId:componentId];
702
+ [ANNScreenEnvironment removeScreenId:componentId];
648
703
  [ANNScreenReadiness removeScreenId:componentId];
649
704
  }
650
705
  }
@@ -1,5 +1,6 @@
1
1
  #import "ANNNativeScreenContext+Internal.h"
2
2
  #import "ANNErrorTexts.h"
3
+ #import "ANNEventContract.h"
3
4
  #import "ANNEventEmitter.h"
4
5
  #import "ANNNativeScreenCalls.h"
5
6
  #import <React/RCTUtils.h>
@@ -71,12 +72,13 @@
71
72
  componentId:self->_componentId]];
72
73
  return;
73
74
  }
75
+ const auto &keys = ANNEventContract.NativeScreenCall;
74
76
  [eventEmitter sendNativeScreenCall:@{
75
- @"componentId" : self->_componentId,
76
- @"callId" : callId,
77
- @"kind" : kind,
78
- @"name" : name,
79
- @"args" : arguments ?: @[],
77
+ keys.componentId : self->_componentId,
78
+ keys.callId : callId,
79
+ keys.kind : kind,
80
+ keys.name : name,
81
+ keys.args : arguments ?: @[],
80
82
  }];
81
83
  });
82
84
  }
@@ -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
 
@@ -24,15 +24,23 @@ static NSMutableSet *ANNPreviews(void) {
24
24
  @implementation ANNPreviewInteraction {
25
25
  UIViewController *_preview;
26
26
  NSInteger _reactTag;
27
+ __weak UIViewController *_source;
28
+ BOOL (^_prepare)(void);
27
29
  BOOL (^_commit)(void);
28
30
  void (^_dismissed)(void);
29
31
  UIContextMenuInteraction *_interaction;
32
+ // The snapshots of the view that the menu of this press lifts and puts back, over the view until
33
+ // the menu is gone. Each press has its own list: a new press may start while the last menu goes.
34
+ NSMutableArray<UIView *> *_snapshots;
35
+ // The list of the menu that goes now: its end removes them.
36
+ __weak NSMutableArray<UIView *> *_endingSnapshots;
30
37
  }
31
38
 
32
39
  + (void)attachPreview:(UIViewController *)preview
33
40
  toView:(UIView *)view
34
41
  reactTag:(NSInteger)reactTag
35
42
  source:(UIViewController *)source
43
+ prepare:(BOOL (^)(void))prepare
36
44
  commit:(BOOL (^)(void))commit
37
45
  dismissed:(void (^)(void))dismissed {
38
46
  if (!view || !preview) {
@@ -45,6 +53,8 @@ static NSMutableSet *ANNPreviews(void) {
45
53
  ANNPreviewInteraction *previewInteraction = [ANNPreviewInteraction new];
46
54
  previewInteraction->_preview = preview;
47
55
  previewInteraction->_reactTag = reactTag;
56
+ previewInteraction->_source = source;
57
+ previewInteraction->_prepare = [prepare copy];
48
58
  previewInteraction->_commit = [commit copy];
49
59
  previewInteraction->_dismissed = [dismissed copy];
50
60
  previewInteraction->_interaction =
@@ -91,7 +101,9 @@ static NSMutableSet *ANNPreviews(void) {
91
101
  [view removeInteraction:_interaction];
92
102
  // A tap's commit animation may still run: a preview that went, its screen destroyed and its push failed, is not
93
103
  // pushed when the animation ends.
104
+ _prepare = nil;
94
105
  _commit = nil;
106
+ [ANNPreviewInteraction removeSnapshots:_snapshots];
95
107
  void (^dismissed)(void) = _dismissed;
96
108
  _dismissed = nil;
97
109
  if (dismissed) {
@@ -116,6 +128,18 @@ static NSMutableSet *ANNPreviews(void) {
116
128
  [self detach];
117
129
  return nil;
118
130
  }
131
+ // UIKit ends a lift that never became a menu too (the touch ended before the long press); should
132
+ // it not, the snapshot of that press goes now.
133
+ if (_snapshots != _endingSnapshots) {
134
+ [ANNPreviewInteraction removeSnapshots:_snapshots];
135
+ }
136
+ _snapshots = [NSMutableArray new];
137
+ // UIKit asks for the configuration as the press starts, about half a second before it shows the preview: the
138
+ // screen renders now, so that its content is there by then.
139
+ if (_prepare && !_prepare()) {
140
+ [self detach];
141
+ return nil;
142
+ }
119
143
  UIViewController *preview = _preview;
120
144
  NSArray *actions = preview.resolveOptions.preview.actions;
121
145
  return [UIContextMenuConfiguration
@@ -129,6 +153,23 @@ static NSMutableSet *ANNPreviews(void) {
129
153
  }];
130
154
  }
131
155
 
156
+ // The menu goes: the snapshots of its press go once it is gone. UIKit asks for the one
157
+ // it goes back to after this call, so the list is read at the end, not now.
158
+ - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction
159
+ willEndForConfiguration:(UIContextMenuConfiguration *)configuration
160
+ animator:(id<UIContextMenuInteractionAnimating>)animator {
161
+ NSMutableArray<UIView *> *snapshots = _snapshots;
162
+ _endingSnapshots = snapshots;
163
+ void (^remove)(void) = ^{
164
+ [ANNPreviewInteraction removeSnapshots:snapshots];
165
+ };
166
+ if (animator) {
167
+ [animator addCompletion:remove];
168
+ } else {
169
+ dispatch_async(dispatch_get_main_queue(), remove);
170
+ }
171
+ }
172
+
132
173
  - (void)contextMenuInteraction:(UIContextMenuInteraction *)interaction
133
174
  willPerformPreviewActionForMenuWithConfiguration:(UIContextMenuConfiguration *)configuration
134
175
  animator:(id<UIContextMenuInteractionCommitAnimating>)
@@ -148,24 +189,45 @@ static NSMutableSet *ANNPreviews(void) {
148
189
 
149
190
  #pragma mark - Targeted previews
150
191
 
151
- // The view the menu lifts from and goes back to: a snapshot of the source view in its window. With
152
- // the source view itself UIKit adds its views next to it, among the React views of its parent, and
153
- // Fabric then mounts and unmounts at the wrong places.
192
+ // The view the menu lifts from and goes back to: a snapshot of the source view, laid over it in the
193
+ // view of its screen, the core's own (in its window when the view is elsewhere), so that it goes with
194
+ // the screen (a pop right after the menu). With the source view itself UIKit adds its views next to
195
+ // it, among the React views of its parent, and Fabric then mounts and unmounts at the wrong places.
196
+ // A snapshot out of the window, with only a target there, iOS 27 doesn't lift: it dims it in place.
154
197
  - (UITargetedPreview *)snapshotPreviewOf:(UIView *)view {
155
- UIWindow *window = view.window;
198
+ UIView *container = _source.viewIfLoaded;
199
+ if (!container || ![view isDescendantOfView:container]) {
200
+ container = view.window;
201
+ }
202
+ // A screen out of its window (a command took it away while the menu showed) has no place for it:
203
+ // UIKit needs the view in a window.
204
+ if (!container.window) {
205
+ return nil;
206
+ }
156
207
  UIView *snapshot = [view snapshotViewAfterScreenUpdates:NO];
157
- if (!window || !snapshot) {
208
+ if (!snapshot) {
158
209
  return nil;
159
210
  }
211
+ snapshot.frame = [view convertRect:view.bounds toView:container];
212
+ snapshot.userInteractionEnabled = NO;
213
+ snapshot.accessibilityElementsHidden = YES;
214
+ [container addSubview:snapshot];
215
+ if (!_snapshots) {
216
+ _snapshots = [NSMutableArray new];
217
+ }
218
+ [_snapshots addObject:snapshot];
160
219
  UIPreviewParameters *parameters = [UIPreviewParameters new];
161
220
  parameters.backgroundColor = UIColor.clearColor;
162
221
  parameters.visiblePath = [UIBezierPath bezierPathWithRoundedRect:view.bounds
163
222
  cornerRadius:view.layer.cornerRadius];
164
- CGPoint center = [view convertPoint:CGPointMake(CGRectGetMidX(view.bounds),
165
- CGRectGetMidY(view.bounds))
166
- toView:window];
167
- UIPreviewTarget *target = [[UIPreviewTarget alloc] initWithContainer:window center:center];
168
- return [[UITargetedPreview alloc] initWithView:snapshot parameters:parameters target:target];
223
+ return [[UITargetedPreview alloc] initWithView:snapshot parameters:parameters];
224
+ }
225
+
226
+ + (void)removeSnapshots:(NSMutableArray<UIView *> *)snapshots {
227
+ for (UIView *snapshot in snapshots) {
228
+ [snapshot removeFromSuperview];
229
+ }
230
+ [snapshots removeAllObjects];
169
231
  }
170
232
 
171
233
  - (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction
@@ -0,0 +1,63 @@
1
+ #import "ANNEventEmitter.h"
2
+ #import <UIKit/UIKit.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ /// A view that keeps a screen's content out of its padding (the screen's safe area view).
7
+ @protocol ANNScreenPaddingListener <NSObject>
8
+ /// The padding of its screen changed. Main queue.
9
+ - (void)screenPaddingDidChange;
10
+ @end
11
+
12
+ /// What JavaScript knows of each screen's place, by the screen's id, in one record: its safe area (the insets
13
+ /// JavaScript gets, `useSafeAreaInsets`, and the padding of its safe area view), its reserved regions
14
+ /// (`useReservedRegions`) and, in a pair, its arrangement (`useArrangement`). The core measures them
15
+ /// (`ANNScreenSafeArea`, `ANNScreenRegions`, the pair's layout) on the main queue and keeps them here; JavaScript reads
16
+ /// them from its own thread for a screen's first render, under one lock, and gets every change as an event. When the
17
+ /// screen goes, `removeScreenId:` clears all of it. As on Android (`ScreenEnvironment`).
18
+ @interface ANNScreenEnvironment : NSObject
19
+
20
+ /// Keeps the screen's insets and the padding of its safe area view. The padding is the part of the insets the safe
21
+ /// area view keeps the content out of (the edges the screen's options give); JavaScript gets the rest, what still
22
+ /// covers the content (0 on a padded edge). Tells the padding's listeners of that screen when the padding changed, then
23
+ /// JavaScript (`ANN.ScreenInsetsChanged`) when its insets did. Main queue.
24
+ + (void)setInsets:(UIEdgeInsets)insets
25
+ padding:(UIEdgeInsets)padding
26
+ forScreenId:(NSString *)screenId
27
+ eventEmitter:(ANNEventEmitter *)eventEmitter;
28
+ /// The padding of the screen's safe area view; none before the screen was laid out. Any thread.
29
+ + (UIEdgeInsets)paddingForScreenId:(NSString *)screenId;
30
+ /// `{ top, right, bottom, left }`, or nil before the screen was laid out. Any thread.
31
+ + (nullable NSDictionary<NSString *, NSNumber *> *)insetsForScreenId:(NSString *)screenId;
32
+
33
+ /// Keeps the screen's regions (`{ division, occlusion }`) and tells JavaScript (`ANN.ScreenRegionsChanged`) when they
34
+ /// changed. None at first is what JavaScript reads before the first layout: it is neither kept nor told. Main queue.
35
+ + (void)setRegions:(NSDictionary<NSString *, NSArray *> *)regions
36
+ forScreenId:(NSString *)screenId
37
+ eventEmitter:(ANNEventEmitter *)eventEmitter;
38
+ /// `{ division, occlusion }`, or nil before the screen's regions were first kept. Any thread.
39
+ + (nullable NSDictionary<NSString *, NSArray *> *)regionsForScreenId:(NSString *)screenId;
40
+
41
+ /// Keeps the screen's arrangement (`{ placement, layout, front, hidden }`) and tells JavaScript
42
+ /// (`ANN.ArrangementChanged`) when it changed; nothing goes without an emitter. Main queue.
43
+ + (void)setArrangement:(NSDictionary<NSString *, id> *)arrangement
44
+ forScreenId:(NSString *)screenId
45
+ eventEmitter:(nullable ANNEventEmitter *)eventEmitter;
46
+ /// The screen's arrangement, or nil for a screen outside a pair. Any thread.
47
+ + (nullable NSDictionary<NSString *, id> *)arrangementForScreenId:(NSString *)screenId;
48
+
49
+ /// Tells `listener` of each change of the screen's padding, until it is removed or goes (held weakly). Several
50
+ /// listeners may listen to one screen. Main queue.
51
+ + (void)addPaddingListener:(id<ANNScreenPaddingListener>)listener forScreenId:(NSString *)screenId;
52
+ + (void)removePaddingListener:(id<ANNScreenPaddingListener>)listener
53
+ forScreenId:(NSString *)screenId;
54
+
55
+ /// Forgets everything kept for the screen. Its padding listeners stay: a live safe area view keeps listening while it
56
+ /// keeps the id, and stops itself. Main queue.
57
+ + (void)removeScreenId:(NSString *)screenId;
58
+ /// Forgets every screen: after a reload the new JavaScript counts its ids anew. Main queue.
59
+ + (void)removeAll;
60
+
61
+ @end
62
+
63
+ NS_ASSUME_NONNULL_END