@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (581) hide show
  1. package/ApexNavigation.podspec +2 -1
  2. package/CHANGELOG.md +132 -0
  3. package/README.md +147 -51
  4. package/android/CLAUDE.md +78 -25
  5. package/android/CORE.md +49 -25
  6. package/android/RECIPES.md +13 -6
  7. package/android/consumer-rules.pro +6 -0
  8. package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
  9. package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
  10. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
  11. package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
  12. package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
  13. package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
  14. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
  15. package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
  16. package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
  17. package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
  18. package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
  19. package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
  20. package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
  21. package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
  22. package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
  23. package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
  24. package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
  25. package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
  26. package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
  27. package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
  28. package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
  29. package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
  30. package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
  31. package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
  32. package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
  33. package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
  34. package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
  35. package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
  36. package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
  37. package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
  38. package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
  39. package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
  40. package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
  41. package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
  42. package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
  43. package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
  44. package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
  45. package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
  46. package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
  47. package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
  48. package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
  49. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
  50. package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
  51. package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
  52. package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
  53. package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
  54. package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
  55. package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
  56. package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
  57. package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
  58. package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
  59. package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
  60. package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
  61. package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
  62. package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
  63. package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
  64. package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
  65. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
  66. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementDefinition.kt +9 -3
  67. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
  68. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
  69. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
  70. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
  71. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
  72. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
  73. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
  74. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
  75. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
  76. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
  77. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
  78. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
  79. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
  80. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
  81. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
  82. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
  83. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
  84. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
  85. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
  86. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
  87. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
  88. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
  89. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
  90. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
  91. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
  92. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
  93. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
  94. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
  95. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
  96. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
  97. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
  98. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
  99. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
  100. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
  101. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
  102. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
  103. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
  104. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
  105. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
  106. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
  107. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
  108. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
  109. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
  110. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
  111. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
  112. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
  113. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
  114. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
  115. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
  116. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
  117. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
  118. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
  119. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
  120. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
  121. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
  122. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
  123. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
  124. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
  125. package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
  126. package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
  127. package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
  128. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
  129. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
  130. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
  131. package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
  132. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
  133. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
  134. package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
  135. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
  136. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
  137. package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
  138. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
  139. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
  140. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
  141. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
  142. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
  143. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
  144. package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
  145. package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
  146. package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
  147. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
  148. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
  149. package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
  150. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
  151. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
  152. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
  153. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
  154. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
  155. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
  156. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
  157. package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
  158. package/android/src/main/jni/ANNContentHeights.cpp +82 -0
  159. package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
  160. package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
  161. package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
  162. package/android/src/main/res/values/styles.xml +1 -1
  163. package/android/src/main/res/values-night/styles.xml +1 -1
  164. package/cli/app.js +1 -1
  165. package/cli/doctor/checks/app.js +77 -14
  166. package/cli/doctor/checks/splash.js +4 -22
  167. package/cli/migrate/native.js +18 -0
  168. package/cli/project.js +10 -2
  169. package/cli/setup/index.js +18 -0
  170. package/cli/setup/source.js +2 -1
  171. package/cli/setup/steps/appDelegate.js +66 -11
  172. package/cli/setup/steps/mainApplication.js +134 -19
  173. package/cli/setup/steps/metro.js +46 -0
  174. package/cli/setup/steps/sceneDelegate.js +108 -0
  175. package/cli/splash/index.js +3 -1
  176. package/docs-md/architecture/native-screens.md +4 -0
  177. package/docs-md/architecture/theme-and-context.md +131 -12
  178. package/docs-md/architecture/transitions.md +58 -12
  179. package/docs-md/containers/arrangement.md +17 -1
  180. package/docs-md/containers/modals.md +8 -4
  181. package/docs-md/containers/overlays.md +3 -1
  182. package/docs-md/containers/side-menu.md +19 -2
  183. package/docs-md/containers/tabs.md +5 -1
  184. package/docs-md/flows/bottom-sheets.md +4 -2
  185. package/docs-md/flows/forms-in-a-modal.md +1 -1
  186. package/docs-md/fundamentals/screens-and-props.md +9 -1
  187. package/docs-md/fundamentals/starting-the-app.md +1 -1
  188. package/docs-md/guides/cli.md +4 -3
  189. package/docs-md/guides/deep-links.md +15 -33
  190. package/docs-md/help/glossary.md +4 -4
  191. package/docs-md/help/troubleshooting.md +44 -6
  192. package/docs-md/index.json +61 -1
  193. package/docs-md/migration/from-expo-router.md +1 -1
  194. package/docs-md/migration/from-react-native-navigation.md +9 -3
  195. package/docs-md/migration/from-react-navigation.md +2 -2
  196. package/docs-md/screen-ui/back-and-gestures.md +46 -2
  197. package/docs-md/screen-ui/bar-buttons.md +5 -5
  198. package/docs-md/screen-ui/search.md +1 -1
  199. package/docs-md/screen-ui/system-ui.md +17 -12
  200. package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
  201. package/docs-md/screen-ui/top-bar.md +8 -4
  202. package/docs-md/start/installation.md +21 -3
  203. package/ios/Animations/ANNFrameDriver.h +55 -15
  204. package/ios/Animations/ANNFrameDriver.mm +216 -60
  205. package/ios/Animations/ANNTransitionAnimator.h +26 -5
  206. package/ios/Animations/ANNTransitionAnimator.mm +61 -13
  207. package/ios/Animations/ANNTransitionPlan.h +2 -2
  208. package/ios/Animations/ANNTransitionPlan.mm +10 -0
  209. package/ios/Animations/ANNTransitionWait.mm +6 -7
  210. package/ios/Animations/Elements/ANNElementFinder.h +57 -0
  211. package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
  212. package/ios/Animations/Elements/ANNElementTransition.h +10 -8
  213. package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
  214. package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
  215. package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
  216. package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
  217. package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
  218. package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
  219. package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
  220. package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
  221. package/ios/CLAUDE.md +60 -24
  222. package/ios/CORE.md +44 -34
  223. package/ios/Contract/ANNCommandAnswer.h +13 -5
  224. package/ios/Contract/ANNCommandAnswer.mm +40 -32
  225. package/ios/Contract/ANNCommandContract.h +15 -0
  226. package/ios/Contract/ANNCommandContract.mm +78 -0
  227. package/ios/Contract/ANNCommandRunner.h +10 -9
  228. package/ios/Contract/ANNCommandRunner.mm +22 -28
  229. package/ios/Contract/ANNErrorTexts.h +6 -2
  230. package/ios/Contract/ANNErrorTexts.mm +18 -10
  231. package/ios/Contract/ANNLayoutNode.h +3 -3
  232. package/ios/Contract/ANNLayoutReader.h +3 -3
  233. package/ios/Core/ANNAppDelegate.mm +0 -2
  234. package/ios/Core/ANNAppearanceDispatcher.h +5 -4
  235. package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
  236. package/ios/Core/ANNDeepLinkQueue.h +22 -2
  237. package/ios/Core/ANNDeepLinkQueue.mm +121 -14
  238. package/ios/Core/ANNErrorHandler.h +9 -4
  239. package/ios/Core/ANNErrorHandler.mm +20 -2
  240. package/ios/Core/ANNEventContract.h +246 -0
  241. package/ios/Core/ANNEventContract.mm +225 -0
  242. package/ios/Core/ANNEventEmitter.h +6 -2
  243. package/ios/Core/ANNEventEmitter.mm +117 -80
  244. package/ios/Core/ANNHinge.h +6 -0
  245. package/ios/Core/ANNHinge.mm +15 -4
  246. package/ios/Core/ANNJavaScriptCalls.h +33 -0
  247. package/ios/Core/ANNJavaScriptCalls.mm +52 -0
  248. package/ios/Core/ANNLayoutProtocol.h +5 -5
  249. package/ios/Core/ANNNavigationState.h +7 -5
  250. package/ios/Core/ANNNavigationState.mm +8 -7
  251. package/ios/Core/ANNNodeHelper.h +32 -12
  252. package/ios/Core/ANNNodeHelper.mm +100 -3
  253. package/ios/Core/ANNParking.h +5 -4
  254. package/ios/Core/ANNReloadCoordinator.mm +5 -12
  255. package/ios/Core/ANNRenderWait.h +20 -6
  256. package/ios/Core/ANNRenderWait.mm +143 -56
  257. package/ios/Core/ANNSceneDelegate.mm +25 -15
  258. package/ios/Core/ANNSystemUI.h +3 -2
  259. package/ios/Core/ANNSystemUI.mm +7 -0
  260. package/ios/Core/ANNUtils.h +7 -0
  261. package/ios/Core/ANNUtils.mm +10 -0
  262. package/ios/Core/ApexNavigation+Internal.h +1 -1
  263. package/ios/Core/ApexNavigation.mm +7 -6
  264. package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
  265. package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
  266. package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
  267. package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
  268. package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +195 -21
  269. package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
  270. package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
  271. package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
  272. package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
  273. package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
  274. package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
  275. package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
  276. package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
  277. package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
  278. package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
  279. package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
  280. package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
  281. package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
  282. package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
  283. package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
  284. package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
  285. package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
  286. package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
  287. package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
  288. package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
  289. package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
  290. package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
  291. package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
  292. package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
  293. package/ios/Layouts/Screen/ANNScreenSettling.h +34 -0
  294. package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -0
  295. package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
  296. package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
  297. package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
  298. package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
  299. package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
  300. package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
  301. package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
  302. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
  303. package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
  304. package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
  305. package/ios/Layouts/Stack/ANNStackController.h +8 -0
  306. package/ios/Layouts/Stack/ANNStackController.mm +184 -16
  307. package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
  308. package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
  309. package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
  310. package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
  311. package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
  312. package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
  313. package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
  314. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
  315. package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
  316. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
  317. package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
  318. package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
  319. package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
  320. package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
  321. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
  322. package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
  323. package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
  324. package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
  325. package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
  326. package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
  327. package/ios/Options/ANNAnimationOptions.h +2 -1
  328. package/ios/Options/ANNAnimationOptions.mm +1 -1
  329. package/ios/Options/ANNBottomTabsOptions.h +2 -0
  330. package/ios/Options/ANNBottomTabsOptions.mm +1 -0
  331. package/ios/Options/ANNOptions.h +25 -0
  332. package/ios/Options/ANNOptions.mm +157 -1
  333. package/ios/Options/ANNOptionsCache.h +7 -6
  334. package/ios/Options/ANNOptionsReader.mm +108 -0
  335. package/ios/Options/ANNSearchBarOptions.h +4 -3
  336. package/ios/Options/ANNSheetOptions.h +4 -1
  337. package/ios/Options/ANNSideMenuOptions.h +2 -0
  338. package/ios/Options/ANNSideMenuOptions.mm +2 -0
  339. package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
  340. package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
  341. package/ios/Options/ANNUserChoice.h +57 -0
  342. package/ios/Options/ANNUserChoice.mm +44 -0
  343. package/ios/Options/Params/ANNImageSource.h +61 -0
  344. package/ios/Options/Params/ANNImageSource.mm +101 -0
  345. package/ios/Options/Params/ANNOptionImages.h +37 -0
  346. package/ios/Options/Params/ANNOptionImages.mm +284 -0
  347. package/ios/Options/Params/ANNParam.h +15 -0
  348. package/ios/Options/Params/ANNParam.mm +61 -0
  349. package/ios/Options/Params/Color.h +3 -0
  350. package/ios/Options/Params/Color.mm +21 -0
  351. package/ios/Options/Params/ColorParser.h +4 -3
  352. package/ios/Options/Params/ColorParser.mm +22 -4
  353. package/ios/Options/Params/Image.h +15 -2
  354. package/ios/Options/Params/Image.mm +35 -2
  355. package/ios/Options/Params/ImageParser.h +5 -5
  356. package/ios/Options/Params/ImageParser.mm +28 -46
  357. package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
  358. package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
  359. package/ios/RECIPES.md +13 -6
  360. package/ios/React/ANNReactView.mm +6 -25
  361. package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
  362. package/ios/React/ANNSurfaceHostingView.h +14 -0
  363. package/ios/React/ANNSurfaceHostingView.mm +144 -1
  364. package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
  365. package/ios/React/Slots/ANNSlotContainers.h +14 -6
  366. package/ios/React/Slots/ANNSlotContainers.mm +75 -2
  367. package/ios/React/Slots/ANNSlotHost.mm +1 -3
  368. package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
  369. package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
  370. package/ios/TopBar/ANNBarAppearance.h +2 -1
  371. package/ios/TopBar/ANNBarAppearance.mm +111 -30
  372. package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
  373. package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
  374. package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
  375. package/ios/TopBar/ANNBarButtons.h +14 -8
  376. package/ios/TopBar/ANNBarButtons.mm +397 -80
  377. package/ios/TopBar/ANNIconButtonImage.h +1 -0
  378. package/ios/TopBar/ANNIconButtonImage.mm +34 -1
  379. package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
  380. package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
  381. package/ios/TopBar/ANNMainList.h +3 -0
  382. package/ios/TopBar/ANNMainList.mm +4 -0
  383. package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
  384. package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
  385. package/ios/TopBar/ANNSearchPresenter.mm +172 -21
  386. package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
  387. package/ios/TopBar/ANNTopBarPresenter.h +8 -2
  388. package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
  389. package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
  390. package/ios/TurboModules/ANNTurboModule.mm +104 -33
  391. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
  392. package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
  393. package/lib/module/ARCHITECTURE.md +40 -27
  394. package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
  395. package/lib/module/api/app/AppRegistry.js +14 -2
  396. package/lib/module/api/app/AppRegistry.js.map +1 -1
  397. package/lib/module/api/app/createNavigation.js +190 -66
  398. package/lib/module/api/app/createNavigation.js.map +1 -1
  399. package/lib/module/api/commands/commands.js +54 -6
  400. package/lib/module/api/commands/commands.js.map +1 -1
  401. package/lib/module/api/events/navigationEvents.js +6 -2
  402. package/lib/module/api/events/navigationEvents.js.map +1 -1
  403. package/lib/module/api/hooks/useNavigation.js +8 -3
  404. package/lib/module/api/hooks/useNavigation.js.map +1 -1
  405. package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
  406. package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
  407. package/lib/module/api/linking/dispatchedLinks.js +23 -0
  408. package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
  409. package/lib/module/api/linking/linking.js +11 -0
  410. package/lib/module/api/linking/linking.js.map +1 -1
  411. package/lib/module/api/navigation.js.map +1 -1
  412. package/lib/module/api/options/OptionsChain.js +2 -2
  413. package/lib/module/api/screens/arrangement.js +5 -2
  414. package/lib/module/api/screens/arrangement.js.map +1 -1
  415. package/lib/module/api/screens/defineScreen.js +45 -3
  416. package/lib/module/api/screens/defineScreen.js.map +1 -1
  417. package/lib/module/api/screens/nativeScreens.js +31 -6
  418. package/lib/module/api/screens/nativeScreens.js.map +1 -1
  419. package/lib/module/api/screens/registerScreens.js +193 -35
  420. package/lib/module/api/screens/registerScreens.js.map +1 -1
  421. package/lib/module/api/theme/theme.js +5 -0
  422. package/lib/module/api/theme/theme.js.map +1 -1
  423. package/lib/module/engine/commands.js +51 -9
  424. package/lib/module/engine/commands.js.map +1 -1
  425. package/lib/module/engine/layout.js +20 -11
  426. package/lib/module/engine/layout.js.map +1 -1
  427. package/lib/module/engine/nativeScreens.js +9 -0
  428. package/lib/module/engine/nativeScreens.js.map +1 -1
  429. package/lib/module/engine/options.js +49 -15
  430. package/lib/module/engine/options.js.map +1 -1
  431. package/lib/module/engine/optionsChange.js +102 -0
  432. package/lib/module/engine/optionsChange.js.map +1 -0
  433. package/lib/module/engine/places.js +52 -7
  434. package/lib/module/engine/places.js.map +1 -1
  435. package/lib/module/engine/props.js +30 -1
  436. package/lib/module/engine/props.js.map +1 -1
  437. package/lib/module/engine/refresh.js +85 -0
  438. package/lib/module/engine/refresh.js.map +1 -0
  439. package/lib/module/engine/rememberedOptions.js +61 -1
  440. package/lib/module/engine/rememberedOptions.js.map +1 -1
  441. package/lib/module/engine/screens.js +77 -16
  442. package/lib/module/engine/screens.js.map +1 -1
  443. package/lib/module/interfaces/contract/commands.json +101 -0
  444. package/lib/module/interfaces/contract/errors.json +275 -0
  445. package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
  446. package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
  447. package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
  448. package/lib/typescript/api/app/createNavigation.d.ts +8 -3
  449. package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
  450. package/lib/typescript/api/commands/commands.d.ts.map +1 -1
  451. package/lib/typescript/api/commands/presentation.d.ts +4 -3
  452. package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
  453. package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
  454. package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
  455. package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
  456. package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
  457. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
  458. package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
  459. package/lib/typescript/api/index.d.ts +1 -1
  460. package/lib/typescript/api/index.d.ts.map +1 -1
  461. package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
  462. package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
  463. package/lib/typescript/api/linking/linking.d.ts +8 -0
  464. package/lib/typescript/api/linking/linking.d.ts.map +1 -1
  465. package/lib/typescript/api/navigation.d.ts +4 -1
  466. package/lib/typescript/api/navigation.d.ts.map +1 -1
  467. package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
  468. package/lib/typescript/api/screens/arrangement.d.ts +12 -2
  469. package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
  470. package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
  471. package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
  472. package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
  473. package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
  474. package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
  475. package/lib/typescript/api/theme/theme.d.ts +2 -0
  476. package/lib/typescript/api/theme/theme.d.ts.map +1 -1
  477. package/lib/typescript/engine/commands.d.ts +5 -0
  478. package/lib/typescript/engine/commands.d.ts.map +1 -1
  479. package/lib/typescript/engine/layout.d.ts.map +1 -1
  480. package/lib/typescript/engine/nativeScreens.d.ts +5 -0
  481. package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
  482. package/lib/typescript/engine/options.d.ts +5 -2
  483. package/lib/typescript/engine/options.d.ts.map +1 -1
  484. package/lib/typescript/engine/optionsChange.d.ts +28 -0
  485. package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
  486. package/lib/typescript/engine/places.d.ts +7 -2
  487. package/lib/typescript/engine/places.d.ts.map +1 -1
  488. package/lib/typescript/engine/props.d.ts +8 -1
  489. package/lib/typescript/engine/props.d.ts.map +1 -1
  490. package/lib/typescript/engine/refresh.d.ts +35 -0
  491. package/lib/typescript/engine/refresh.d.ts.map +1 -0
  492. package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
  493. package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
  494. package/lib/typescript/engine/screens.d.ts +27 -6
  495. package/lib/typescript/engine/screens.d.ts.map +1 -1
  496. package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
  497. package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
  498. package/lib/typescript/interfaces/Events.d.ts +28 -10
  499. package/lib/typescript/interfaces/Events.d.ts.map +1 -1
  500. package/lib/typescript/interfaces/Options.d.ts +1 -1
  501. package/lib/typescript/interfaces/Options.d.ts.map +1 -1
  502. package/lib/typescript/interfaces/options/animations.d.ts +80 -22
  503. package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
  504. package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
  505. package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
  506. package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
  507. package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
  508. package/lib/typescript/interfaces/options/modals.d.ts +34 -26
  509. package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
  510. package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
  511. package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
  512. package/lib/typescript/interfaces/options/stack.d.ts +17 -3
  513. package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
  514. package/lib/typescript/interfaces/options/system.d.ts +18 -11
  515. package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
  516. package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
  517. package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
  518. package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
  519. package/metro/acceptPlugin.js +57 -0
  520. package/metro/babelTransformer.js +45 -0
  521. package/metro/index.js +36 -0
  522. package/package.json +3 -1
  523. package/src/ARCHITECTURE.md +40 -27
  524. package/src/adapters/NativeANNTurboModule.ts +12 -2
  525. package/src/api/app/AppRegistry.ts +16 -2
  526. package/src/api/app/createNavigation.ts +203 -69
  527. package/src/api/commands/commands.ts +48 -7
  528. package/src/api/commands/presentation.ts +4 -3
  529. package/src/api/events/navigationEvents.ts +10 -4
  530. package/src/api/hooks/useNavigation.ts +9 -4
  531. package/src/api/hooks/useSafeAreaInsets.ts +4 -3
  532. package/src/api/index.ts +1 -0
  533. package/src/api/linking/dispatchedLinks.ts +18 -0
  534. package/src/api/linking/linking.ts +22 -1
  535. package/src/api/navigation.ts +4 -1
  536. package/src/api/options/OptionsChain.ts +2 -2
  537. package/src/api/screens/arrangement.ts +17 -4
  538. package/src/api/screens/defineScreen.ts +49 -5
  539. package/src/api/screens/nativeScreens.ts +40 -4
  540. package/src/api/screens/registerScreens.tsx +185 -42
  541. package/src/api/theme/theme.ts +5 -0
  542. package/src/engine/commands.ts +70 -13
  543. package/src/engine/layout.ts +27 -11
  544. package/src/engine/nativeScreens.ts +10 -1
  545. package/src/engine/options.ts +45 -19
  546. package/src/engine/optionsChange.ts +107 -0
  547. package/src/engine/places.ts +65 -7
  548. package/src/engine/props.ts +30 -1
  549. package/src/engine/refresh.ts +97 -0
  550. package/src/engine/rememberedOptions.ts +74 -1
  551. package/src/engine/screens.tsx +76 -21
  552. package/src/interfaces/ComponentEvents.ts +4 -4
  553. package/src/interfaces/Events.ts +29 -10
  554. package/src/interfaces/Options.ts +1 -0
  555. package/src/interfaces/contract/commands.json +101 -0
  556. package/src/interfaces/contract/errors.json +275 -0
  557. package/src/interfaces/options/animations.ts +81 -22
  558. package/src/interfaces/options/bottomTabs.ts +21 -7
  559. package/src/interfaces/options/buttons.ts +23 -15
  560. package/src/interfaces/options/modals.ts +34 -26
  561. package/src/interfaces/options/sideMenu.ts +24 -6
  562. package/src/interfaces/options/stack.ts +17 -3
  563. package/src/interfaces/options/system.ts +18 -11
  564. package/src/interfaces/options/toolbar.ts +2 -2
  565. package/src/interfaces/options/topBar.ts +68 -38
  566. package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
  567. package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
  568. package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
  569. package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
  570. package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
  571. package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
  572. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
  573. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
  574. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
  575. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
  576. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
  577. package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
  578. package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
  579. package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
  580. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
  581. package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
