@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
@@ -2,7 +2,8 @@
2
2
  # ApexNavigation): the Objective-C++ core and modules under ios/, with the public headers of ios/Public/ApexNavigation
3
3
  # (<ApexNavigation/ApexNavigation.h>, <ApexNavigation/ANNAppDelegate.h>, <ApexNavigation/ANNSceneDelegate.h>). Other
4
4
  # headers stay private to the pod and are imported by bare name. The C++ of the Fabric components ANNSlot and
5
- # ANNSafeAreaView is header-only, under ios/cpp, next to the code React Native's codegen makes from src/.
5
+ # ANNSafeAreaView is under ios/cpp, next to the code React Native's codegen makes from src/: headers, and one source
6
+ # file with the store of the slots' measured heights.
6
7
  require "json"
7
8
 
8
9
  package = JSON.parse(File.read(File.join(__dir__, "package.json")))
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.0-alpha.7](https://github.com/apexnative/navigation/compare/v1.0.0-alpha.6...v1.0.0-alpha.7) (2026-10-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * own android sheet and bar row, ios transitions in core animation, fast refresh of screens ([#56](https://github.com/apexnative/navigation/issues/56)) ([3113b42](https://github.com/apexnative/navigation/commit/3113b42a466f59490faaca181178a7840dab2826))
9
+
10
+ ## [1.0.0-alpha.6](https://github.com/apexnative/navigation/compare/v1.0.0-alpha.5...v1.0.0-alpha.6) (2026-10-25)
11
+
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * leave the bottom edge of a screen free by default ([#49](https://github.com/apexnative/navigation/issues/49))
16
+
17
+ ### Features
18
+
19
+ * a sheet's back preview on android, lighter tabs and top bar, the compatibility mode on ios 27 ([#46](https://github.com/apexnative/navigation/issues/46)) ([24d333d](https://github.com/apexnative/navigation/commit/24d333dd43fc5e056786f22dc8d7f1a0ff82a1ad))
20
+ * leave the bottom edge of a screen free by default ([#49](https://github.com/apexnative/navigation/issues/49)) ([b6bb165](https://github.com/apexnative/navigation/commit/b6bb165152114fb2886bd3c4ee55560c418f0cbe))
21
+ * **tabs:** choose whether a tab switch animates with bottomTabs.switchAnimation ([#52](https://github.com/apexnative/navigation/issues/52)) ([c6185b6](https://github.com/apexnative/navigation/commit/c6185b6b42574cff671def1ebdf8aa4f5e4be681))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * an explicit top edge stays free under a large title ([#53](https://github.com/apexnative/navigation/issues/53)) ([188a89e](https://github.com/apexnative/navigation/commit/188a89e8d160c071f91cc010ed43ccc0683e12b3))
27
+ * shared elements fly turned and scaled views the same way on ios and android ([#50](https://github.com/apexnative/navigation/issues/50)) ([bf63ab6](https://github.com/apexnative/navigation/commit/bf63ab624d33ff9295af297ce6506206b1bfa0e6))
28
+ * the custom tab row moves with its tabs on android, and tab cells get selected and badge ([#51](https://github.com/apexnative/navigation/issues/51)) ([fd8f41d](https://github.com/apexnative/navigation/commit/fd8f41d2efd108741672220c54253a86704929a5))
29
+
30
+
31
+ ### Performance Improvements
32
+
33
+ * **ios:** render a preview's screen when a press on its view starts ([#48](https://github.com/apexnative/navigation/issues/48)) ([4a57d1a](https://github.com/apexnative/navigation/commit/4a57d1aee1df7690dbde4c7d08dca2a70773d1f5))
34
+
3
35
  ## [1.0.0-alpha.5](https://github.com/apexnative/navigation/compare/v1.0.0-alpha.4...v1.0.0-alpha.5) (2026-10-23)
4
36
 
5
37
 
package/README.md CHANGED
@@ -97,7 +97,7 @@ navigation.push('Details', { props: { title: 'Order 42' } });
97
97
  each other: tabs of stacks, a stack in a modal, tabs in a side menu.
98
98
  - **Screen UI as options:** the top bar, bar buttons, search, the toolbar and the floating action button, the status
99
99
  bar and the system bars.
100
- - **No safe area code:** every screen keeps its content clear of the bars, the cutout and the home indicator by itself.
100
+ - **No safe area code:** every screen keeps its top and sides clear of the bars and the cutout by itself; the bottom is free, and a list adds `useSafeAreaInsets().bottom`.
101
101
  - **Native screens:** SwiftUI, UIKit and Compose screens are pushed, presented and put in tabs the same way as React
102
102
  screens.
103
103
  - **One React tree when you want it:** each screen is its own React root by default; with `appProvider` all screens
package/android/CLAUDE.md CHANGED
@@ -22,8 +22,9 @@ top-level folder. Main thread only, unless a line says otherwise.
22
22
  `Variant`, `ThemeColour`); `parsers/` reads them tolerantly from React Native data.
23
23
  - `react/`: the way in and out: `NavigationTurboModule`, `CommandRunner`, `CommandAnswer`, `ErrorTexts`,
24
24
  `OptionsCommands`, `PendingCalls` (a task behind the calls JavaScript made), `ReloadCoordinator`, `ReactGateway`,
25
- `ReactView` (a React root), the stores (`ScreenInsets`, `ScreenRegions`, `ArrangementStates`, `Hinge`, `StartInfo`),
26
- `LaunchLink`, `ScrollEvents`.
25
+ `ReactView` (a React root), `ContentHeights` (content measured without a height limit, through JNI), the stores
26
+ (`ScreenEnvironment`: a screen's insets, padding, regions and pair state; `Hinge`, `StartInfo`), `ScreenRegions`
27
+ (measures a screen's regions), `LaunchLink`, `ScrollEvents`.
27
28
  - `react/events/`: `AppearanceDispatcher`, `ScreenAppearance`, `EventEmitter`, `EventContract` (made by
28
29
  `scripts/contract.mjs`), `NavigationState`, `ComponentType`.
29
30
  - `viewcontrollers/viewcontroller/`: `ViewController` (the base of every node), `Presenter`, `IReactView` (what a
@@ -44,7 +45,7 @@ top-level folder. Main thread only, unless a line says otherwise.
44
45
  - `viewcontrollers/sidemenu/`: `SideMenuController`, `SideMenuMotion`, `SideMenuPresenter`, `SideMenuRules`.
45
46
  - `viewcontrollers/splitview/`, `arrangement/`: the split view and the pair (modules, plus the core's
46
47
  `SplitViewPresenter`).
47
- - `viewcontrollers/modal/`, `overlay/`: `ModalCoordinator`, `ModalRecord`, `ModalViews`, `ModalSheet`;
48
+ - `viewcontrollers/modal/`, `overlay/`: `ModalCoordinator`, `ModalRecord`, `ModalViews`, `ModalSheet`, `SheetBack`;
48
49
  `OverlayCoordinator`, `OverlayRecord`, `OverlayViews`, `OverlayTouches`.
49
50
  - `views/`: Android views and animators, no rules: `component/`, `externalcomponent/`, `stack/` (`StackLayout`,
50
51
  `topbar/`, `fab/`), `bottomtabs/`, `sidemenu/`, `animations/` (curves, `SideAnimator`, `AnimationRules`), `element/`
@@ -58,7 +59,8 @@ top-level folder. Main thread only, unless a line says otherwise.
58
59
  `DevelopmentLog`).
59
60
  - `android/src/main/jni/`: `CMakeLists.txt` builds the codegen target with the C++ of `ios/cpp` (the slot's and the
60
61
  safe area view's shadow nodes); `ApexNavigationSpec.h` replaces the generated header so autolinking sees their
61
- descriptors.
62
+ descriptors; `ANNContentHeights.cpp` measures React content without a height limit for `react/ContentHeights.kt`
63
+ (a sheet's `'content'` detent).
62
64
  - `android/src/main/res/`: theme `Theme.ApexNavigation` (and `values-night`), `attrs.xml` (splash attributes),
63
65
  `ids.xml`, `dimens*.xml`, text colors, icons.
64
66
  - `android/src/test/java/…`: unit tests, one package per main package; fakes beside them (`Fakes.kt`,
@@ -78,16 +80,21 @@ top-level folder. Main thread only, unless a line says otherwise.
78
80
  `StackViews.kt`, `StackTransitions.kt`, `PreparedPushes.kt`; `views/stack/StackLayout.kt`, `ScreenEdge.kt` (the edge
79
81
  a moving screen extends); back: `NavigationActivity.kt`, `viewcontrollers/navigator/BackCallbackState.kt`; the
80
82
  preview of a pop during the back gesture (Android 14+): `StackController.BackGesture`, `BackPreview.kt`,
81
- `stackPoppedByBack` of the layouts.
82
- - Stack FAB: `viewcontrollers/stack/fab/FabPresenter.kt`, `FabPlan.kt`, `FabPlacement.kt`; `views/stack/fab/`.
83
+ `stackPoppedByBack` of the layouts; of a sheet's dismissal: `viewcontrollers/modal/SheetBack.kt`,
84
+ `ModalCoordinator.backTargetSheet`, `ModalSheet.BackPreview`.
85
+ - Stack FAB: `viewcontrollers/stack/fab/FabPresenter.kt`, `FabPlan.kt`, `FabPlacement.kt`, `FabMotion.kt` (how it goes
86
+ with a transition); `views/stack/fab/` (`FabCopy`: the picture of a FAB that leaves).
83
87
  - Top bar (title, buttons, menus, large title): `viewcontrollers/stack/topbar/TopBarPresenter.kt`, `TopBarRoom.kt`,
84
88
  `TopBarVisibility.kt`, `BarComponents.kt`, `ButtonPlaces.kt`, `LargeTitleCollapse.kt`, `BarRowTransition.kt`;
85
- `views/stack/topbar/TopBar.kt`, `TitleBar.kt`, `titlebar/ButtonBar.kt`, `titlebar/ButtonMenus.kt`.
89
+ `views/stack/topbar/TopBar.kt`, `TitleBar.kt`, `titlebar/ButtonRow.kt` (the views of a side: back, buttons,
90
+ magnifier, "⋮"), `titlebar/ButtonBar.kt` (the buttons from the options, "⋮"'s popup), `titlebar/BarButtonView.kt`,
91
+ `titlebar/BarMenu.kt` (the bar's menus: a `ListPopupWindow` with the theme's popup style and the options' colors),
92
+ `titlebar/ButtonMenus.kt` (menu options to its items).
86
93
  - Search: `viewcontrollers/stack/search/StackSearchPresenter.kt`, `ScreenSearch.kt`, `SearchPanel.kt`;
87
94
  `views/stack/topbar/search/`.
88
95
  - Tabs: `viewcontrollers/bottomtabs/BottomTabsController.kt`, `BottomTabsPresenter.kt`, `TabSelection.kt`,
89
96
  `TabItems.kt`, `TabsRoom.kt`; `views/bottomtabs/`; `customrow/BottomTabsCustomRowOptions.kt`,
90
- `viewcontrollers/bottomtabs/CustomTabRowPlacer.kt`.
97
+ `viewcontrollers/bottomtabs/CustomTabRowGeometry.kt`.
91
98
  - Modals and sheets: `viewcontrollers/modal/ModalCoordinator.kt`, `ModalRecord.kt`, `ModalViews.kt`, `ModalSheet.kt`,
92
99
  `ModalAnimations.kt`; `options/SheetOptions.kt`.
93
100
  - Overlays: `viewcontrollers/overlay/OverlayCoordinator.kt`, `OverlayViews.kt`, `OverlayTouches.kt`.
@@ -96,12 +103,13 @@ top-level folder. Main thread only, unless a line says otherwise.
96
103
  - Split view: `viewcontrollers/splitview/SplitViewController.kt`, `SplitViewLayout.kt`, `SplitPanes.kt`,
97
104
  `SplitViewPresenter.kt`; `StackCommands.showInColumn`.
98
105
  - Pair (arrangement): `viewcontrollers/arrangement/ArrangementController.kt`, `ArrangementPlanner.kt`,
99
- `ArrangementLayout.kt`, `ArrangementDefinition.kt`; `react/ArrangementStates.kt`.
106
+ `ArrangementLayout.kt`, `ArrangementDefinition.kt`; the pair's state in `react/ScreenEnvironment.kt`.
100
107
  - Preview, key commands: iOS only. The options are parsed and merged (`options/PreviewOptions.kt`,
101
108
  `options/KeyCommandOptions.kt`) and not applied; `dismissPreview` does nothing.
102
109
  - Animations and transitions: `views/animations/` (`AnimationRules`, `Curves`, `SideAnimator`, `ValueInterpolation`,
103
- `FadeThrough`, `SystemTransition`); `views/element/` (`ElementTransitions`, `TransitionLayer`, `TargetsWait`,
104
- `animators/`); `options/StackAnimationOptions.kt`, `ViewAnimationOptions.kt`.
110
+ `FadeThrough`, `SystemTransition`, `AnimationLayer`: the hardware layer of a fade); `views/element/`
111
+ (`ElementTransitions`, `TransitionLayer`, `TargetsWait`, `animators/`); `options/StackAnimationOptions.kt`,
112
+ `ViewAnimationOptions.kt`.
105
113
  - System bars: `system/SystemUiOwner.kt`, `SystemUiLayers.kt`, `SystemUiRules.kt`, `SystemUiWindow.kt`,
106
114
  `AppDirection.kt`; `viewcontrollers/parent/ContainerBackground.kt`.
107
115
  - Events and state: `react/events/AppearanceDispatcher.kt`, `ScreenAppearance.kt`, `EventEmitter.kt`,
@@ -111,21 +119,21 @@ top-level folder. Main thread only, unless a line says otherwise.
111
119
  - Error texts and answers: `react/ErrorTexts.kt` and `react/CommandContract.kt`, made by `scripts/contract.mjs` from
112
120
  `src/interfaces/contract/errors.json` and `commands.json`.
113
121
  - Links: `react/LaunchLink.kt`, `NavigationActivity.kt` (`onNewIntent`); `react/StartInfo.kt`.
114
- - Hinge and regions: `react/Hinge.kt`, `react/ScreenRegions.kt`, `react/ScreenInsets.kt`, `utils/WindowFolds.kt`.
122
+ - Hinge and regions: `react/Hinge.kt`, `react/ScreenRegions.kt`, `react/ScreenEnvironment.kt`, `utils/WindowFolds.kt`.
115
123
  - Native screens: `nativescreen/NativeScreenContext.kt`, `NativeScreenCalls.kt`, `NativeScreenCreator.kt`;
116
124
  `viewcontrollers/externalcomponent/`.
117
125
  - Slots: `slots/SlotHost.kt`, `SlotView.kt`, `SlotScreenView.kt`, `SlotContainers.kt` (containers and slot views by
118
126
  slot id: a change goes straight to the views of its id, `SlotViews.kt`), `SlotViewManager.kt`.
119
127
  - Safe area: `safearea/SafeAreaView.kt`, `SafeAreaViewManager.kt`; `viewcontrollers/component/ScreenReadiness.kt`;
120
- `react/ScreenInsets.kt`.
128
+ `react/ScreenEnvironment.kt`.
121
129
  - The C++ of `ANNSlot`, `ANNSafeAreaView`: `android/src/main/jni/CMakeLists.txt`, `ApexNavigationSpec.h`; sources in
122
130
  `ios/cpp/`.
123
131
 
124
132
  ## Threads
125
133
 
126
134
  - **JS thread.** The sync getters `getScreenInsets`, `getScreenRegions`, `getArrangementState`, `getHinge`,
127
- `getStartInfo` read stores (`ConcurrentHashMap` in `ScreenInsets`, `ScreenRegions`, `ArrangementStates`; `@Volatile`
128
- in `Hinge`). They never touch a node.
135
+ `getStartInfo` read stores (one `ConcurrentHashMap` of immutable records in `ScreenEnvironment`; `@Volatile` in
136
+ `Hinge`). They never touch a node.
129
137
  - **Module thread.** The `check` of every command with a promise: `LayoutReader` and, through it, `OptionsReader` (also
130
138
  for `setDefaultOptions`, `mergeOptions` and the options of `dismissModal`, in the runner's `prepare` step);
131
139
  `ReadableJson` for native-screen props. The registry of native screens is read under its lock. Images are not loaded
@@ -156,9 +164,9 @@ top-level folder. Main thread only, unless a line says otherwise.
156
164
  - Native code never touches React Native's views (their children, their layout): Fabric owns and recycles them. Move
157
165
  content through `SlotContainers` and `SlotView`, and find views by `nativeID` only through React Native's own search
158
166
  or its tag (`ReactR.id.view_tag_native_id`); a transition's elements in one walk per screen (`TransitionViews`).
159
- - Each step of a transition's element (its move into the layer, its animator, a flight's start and frames in
160
- `MoveAnimator`) runs in `elementStep`: an exception skips that element only. A new step of an element goes there
161
- too, or one bad element takes the whole transition down.
167
+ - Each step of a transition's element (its start, its animator, a flight's start and frames in `MoveAnimator`) runs
168
+ in `elementStep`, and the layer draws each copy on its own: an exception skips that element only. A new step of an
169
+ element goes there too, or one bad element takes the whole transition down.
162
170
  - Every change of a stack's children goes through its `StackQueue`; a direct change of `shown` or of the container
163
171
  skips the table that decides interrupts and answers.
164
172
  - Every event of an appearance goes through `AppearanceDispatcher`. A container with its own loop of
@@ -198,8 +206,11 @@ top-level folder. Main thread only, unless a line says otherwise.
198
206
  - The bar measures to its children: a picture laid into it for a transition that is taller than the bar the incoming
199
207
  screen gives holds the bar at that height to the end (the row's picture of a pop from a large title). What doesn't
200
208
  stay in the bar rides with the leaving screen (`TopBarPresenter.pictureUnderRow`).
201
- - A `Toolbar` centers its navigation button and its menu in `min(minimumHeight, height)` (`buttonGravity` is top):
202
- the row's toolbars take the row's height as their minimum (`TitleBar`); 0 pins the buttons to the row's top.
209
+ - The bar's buttons are plain views of the row (`ButtonRow`), not a toolbar's menu: a button keeps its view while its id
210
+ stays, and its `testID` is set when it is bound. They copy a Material 3 toolbar's look through the theme's
211
+ attributes (`actionButtonStyle`, `actionMenuTextAppearance`, `actionOverflowButtonStyle`,
212
+ `toolbarNavigationButtonStyle`) and its `maxButtonHeight` of 56 dp; the count of places is AppCompat's
213
+ (`ButtonPlaces.maxActionButtons`).
203
214
  - A screen's overlay is clipped to the screen, and a screen without a large title is laid out under the bar (its `top`
204
215
  is the bar's height): a picture of the bar in its overlay doesn't show. The bar's picture in a transition of the
205
216
  stack's own is drawn by the stack's view with the screen's transform (`StackLayout.barTravels`).
package/android/CORE.md CHANGED
@@ -10,7 +10,7 @@ otherwise.
10
10
  ```
11
11
  JS ─ ANNTurboModule (codegen NativeANNTurboModuleSpec)
12
12
  │ sync getters answer on the JS thread from stores the main thread fills
13
- │ (ScreenInsets, ScreenRegions, ArrangementStates, Hinge, StartInfo)
13
+ │ (ScreenEnvironment, Hinge, StartInfo)
14
14
  ▼ module thread
15
15
  react/NavigationTurboModule one override per method
16
16
  │ layout/LayoutReader ► options/OptionsReader the whole layout read and checked, its options read
@@ -188,7 +188,7 @@ Each rule has one owner. Change the owner, not a caller; if a new feature needs
188
188
  - **Room for the bars.** A screen's room at the top and bottom is `ScreenFrame` with `ScreenSafeArea` and the
189
189
  `ParentController` room hooks (`getTopInset`, `keepsStatusBarRoomOf`, …). A screen in a pair forwards its room to
190
190
  the pair (`ScreenFrame.applyRoom`), and the pair's `getTopInset` uses the screens' rule (`ScreenFrame.topRoomOf`)
191
- with the options it shows with. A view's place in the window for the safe area (the React root, the stack's header
191
+ with the options it shows with. The bottom edge is not padded by default (only `'bottom'` in the edges pads it); `roomPadding` still shrinks the view for an opaque navigation bar and the keyboard. A view's place in the window for the safe area (the React root, the stack's header
192
192
  bottom in `headerBottomOf`, the tabs' top in `tabsTopOf`) is `RestPlace`: from layout, without translations, a sheet
193
193
  at rest.
194
194
  - **A container's own move.** A container that moves children in or out of the window without a command (the split
@@ -207,11 +207,12 @@ Modules are the feature classes that plug into the core through its contract (th
207
207
  custom row (`BottomTabsCustomRowOptions`).
208
208
  - **Views and helpers:** tabs bar (`BottomTabs`, `BottomTabItem`, `BottomTabsCollapseBehavior`, `scrollToTop`), slots
209
209
  (`SlotHost`, `SlotView`, `SlotContainers`), safe area (`SafeAreaView`), native screens (`nativescreen/`), splash
210
- (`splash/`), animations (`FadeThrough`, `SystemTransition`, `TransitionTargets`, three element animators), utils
211
- (`MaterialTheme`, `NavigationLog`, `awaitBarComponents`, `whenDrawn`).
212
- - **Stores and singletons:** regions (`Hinge`, `ScreenInsets`, `ScreenRegions`, `WindowFolds`), pair state
213
- (`ArrangementStates`), links (`LaunchLink`, `StartInfo`), events (`NavigationState`), commands
214
- (`BackCallbackState`), stack (`PreparedFrame`).
210
+ (`splash/`), animations (`FadeThrough`, `SystemTransition`, `TransitionTargets`, the copies of shared elements:
211
+ `TextMorph`, `ViewMorph`, `ImageMorph`), utils (`MaterialTheme`, `NavigationLog`, `awaitBarComponents`,
212
+ `whenDrawn`).
213
+ - **Stores and singletons:** a screen's environment (`ScreenEnvironment`: its insets and padding, its regions as
214
+ `ScreenRegions` measures them, its pair state), the window (`Hinge`, `WindowFolds`), links (`LaunchLink`,
215
+ `StartInfo`), events (`NavigationState`), commands (`BackCallbackState`), stack (`PreparedFrame`).
215
216
 
216
217
  How they plug in:
217
218
 
@@ -235,5 +236,8 @@ How they plug in:
235
236
  - **Core code in a module's folder:** `viewcontrollers/splitview/SplitViewPresenter.kt`, `slots/SlotScreenView.kt`,
236
237
  and in `views/animations/` and `views/element/` everything except the files named above.
237
238
  - **Stores** are written on the main thread by the core and read from any thread; they are cleared with their nodes and on
238
- reload. Their events, and the search's, go through the emitter of the JavaScript the screen was made for
239
+ reload. A screen's environment is one immutable record per id in `ScreenEnvironment` (insets for JavaScript, padding,
240
+ regions, pair state), replaced at once; the screen's node clears it with one `remove` when it is destroyed, unless a
241
+ later node has its id; the padding listeners of its safe area views stay until the views stop. Their events, and
242
+ the search's, go through the emitter of the JavaScript the screen was made for
239
243
  (`EventEmitter.of(node.jsGeneration)`); the hinge keeps the `EventEmitter.current()` of the call that turned it on.
@@ -1,2 +1,8 @@
1
1
  # The native screens `npx apex-navigation codegen` lists in the app: the navigation finds the list by its name.
2
2
  -keep class dev.apexnative.navigation.generated.ApexNavigationGeneratedScreens { *; }
3
+
4
+ # The library's C++ measures a React root's content through the surface's handler, which it reads by this getter's
5
+ # name (`android/src/main/jni/ANNContentHeights.cpp`).
6
+ -keepclassmembers class com.facebook.react.runtime.ReactSurfaceImpl {
7
+ com.facebook.react.fabric.SurfaceHandlerBinding getSurfaceHandler();
8
+ }
@@ -35,6 +35,7 @@ import dev.apexnative.navigation.splash.SplashTheme
35
35
  import dev.apexnative.navigation.splash.SplashView
36
36
  import dev.apexnative.navigation.system.SystemUiWindow
37
37
  import dev.apexnative.navigation.utils.MaterialTheme
38
+ import dev.apexnative.navigation.viewcontrollers.modal.SheetBack
38
39
  import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackCheck
39
40
  import dev.apexnative.navigation.viewcontrollers.navigator.BackCallbackState
40
41
  import dev.apexnative.navigation.viewcontrollers.navigator.Navigator
@@ -72,23 +73,33 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
72
73
  // Enabled while back has something to do in the app (BackCallbackState); otherwise the system does its own back.
73
74
  // From Android 14, where the app hears the progress of the back gesture, a gesture that would pop a stack with the
74
75
  // default transition previews the pop as the system previews back between activities (`StackController
75
- // .BackGesture`); JavaScript's listeners hear back first, so with them there is no preview.
76
+ // .BackGesture`), and one that would dismiss a sheet previews its hide as Material's sheets do (`SheetBack`), its
77
+ // release closing it as a drag down does; JavaScript's listeners hear back first, so with them there is no preview.
76
78
  private val backCallback = object : OnBackPressedCallback(false) {
77
79
  override fun handleOnBackStarted(backEvent: BackEventCompat) {
78
80
  backGesture = null
79
- navigator?.let { backCheck?.atBack(it) }
81
+ sheetGesture = null
82
+ val navigator = navigator ?: return
83
+ backCheck?.atBack(navigator)
80
84
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE || BackCallbackState.hasJsListeners) return
81
- val stack = navigator?.stackPoppedByBack() ?: return
82
- backGesture = stack.startBackGesture(backEvent.swipeEdge == BackEventCompat.EDGE_LEFT, backEvent.touchY)
85
+ val stack = navigator.stackPoppedByBack()
86
+ if (stack != null) {
87
+ backGesture = stack.startBackGesture(backEvent.swipeEdge == BackEventCompat.EDGE_LEFT, backEvent.touchY)
88
+ return
89
+ }
90
+ sheetGesture = navigator.sheetDismissedByBack()?.startBackPreview(backEvent)
83
91
  }
84
92
 
85
93
  override fun handleOnBackProgressed(backEvent: BackEventCompat) {
86
94
  backGesture?.progress(backEvent.progress, backEvent.touchY)
95
+ sheetGesture?.progress(backEvent)
87
96
  }
88
97
 
89
98
  override fun handleOnBackCancelled() {
90
99
  backGesture?.cancel()
91
100
  backGesture = null
101
+ sheetGesture?.cancel()
102
+ sheetGesture = null
92
103
  navigator?.let(BackCallbackState::update)
93
104
  }
94
105
 
@@ -96,13 +107,33 @@ open class NavigationActivity : AppCompatActivity(), DefaultHardwareBackBtnHandl
96
107
  navigator?.let { backCheck?.atBack(it) }
97
108
  val gesture = backGesture
98
109
  backGesture = null
99
- if (gesture?.commit() == true) BackCallbackState.update() else passBack()
110
+ val sheet = sheetGesture
111
+ sheetGesture = null
112
+ when {
113
+ gesture?.commit() == true -> BackCallbackState.update()
114
+ sheet != null && commitSheet(sheet) -> BackCallbackState.update()
115
+ else -> passBack()
116
+ }
100
117
  }
101
118
  }
102
119
 
103
120
  // The back gesture that previews a pop now; none.
104
121
  private var backGesture: StackController.BackGesture? = null
105
122
 
123
+ // The back gesture that previews a sheet's hide now; none.
124
+ private var sheetGesture: SheetBack.Gesture? = null
125
+
126
+ // A sheet's preview released: the sheet goes as the user's drag down closes it, and back doesn't go on (no
127
+ // `passBack`, which would dismiss it a second time). A command that changed what back does since the gesture
128
+ // started (a push in the sheet, a modal over it, a hold) leaves it to the usual back, the sheet back in place.
129
+ private fun commitSheet(gesture: SheetBack.Gesture): Boolean {
130
+ if (navigator?.sheetDismissedByBack() !== gesture.sheet) {
131
+ gesture.cancel()
132
+ return false
133
+ }
134
+ return gesture.commit()
135
+ }
136
+
106
137
  // Debug builds only: the check that what back does never changes without its trigger (BackCallbackState), sampled
107
138
  // before frames and at back events. It only logs; release builds have neither the check nor the listener.
108
139
  private val backCheck = if (BuildConfig.DEBUG) BackCallbackCheck() else null
@@ -105,7 +105,7 @@ class BottomTabOptions {
105
105
  @JvmField var textColor: ThemeColour = NullThemeColour()
106
106
  @JvmField var selectedIconColor: ThemeColour = NullThemeColour()
107
107
  @JvmField var selectedTextColor: ThemeColour = NullThemeColour()
108
- @JvmField var font = FontOptions()
108
+ @ReadFromParent @JvmField var font = FontOptions()
109
109
  @JvmField var fontSize: Fraction = NullFraction()
110
110
  @JvmField var selectedFontSize: Fraction = NullFraction()
111
111
  @JvmField var iconInsets = IconInsetsOptions()
@@ -95,6 +95,7 @@ class BottomTabsAccessoryOptions {
95
95
  class BottomTabsOptions {
96
96
  @JvmField var visible: Bool = NullBool()
97
97
  @JvmField var animate: Bool = NullBool()
98
+ @JvmField var switchAnimation: Text = NullText()
98
99
  /** Selects a tab once; a whole number, truncated where it is read. */
99
100
  @JvmField var currentTabIndex: Fraction = NullFraction()
100
101
  /** Selects a tab once. */
@@ -124,18 +125,19 @@ class BottomTabsOptions {
124
125
  @JvmField var minimizeBehavior: Text = NullText()
125
126
  @JvmField var bottomAccessory = BottomTabsAccessoryOptions()
126
127
 
127
- fun hasValue(): Boolean = visible.hasValue() || animate.hasValue() || currentTabIndex.hasValue() ||
128
- currentTabId.hasValue() || testID.hasValue() || accessibilityLabel.hasValue() || moreTestID.hasValue() ||
129
- drawBehind.hasValue() || backgroundColor.hasValue() || tabsAttachMode.hasValue() || barStyle.hasValue() ||
130
- layoutStyle.hasValue() || cornerRadius.hasValue() || bottomMargin.hasValue() || translucent.hasValue() ||
131
- hideShadow.hasValue() || titleDisplayMode.hasValue() || elevation.hasValue() || hideOnScroll.hasValue() ||
132
- borderColor.hasValue() || borderWidth.hasValue() || shadow.hasValue() || customRow.hasValue() ||
133
- sidebar.hasValue() || sidebarLayout.hasValue() || customizationId.hasValue() || minimizeBehavior.hasValue() ||
134
- bottomAccessory.hasValue()
128
+ fun hasValue(): Boolean = visible.hasValue() || animate.hasValue() || switchAnimation.hasValue() ||
129
+ currentTabIndex.hasValue() || currentTabId.hasValue() || testID.hasValue() || accessibilityLabel.hasValue() ||
130
+ moreTestID.hasValue() || drawBehind.hasValue() || backgroundColor.hasValue() || tabsAttachMode.hasValue() ||
131
+ barStyle.hasValue() || layoutStyle.hasValue() || cornerRadius.hasValue() || bottomMargin.hasValue() ||
132
+ translucent.hasValue() || hideShadow.hasValue() || titleDisplayMode.hasValue() || elevation.hasValue() ||
133
+ hideOnScroll.hasValue() || borderColor.hasValue() || borderWidth.hasValue() || shadow.hasValue() ||
134
+ customRow.hasValue() || sidebar.hasValue() || sidebarLayout.hasValue() || customizationId.hasValue() ||
135
+ minimizeBehavior.hasValue() || bottomAccessory.hasValue()
135
136
 
136
137
  fun mergeWith(other: BottomTabsOptions) {
137
138
  if (other.visible.hasValue()) visible = other.visible
138
139
  if (other.animate.hasValue()) animate = other.animate
140
+ if (other.switchAnimation.hasValue()) switchAnimation = other.switchAnimation
139
141
  if (other.currentTabIndex.hasValue()) currentTabIndex = other.currentTabIndex
140
142
  if (other.currentTabId.hasValue()) currentTabId = other.currentTabId
141
143
  if (other.testID.hasValue()) testID = other.testID
@@ -167,6 +169,7 @@ class BottomTabsOptions {
167
169
  fun mergeWithDefault(defaults: BottomTabsOptions) {
168
170
  if (!visible.hasValue()) visible = defaults.visible
169
171
  if (!animate.hasValue()) animate = defaults.animate
172
+ if (!switchAnimation.hasValue()) switchAnimation = defaults.switchAnimation
170
173
  if (!currentTabIndex.hasValue()) currentTabIndex = defaults.currentTabIndex
171
174
  if (!currentTabId.hasValue()) currentTabId = defaults.currentTabId
172
175
  if (!testID.hasValue()) testID = defaults.testID
@@ -198,6 +201,7 @@ class BottomTabsOptions {
198
201
  fun copy() = BottomTabsOptions().also { it.mergeWith(this) }
199
202
 
200
203
  companion object {
204
+ private val SWITCH_ANIMATIONS = setOf("platform", "none")
201
205
  private val TABS_ATTACH_MODES = setOf("together", "afterInitialTab", "onSwitchToTab")
202
206
  private val BAR_STYLES = setOf("default", "black")
203
207
  private val LAYOUT_STYLES = setOf("stretch", "compact")
@@ -212,6 +216,7 @@ class BottomTabsOptions {
212
216
  if (map == null) return options
213
217
  options.visible = BoolParser.parse(map, "visible")
214
218
  options.animate = BoolParser.parse(map, "animate")
219
+ options.switchAnimation = TextParser.parse(map, "switchAnimation", SWITCH_ANIMATIONS)
215
220
  options.currentTabIndex = FractionParser.parse(map, "currentTabIndex")
216
221
  options.currentTabId = TextParser.parse(map, "currentTabId")
217
222
  options.testID = TextParser.parse(map, "testID")
@@ -31,7 +31,7 @@ class ButtonOptions(@JvmField var id: Text = NullText()) {
31
31
  @JvmField var systemItem: Text = NullText()
32
32
  @JvmField var text: Text = NullText()
33
33
  @JvmField var accessibilityLabel: Text = NullText()
34
- @JvmField var font = FontOptions()
34
+ @ReadFromParent @JvmField var font = FontOptions()
35
35
  @JvmField var fontSize: Fraction = NullFraction()
36
36
  @JvmField var enabled: Bool = NullBool()
37
37
  @JvmField var disableIconTint: Bool = NullBool()
@@ -22,7 +22,7 @@ class LargeTitleOptions {
22
22
  @JvmField var collapseOnScroll: Bool = NullBool()
23
23
  @JvmField var fontSize: Fraction = NullFraction()
24
24
  @JvmField var color: ThemeColour = NullThemeColour()
25
- @JvmField var font = FontOptions()
25
+ @ReadFromParent @JvmField var font = FontOptions()
26
26
 
27
27
  /**
28
28
  * When the large title shows: [ALWAYS], [NEVER] or [AUTOMATIC], as on the screen below. `displayMode` over
@@ -9,7 +9,7 @@ import com.facebook.react.bridge.ReadableMap
9
9
  * first).
10
10
  */
11
11
  open class LayoutAnimation(
12
- @JvmField var sharedElements: SharedElements = SharedElements(),
12
+ @OptionKey("sharedElementTransitions") @JvmField var sharedElements: SharedElements = SharedElements(),
13
13
  @JvmField var elementTransitions: ElementTransitions = ElementTransitions(),
14
14
  ) {
15
15
  open fun hasValue(): Boolean = sharedElements.hasValue() || elementTransitions.hasValue()
@@ -0,0 +1,18 @@
1
+ package dev.apexnative.navigation.options
2
+
3
+ /**
4
+ * The JSON key of an option field whose name is not that key (`topBar.backButton` is `TopBarButtons.back`), for the
5
+ * paths of [OptionPaths]; also the flag that tells a value is given, which goes with it. A field without it answers to
6
+ * its own name.
7
+ */
8
+ @Target(AnnotationTarget.FIELD)
9
+ @Retention(AnnotationRetention.RUNTIME)
10
+ annotation class OptionKey(val name: String)
11
+
12
+ /**
13
+ * A group the reader takes from the object of the group that holds it, not from a key of its own (the font of a text,
14
+ * the top bar's buttons): for the paths of [OptionPaths] its fields answer to the keys of that object.
15
+ */
16
+ @Target(AnnotationTarget.FIELD)
17
+ @Retention(AnnotationRetention.RUNTIME)
18
+ annotation class ReadFromParent
@@ -0,0 +1,91 @@
1
+ package dev.apexnative.navigation.options
2
+
3
+ import dev.apexnative.navigation.options.params.Param
4
+ import dev.apexnative.navigation.options.params.ThemeColour
5
+ import java.lang.reflect.Field
6
+ import java.lang.reflect.Modifier
7
+ import java.util.concurrent.ConcurrentHashMap
8
+
9
+ /**
10
+ * The options at a JSON key path, the keys of the options joined with dots (`topBar.subtitle`, `bottomTab.badge`), as
11
+ * the readers parse them: `clearOptions` takes them out of a node's own options. Generic over the whole tree, by
12
+ * reflection on the fields of the groups: a field answers to the key of its name, or of its [OptionKey]; a group the
13
+ * reader takes from the object of its parent ([ReadFromParent]: the font of a text, the top bar's buttons) answers with
14
+ * its fields to the keys of that object. A group is a class with a `mergeWith` of its own class; anything else (a
15
+ * value, a color, a list, a button menu) ends a path.
16
+ */
17
+ internal object OptionPaths {
18
+ /**
19
+ * What a path names: the fields of [group] that answer to its last key, [members] (one, or a value and the flag
20
+ * that tells it is given, as `modal.sheet.largestUndimmedDetent`).
21
+ */
22
+ class Place(val group: Any, val members: List<Field>) {
23
+ /** The value at the path, of the first field. */
24
+ val value: Any? get() = members.first().get(group)
25
+ }
26
+
27
+ // The fields of each class walked, its superclasses' first.
28
+ private val fieldsOfType = ConcurrentHashMap<Class<*>, List<Field>>()
29
+
30
+ /**
31
+ * Takes the value at [path] out of [options], which it changes in place: the field gets the value a freshly made
32
+ * group has for it (unset; a group, an empty one). Whether the path names a field; an empty or unknown path, or
33
+ * one that goes on inside a value (a side of a color), changes nothing.
34
+ */
35
+ fun clear(options: Options, path: String): Boolean {
36
+ val place = find(options, path) ?: return false
37
+ val fresh = newGroup(place.group.javaClass) ?: return false
38
+ place.members.forEach { it.set(place.group, it.get(fresh)) }
39
+ return true
40
+ }
41
+
42
+ /** The fields [path] names in [options]; none for an empty or unknown path or one inside a value. */
43
+ fun find(options: Options, path: String): Place? {
44
+ val keys = path.split('.')
45
+ if (keys.any(String::isEmpty)) return null
46
+ var group: Any = options
47
+ for (key in keys.dropLast(1)) {
48
+ group = fieldOf(group, key)?.value?.takeIf(::isGroup) ?: return null
49
+ }
50
+ return fieldOf(group, keys.last())?.takeIf { newGroup(it.group.javaClass) != null }
51
+ }
52
+
53
+ // The fields of [group] that answer to [key]: its own, else those of a group read from the same object.
54
+ private fun fieldOf(group: Any, key: String): Place? {
55
+ val fields = fieldsOf(group.javaClass)
56
+ fields.filter { !it.isAnnotationPresent(ReadFromParent::class.java) && keyOf(it) == key }
57
+ .takeIf { it.isNotEmpty() }
58
+ ?.let { return Place(group, it) }
59
+ for (field in fields) {
60
+ if (!field.isAnnotationPresent(ReadFromParent::class.java)) continue
61
+ val inner = field.get(group)?.takeIf(::isGroup) ?: continue
62
+ fieldOf(inner, key)?.let { return it }
63
+ }
64
+ return null
65
+ }
66
+
67
+ private fun keyOf(field: Field): String = field.getAnnotation(OptionKey::class.java)?.name ?: field.name
68
+
69
+ private fun fieldsOf(type: Class<*>): List<Field> = fieldsOfType.getOrPut(type) {
70
+ generateSequence(type) { it.superclass }
71
+ .takeWhile { it != Any::class.java }
72
+ .toList()
73
+ .asReversed()
74
+ .flatMap { it.declaredFields.asList() }
75
+ .filter { !Modifier.isStatic(it.modifiers) && !it.isSynthetic }
76
+ .onEach { it.isAccessible = true }
77
+ }
78
+
79
+ private fun isGroup(value: Any): Boolean {
80
+ if (value is Param<*> || value is ThemeColour) return false
81
+ val type = value.javaClass
82
+ return type.declaredMethods.any { it.name == "mergeWith" && it.parameterTypes.contentEquals(arrayOf(type)) }
83
+ }
84
+
85
+ // A group as its class makes it, every field unset; none for a class without a constructor of no arguments.
86
+ private fun newGroup(type: Class<*>): Any? = try {
87
+ type.getDeclaredConstructor().newInstance()
88
+ } catch (_: ReflectiveOperationException) {
89
+ null
90
+ }
91
+ }
@@ -12,25 +12,28 @@ import dev.apexnative.navigation.options.parsers.FractionParser
12
12
  import dev.apexnative.navigation.options.parsers.TextParser
13
13
 
14
14
  /**
15
- * A height a sheet stops at: about half the screen, the full height, or a height in dp. `content` stops at half the
16
- * screen on Android: the Material sheet has no height of its content.
15
+ * A height a sheet stops at: about half the screen, the full height, the height of the screen's content, or a height in
16
+ * dp.
17
17
  */
18
18
  sealed class SheetDetent {
19
19
  object Medium : SheetDetent()
20
20
  object Large : SheetDetent()
21
+ object Content : SheetDetent()
21
22
  data class Height(val dp: Double) : SheetDetent()
22
23
 
23
24
  /** The detent as the app names it, in `sheetDetentChanged`. */
24
25
  fun toValue(): Any = when (this) {
25
26
  Medium -> "medium"
26
27
  Large -> "large"
28
+ Content -> "content"
27
29
  is Height -> dp
28
30
  }
29
31
 
30
32
  companion object {
31
33
  fun parse(value: Any?): SheetDetent? = when (value) {
32
- "medium", "content" -> Medium
34
+ "medium" -> Medium
33
35
  "large" -> Large
36
+ "content" -> Content
34
37
  // A number is a height only when it is finite and positive.
35
38
  is Number -> value.toDouble().takeIf { it.isFinite() && it > 0 }?.let { Height(it) }
36
39
  else -> null
@@ -47,7 +50,7 @@ class SheetOptions {
47
50
  @JvmField var selectedDetent: SheetDetent? = null
48
51
  @JvmField var largestUndimmedDetent: SheetDetent? = null
49
52
  /** The options give `largestUndimmedDetent`, `null` included. */
50
- @JvmField var hasLargestUndimmedDetent = false
53
+ @OptionKey("largestUndimmedDetent") @JvmField var hasLargestUndimmedDetent = false
51
54
  @JvmField var grabber: Bool = NullBool()
52
55
  @JvmField var expandsOnScroll: Bool = NullBool()
53
56
  @JvmField var cornerRadius: Fraction = NullFraction()
@@ -22,7 +22,7 @@ class TitleOptions {
22
22
  @JvmField var text: Text = NullText()
23
23
  @JvmField var fontSize: Fraction = NullFraction()
24
24
  @JvmField var color: ThemeColour = NullThemeColour()
25
- @JvmField var font = FontOptions()
25
+ @ReadFromParent @JvmField var font = FontOptions()
26
26
  @JvmField var component = TitleComponentOptions()
27
27
  /** Shared between copies, as its module wants. */
28
28
  @JvmField var menu: ButtonMenuOptions? = null
@@ -98,7 +98,7 @@ class SubtitleOptions {
98
98
  @JvmField var text: Text = NullText()
99
99
  @JvmField var fontSize: Fraction = NullFraction()
100
100
  @JvmField var color: ThemeColour = NullThemeColour()
101
- @JvmField var font = FontOptions()
101
+ @ReadFromParent @JvmField var font = FontOptions()
102
102
  @JvmField var alignment: Text = NullText()
103
103
 
104
104
  fun hasValue(): Boolean =
@@ -109,7 +109,7 @@ class TopBarBackgroundOptions {
109
109
  */
110
110
  class ScrollEdgeAppearanceTitleOptions {
111
111
  @JvmField var color: ThemeColour = NullThemeColour()
112
- @JvmField var font = FontOptions()
112
+ @ReadFromParent @JvmField var font = FontOptions()
113
113
  @JvmField var fontSize: Fraction = NullFraction()
114
114
 
115
115
  fun hasValue(): Boolean = color.hasValue() || font.hasValue() || fontSize.hasValue()