@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
@@ -3,19 +3,25 @@
3
3
  #import "ANNInterpolate.h"
4
4
  #import "ANNSharedElementTransitionOptions.h"
5
5
  #import "ANNTrack.h"
6
+ #import "ANNTransformParts.h"
6
7
  #import "ANNUtils.h"
7
8
  #import <React/RCTViewComponentView.h>
8
9
  #import <react/renderer/components/view/ViewProps.h>
10
+ #include <cmath>
9
11
 
10
12
  // How close two rectangles count as the same (points): a visible part that is the whole element needs no mask.
11
13
  static const CGFloat ANNSameRectTolerance = 0.5;
12
14
 
13
15
  // One end of a flight: the place, the size, the transform, the corners and the visible part of a React view, in the
14
- // container's coordinates.
16
+ // container's coordinates. The transform is the whole one the view is drawn with there (its own and its parents'),
17
+ // about its center; once split, its scale goes into the size, the corners and the visible part, so the size the copy
18
+ // shows changes evenly on the way.
15
19
  typedef struct {
16
20
  CGPoint center;
17
21
  CGSize size;
18
22
  CATransform3D transform;
23
+ // The transform's parts, which the flight interpolates; their scale is only its sign once the scale is in the size.
24
+ ANNTransformParts parts;
19
25
  CGFloat cornerRadius;
20
26
  // The part the clipping parents leave visible, in the copy's coordinates, and its corners.
21
27
  CGRect visible;
@@ -23,6 +29,21 @@ typedef struct {
23
29
  BOOL clipped;
24
30
  } ANNFlightEnd;
25
31
 
32
+ // What the copy shows at one time: its size, center, transform and corners, its two pictures' frames and alphas, and
33
+ // its visible part (in the copy's coordinates) with its corners.
34
+ typedef struct {
35
+ CGSize size;
36
+ CGPoint center;
37
+ CATransform3D transform;
38
+ CGFloat cornerRadius;
39
+ CGRect fromFrame;
40
+ CGRect toFrame;
41
+ CGFloat fromAlpha;
42
+ CGFloat toAlpha;
43
+ CGRect mask;
44
+ CGFloat maskRadius;
45
+ } ANNFlightState;
46
+
26
47
  static BOOL ANNIsText(UIView *view) {
27
48
  static Class paragraph;
28
49
  static dispatch_once_t once;
@@ -71,12 +92,44 @@ static CGFloat ANNCornerRadiusOf(UIView *view) {
71
92
  return 0;
72
93
  }
73
94
 
95
+ // The anchor of a layer in the coordinates of its bounds.
96
+ static CGPoint ANNAnchorInBounds(CALayer *layer) {
97
+ CGRect bounds = layer.bounds;
98
+ return CGPointMake(bounds.origin.x + layer.anchorPoint.x * bounds.size.width,
99
+ bounds.origin.y + layer.anchorPoint.y * bounds.size.height);
100
+ }
101
+
102
+ // What takes a point of the layer, counted from its anchor, to the top of its tree: its transform and place, then each
103
+ // superlayer's `sublayerTransform`, transform and place the same way (a layer's transforms turn about its anchor).
104
+ static CATransform3D ANNTransformToTop(CALayer *layer) {
105
+ CATransform3D transform = CATransform3DConcat(
106
+ layer.transform, CATransform3DMakeTranslation(layer.position.x, layer.position.y, 0));
107
+ for (CALayer *parent = layer.superlayer; parent; parent = parent.superlayer) {
108
+ CGPoint anchor = ANNAnchorInBounds(parent);
109
+ transform = CATransform3DConcat(transform,
110
+ CATransform3DMakeTranslation(-anchor.x, -anchor.y, 0));
111
+ transform = CATransform3DConcat(transform, parent.sublayerTransform);
112
+ transform = CATransform3DConcat(transform, parent.transform);
113
+ transform = CATransform3DConcat(
114
+ transform, CATransform3DMakeTranslation(parent.position.x, parent.position.y, 0));
115
+ }
116
+ return transform;
117
+ }
118
+
74
119
  static ANNFlightEnd ANNFlightEndOf(UIView *view, UIView *screenRoot, UIView *container) {
75
120
  ANNFlightEnd end;
76
121
  CALayer *layer = view.layer;
77
122
  end.size = layer.bounds.size;
78
- end.center = [view.superview convertPoint:layer.position toView:container];
79
- end.transform = layer.transform;
123
+ // From the view's center to the container's bounds: up to the top, then down into the container.
124
+ CGPoint containerAnchor = ANNAnchorInBounds(container.layer);
125
+ CATransform3D toContainer =
126
+ CATransform3DConcat(CATransform3DInvert(ANNTransformToTop(container.layer)),
127
+ CATransform3DMakeTranslation(containerAnchor.x, containerAnchor.y, 0));
128
+ CATransform3D whole = CATransform3DConcat(ANNTransformToTop(layer), toContainer);
129
+ // The center is where the view's center lands; the rest of the transform turns about it.
130
+ end.center = CGPointMake(whole.m41 / whole.m44, whole.m42 / whole.m44);
131
+ end.transform = CATransform3DConcat(
132
+ whole, CATransform3DMakeTranslation(-end.center.x, -end.center.y, 0));
80
133
  end.cornerRadius = ANNCornerRadiusOf(view);
81
134
  // The visible part: the element's bounds cut by every parent that clips (`overflow: hidden`, a scroll view) up to
82
135
  // the screen's root, in the element's own coordinates, moved to the copy's (its bounds start at 0, 0).
@@ -122,6 +175,28 @@ static BOOL ANNFlightEndIsFinite(ANNFlightEnd end) {
122
175
  ANNIsFiniteRect(end.visible);
123
176
  }
124
177
 
178
+ // The parts of the end's transform, its scale moved into the size, the corners and the visible part (a mirror keeps
179
+ // its sign); NO when the transform flattens the view.
180
+ static BOOL ANNSplitFlightEnd(ANNFlightEnd *end) {
181
+ ANNTransformParts parts;
182
+ if (!ANNTransformPartsOf(end->transform, &parts)) {
183
+ return NO;
184
+ }
185
+ CGFloat scaleX = (CGFloat)std::fabs(parts.scale[0]);
186
+ CGFloat scaleY = (CGFloat)std::fabs(parts.scale[1]);
187
+ CGFloat scale = MIN(scaleX, scaleY);
188
+ parts.scale[0] = std::copysign(1.0, parts.scale[0]);
189
+ parts.scale[1] = std::copysign(1.0, parts.scale[1]);
190
+ end->parts = parts;
191
+ end->size = CGSizeMake(end->size.width * scaleX, end->size.height * scaleY);
192
+ end->cornerRadius *= scale;
193
+ end->visibleRadius *= scale;
194
+ end->visible = CGRectMake(end->visible.origin.x * scaleX, end->visible.origin.y * scaleY,
195
+ end->visible.size.width * scaleX,
196
+ end->visible.size.height * scaleY);
197
+ return YES;
198
+ }
199
+
125
200
  // The picture of the view's layer and its sublayers at the screen's scale, in the layer's own coordinates.
126
201
  static UIImage *ANNPictureOf(UIView *view) {
127
202
  CGSize size = view.bounds.size;
@@ -140,6 +215,30 @@ static UIImage *ANNPictureOf(UIView *view) {
140
215
  }];
141
216
  }
142
217
 
218
+ // A layer at `frame` in its superlayer: its bounds and its position (its anchor is its center).
219
+ static void ANNPlaceLayer(CALayer *layer, CGRect frame) {
220
+ layer.bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
221
+ layer.position = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
222
+ }
223
+
224
+ // The core's animation of `keyPath` on `layer` (`ANNKeyframes`), under its key.
225
+ static void ANNAddKeyframes(CALayer *layer, NSString *keyPath, NSArray *values,
226
+ NSArray<NSNumber *> *times, NSTimeInterval length) {
227
+ CAKeyframeAnimation *animation = ANNKeyframes(keyPath, values, times, length);
228
+ if (animation) {
229
+ [layer addAnimation:animation forKey:ANNAnimationKey(keyPath)];
230
+ }
231
+ }
232
+
233
+ // The bounds and the position of a layer at `frame`, as values of its animations.
234
+ static NSValue *ANNBoundsValue(CGRect frame) {
235
+ return [NSValue valueWithCGRect:CGRectMake(0, 0, frame.size.width, frame.size.height)];
236
+ }
237
+
238
+ static NSValue *ANNPositionValue(CGRect frame) {
239
+ return [NSValue valueWithCGPoint:CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame))];
240
+ }
241
+
143
242
  @implementation ANNSharedElementFlight {
144
243
  __weak UIView *_fromView;
145
244
  __weak UIView *_toView;
@@ -148,7 +247,9 @@ static UIImage *ANNPictureOf(UIView *view) {
148
247
  UIView *_copy;
149
248
  UIImageView *_fromPicture;
150
249
  UIImageView *_toPicture;
151
- CAShapeLayer *_mask;
250
+ // The visible part of the copy: a plain layer with corners, as Core Animation can't animate a path whose corners
251
+ // change.
252
+ CALayer *_mask;
152
253
  ANNFlightEnd _from;
153
254
  ANNFlightEnd _to;
154
255
  ANNTrack *_track;
@@ -251,6 +352,11 @@ static UIImage *ANNPictureOf(UIView *view) {
251
352
  ANNElementSkipped(name, @"the place of a view of the pair can't be worked out");
252
353
  return nil;
253
354
  }
355
+ // A transform that flattens the view (a scale of 0) has no parts to fly between.
356
+ if (!ANNSplitFlightEnd(&_from) || !ANNSplitFlightEnd(&_to)) {
357
+ ANNElementSkipped(name, @"the transform of a view of the pair flattens it");
358
+ return nil;
359
+ }
254
360
  _text = ANNIsText(from) || ANNIsText(to);
255
361
  _grows = _to.size.height >= _from.size.height;
256
362
  _rightToLeft =
@@ -278,7 +384,8 @@ static UIImage *ANNPictureOf(UIView *view) {
278
384
  // A text's pictures are neither clipped nor masked.
279
385
  _copy.clipsToBounds = !_text;
280
386
  if (!_text && (_from.clipped || _to.clipped)) {
281
- _mask = [CAShapeLayer layer];
387
+ _mask = [CALayer layer];
388
+ _mask.backgroundColor = UIColor.blackColor.CGColor;
282
389
  _copy.layer.mask = _mask;
283
390
  }
284
391
  [_copy addSubview:_fromPicture];
@@ -295,71 +402,168 @@ static UIImage *ANNPictureOf(UIView *view) {
295
402
  [container addSubview:_copy];
296
403
  from.hidden = YES;
297
404
  to.hidden = YES;
298
- [self applyAtTime:0];
405
+ [self placeAtTime:0];
299
406
  }
300
407
 
301
408
  - (UIView *)copyView {
302
409
  return _copy;
303
410
  }
304
411
 
305
- #pragma mark - ANNFrameClient
306
-
307
- - (NSTimeInterval)endTime {
308
- return _track.endTime;
309
- }
310
-
311
- - (void)applyAtTime:(NSTimeInterval)time {
312
- if (_restored) {
313
- return;
314
- }
412
+ // The copy's whole state at `time`: its own geometry, its pictures' and its visible part's.
413
+ - (ANNFlightState)stateAtTime:(NSTimeInterval)time {
414
+ ANNFlightState state;
315
415
  double f = [_track fractionAt:time];
316
- CGSize size = ANNInterpolateSize(_from.size, _to.size, f);
317
- _copy.layer.transform = CATransform3DIdentity;
318
- _copy.bounds = CGRectMake(0, 0, size.width, size.height);
319
- _copy.center = ANNInterpolatePoint(_from.center, _to.center, f);
320
- _copy.layer.transform = ANNInterpolateTransform(_from.transform, _to.transform, f);
416
+ state.size = ANNInterpolateSize(_from.size, _to.size, f);
417
+ state.center = ANNInterpolatePoint(_from.center, _to.center, f);
418
+ state.transform = ANNTransformOfParts(ANNInterpolateTransformParts(_from.parts, _to.parts, f));
419
+ state.cornerRadius = 0;
420
+ state.mask = CGRectZero;
421
+ state.maskRadius = 0;
321
422
  if (_text) {
322
- [self placeTextPicturesAtTime:time size:size];
323
- return;
423
+ [self placeTextPicturesOf:&state atTime:time];
424
+ return state;
324
425
  }
325
- _copy.layer.cornerRadius = ANNInterpolateNumber(_from.cornerRadius, _to.cornerRadius, f);
326
- _fromPicture.frame = _copy.bounds;
327
- _toPicture.frame = _copy.bounds;
328
- _fromPicture.alpha = 1;
329
- _toPicture.alpha = (CGFloat)f;
426
+ state.cornerRadius = ANNInterpolateNumber(_from.cornerRadius, _to.cornerRadius, f);
427
+ CGRect whole = CGRectMake(0, 0, state.size.width, state.size.height);
428
+ state.fromFrame = whole;
429
+ state.toFrame = whole;
430
+ state.fromAlpha = 1;
431
+ state.toAlpha = (CGFloat)f;
330
432
  if (_mask) {
331
433
  CGRect fromWhole = CGRectMake(0, 0, _from.size.width, _from.size.height);
332
434
  CGRect toWhole = CGRectMake(0, 0, _to.size.width, _to.size.height);
333
435
  CGRect fromVisible = _from.clipped ? _from.visible : fromWhole;
334
436
  CGRect toVisible = _to.clipped ? _to.visible : toWhole;
335
- CGRect visible = ANNInterpolateRect(fromVisible, toVisible, f);
437
+ state.mask = ANNInterpolateRect(fromVisible, toVisible, f);
438
+ // At most half the shorter side, as a rounded path has it.
336
439
  CGFloat radius = ANNInterpolateNumber(_from.visibleRadius, _to.visibleRadius, f);
337
- _mask.frame = _copy.bounds;
338
- _mask.path = [UIBezierPath bezierPathWithRoundedRect:visible cornerRadius:radius].CGPath;
440
+ CGFloat half = MIN(state.mask.size.width, state.mask.size.height) / 2;
441
+ state.maskRadius = MAX(MIN(radius, half), 0);
339
442
  }
443
+ return state;
340
444
  }
341
445
 
342
446
  // The text's pictures keep their aspect at the height of the copy, at the line's start; they swap by the clock,
343
447
  // linearly, in the first quarter of the flight when the text grows, in the last when it shrinks.
344
- - (void)placeTextPicturesAtTime:(NSTimeInterval)time size:(CGSize)size {
345
- for (UIImageView *picture in @[ _fromPicture, _toPicture ]) {
346
- CGSize imageSize = picture.image.size;
347
- CGFloat height = size.height;
448
+ - (void)placeTextPicturesOf:(ANNFlightState *)state atTime:(NSTimeInterval)time {
449
+ CGRect frames[2];
450
+ UIImageView *pictures[2] = {_fromPicture, _toPicture};
451
+ for (int index = 0; index < 2; index++) {
452
+ CGSize imageSize = pictures[index].image.size;
453
+ CGFloat height = state->size.height;
348
454
  CGFloat width = imageSize.height > 0 ? imageSize.width * height / imageSize.height : 0;
349
- CGFloat x = _rightToLeft ? size.width - width : 0;
350
- picture.frame = CGRectMake(x, 0, width, height);
455
+ CGFloat x = _rightToLeft ? state->size.width - width : 0;
456
+ frames[index] = CGRectMake(x, 0, width, height);
351
457
  }
458
+ state->fromFrame = frames[0];
459
+ state->toFrame = frames[1];
460
+ double swap = [self swapAtTime:time];
461
+ state->fromAlpha = (CGFloat)(1 - swap);
462
+ state->toAlpha = (CGFloat)swap;
463
+ }
464
+
465
+ // The quarter of the flight the text's pictures swap in.
466
+ - (NSTimeInterval)swapStart {
352
467
  NSTimeInterval duration = _track.duration;
353
- NSTimeInterval quarter = duration / 4;
354
- NSTimeInterval start = _track.delay + (_grows ? 0 : duration - quarter);
355
- double swap;
468
+ return _track.delay + (_grows ? 0 : duration - duration / 4);
469
+ }
470
+
471
+ - (double)swapAtTime:(NSTimeInterval)time {
472
+ NSTimeInterval quarter = _track.duration / 4;
356
473
  if (quarter <= 0) {
357
- swap = time >= _track.delay ? 1 : 0;
358
- } else {
359
- swap = MIN(MAX((time - start) / quarter, 0.0), 1.0);
474
+ return time >= _track.delay ? 1 : 0;
475
+ }
476
+ return MIN(MAX((time - [self swapStart]) / quarter, 0.0), 1.0);
477
+ }
478
+
479
+ // The copy shows its state at `time` (its own values, with no animation).
480
+ - (void)placeAtTime:(NSTimeInterval)time {
481
+ ANNFlightState state = [self stateAtTime:time];
482
+ [CATransaction begin];
483
+ [CATransaction setDisableActions:YES];
484
+ _copy.layer.transform = CATransform3DIdentity;
485
+ _copy.bounds = CGRectMake(0, 0, state.size.width, state.size.height);
486
+ _copy.center = state.center;
487
+ _copy.layer.transform = state.transform;
488
+ if (!_text) {
489
+ _copy.layer.cornerRadius = state.cornerRadius;
490
+ }
491
+ ANNPlaceLayer(_fromPicture.layer, state.fromFrame);
492
+ ANNPlaceLayer(_toPicture.layer, state.toFrame);
493
+ _fromPicture.alpha = state.fromAlpha;
494
+ _toPicture.alpha = state.toAlpha;
495
+ if (_mask) {
496
+ ANNPlaceLayer(_mask, state.mask);
497
+ _mask.cornerRadius = state.maskRadius;
498
+ }
499
+ [CATransaction commit];
500
+ }
501
+
502
+ #pragma mark - ANNFrameClient
503
+
504
+ - (NSTimeInterval)endTime {
505
+ return _track.endTime;
506
+ }
507
+
508
+ - (void)addAnimationsWithLength:(NSTimeInterval)length {
509
+ if (_restored) {
510
+ return;
511
+ }
512
+ NSMutableArray<NSNumber *> *marks =
513
+ [NSMutableArray arrayWithObjects:@(_track.delay), @(_track.endTime), nil];
514
+ if (_text) {
515
+ [marks addObject:@([self swapStart])];
516
+ [marks addObject:@([self swapStart] + _track.duration / 4)];
517
+ }
518
+ NSArray<NSNumber *> *times = ANNSampleTimes(_track.endTime, length, marks);
519
+ NSMutableArray *bounds = [NSMutableArray new];
520
+ NSMutableArray *positions = [NSMutableArray new];
521
+ NSMutableArray *transforms = [NSMutableArray new];
522
+ NSMutableArray *radii = [NSMutableArray new];
523
+ NSMutableArray *fromBounds = [NSMutableArray new];
524
+ NSMutableArray *fromPositions = [NSMutableArray new];
525
+ NSMutableArray *fromAlphas = [NSMutableArray new];
526
+ NSMutableArray *toBounds = [NSMutableArray new];
527
+ NSMutableArray *toPositions = [NSMutableArray new];
528
+ NSMutableArray *toAlphas = [NSMutableArray new];
529
+ NSMutableArray *maskBounds = [NSMutableArray new];
530
+ NSMutableArray *maskPositions = [NSMutableArray new];
531
+ NSMutableArray *maskRadii = [NSMutableArray new];
532
+ for (NSNumber *time in times) {
533
+ ANNFlightState state = [self stateAtTime:time.doubleValue];
534
+ CGRect whole = CGRectMake(0, 0, state.size.width, state.size.height);
535
+ [bounds addObject:ANNBoundsValue(whole)];
536
+ [positions addObject:[NSValue valueWithCGPoint:state.center]];
537
+ [transforms addObject:[NSValue valueWithCATransform3D:state.transform]];
538
+ [radii addObject:@(state.cornerRadius)];
539
+ [fromBounds addObject:ANNBoundsValue(state.fromFrame)];
540
+ [fromPositions addObject:ANNPositionValue(state.fromFrame)];
541
+ [fromAlphas addObject:@(state.fromAlpha)];
542
+ [toBounds addObject:ANNBoundsValue(state.toFrame)];
543
+ [toPositions addObject:ANNPositionValue(state.toFrame)];
544
+ [toAlphas addObject:@(state.toAlpha)];
545
+ [maskBounds addObject:ANNBoundsValue(state.mask)];
546
+ [maskPositions addObject:ANNPositionValue(state.mask)];
547
+ [maskRadii addObject:@(state.maskRadius)];
548
+ }
549
+ CALayer *copy = _copy.layer;
550
+ ANNAddKeyframes(copy, @"bounds", bounds, times, length);
551
+ ANNAddKeyframes(copy, @"position", positions, times, length);
552
+ ANNAddKeyframes(copy, @"transform", transforms, times, length);
553
+ if (!_text) {
554
+ ANNAddKeyframes(copy, @"cornerRadius", radii, times, length);
555
+ }
556
+ ANNAddKeyframes(_fromPicture.layer, @"bounds", fromBounds, times, length);
557
+ ANNAddKeyframes(_fromPicture.layer, @"position", fromPositions, times, length);
558
+ ANNAddKeyframes(_fromPicture.layer, @"opacity", fromAlphas, times, length);
559
+ ANNAddKeyframes(_toPicture.layer, @"bounds", toBounds, times, length);
560
+ ANNAddKeyframes(_toPicture.layer, @"position", toPositions, times, length);
561
+ ANNAddKeyframes(_toPicture.layer, @"opacity", toAlphas, times, length);
562
+ if (_mask) {
563
+ ANNAddKeyframes(_mask, @"bounds", maskBounds, times, length);
564
+ ANNAddKeyframes(_mask, @"position", maskPositions, times, length);
565
+ ANNAddKeyframes(_mask, @"cornerRadius", maskRadii, times, length);
360
566
  }
361
- _fromPicture.alpha = (CGFloat)(1 - swap);
362
- _toPicture.alpha = (CGFloat)swap;
363
567
  }
364
568
 
365
569
  - (void)restore {
@@ -5,7 +5,8 @@ NS_ASSUME_NONNULL_BEGIN
5
5
 
6
6
  // The interpolation of values: from + f·(to − from) per component, where f is the share of the way a track gives
7
7
  // (`ANNTrack fractionAt:`); exactly `from` at f = 0 and exactly `to` at f = 1, whatever the floating point would give.
8
- // iOS never interpolates colors: a shared element flies as pictures.
8
+ // iOS never interpolates colors: a shared element flies as pictures. A transform goes by its parts
9
+ // (`ANNTransformParts`).
9
10
 
10
11
  /// A number.
11
12
  static inline CGFloat ANNInterpolateNumber(CGFloat from, CGFloat to, double f) {
@@ -37,33 +38,4 @@ static inline CGRect ANNInterpolateRect(CGRect from, CGRect to, double f) {
37
38
  return CGRectMake(origin.x, origin.y, size.width, size.height);
38
39
  }
39
40
 
40
- /// A 4×4 transform, element by element (a shared element with a `transform` style, as iOS does it now).
41
- static inline CATransform3D ANNInterpolateTransform(CATransform3D from, CATransform3D to,
42
- double f) {
43
- if (f == 0) {
44
- return from;
45
- }
46
- if (f == 1) {
47
- return to;
48
- }
49
- CATransform3D t;
50
- t.m11 = ANNInterpolateNumber(from.m11, to.m11, f);
51
- t.m12 = ANNInterpolateNumber(from.m12, to.m12, f);
52
- t.m13 = ANNInterpolateNumber(from.m13, to.m13, f);
53
- t.m14 = ANNInterpolateNumber(from.m14, to.m14, f);
54
- t.m21 = ANNInterpolateNumber(from.m21, to.m21, f);
55
- t.m22 = ANNInterpolateNumber(from.m22, to.m22, f);
56
- t.m23 = ANNInterpolateNumber(from.m23, to.m23, f);
57
- t.m24 = ANNInterpolateNumber(from.m24, to.m24, f);
58
- t.m31 = ANNInterpolateNumber(from.m31, to.m31, f);
59
- t.m32 = ANNInterpolateNumber(from.m32, to.m32, f);
60
- t.m33 = ANNInterpolateNumber(from.m33, to.m33, f);
61
- t.m34 = ANNInterpolateNumber(from.m34, to.m34, f);
62
- t.m41 = ANNInterpolateNumber(from.m41, to.m41, f);
63
- t.m42 = ANNInterpolateNumber(from.m42, to.m42, f);
64
- t.m43 = ANNInterpolateNumber(from.m43, to.m43, f);
65
- t.m44 = ANNInterpolateNumber(from.m44, to.m44, f);
66
- return t;
67
- }
68
-
69
41
  NS_ASSUME_NONNULL_END
@@ -0,0 +1,48 @@
1
+ #import <QuartzCore/QuartzCore.h>
2
+ #import <UIKit/UIKit.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ /// A 4×4 transform split into the parts it is made of (the decomposition of CSS Transforms Level 2): applied to a point
7
+ /// in the order scale, skew, rotation, translation, perspective. Two transforms interpolate part by part, the rotation
8
+ /// along the shorter arc between the two (a quaternion's slerp), so a rotation never collapses on the way.
9
+ typedef struct {
10
+ double translate[3];
11
+ double scale[3];
12
+ /// The shears xy, xz, yz.
13
+ double skew[3];
14
+ double perspective[4];
15
+ /// x, y, z, w.
16
+ double quaternion[4];
17
+ } ANNTransformParts;
18
+
19
+ /// The parts of no transform.
20
+ FOUNDATION_EXPORT ANNTransformParts ANNTransformPartsIdentity(void);
21
+
22
+ /// The parts of `transform` into `parts`; NO when it can't be split (a scale of 0 flattens it).
23
+ FOUNDATION_EXPORT BOOL ANNTransformPartsOf(CATransform3D transform, ANNTransformParts *parts);
24
+
25
+ /// The transform the parts make.
26
+ FOUNDATION_EXPORT CATransform3D ANNTransformOfParts(ANNTransformParts parts);
27
+
28
+ /// The parts at `f` of the way: each number from + f·(to − from), the rotation by slerp along the shorter arc; exactly
29
+ /// `from` at f = 0 and `to` at f = 1. Two rotations half a turn apart go either way.
30
+ FOUNDATION_EXPORT ANNTransformParts ANNInterpolateTransformParts(ANNTransformParts from,
31
+ ANNTransformParts to, double f);
32
+
33
+ /// The rotation of the parts as the turns about x, then y, then z (degrees, each in −180…180), the order a view's
34
+ /// tracks compose them in (`ANNViewTracks`).
35
+ FOUNDATION_EXPORT void ANNRotationDegreesOf(ANNTransformParts parts, double *x, double *y,
36
+ double *z);
37
+
38
+ /// The shears of the parts as a transform of their own (the scale, rotation and the rest aside).
39
+ FOUNDATION_EXPORT CATransform3D ANNSkewTransformOf(ANNTransformParts parts);
40
+
41
+ #if DEBUG
42
+ /// Development only (there is no iOS test target): splits and rebuilds known transforms and checks the rotations a
43
+ /// shared element takes (0° → 90°, 0° → 180°, 45° → −45°, 270°, 170° → −170°, a scale, a tilt), once; a mismatch is
44
+ /// logged.
45
+ FOUNDATION_EXPORT void ANNTransformPartsSelfCheck(void);
46
+ #endif
47
+
48
+ NS_ASSUME_NONNULL_END