@@ -0,0 +1,219 @@
1
+ package dev.apexnative.navigation.views.stack.topbar.titlebar
2
+
3
+ import android.content.Context
4
+ import android.content.res.ColorStateList
5
+ import android.graphics.drawable.ColorDrawable
6
+ import android.graphics.drawable.Drawable
7
+ import android.view.LayoutInflater
8
+ import android.view.View
9
+ import android.view.ViewGroup
10
+ import android.widget.BaseAdapter
11
+ import android.widget.CompoundButton
12
+ import android.widget.FrameLayout
13
+ import android.widget.ImageView
14
+ import android.widget.PopupWindow
15
+ import android.widget.TextView
16
+ import androidx.appcompat.widget.ListPopupWindow
17
+ import androidx.core.graphics.ColorUtils
18
+ import androidx.core.widget.ImageViewCompat
19
+ import dev.apexnative.navigation.R
20
+ import dev.apexnative.navigation.utils.TestIds
21
+ import kotlin.math.max
22
+
23
+ /**
24
+ * A menu of the top bar, the menu of a button or "⋮": a popup list under [anchor] as AppCompat shows a popup menu, with
25
+ * the theme's style of [styleAttr] (`popupMenuStyle`, or `actionOverflowMenuStyle` for "⋮": its background, shadow,
26
+ * offsets and place over the anchor) and [gravity] against the anchor. A submenu takes the menu's place, under its title.
27
+ * Its [Colors] go over the theme's. Main thread only.
28
+ */
29
+ internal class BarMenu(
30
+ val context: Context,
31
+ private val anchor: View,
32
+ private val gravity: Int,
33
+ private val styleAttr: Int,
34
+ val colors: Colors,
35
+ ) {
36
+ /** The menu's colors over the theme's; none keeps the theme's. */
37
+ class Colors(val background: Int?, val text: Int?)
38
+
39
+ /** How an item shows its check: none, a check box, or a radio button of a single selection. */
40
+ enum class Check { None, Box, Radio }
41
+
42
+ /**
43
+ * An item of the menu: [title], [icon] (tinted already), [enabled], its [check] and whether it is [checked], and
44
+ * either [submenu] (its items, under its title) or [onPick]. [testId] goes on the item's view, [label] is its
45
+ * accessibility label.
46
+ */
47
+ class Entry(
48
+ val title: CharSequence,
49
+ val icon: Drawable?,
50
+ val enabled: Boolean = true,
51
+ val check: Check = Check.None,
52
+ val checked: Boolean = false,
53
+ val submenu: List<Entry>? = null,
54
+ val testId: String? = null,
55
+ val label: CharSequence? = null,
56
+ val onPick: () -> Unit = {},
57
+ )
58
+
59
+ private var popup: ListPopupWindow? = null
60
+ // The level that shows is the top one, not a submenu.
61
+ private var atTop = false
62
+ // The text color of the options, dimmed as Material 3 dims a disabled item.
63
+ private val itemTextColors = colors.text?.let {
64
+ ColorStateList(
65
+ arrayOf(intArrayOf(-android.R.attr.state_enabled), intArrayOf()),
66
+ intArrayOf(ColorUtils.setAlphaComponent(it, DISABLED_ALPHA), it),
67
+ )
68
+ }
69
+ // The menu goes from one level to the next: the level that closes doesn't close the menu.
70
+ private var switching = false
71
+
72
+ /** The menu closed: picked, dismissed, or taken away. */
73
+ var onDismiss: (() -> Unit)? = null
74
+
75
+ /** The menu shows. */
76
+ val isShowing: Boolean
77
+ get() = popup?.isShowing == true
78
+
79
+ /** Shows [entries], the top level, with their icons when [icons]. */
80
+ fun show(entries: List<Entry>, icons: Boolean = entries.any { it.icon != null }) =
81
+ showLevel(entries, null, icons)
82
+
83
+ /** The top level, while it shows, holds [entries] now; a submenu that shows stays. */
84
+ fun update(entries: List<Entry>, icons: Boolean = entries.any { it.icon != null }) {
85
+ val popup = popup?.takeIf { atTop && it.isShowing } ?: return
86
+ val adapter = Adapter(entries, icons)
87
+ popup.setAdapter(adapter)
88
+ popup.setContentWidth(contentWidth(adapter))
89
+ popup.show()
90
+ }
91
+
92
+ /** Closes the menu. */
93
+ fun dismiss() {
94
+ popup?.dismiss()
95
+ }
96
+
97
+ private fun showLevel(entries: List<Entry>, title: CharSequence?, icons: Boolean) {
98
+ val adapter = Adapter(entries, icons)
99
+ val popup = ListPopupWindow(context, null, styleAttr)
100
+ popup.anchorView = anchor
101
+ popup.setDropDownGravity(gravity)
102
+ popup.isModal = true
103
+ // As AppCompat's menus: the menu goes over an open keyboard, which stays.
104
+ popup.inputMethodMode = PopupWindow.INPUT_METHOD_NOT_NEEDED
105
+ popup.setAdapter(adapter)
106
+ popup.setContentWidth(contentWidth(adapter))
107
+ colors.background?.let { color ->
108
+ val background = popup.background?.mutate()
109
+ if (background != null) {
110
+ background.setTint(color)
111
+ popup.setBackgroundDrawable(background)
112
+ } else {
113
+ popup.setBackgroundDrawable(ColorDrawable(color))
114
+ }
115
+ }
116
+ popup.setOnItemClickListener { parent, _, position, _ ->
117
+ val entry = parent.adapter.getItem(position) as? Entry ?: return@setOnItemClickListener
118
+ val submenu = entry.submenu
119
+ if (submenu != null) {
120
+ // The submenu shows where the menu was, as AppCompat shows it.
121
+ switching = true
122
+ popup.dismiss()
123
+ switching = false
124
+ showLevel(submenu, entry.title, submenu.any { it.icon != null })
125
+ } else {
126
+ popup.dismiss()
127
+ entry.onPick()
128
+ }
129
+ }
130
+ popup.setOnDismissListener {
131
+ if (this.popup === popup) this.popup = null
132
+ if (!switching) onDismiss?.invoke()
133
+ }
134
+ this.popup = popup
135
+ atTop = title == null
136
+ popup.show()
137
+ if (title != null) {
138
+ // The list exists once the popup shows; a header added then shows at once.
139
+ popup.listView?.let { list ->
140
+ list.addHeaderView(header(title, list), null, false)
141
+ popup.show()
142
+ }
143
+ }
144
+ }
145
+
146
+ // As wide as the widest item, at most half the screen or 320 dp (AppCompat's rule for its menus).
147
+ private fun contentWidth(adapter: Adapter): Int {
148
+ val parent = FrameLayout(context)
149
+ val spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
150
+ val metrics = context.resources.displayMetrics
151
+ val most = max(metrics.widthPixels / 2, (MAX_WIDTH_DP * metrics.density).toInt())
152
+ var width = 0
153
+ for (index in 0 until adapter.count) {
154
+ val view = adapter.getView(index, null, parent)
155
+ view.measure(spec, spec)
156
+ width = max(width, view.measuredWidth)
157
+ if (width >= most) return most
158
+ }
159
+ return width
160
+ }
161
+
162
+ private fun header(title: CharSequence, parent: ViewGroup): View {
163
+ val view = LayoutInflater.from(context).inflate(R.layout.apex_navigation_menu_header, parent, false)
164
+ view.findViewById<TextView>(R.id.apex_navigation_menu_title).apply {
165
+ text = title
166
+ itemTextColors?.let(::setTextColor)
167
+ }
168
+ return view
169
+ }
170
+
171
+ // The icons show when [icons], as in AppCompat's menus with optional icons shown.
172
+ private inner class Adapter(private val entries: List<Entry>, private val icons: Boolean) : BaseAdapter() {
173
+ override fun getCount(): Int = entries.size
174
+
175
+ override fun getItem(position: Int): Entry = entries[position]
176
+
177
+ override fun getItemId(position: Int): Long = position.toLong()
178
+
179
+ override fun areAllItemsEnabled(): Boolean = false
180
+
181
+ override fun isEnabled(position: Int): Boolean = entries[position].enabled
182
+
183
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
184
+ val view = convertView
185
+ ?: LayoutInflater.from(context).inflate(R.layout.apex_navigation_menu_item, parent, false)
186
+ val entry = entries[position]
187
+ view.isEnabled = entry.enabled
188
+ view.findViewById<TextView>(R.id.apex_navigation_menu_title).apply {
189
+ text = entry.title
190
+ itemTextColors?.let(::setTextColor)
191
+ }
192
+ view.findViewById<ImageView>(R.id.apex_navigation_menu_icon).apply {
193
+ setImageDrawable(entry.icon)
194
+ visibility = if (icons && entry.icon != null) View.VISIBLE else View.GONE
195
+ }
196
+ view.findViewById<ImageView>(R.id.apex_navigation_menu_arrow).apply {
197
+ visibility = if (entry.submenu != null) View.VISIBLE else View.GONE
198
+ ImageViewCompat.setImageTintList(this, colors.text?.let(ColorStateList::valueOf))
199
+ }
200
+ check(view.findViewById(R.id.apex_navigation_menu_check), entry, Check.Box)
201
+ check(view.findViewById(R.id.apex_navigation_menu_radio), entry, Check.Radio)
202
+ view.contentDescription = entry.label
203
+ TestIds.apply(view, entry.testId)
204
+ return view
205
+ }
206
+
207
+ private fun check(button: CompoundButton, entry: Entry, kind: Check) {
208
+ val shown = entry.check == kind
209
+ button.visibility = if (shown) View.VISIBLE else View.GONE
210
+ if (shown) button.isChecked = entry.checked
211
+ }
212
+ }
213
+
214
+ private companion object {
215
+ // AppCompat's `abc_config_prefDialogWidth`.
216
+ const val MAX_WIDTH_DP = 320
217
+ const val DISABLED_ALPHA = 97
218
+ }
219
+ }
@@ -1,6 +1,5 @@
1
1
  package dev.apexnative.navigation.views.stack.topbar.titlebar
