@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
@@ -0,0 +1,507 @@
1
+ #import "ANNTransformParts.h"
2
+ #import <React/RCTLog.h>
3
+ #include <algorithm>
4
+ #include <cmath>
5
+
6
+ // The math works on m[i][j] = m(i+1)(j+1) of `CATransform3D`: a row is what a point's coordinate multiplies (row
7
+ // vectors), the layout of the decomposition's own pseudo-code (its matrix[3][0..2] is the translation).
8
+ typedef double ANNMatrix[4][4];
9
+
10
+ static void ANNMatrixOf(CATransform3D t, ANNMatrix m) {
11
+ const CGFloat values[16] = {t.m11, t.m12, t.m13, t.m14, t.m21, t.m22, t.m23, t.m24,
12
+ t.m31, t.m32, t.m33, t.m34, t.m41, t.m42, t.m43, t.m44};
13
+ for (int i = 0; i < 16; i++) {
14
+ m[i / 4][i % 4] = values[i];
15
+ }
16
+ }
17
+
18
+ static CATransform3D ANNTransformOfMatrix(const ANNMatrix m) {
19
+ CATransform3D t;
20
+ t.m11 = m[0][0];
21
+ t.m12 = m[0][1];
22
+ t.m13 = m[0][2];
23
+ t.m14 = m[0][3];
24
+ t.m21 = m[1][0];
25
+ t.m22 = m[1][1];
26
+ t.m23 = m[1][2];
27
+ t.m24 = m[1][3];
28
+ t.m31 = m[2][0];
29
+ t.m32 = m[2][1];
30
+ t.m33 = m[2][2];
31
+ t.m34 = m[2][3];
32
+ t.m41 = m[3][0];
33
+ t.m42 = m[3][1];
34
+ t.m43 = m[3][2];
35
+ t.m44 = m[3][3];
36
+ return t;
37
+ }
38
+
39
+ static void ANNMatrixIdentity(ANNMatrix m) {
40
+ for (int i = 0; i < 4; i++) {
41
+ for (int j = 0; j < 4; j++) {
42
+ m[i][j] = i == j ? 1 : 0;
43
+ }
44
+ }
45
+ }
46
+
47
+ // a · b: the point goes through a, then through b.
48
+ static void ANNMatrixMultiply(const ANNMatrix a, const ANNMatrix b, ANNMatrix out) {
49
+ ANNMatrix product;
50
+ for (int i = 0; i < 4; i++) {
51
+ for (int j = 0; j < 4; j++) {
52
+ double sum = 0;
53
+ for (int k = 0; k < 4; k++) {
54
+ sum += a[i][k] * b[k][j];
55
+ }
56
+ product[i][j] = sum;
57
+ }
58
+ }
59
+ memcpy(out, product, sizeof(ANNMatrix));
60
+ }
61
+
62
+ // The inverse of m into `out`; NO when m has none.
63
+ static BOOL ANNMatrixInvert(const ANNMatrix m, ANNMatrix out) {
64
+ const double *a = &m[0][0];
65
+ double inv[16];
66
+ inv[0] = a[5] * a[10] * a[15] - a[5] * a[11] * a[14] - a[9] * a[6] * a[15] +
67
+ a[9] * a[7] * a[14] + a[13] * a[6] * a[11] - a[13] * a[7] * a[10];
68
+ inv[4] = -a[4] * a[10] * a[15] + a[4] * a[11] * a[14] + a[8] * a[6] * a[15] -
69
+ a[8] * a[7] * a[14] - a[12] * a[6] * a[11] + a[12] * a[7] * a[10];
70
+ inv[8] = a[4] * a[9] * a[15] - a[4] * a[11] * a[13] - a[8] * a[5] * a[15] +
71
+ a[8] * a[7] * a[13] + a[12] * a[5] * a[11] - a[12] * a[7] * a[9];
72
+ inv[12] = -a[4] * a[9] * a[14] + a[4] * a[10] * a[13] + a[8] * a[5] * a[14] -
73
+ a[8] * a[6] * a[13] - a[12] * a[5] * a[10] + a[12] * a[6] * a[9];
74
+ inv[1] = -a[1] * a[10] * a[15] + a[1] * a[11] * a[14] + a[9] * a[2] * a[15] -
75
+ a[9] * a[3] * a[14] - a[13] * a[2] * a[11] + a[13] * a[3] * a[10];
76
+ inv[5] = a[0] * a[10] * a[15] - a[0] * a[11] * a[14] - a[8] * a[2] * a[15] +
77
+ a[8] * a[3] * a[14] + a[12] * a[2] * a[11] - a[12] * a[3] * a[10];
78
+ inv[9] = -a[0] * a[9] * a[15] + a[0] * a[11] * a[13] + a[8] * a[1] * a[15] -
79
+ a[8] * a[3] * a[13] - a[12] * a[1] * a[11] + a[12] * a[3] * a[9];
80
+ inv[13] = a[0] * a[9] * a[14] - a[0] * a[10] * a[13] - a[8] * a[1] * a[14] +
81
+ a[8] * a[2] * a[13] + a[12] * a[1] * a[10] - a[12] * a[2] * a[9];
82
+ inv[2] = a[1] * a[6] * a[15] - a[1] * a[7] * a[14] - a[5] * a[2] * a[15] +
83
+ a[5] * a[3] * a[14] + a[13] * a[2] * a[7] - a[13] * a[3] * a[6];
84
+ inv[6] = -a[0] * a[6] * a[15] + a[0] * a[7] * a[14] + a[4] * a[2] * a[15] -
85
+ a[4] * a[3] * a[14] - a[12] * a[2] * a[7] + a[12] * a[3] * a[6];
86
+ inv[10] = a[0] * a[5] * a[15] - a[0] * a[7] * a[13] - a[4] * a[1] * a[15] +
87
+ a[4] * a[3] * a[13] + a[12] * a[1] * a[7] - a[12] * a[3] * a[5];
88
+ inv[14] = -a[0] * a[5] * a[14] + a[0] * a[6] * a[13] + a[4] * a[1] * a[14] -
89
+ a[4] * a[2] * a[13] - a[12] * a[1] * a[6] + a[12] * a[2] * a[5];
90
+ inv[3] = -a[1] * a[6] * a[11] + a[1] * a[7] * a[10] + a[5] * a[2] * a[11] -
91
+ a[5] * a[3] * a[10] - a[9] * a[2] * a[7] + a[9] * a[3] * a[6];
92
+ inv[7] = a[0] * a[6] * a[11] - a[0] * a[7] * a[10] - a[4] * a[2] * a[11] +
93
+ a[4] * a[3] * a[10] + a[8] * a[2] * a[7] - a[8] * a[3] * a[6];
94
+ inv[11] = -a[0] * a[5] * a[11] + a[0] * a[7] * a[9] + a[4] * a[1] * a[11] -
95
+ a[4] * a[3] * a[9] - a[8] * a[1] * a[7] + a[8] * a[3] * a[5];
96
+ inv[15] = a[0] * a[5] * a[10] - a[0] * a[6] * a[9] - a[4] * a[1] * a[10] +
97
+ a[4] * a[2] * a[9] + a[8] * a[1] * a[6] - a[8] * a[2] * a[5];
98
+ double determinant = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
99
+ if (determinant == 0 || !std::isfinite(determinant)) {
100
+ return NO;
101
+ }
102
+ for (int i = 0; i < 16; i++) {
103
+ out[i / 4][i % 4] = inv[i] / determinant;
104
+ }
105
+ return YES;
106
+ }
107
+
108
+ static double ANNLength(const double v[3]) {
109
+ return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
110
+ }
111
+
112
+ static double ANNDot(const double a[3], const double b[3]) {
113
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
114
+ }
115
+
116
+ // a·sa + b·sb into a.
117
+ static void ANNCombine(double a[3], const double b[3], double sa, double sb) {
118
+ for (int i = 0; i < 3; i++) {
119
+ a[i] = a[i] * sa + b[i] * sb;
120
+ }
121
+ }
122
+
123
+ ANNTransformParts ANNTransformPartsIdentity(void) {
124
+ ANNTransformParts parts = {};
125
+ parts.scale[0] = parts.scale[1] = parts.scale[2] = 1;
126
+ parts.perspective[3] = 1;
127
+ parts.quaternion[3] = 1;
128
+ return parts;
129
+ }
130
+
131
+ BOOL ANNTransformPartsOf(CATransform3D transform, ANNTransformParts *parts) {
132
+ ANNMatrix m;
133
+ ANNMatrixOf(transform, m);
134
+ if (m[3][3] == 0) {
135
+ return NO;
136
+ }
137
+ double w = m[3][3];
138
+ for (int i = 0; i < 4; i++) {
139
+ for (int j = 0; j < 4; j++) {
140
+ m[i][j] /= w;
141
+ }
142
+ }
143
+ // The perspective's own matrix: the rest without the perspective column; it also tells a flat transform.
144
+ ANNMatrix perspectiveMatrix;
145
+ memcpy(perspectiveMatrix, m, sizeof(ANNMatrix));
146
+ for (int i = 0; i < 3; i++) {
147
+ perspectiveMatrix[i][3] = 0;
148
+ }
149
+ perspectiveMatrix[3][3] = 1;
150
+ ANNMatrix inverse;
151
+ if (!ANNMatrixInvert(perspectiveMatrix, inverse)) {
152
+ return NO;
153
+ }
154
+ ANNTransformParts result = {};
155
+ if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0) {
156
+ const double right[4] = {m[0][3], m[1][3], m[2][3], m[3][3]};
157
+ // right · (inverse transposed): each component is a row of the inverse dotted with `right`.
158
+ for (int i = 0; i < 4; i++) {
159
+ double sum = 0;
160
+ for (int j = 0; j < 4; j++) {
161
+ sum += right[j] * inverse[i][j];
162
+ }
163
+ result.perspective[i] = sum;
164
+ }
165
+ } else {
166
+ result.perspective[3] = 1;
167
+ }
168
+ for (int i = 0; i < 3; i++) {
169
+ result.translate[i] = m[3][i];
170
+ }
171
+ double row[3][3];
172
+ for (int i = 0; i < 3; i++) {
173
+ for (int j = 0; j < 3; j++) {
174
+ row[i][j] = m[i][j];
175
+ }
176
+ }
177
+ result.scale[0] = ANNLength(row[0]);
178
+ if (result.scale[0] == 0) {
179
+ return NO;
180
+ }
181
+ ANNCombine(row[0], row[0], 1 / result.scale[0], 0);
182
+ result.skew[0] = ANNDot(row[0], row[1]);
183
+ ANNCombine(row[1], row[0], 1, -result.skew[0]);
184
+ result.scale[1] = ANNLength(row[1]);
185
+ if (result.scale[1] == 0) {
186
+ return NO;
187
+ }
188
+ ANNCombine(row[1], row[1], 1 / result.scale[1], 0);
189
+ result.skew[0] /= result.scale[1];
190
+ result.skew[1] = ANNDot(row[0], row[2]);
191
+ ANNCombine(row[2], row[0], 1, -result.skew[1]);
192
+ result.skew[2] = ANNDot(row[1], row[2]);
193
+ ANNCombine(row[2], row[1], 1, -result.skew[2]);
194
+ result.scale[2] = ANNLength(row[2]);
195
+ if (result.scale[2] == 0) {
196
+ return NO;
197
+ }
198
+ ANNCombine(row[2], row[2], 1 / result.scale[2], 0);
199
+ result.skew[1] /= result.scale[2];
200
+ result.skew[2] /= result.scale[2];
201
+ // The rows are orthonormal now; a mirrored system turns into a rotation with every scale negated. A flat transform
202
+ // (nothing out of the screen's plane) negates only x and keeps its rotation in the plane, as Android's views hold a
203
+ // mirror: it then flips across the element's own axis on the way, on both platforms, rather than through 3D.
204
+ const double cross[3] = {row[1][1] * row[2][2] - row[1][2] * row[2][1],
205
+ row[1][2] * row[2][0] - row[1][0] * row[2][2],
206
+ row[1][0] * row[2][1] - row[1][1] * row[2][0]};
207
+ if (ANNDot(row[0], cross) < 0) {
208
+ const double flatness = std::fabs(m[0][2]) + std::fabs(m[1][2]) + std::fabs(m[2][0]) +
209
+ std::fabs(m[2][1]) + std::fabs(m[0][3]) + std::fabs(m[1][3]) +
210
+ std::fabs(m[2][3]);
211
+ const int negated = flatness < 1e-9 ? 1 : 3;
212
+ for (int i = 0; i < negated; i++) {
213
+ result.scale[i] = -result.scale[i];
214
+ ANNCombine(row[i], row[i], -1, 0);
215
+ }
216
+ }
217
+ // The quaternion by Shepperd's method, from the largest of its four terms: the signs of the others follow from
218
+ // the off-diagonal terms, also for half a turn (w = 0), where the comparisons of the pseudo-code lose them. `r` is
219
+ // the rotation for column vectors, the transpose of the rows.
220
+ auto r = [&row](int i, int j) {
221
+ return row[j][i];
222
+ };
223
+ double *q = result.quaternion;
224
+ double trace = r(0, 0) + r(1, 1) + r(2, 2);
225
+ if (trace > 0) {
226
+ double s = 2 * std::sqrt(trace + 1);
227
+ q[3] = s / 4;
228
+ q[0] = (r(2, 1) - r(1, 2)) / s;
229
+ q[1] = (r(0, 2) - r(2, 0)) / s;
230
+ q[2] = (r(1, 0) - r(0, 1)) / s;
231
+ } else if (r(0, 0) > r(1, 1) && r(0, 0) > r(2, 2)) {
232
+ double s = 2 * std::sqrt(1 + r(0, 0) - r(1, 1) - r(2, 2));
233
+ q[3] = (r(2, 1) - r(1, 2)) / s;
234
+ q[0] = s / 4;
235
+ q[1] = (r(0, 1) + r(1, 0)) / s;
236
+ q[2] = (r(0, 2) + r(2, 0)) / s;
237
+ } else if (r(1, 1) > r(2, 2)) {
238
+ double s = 2 * std::sqrt(1 + r(1, 1) - r(0, 0) - r(2, 2));
239
+ q[3] = (r(0, 2) - r(2, 0)) / s;
240
+ q[0] = (r(0, 1) + r(1, 0)) / s;
241
+ q[1] = s / 4;
242
+ q[2] = (r(1, 2) + r(2, 1)) / s;
243
+ } else {
244
+ double s = 2 * std::sqrt(1 + r(2, 2) - r(0, 0) - r(1, 1));
245
+ q[3] = (r(1, 0) - r(0, 1)) / s;
246
+ q[0] = (r(0, 2) + r(2, 0)) / s;
247
+ q[1] = (r(1, 2) + r(2, 1)) / s;
248
+ q[2] = s / 4;
249
+ }
250
+ *parts = result;
251
+ return YES;
252
+ }
253
+
254
+ // The rotation of a unit quaternion as a matrix of row vectors: the transpose of the decomposition's pseudo-code,
255
+ // whose matrix is written for column vectors there.
256
+ static void ANNRotationMatrixOf(const double q[4], ANNMatrix m) {
257
+ double x = q[0], y = q[1], z = q[2], w = q[3];
258
+ ANNMatrixIdentity(m);
259
+ m[0][0] = 1 - 2 * (y * y + z * z);
260
+ m[0][1] = 2 * (x * y + z * w);
261
+ m[0][2] = 2 * (x * z - y * w);
262
+ m[1][0] = 2 * (x * y - z * w);
263
+ m[1][1] = 1 - 2 * (x * x + z * z);
264
+ m[1][2] = 2 * (y * z + x * w);
265
+ m[2][0] = 2 * (x * z + y * w);
266
+ m[2][1] = 2 * (y * z - x * w);
267
+ m[2][2] = 1 - 2 * (x * x + y * y);
268
+ }
269
+
270
+ // The shears as the decomposition took them off the rows: row 1 gains xy of row 0, row 2 xz of row 0 and yz of row 1.
271
+ static void ANNSkewMatrixOf(const double skew[3], ANNMatrix m) {
272
+ ANNMatrixIdentity(m);
273
+ m[1][0] = skew[0];
274
+ m[2][0] = skew[1];
275
+ m[2][1] = skew[2];
276
+ }
277
+
278
+ CATransform3D ANNTransformOfParts(ANNTransformParts parts) {
279
+ // Built from the last step back: perspective, translation, rotation, skew, then the scale goes first.
280
+ ANNMatrix m;
281
+ ANNMatrixIdentity(m);
282
+ for (int i = 0; i < 4; i++) {
283
+ m[i][3] = parts.perspective[i];
284
+ }
285
+ for (int i = 0; i < 4; i++) {
286
+ for (int j = 0; j < 3; j++) {
287
+ m[3][i] += parts.translate[j] * m[j][i];
288
+ }
289
+ }
290
+ ANNMatrix rotation;
291
+ ANNRotationMatrixOf(parts.quaternion, rotation);
292
+ ANNMatrixMultiply(rotation, m, m);
293
+ ANNMatrix skew;
294
+ ANNSkewMatrixOf(parts.skew, skew);
295
+ ANNMatrixMultiply(skew, m, m);
296
+ for (int i = 0; i < 3; i++) {
297
+ for (int j = 0; j < 4; j++) {
298
+ m[i][j] *= parts.scale[i];
299
+ }
300
+ }
301
+ return ANNTransformOfMatrix(m);
302
+ }
303
+
304
+ static double ANNLerp(double from, double to, double f) {
305
+ return from + f * (to - from);
306
+ }
307
+
308
+ ANNTransformParts ANNInterpolateTransformParts(ANNTransformParts from, ANNTransformParts to,
309
+ double f) {
310
+ if (f == 0) {
311
+ return from;
312
+ }
313
+ if (f == 1) {
314
+ return to;
315
+ }
316
+ ANNTransformParts parts;
317
+ for (int i = 0; i < 3; i++) {
318
+ parts.translate[i] = ANNLerp(from.translate[i], to.translate[i], f);
319
+ parts.scale[i] = ANNLerp(from.scale[i], to.scale[i], f);
320
+ parts.skew[i] = ANNLerp(from.skew[i], to.skew[i], f);
321
+ }
322
+ for (int i = 0; i < 4; i++) {
323
+ parts.perspective[i] = ANNLerp(from.perspective[i], to.perspective[i], f);
324
+ }
325
+ // The slerp, along the shorter arc: q and −q are the same rotation.
326
+ const double *a = from.quaternion;
327
+ double b[4] = {to.quaternion[0], to.quaternion[1], to.quaternion[2], to.quaternion[3]};
328
+ double product = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
329
+ if (product < 0) {
330
+ for (int i = 0; i < 4; i++) {
331
+ b[i] = -b[i];
332
+ }
333
+ product = -product;
334
+ }
335
+ product = std::min(product, 1.0);
336
+ if (product >= 1.0 - 1e-12) {
337
+ for (int i = 0; i < 4; i++) {
338
+ parts.quaternion[i] = ANNLerp(a[i], b[i], f);
339
+ }
340
+ return parts;
341
+ }
342
+ double theta = std::acos(product);
343
+ double sinTheta = std::sqrt(1 - product * product);
344
+ double wa = std::sin((1 - f) * theta) / sinTheta;
345
+ double wb = std::sin(f * theta) / sinTheta;
346
+ for (int i = 0; i < 4; i++) {
347
+ parts.quaternion[i] = a[i] * wa + b[i] * wb;
348
+ }
349
+ return parts;
350
+ }
351
+
352
+ void ANNRotationDegreesOf(ANNTransformParts parts, double *x, double *y, double *z) {
353
+ ANNMatrix r;
354
+ ANNRotationMatrixOf(parts.quaternion, r);
355
+ // r = Rx(a)·Ry(b)·Rz(c) in row vectors: r[0][2] = −sin b, r[1][2] = sin a·cos b, r[2][2] = cos a·cos b,
356
+ // r[0][1] = cos b·sin c, r[0][0] = cos b·cos c.
357
+ double sinB = std::max(-1.0, std::min(1.0, -r[0][2]));
358
+ double b = std::asin(sinB);
359
+ double a;
360
+ double c;
361
+ if (std::fabs(std::cos(b)) > 1e-6) {
362
+ a = std::atan2(r[1][2], r[2][2]);
363
+ c = std::atan2(r[0][1], r[0][0]);
364
+ } else {
365
+ // Turned a quarter about y: x and z turn about one axis, all of it goes to x.
366
+ c = 0;
367
+ a = std::atan2(sinB * r[1][0], r[1][1]);
368
+ }
369
+ const double degrees = 180.0 / M_PI;
370
+ *x = a * degrees;
371
+ *y = b * degrees;
372
+ *z = c * degrees;
373
+ }
374
+
375
+ CATransform3D ANNSkewTransformOf(ANNTransformParts parts) {
376
+ ANNMatrix m;
377
+ ANNSkewMatrixOf(parts.skew, m);
378
+ return ANNTransformOfMatrix(m);
379
+ }
380
+
381
+ #if DEBUG
382
+
383
+ static BOOL ANNSameTransform(CATransform3D a, CATransform3D b, double tolerance) {
384
+ ANNMatrix ma;
385
+ ANNMatrix mb;
386
+ ANNMatrixOf(a, ma);
387
+ ANNMatrixOf(b, mb);
388
+ for (int i = 0; i < 4; i++) {
389
+ for (int j = 0; j < 4; j++) {
390
+ if (!(std::fabs(ma[i][j] - mb[i][j]) <= tolerance)) {
391
+ return NO;
392
+ }
393
+ }
394
+ }
395
+ return YES;
396
+ }
397
+
398
+ static void ANNExpectTransform(const char *what, CATransform3D value, CATransform3D expected) {
399
+ if (!ANNSameTransform(value, expected, 1e-6)) {
400
+ RCTLogWarn(@"[ApexNavigation] transform self-check: %s is off", what);
401
+ }
402
+ }
403
+
404
+ static CATransform3D ANNRotationZ(double degrees) {
405
+ return CATransform3DMakeRotation(degrees * M_PI / 180.0, 0, 0, 1);
406
+ }
407
+
408
+ // The transform at f of the way from `from` to `to`, split and rebuilt.
409
+ static CATransform3D ANNTransformBetween(CATransform3D from, CATransform3D to, double f) {
410
+ ANNTransformParts a;
411
+ ANNTransformParts b;
412
+ if (!ANNTransformPartsOf(from, &a) || !ANNTransformPartsOf(to, &b)) {
413
+ return CATransform3DIdentity;
414
+ }
415
+ return ANNTransformOfParts(ANNInterpolateTransformParts(a, b, f));
416
+ }
417
+
418
+ void ANNTransformPartsSelfCheck(void) {
419
+ static dispatch_once_t once;
420
+ dispatch_once(&once, ^{
421
+ CATransform3D tilt = CATransform3DMakeRotation(40 * M_PI / 180.0, 1, 0, 0);
422
+ tilt.m34 = -1.0 / 500;
423
+ CATransform3D shear = CATransform3DIdentity;
424
+ shear.m21 = 0.3;
425
+ const struct {
426
+ const char *name;
427
+ CATransform3D transform;
428
+ } splits[] = {
429
+ {"a rotation of 90", ANNRotationZ(90)},
430
+ {"a rotation of 180", ANNRotationZ(180)},
431
+ {"a scale, a rotation and a translation",
432
+ CATransform3DConcat(CATransform3DConcat(CATransform3DMakeScale(2, 0.5, 1),
433
+ ANNRotationZ(30)),
434
+ CATransform3DMakeTranslation(12, -7, 0))},
435
+ {"a skew", CATransform3DConcat(shear, ANNRotationZ(-20))},
436
+ {"a tilt with perspective", tilt},
437
+ {"a mirror", CATransform3DMakeScale(-1, 1, 1)},
438
+ {"a mirror and a turn of 30",
439
+ CATransform3DConcat(ANNRotationZ(30), CATransform3DMakeScale(-1, 1, 1))},
440
+ {"a turn of -90 and a mirror",
441
+ CATransform3DConcat(CATransform3DMakeScale(-1, 1, 1), ANNRotationZ(-90))},
442
+ {"a mirror upside down and a turn of -30",
443
+ CATransform3DConcat(ANNRotationZ(-30), CATransform3DMakeScale(1, -1, 1))},
444
+ {"half a turn and a tilt",
445
+ CATransform3DConcat(ANNRotationZ(180),
446
+ CATransform3DMakeRotation(20 * M_PI / 180.0, 1, 0, 0))},
447
+ };
448
+ for (const auto &split : splits) {
449
+ ANNTransformParts parts;
450
+ if (!ANNTransformPartsOf(split.transform, &parts)) {
451
+ RCTLogWarn(@"[ApexNavigation] transform self-check: %s can't be split", split.name);
452
+ continue;
453
+ }
454
+ ANNExpectTransform(split.name, ANNTransformOfParts(parts), split.transform);
455
+ }
456
+ ANNExpectTransform("0 to 90 half way",
457
+ ANNTransformBetween(ANNRotationZ(0), ANNRotationZ(90), 0.5),
458
+ ANNRotationZ(45));
459
+ ANNExpectTransform("45 to -45 half way",
460
+ ANNTransformBetween(ANNRotationZ(45), ANNRotationZ(-45), 0.5),
461
+ CATransform3DIdentity);
462
+ ANNExpectTransform("0 to 270 half way, the shorter arc",
463
+ ANNTransformBetween(ANNRotationZ(0), ANNRotationZ(270), 0.5),
464
+ ANNRotationZ(-45));
465
+ ANNExpectTransform("170 to -170 half way, the shorter arc",
466
+ ANNTransformBetween(ANNRotationZ(170), ANNRotationZ(-170), 0.5),
467
+ ANNRotationZ(180));
468
+ ANNExpectTransform("a scale half way",
469
+ ANNTransformBetween(CATransform3DIdentity,
470
+ CATransform3DMakeScale(3, 2, 1), 0.5),
471
+ CATransform3DMakeScale(2, 1.5, 1));
472
+ // Half a turn keeps its size on the way: a quarter turn, either way, half way.
473
+ CATransform3D half = ANNTransformBetween(ANNRotationZ(0), ANNRotationZ(180), 0.5);
474
+ if (!ANNSameTransform(half, ANNRotationZ(90), 1e-6) &&
475
+ !ANNSameTransform(half, ANNRotationZ(-90), 1e-6)) {
476
+ RCTLogWarn(@"[ApexNavigation] transform self-check: 0 to 180 half way is off");
477
+ }
478
+ // A flat mirror turned keeps its rotation in the plane, the mirror in x, as Android's views hold it.
479
+ ANNTransformParts mirrored;
480
+ CATransform3D mirror =
481
+ CATransform3DConcat(ANNRotationZ(30), CATransform3DMakeScale(-1, 1, 1));
482
+ if (ANNTransformPartsOf(mirror, &mirrored)) {
483
+ BOOL flat = std::fabs(mirrored.quaternion[0]) < 1e-9 &&
484
+ std::fabs(mirrored.quaternion[1]) < 1e-9;
485
+ if (!(mirrored.scale[0] < 0 && mirrored.scale[1] > 0 && flat)) {
486
+ RCTLogWarn(@"[ApexNavigation] transform self-check: a flat mirror leaves the plane");
487
+ }
488
+ }
489
+ // The turns about x, y and z rebuild the rotation in the order of a view's tracks.
490
+ CATransform3D turned = CATransform3DConcat(
491
+ CATransform3DConcat(CATransform3DMakeRotation(25 * M_PI / 180.0, 1, 0, 0),
492
+ CATransform3DMakeRotation(-35 * M_PI / 180.0, 0, 1, 0)),
493
+ ANNRotationZ(120));
494
+ ANNTransformParts turnedParts;
495
+ if (ANNTransformPartsOf(turned, &turnedParts)) {
496
+ double x = 0, y = 0, z = 0;
497
+ ANNRotationDegreesOf(turnedParts, &x, &y, &z);
498
+ CATransform3D rebuilt = CATransform3DConcat(
499
+ CATransform3DConcat(CATransform3DMakeRotation(x * M_PI / 180.0, 1, 0, 0),
500
+ CATransform3DMakeRotation(y * M_PI / 180.0, 0, 1, 0)),
501
+ ANNRotationZ(z));
502
+ ANNExpectTransform("the turns about x, y and z", rebuilt, turned);
503
+ }
504
+ });
505
+ }
506
+
507
+ #endif
@@ -17,14 +17,17 @@ FOUNDATION_EXPORT CGFloat ANNCameraDistance(void);
17
17
  /// `rotationY`, `rotation` (clockwise, degrees), the perspective, the translation.