2
2
 
3
- import android.annotation.SuppressLint
4
3
  import android.content.Context
5
4
  import android.graphics.Color
6
5
  import android.graphics.Paint
@@ -15,20 +14,12 @@ import android.text.style.MetricAffectingSpan
15
14
  import android.transition.AutoTransition
16
15
  import android.transition.TransitionManager
17
16
  import android.util.TypedValue
17
+ import android.view.ContextThemeWrapper
18
18
  import android.view.Gravity
19
- import android.view.Menu
20
- import android.view.MenuItem
21
19
  import android.view.View
22
- import android.view.ViewGroup
23
20
  import androidx.appcompat.R as AppCompatR
24
21
  import androidx.appcompat.content.res.AppCompatResources
25
- import androidx.appcompat.view.menu.MenuView
26
- import androidx.appcompat.widget.ActionMenuView
27
- import androidx.appcompat.widget.PopupMenu
28
- import androidx.appcompat.widget.TooltipCompat
29
22
  import androidx.core.graphics.drawable.DrawableCompat
30
- import androidx.core.view.MenuItemCompat
31
- import com.google.android.material.appbar.MaterialToolbar
32
23
  import dev.apexnative.navigation.R
33
24
  import dev.apexnative.navigation.options.ButtonMenuOptions
34
25
  import dev.apexnative.navigation.options.ButtonOptions
@@ -36,18 +27,17 @@ import dev.apexnative.navigation.options.parsers.TypefaceLoader
36
27
  import dev.apexnative.navigation.utils.MaterialTheme
37
28
  import dev.apexnative.navigation.utils.TestIds
38
29
  import dev.apexnative.navigation.utils.UiUtils
39
- import java.util.WeakHashMap
30
+ import kotlin.math.roundToInt
40
31
 
41
32
  /**
42
- * The buttons of one side of the bar in its toolbar: each button a menu item — a text, an icon (on its background), or
43
- * a React button's cell as the item's action view —, in the bar or in "⋮" as [set] says, with the `overflowMenu` items
44
- * first in "⋮". A press sends the button's id; a button with a `menu` opens it under the button (in "⋮" or not laid
45
- * out: at the bar's end), or on a long press with `menuOnLongPress`. The views of the items get their `testID`s after
46
- * each layout of the toolbar, which makes them again. Main thread only.
33
+ * The buttons of one side of the bar in its [ButtonRow]: each button a view of its own — a text or an icon (on its
34
+ * background) as a toolbar draws its items ([BarButtonView]), or a React button's cell —, in the bar or in "⋮" as
35
+ * [set] says, with the `overflowMenu` items first in "⋮". A press sends the button's id; a button with a `menu` opens
36
+ * it under the button (in "⋮": at the bar's end), or on a long press with `menuOnLongPress`. A button keeps its view
37
+ * while its id stays, and the view takes its `testID` as it is set. Main thread only.
47
38
  */