18
18
  ///
19
19
  /// A missing end is the view's value when the tracks are made: `x`, `y` its place in its parent (from its layer's
20
- /// position and bounds, never its frame), the translations 0, `alpha` its alpha before any hide, the scales 1, the
21
- /// rotations 0. Each frame writes only what plays: `alpha` only with an `alpha` track, `layer.transform` only when a
22
- /// property of the transform plays; with `translationX` and `x` on one side the translation wins. The frame is never
23
- /// changed (React keeps the layout). `restore` puts back the alpha and the transform as they were read.
20
+ /// position and bounds, never its frame) moved by its own translation, `alpha` its alpha before any hide, the
21
+ /// translations, scales and rotations those of its own transform (React Native's `transform`, split into its parts as
22
+ /// Android's views hold it: the shorter angle, −180…180). A property that doesn't play keeps the view's own value, its
23
+ /// skew and perspective stay. Only what plays animates, in Core Animation (`ANNKeyframes`): `opacity` only with an
24
+ /// `alpha` track, `transform` only when a property of the transform plays; with `translationX` and `x` on one side the
25
+ /// translation wins. The view's own values (its frame, alpha and transform) are never written: the animations show
26
+ /// over them, and `restore` removes the animations.
24
27
  @interface ANNViewTracks : NSObject <ANNFrameClient>
25
28
 
26
29
  /// The playing properties of `side` on `view`. `alphaBefore`: the view's alpha before the core hid it for the
27
- /// transition (the arriving screen), else its alpha now; it is also what `restore` puts back.
30
+ /// transition (the arriving screen), else its alpha now.
28
31
  - (instancetype)initWithView:(UIView *)view
29
32
  side:(ANNViewAnimationOptions *)side
30
33
  alphaBefore:(CGFloat)alphaBefore;
@@ -33,7 +36,7 @@ FOUNDATION_EXPORT CGFloat ANNCameraDistance(void);
33
36
  /// disappearing from it to `to`, or both ends given.
34
37
  - (instancetype)initWithView:(UIView *)view element:(ANNElementTransitionOptions *)element;
35
38
 
36
- /// A linear fade of `view`'s alpha (a dismissed popover with nothing to play); `restore` puts back `alphaBefore`.
39
+ /// A linear fade of `view`'s alpha (a dismissed popover with nothing to play, a transition under Reduce Motion).
37
40
  - (instancetype)initWithView:(UIView *)view
38
41
  fadeFrom:(CGFloat)from
39
42
  to:(CGFloat)to