48
39
  internal class ButtonBar(
49
- private val toolbar: MaterialToolbar,
50
- private val left: Boolean,
40
+ private val row: ButtonRow,
51
41
  private val loadIcon: (String) -> Drawable?,
52
42
  private val host: Host,
53
43
  ) {
@@ -62,97 +52,139 @@ internal class ButtonBar(
62
52
  /** The menu of the button [buttonId] as the screen's options give it now; none. */
63
53
  fun menuOf(buttonId: String): ButtonMenuOptions?
64
54
 
65
- /** The `testID` of an item the side holds besides its buttons (the search's magnifier); none. */
66
- fun testIdOf(item: MenuItem): String? = null
55
+ /** The colors of the bar's menus as the screen's options give them now (`topBar.menu*Color`). */
56
+ fun menuColors(): BarMenu.Colors
67
57
  }
68
58
 
69
59
  /** One button as the bar shows it: its options with the side's colors on them, and its React cell if it has one. */
70
60
  class Button(val options: ButtonOptions, val cell: BarButtonComponentCell?)
71
61
 
72
- private val context: Context = toolbar.context
62
+ private val context: Context = row.context
73
63
  private val typefaces = TypefaceLoader(context)
74
- private val itemIds = HashMap<MenuItem, ButtonOptions>()
75
- private var overflowTestId: String? = null
76
- private var popup: PopupMenu? = null
77
- private var watched: ActionMenuView? = null
78
- // The item views that have the long press of a menu.
79
- private val hooked = WeakHashMap<View, Boolean>()
80
-
81
- init {
82
- toolbar.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> applyViewIds() }
83
- }
64
+ // The views of the buttons in the bar by their ids, kept from one set to the next.
65
+ private var views = HashMap<String, BarButtonView>()
66
+ private var overflowMenu: ButtonMenuOptions? = null
67
+ private var inOverflow: List<ButtonOptions> = emptyList()
68
+ private var popup: BarMenu? = null
69
+ private var overflowPopup: BarMenu? = null
84
70
 
85
71
  /**
86
- * The buttons of the side: [inBar] in the bar, [inOverflow] in "⋮" (the right side; the left one keeps all in
87
- * the bar), each in the list's order; [overflow], the items of `overflowMenu` (right side). [animated]: the change
88
- * goes with an `AutoTransition` (`animateLeftButtons` / `animateRightButtons`).
72
+ * The buttons of the side: [line] in the bar, in the line's order from its start; [inOverflow] in "⋮" (the right
73
+ * side; the left one keeps all in the bar), in the list's order; [overflow], the items of `overflowMenu` (right
74
+ * side). [animated]: the change goes with an `AutoTransition` (`animateLeftButtons` / `animateRightButtons`).
89
75
  */
90
- fun set(inBar: List<Button>, inOverflow: List<Button>, overflow: ButtonMenuOptions?, animated: Boolean) {
91
- if (animated && toolbar.isLaidOut) TransitionManager.beginDelayedTransition(toolbar, AutoTransition())
92
- val menu = toolbar.menu
93
- menu.clear()
94
- itemIds.clear()
95
- var order = 0
96
- overflow?.let {
97
- ButtonMenus.fill(context, menu, OVERFLOW_GROUP, 0, it, MenuItem.SHOW_AS_ACTION_NEVER, loadIcon) { id ->
98
- host.picked(null, id)
99
- }
100
- order = it.items.size
76
+ fun set(line: List<Button>, inOverflow: List<Button>, overflow: ButtonMenuOptions?, animated: Boolean) {
77
+ if (animated && row.isLaidOut) TransitionManager.beginDelayedTransition(row, AutoTransition())
78
+ val kept = this.views
79
+ this.views = HashMap()
80
+ val views = line.mapNotNull { button ->
81
+ val id = button.options.id.get(null) ?: return@mapNotNull null
82
+ button.cell?.let { return@mapNotNull cellOf(it, button.options) }
83
+ val view = kept.remove(id)?.takeIf { id !in this.views } ?: BarButtonView(context)
84
+ this.views[id] = view
85
+ bind(view, id, button.options)
101
86
  }
102
- overflowTestId = overflow?.testID
103
- inOverflow.forEachIndexed { index, button -> add(menu, button, OVERFLOW_ORDER + order + index, false) }
104
- inBar.forEachIndexed { index, button ->
105
- // The first right button is the last of the line: the menu lays its items out in their order.
106
- val place = if (left) index else inBar.size - 1 - index
107
- add(menu, button, BAR_ORDER + place, true)
87
+ row.setButtons(views)
88
+ overflowMenu = overflow
89
+ this.inOverflow = inOverflow.map { it.options }.filter { it.id.get(null) != null }
90
+ val showsOverflow = overflow != null || this.inOverflow.isNotEmpty()
91
+ if (showsOverflow) {
92
+ val button = row.overflowButton
93
+ button.setOnClickListener { openOverflow(it) }
94
+ TestIds.apply(button, overflow?.testID)
95
+ }
96
+ row.setOverflowShown(showsOverflow)
97
+ // An open "⋮" shows what it holds now.
98
+ overflowPopup?.let { menu ->
99
+ if (showsOverflow) {
100
+ menu.update(overflowEntries(menu.context, menu.colors.text), overflowIcons())
101
+ } else {
102
+ menu.dismiss()
103
+ }
108
104
  }
109
- toolbar.post { applyViewIds() }
110
105
  }
111
106
 
112
107
  /** The color of "⋮" (`rightButtonColor`, else `colorOnSurfaceVariant`). */
113
- fun setOverflowColor(color: Int) {
114
- val icon = toolbar.overflowIcon ?: return
115
- val tinted = DrawableCompat.wrap(icon.mutate())
116
- DrawableCompat.setTint(tinted, color)
117
- toolbar.overflowIcon = tinted
118
- }
108
+ fun setOverflowColor(color: Int) = row.setOverflowColor(color)
119
109
 
120
110
  /** An open menu of the side closes: the bar shows another screen. */
121
111
  fun closeMenus() {
122
112
  popup?.dismiss()
123
113
  popup = null
124
- toolbar.dismissPopupMenus()
114
+ overflowPopup?.dismiss()
115
+ overflowPopup = null
116
+ }
117
+
118
+ // A React button's cell: its label and its `testID` on the cell, the press its content's own.
119
+ private fun cellOf(cell: BarButtonComponentCell, options: ButtonOptions): View {
120
+ cell.contentDescription = options.accessibilityLabel.get(null)
121
+ TestIds.apply(cell, options.testID.get(null))
122
+ return cell
125
123
  }
126
124
 
127
- private fun add(menu: Menu, button: Button, order: Int, inBar: Boolean) {
128
- val options = button.options
129
- val id = options.id.get(null) ?: return
130
- val item = menu.add(BUTTONS_GROUP, Menu.NONE, order, titleOf(options))
131
- itemIds[item] = options
125
+ // A text or icon button: its look, its press and long press, its `testID`. The long press shows the tooltip, or
126
+ // opens the menu of a button with `menuOnLongPress`.
127
+ private fun bind(view: BarButtonView, id: String, options: ButtonOptions): View {
132
128
  val enabled = !options.enabled.isFalse
133
- item.isEnabled = enabled
134
- if (inBar) {
135
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
136
- } else {
137
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
138
- }
139
- val cell = button.cell
140
- if (cell != null) {
141
- item.actionView = cell
142
- cell.contentDescription = options.accessibilityLabel.get(null)
143
- } else {
144
- iconOf(options, enabled)?.let { item.icon = it }
145
- options.accessibilityLabel.get(null)?.let { MenuItemCompat.setContentDescription(item, it) }
146
- }
147
- item.setOnMenuItemClickListener {
148
- val menuOptions = host.menuOf(id)
149
- if (cell == null && menuOptions != null && !options.menuOnLongPress.isTrue) {
150
- openMenu(id, menuOptions, viewOf(item))
151
- } else if (cell == null) {
152
- host.pressed(id)
129
+ view.isEnabled = enabled
130
+ view.restyle()
131
+ val longPressMenu = options.menuOnLongPress.isTrue && host.menuOf(id) != null
132
+ view.setOnLongClickListener(null)
133
+ // A listener, even none, makes the view long-clickable: TalkBack would offer a long press that does nothing.
134
+ view.isLongClickable = false
135
+ view.show(titleOf(options), iconOf(options, enabled), options.accessibilityLabel.get(null), !longPressMenu)
136
+ if (longPressMenu) {
137
+ view.setOnLongClickListener { pressed ->
138
+ val menu = host.menuOf(id) ?: return@setOnLongClickListener false
139
+ openMenu(id, menu, pressed)
140
+ true
153
141
  }
154
- true
155
142
  }
143
+ view.setOnClickListener { pressed -> press(id, options, pressed) }
144
+ TestIds.apply(view, options.testID.get(null))
145
+ return view
146
+ }
147
+
148
+ // A press: the button's menu opens under [anchor] (at the bar's end without one), or the press goes to the screen.
149
+ private fun press(id: String, options: ButtonOptions, anchor: View?) {
150
+ val menu = host.menuOf(id)
151
+ if (menu != null && !options.menuOnLongPress.isTrue) openMenu(id, menu, anchor) else host.pressed(id)
152
+ }
153
+
154
+ // "⋮" opens as a toolbar opens it: the theme's overflow popup from the end of the button, in the bar's popup theme.
155
+ private fun openOverflow(anchor: View) {
156
+ closeMenus()
157
+ val popupTheme = MaterialTheme.popupTheme(context)
158
+ val themed = if (popupTheme != 0) ContextThemeWrapper(context, popupTheme) else context
159
+ val colors = host.menuColors()
160
+ val menu = BarMenu(themed, anchor, Gravity.END, AppCompatR.attr.actionOverflowMenuStyle, colors)
161
+ menu.onDismiss = { if (overflowPopup === menu) overflowPopup = null }
162
+ overflowPopup = menu
163
+ menu.show(overflowEntries(themed, colors.text), overflowIcons())
164
+ }
165
+
166
+ // The icons of "⋮" show when an `overflowMenu` item has one, the moved buttons' icons with them.
167
+ private fun overflowIcons(): Boolean = overflowMenu?.items.orEmpty().any { it.icon != null }
168
+
169
+ // The `overflowMenu` items, then the buttons that don't fit in the bar, in the list's order; a button keeps its own
170
+ // color.
171
+ private fun overflowEntries(themed: Context, textColor: Int?): List<BarMenu.Entry> {
172
+ val items = overflowMenu?.let {
173
+ ButtonMenus.entries(themed, it, textColor, loadIcon) { id -> host.picked(null, id) }
174
+ }.orEmpty()
175
+ val buttons = inOverflow.mapNotNull { options ->
176
+ val id = options.id.get(null) ?: return@mapNotNull null
177
+ val enabled = !options.enabled.isFalse
178
+ BarMenu.Entry(
179
+ titleOf(options),
180
+ iconOf(options, enabled),
181
+ enabled = enabled,
182
+ testId = options.testID.get(null),
183
+ label = options.accessibilityLabel.get(null),
184
+ onPick = { press(id, options, null) },
185
+ )
186
+ }
187
+ return items + buttons
156
188
  }
157
189
 
158
190
  // The text of a button: its font (missing weight or italic made synthetically), its size in sp, its color, its
@@ -171,7 +203,7 @@ internal class ButtonBar(
171
203
  options.fontSize.get(0.0).toFloat(),
172
204
  context.resources.displayMetrics,
173
205
  )
174
- spannable.setSpan(AbsoluteSizeSpan(size.toInt()), 0, text.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
206
+ spannable.setSpan(AbsoluteSizeSpan(size.roundToInt()), 0, text.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
175
207
  }
176
208
  if (options.font.hasValue()) {
177
209
  val typeface = options.font.getTypeface(typefaces, Typeface.DEFAULT)
@@ -207,8 +239,8 @@ internal class ButtonBar(
207
239
  icon,
208
240
  color,
209
241
  UiUtils.dpToPx(context, background.cornerRadius.get(0.0).toFloat()),
210
- UiUtils.dpToPx(context, background.width.get(0.0).toFloat()).toInt(),
211
- UiUtils.dpToPx(context, background.height.get(0.0).toFloat()).toInt(),
242
+ UiUtils.dpToPx(context, background.width.get(0.0).toFloat()).roundToInt(),
243
+ UiUtils.dpToPx(context, background.height.get(0.0).toFloat()).roundToInt(),
212
244
  )
213
245
  }
214
246
 
@@ -217,93 +249,12 @@ internal class ButtonBar(
217
249
  if (options.items.isEmpty()) return
218
250
  popup?.dismiss()
219
251
  val themed = MaterialTheme.context(context)
220
- val menu = if (anchor != null) {
221
- PopupMenu(themed, anchor)
222
- } else {
223
- PopupMenu(themed, toolbar, Gravity.END)
224
- }
225
- ButtonMenus.fill(themed, menu.menu, Menu.NONE, 0, options, null, loadIcon) { id -> host.picked(buttonId, id) }
226
- menu.setOnDismissListener { if (popup === menu) popup = null }
252
+ val colors = host.menuColors()
253
+ val gravity = if (anchor != null) Gravity.START else Gravity.END
254
+ val menu = BarMenu(themed, anchor ?: row, gravity, AppCompatR.attr.popupMenuStyle, colors)
255
+ menu.onDismiss = { if (popup === menu) popup = null }
227
256
  popup = menu
228
- menu.show()
229
- }
230
-
231
- // The view of [item] in the bar; none in "⋮" or before the bar laid it out.
232
- private fun viewOf(item: MenuItem): View? {
233
- val menuView = actionMenuView() ?: return null
234
- for (index in 0 until menuView.childCount) {
235
- val child = menuView.getChildAt(index)
236
- if (itemOf(child) === item || item.actionView === child) return child
237
- }
238
- return null
239
- }
240
-
241
- private fun actionMenuView(): ActionMenuView? {
242
- for (index in 0 until toolbar.childCount) {
243
- val child = toolbar.getChildAt(index)
244
- if (child is ActionMenuView) return child
245
- }
246
- return null
247
- }
248
-
249
- // AppCompat gives an item's view no public way back to its item: the item view's own interface, which only
250
- // AppCompat's own views implement, is read and never changed.
251
- @SuppressLint("RestrictedApi")
252
- private fun itemOf(view: View): MenuItem? = (view as? MenuView.ItemView)?.itemData
253
-
254
- // The `testID`s of the item views: the bar makes its views again, so after every layout; a view used again without
255
- // one loses the one it had. "⋮" by AppCompat's description of it. A long press opens the menu of a button with
256
- // `menuOnLongPress`: the handler finds the item by the view pressed.
257
- private fun applyViewIds() {
258
- val menuView = actionMenuView() ?: return
259
- if (watched !== menuView) {
260
- watched = menuView
261
- menuView.setOnHierarchyChangeListener(object : ViewGroup.OnHierarchyChangeListener {
262
- override fun onChildViewAdded(parent: View?, child: View?) {
263
- toolbar.post { applyViewIds() }
264
- }
265
-
266
- override fun onChildViewRemoved(parent: View?, child: View?) = Unit
267
- })
268
- }
269
- val overflowDescription = context.getString(AppCompatR.string.abc_action_menu_overflow_description)
270
- for (index in 0 until menuView.childCount) {
271
- val child = menuView.getChildAt(index)
272
- val item = itemOf(child) ?: itemIds.keys.firstOrNull { it.actionView === child }
273
- val options = item?.let(itemIds::get)
274
- when {
275
- options != null -> {
276
- TestIds.apply(child, options.testID.get(null))
277
- if (child !is BarButtonComponentCell) longPressOf(child, options)
278
- }
279
- child.contentDescription == overflowDescription -> TestIds.apply(child, overflowTestId)
280
- item != null -> TestIds.apply(child, host.testIdOf(item))
281
- else -> Unit
282
- }
283
- }
284
- }
285
-
286
- // The toolbar uses its item views again for other items: the handler finds the button by the view pressed, at the
287
- // press, and a view that no longer needs it gets the toolbar's tooltip back.
288
- private fun longPressOf(view: View, options: ButtonOptions) {
289
- val id = options.id.get(null)
290
- if (id != null && options.menuOnLongPress.isTrue && host.menuOf(id) != null) {
291
- hooked[view] = true
292
- view.setOnLongClickListener { pressed -> openOnLongPress(pressed) }
293
- return
294
- }
295
- if (hooked.remove(view) == null) return
296
- view.setOnLongClickListener(null)
297
- itemOf(view)?.let { TooltipCompat.setTooltipText(view, MenuItemCompat.getTooltipText(it) ?: it.title) }
298
- }
299
-
300
- private fun openOnLongPress(pressed: View): Boolean {
301
- val options = itemOf(pressed)?.let(itemIds::get) ?: return false
302
- val id = options.id.get(null) ?: return false
303
- if (!options.menuOnLongPress.isTrue) return false
304
- val menu = host.menuOf(id) ?: return false
305
- openMenu(id, menu, pressed)
306
- return true
257
+ menu.show(ButtonMenus.entries(themed, options, colors.text, loadIcon) { id -> host.picked(buttonId, id) })
307
258
  }
308
259
 
309
260
  // A font of the options on a button's text, with the weight and the slant the typeface lacks drawn synthetically.
@@ -322,10 +273,6 @@ internal class ButtonBar(
322
273
  }
323
274
 
324
275
  private companion object {
325
- const val BUTTONS_GROUP = 1
326
- const val OVERFLOW_GROUP = 2
327
- const val OVERFLOW_ORDER = 100
328
- const val BAR_ORDER = 1000
329
276
  const val CLOSE = "close"
330
277
  const val BOLD_WEIGHT = 600
331
278
  const val ITALIC_SKEW = -0.25f