@apexnative/navigation 1.0.0-alpha.0 → 1.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +128 -0
- package/README.md +147 -51
- package/android/CLAUDE.md +78 -25
- package/android/CORE.md +49 -25
- package/android/RECIPES.md +13 -6
- package/android/consumer-rules.pro +6 -0
- package/android/src/main/java/dev/apexnative/navigation/NavigationActivity.kt +85 -10
- package/android/src/main/java/dev/apexnative/navigation/NavigationApplication.kt +34 -13
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutChecks.kt +5 -1
- package/android/src/main/java/dev/apexnative/navigation/layout/LayoutNode.kt +6 -2
- package/android/src/main/java/dev/apexnative/navigation/nativescreen/NativeScreenContext.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/AnimationsOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/BottomTabsOptions.kt +13 -8
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonMenuOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/ButtonOptions.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/options/HardwareBackButtonOptions.kt +9 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LargeTitleOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/LayoutAnimation.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/OptionKey.kt +18 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionPaths.kt +91 -0
- package/android/src/main/java/dev/apexnative/navigation/options/OptionsCache.kt +8 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SheetOptions.kt +7 -4
- package/android/src/main/java/dev/apexnative/navigation/options/SideMenuOptions.kt +6 -1
- package/android/src/main/java/dev/apexnative/navigation/options/StackAnimationOptions.kt +40 -2
- package/android/src/main/java/dev/apexnative/navigation/options/StatusBarOptions.kt +7 -3
- package/android/src/main/java/dev/apexnative/navigation/options/TitleOptions.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarAppearanceOptions.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/options/TopBarOptions.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/options/UserChoices.kt +159 -0
- package/android/src/main/java/dev/apexnative/navigation/react/CommandAnswer.kt +29 -36
- package/android/src/main/java/dev/apexnative/navigation/react/CommandContract.kt +59 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentHeights.kt +95 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ContentMounts.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ErrorTexts.kt +75 -60
- package/android/src/main/java/dev/apexnative/navigation/react/Hinge.kt +35 -23
- package/android/src/main/java/dev/apexnative/navigation/react/NavigationTurboModule.kt +12 -7
- package/android/src/main/java/dev/apexnative/navigation/react/OptionsCommands.kt +42 -4
- package/android/src/main/java/dev/apexnative/navigation/react/PendingCalls.kt +48 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ReactView.kt +54 -20
- package/android/src/main/java/dev/apexnative/navigation/react/ReloadCoordinator.kt +7 -6
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenEnvironment.kt +177 -0
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenRegions.kt +19 -50
- package/android/src/main/java/dev/apexnative/navigation/react/ScrollEvents.kt +49 -128
- package/android/src/main/java/dev/apexnative/navigation/react/events/AppearanceDispatcher.kt +50 -81
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventContract.kt +226 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/EventEmitter.kt +135 -94
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationState.kt +154 -0
- package/android/src/main/java/dev/apexnative/navigation/react/events/ScreenAppearance.kt +0 -6
- package/android/src/main/java/dev/apexnative/navigation/safearea/SafeAreaView.kt +12 -10
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotContainers.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotScreenView.kt +39 -19
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotView.kt +16 -4
- package/android/src/main/java/dev/apexnative/navigation/slots/SlotViews.kt +40 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageKey.kt +66 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageLoader.kt +7 -89
- package/android/src/main/java/dev/apexnative/navigation/utils/ImageRequests.kt +76 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/MaterialTheme.kt +5 -6
- package/android/src/main/java/dev/apexnative/navigation/utils/OptionImages.kt +262 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/SystemAnimations.kt +36 -0
- package/android/src/main/java/dev/apexnative/navigation/utils/UiUtils.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewController.kt +3 -1
- package/android/src/main/java/dev/apexnative/navigation/utils/ViewExtensions.kt +0 -13
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementController.kt +10 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/SecondaryScreenPresenter.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/AppliedTabCalls.kt +49 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsCollapseBehavior.kt +5 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsController.kt +108 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/BottomTabsPresenter.kt +25 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowGeometry.kt +22 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabItems.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/TabsRoom.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentPresenter.kt +28 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ComponentViewController.kt +12 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ContentReadiness.kt +2 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/RenderWait.kt +27 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenFrame.kt +1 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenReadiness.kt +103 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/component/ScreenSafeArea.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/externalcomponent/ExternalComponentViewController.kt +2 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalAnimations.kt +22 -24
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalCoordinator.kt +109 -21
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalRecord.kt +21 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalSheet.kt +476 -73
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/ModalViews.kt +57 -25
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetBack.kt +42 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/modal/SheetStops.kt +83 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackCheck.kt +50 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/BackCallbackState.kt +49 -14
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/Navigator.kt +71 -12
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/navigator/RootCoordinator.kt +37 -11
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/overlay/OverlayCoordinator.kt +10 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/Capabilities.kt +11 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ContainerBackground.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/parent/ParentController.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuController.kt +42 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuMotion.kt +19 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuPresenter.kt +16 -7
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/sidemenu/SideMenuRules.kt +43 -4
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitPanes.kt +23 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/splitview/SplitViewController.kt +77 -17
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/BackPreview.kt +315 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/PreparedFrame.kt +3 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackCommands.kt +30 -20
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackController.kt +216 -18
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackDisplay.kt +26 -1
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackQueue.kt +149 -41
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackTransitions.kt +26 -8
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/StackViews.kt +115 -6
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabMotion.kt +142 -0
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/fab/FabPresenter.kt +222 -48
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/ScreenSearch.kt +3 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/search/StackSearchPresenter.kt +30 -34
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarComponents.kt +5 -51
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/BarRowTransition.kt +3 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/ButtonPlaces.kt +11 -5
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/MenuChecks.kt +13 -56
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarPresenter.kt +219 -54
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/stack/topbar/TopBarVisibility.kt +9 -2
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ScrollEventListener.kt +6 -9
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/viewcontroller/ViewController.kt +75 -21
- package/android/src/main/java/dev/apexnative/navigation/views/animations/AnimationLayer.kt +73 -0
- package/android/src/main/java/dev/apexnative/navigation/views/animations/Curves.kt +29 -11
- package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt +14 -0
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabs.kt +9 -7
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt +61 -2
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt +0 -5
- package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomTabRow.kt +72 -10
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStep.kt +31 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementTransitions.kt +143 -135
- package/android/src/main/java/dev/apexnative/navigation/views/element/TargetsWait.kt +13 -5
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionLayer.kt +37 -112
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionTargets.kt +9 -6
- package/android/src/main/java/dev/apexnative/navigation/views/element/TransitionViews.kt +100 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ElementPictures.kt +112 -4
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/FlightGeometry.kt +346 -36
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMorph.kt +199 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/SharedAnimatorFactory.kt +56 -41
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextMorph.kt +176 -0
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewMorph.kt +108 -0
- package/android/src/main/java/dev/apexnative/navigation/views/sidemenu/SideMenuView.kt +12 -3
- package/android/src/main/java/dev/apexnative/navigation/views/stack/ScreenEdge.kt +45 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/StackLayout.kt +140 -1
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/Fab.kt +14 -10
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabCopy.kt +85 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/fab/FabMenu.kt +13 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TitleBar.kt +5 -17
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/TopBar.kt +73 -34
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonComponentCell.kt +6 -6
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarButtonView.kt +113 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/BarMenu.kt +219 -0
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonBar.kt +125 -178
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonMenus.kt +34 -64
- package/android/src/main/java/dev/apexnative/navigation/views/stack/topbar/titlebar/ButtonRow.kt +216 -0
- package/android/src/main/jni/ANNContentHeights.cpp +82 -0
- package/android/src/main/res/drawable/apex_navigation_ic_arrow_right.xml +14 -0
- package/android/src/main/res/layout/apex_navigation_menu_header.xml +19 -0
- package/android/src/main/res/layout/apex_navigation_menu_item.xml +68 -0
- package/android/src/main/res/values/styles.xml +1 -1
- package/android/src/main/res/values-night/styles.xml +1 -1
- package/cli/app.js +1 -1
- package/cli/doctor/checks/app.js +77 -14
- package/cli/doctor/checks/splash.js +4 -22
- package/cli/migrate/native.js +18 -0
- package/cli/project.js +10 -2
- package/cli/setup/index.js +18 -0
- package/cli/setup/source.js +2 -1
- package/cli/setup/steps/appDelegate.js +66 -11
- package/cli/setup/steps/mainApplication.js +134 -19
- package/cli/setup/steps/metro.js +46 -0
- package/cli/setup/steps/sceneDelegate.js +108 -0
- package/cli/splash/index.js +3 -1
- package/cli/upgrade/changelog.js +2 -2
- package/docs-md/architecture/native-screens.md +4 -0
- package/docs-md/architecture/theme-and-context.md +131 -12
- package/docs-md/architecture/transitions.md +58 -12
- package/docs-md/containers/modals.md +8 -4
- package/docs-md/containers/overlays.md +3 -1
- package/docs-md/containers/side-menu.md +19 -2
- package/docs-md/containers/tabs.md +5 -1
- package/docs-md/flows/bottom-sheets.md +4 -2
- package/docs-md/flows/forms-in-a-modal.md +1 -1
- package/docs-md/fundamentals/screens-and-props.md +9 -1
- package/docs-md/fundamentals/starting-the-app.md +1 -1
- package/docs-md/guides/cli.md +4 -3
- package/docs-md/guides/deep-links.md +15 -33
- package/docs-md/help/glossary.md +4 -4
- package/docs-md/help/troubleshooting.md +44 -6
- package/docs-md/index.json +57 -1
- package/docs-md/migration/from-expo-router.md +1 -1
- package/docs-md/migration/from-react-native-navigation.md +9 -3
- package/docs-md/migration/from-react-navigation.md +2 -2
- package/docs-md/screen-ui/back-and-gestures.md +46 -2
- package/docs-md/screen-ui/bar-buttons.md +5 -5
- package/docs-md/screen-ui/search.md +1 -1
- package/docs-md/screen-ui/system-ui.md +17 -12
- package/docs-md/screen-ui/toolbar-and-fab.md +4 -2
- package/docs-md/screen-ui/top-bar.md +8 -4
- package/docs-md/start/installation.md +21 -3
- package/ios/Animations/ANNFrameDriver.h +55 -15
- package/ios/Animations/ANNFrameDriver.mm +216 -60
- package/ios/Animations/ANNTransitionAnimator.h +26 -5
- package/ios/Animations/ANNTransitionAnimator.mm +61 -13
- package/ios/Animations/ANNTransitionPlan.h +2 -2
- package/ios/Animations/ANNTransitionPlan.mm +10 -0
- package/ios/Animations/ANNTransitionWait.mm +6 -7
- package/ios/Animations/Elements/ANNElementFinder.h +57 -0
- package/ios/Animations/Elements/ANNElementFinder.mm +174 -2
- package/ios/Animations/Elements/ANNElementTransition.h +10 -8
- package/ios/Animations/Elements/ANNElementTransition.mm +19 -21
- package/ios/Animations/Elements/ANNSharedElementFlight.h +16 -11
- package/ios/Animations/Elements/ANNSharedElementFlight.mm +308 -69
- package/ios/Animations/Interpolators/ANNInterpolate.h +2 -30
- package/ios/Animations/Interpolators/ANNTransformParts.h +48 -0
- package/ios/Animations/Interpolators/ANNTransformParts.mm +507 -0
- package/ios/Animations/Interpolators/ANNViewTracks.h +9 -6
- package/ios/Animations/Interpolators/ANNViewTracks.mm +100 -30
- package/ios/CLAUDE.md +60 -24
- package/ios/CORE.md +44 -34
- package/ios/Contract/ANNCommandAnswer.h +13 -5
- package/ios/Contract/ANNCommandAnswer.mm +40 -32
- package/ios/Contract/ANNCommandContract.h +15 -0
- package/ios/Contract/ANNCommandContract.mm +78 -0
- package/ios/Contract/ANNCommandRunner.h +10 -9
- package/ios/Contract/ANNCommandRunner.mm +22 -28
- package/ios/Contract/ANNErrorTexts.h +6 -2
- package/ios/Contract/ANNErrorTexts.mm +18 -10
- package/ios/Contract/ANNLayoutNode.h +3 -3
- package/ios/Contract/ANNLayoutReader.h +3 -3
- package/ios/Core/ANNAppDelegate.mm +0 -2
- package/ios/Core/ANNAppearanceDispatcher.h +5 -4
- package/ios/Core/ANNAppearanceDispatcher.mm +12 -1
- package/ios/Core/ANNDeepLinkQueue.h +22 -2
- package/ios/Core/ANNDeepLinkQueue.mm +121 -14
- package/ios/Core/ANNErrorHandler.h +9 -4
- package/ios/Core/ANNErrorHandler.mm +20 -2
- package/ios/Core/ANNEventContract.h +246 -0
- package/ios/Core/ANNEventContract.mm +225 -0
- package/ios/Core/ANNEventEmitter.h +6 -2
- package/ios/Core/ANNEventEmitter.mm +117 -80
- package/ios/Core/ANNHinge.h +6 -0
- package/ios/Core/ANNHinge.mm +15 -4
- package/ios/Core/ANNJavaScriptCalls.h +33 -0
- package/ios/Core/ANNJavaScriptCalls.mm +52 -0
- package/ios/Core/ANNLayoutProtocol.h +5 -5
- package/ios/Core/ANNNavigationState.h +7 -5
- package/ios/Core/ANNNavigationState.mm +8 -7
- package/ios/Core/ANNNodeHelper.h +32 -12
- package/ios/Core/ANNNodeHelper.mm +100 -3
- package/ios/Core/ANNParking.h +5 -4
- package/ios/Core/ANNReloadCoordinator.mm +5 -12
- package/ios/Core/ANNRenderWait.h +20 -6
- package/ios/Core/ANNRenderWait.mm +143 -56
- package/ios/Core/ANNSceneDelegate.mm +25 -15
- package/ios/Core/ANNSystemUI.h +3 -2
- package/ios/Core/ANNSystemUI.mm +7 -0
- package/ios/Core/ANNUtils.h +7 -0
- package/ios/Core/ANNUtils.mm +10 -0
- package/ios/Core/ApexNavigation+Internal.h +1 -1
- package/ios/Core/ApexNavigation.mm +7 -6
- package/ios/Core/UIViewController+LayoutProtocol.h +9 -2
- package/ios/Core/UIViewController+LayoutProtocol.mm +8 -0
- package/ios/Layouts/Arrangement/ANNArrangementState.h +2 -17
- package/ios/Layouts/Arrangement/ANNArrangementState.mm +0 -38
- package/ios/Layouts/Arrangement/ANNArrangementViewController.mm +10 -8
- package/ios/Layouts/Modal/ANNModalCoordinator.h +1 -1
- package/ios/Layouts/Modal/ANNModalCoordinator.mm +57 -16
- package/ios/Layouts/Modal/ANNModalPresentation.h +8 -5
- package/ios/Layouts/Modal/ANNModalPresentation.mm +12 -12
- package/ios/Layouts/Modal/ANNSheetPresenter.mm +83 -1
- package/ios/Layouts/Overlay/ANNOverlayCoordinator.mm +2 -8
- package/ios/Layouts/Root/ANNRootCoordinator.mm +58 -19
- package/ios/Layouts/Root/ANNSplashViewController.h +5 -3
- package/ios/Layouts/Root/ANNSplashViewController.mm +147 -0
- package/ios/Layouts/Screen/ANNComponentPresenter.h +11 -3
- package/ios/Layouts/Screen/ANNComponentPresenter.mm +34 -6
- package/ios/Layouts/Screen/ANNComponentViewController.h +15 -13
- package/ios/Layouts/Screen/ANNComponentViewController.mm +130 -75
- package/ios/Layouts/Screen/ANNNativeScreenContext.mm +7 -5
- package/ios/Layouts/Screen/ANNPreviewInteraction.h +7 -4
- package/ios/Layouts/Screen/ANNPreviewInteraction.mm +72 -10
- package/ios/Layouts/Screen/ANNScreenEnvironment.h +63 -0
- package/ios/Layouts/Screen/ANNScreenEnvironment.mm +181 -0
- package/ios/Layouts/Screen/ANNScreenPlace.h +53 -0
- package/ios/Layouts/Screen/ANNScreenPlace.mm +205 -0
- package/ios/Layouts/Screen/ANNScreenRegions.h +3 -18
- package/ios/Layouts/Screen/ANNScreenRegions.mm +9 -44
- package/ios/Layouts/Screen/ANNScreenSafeArea.h +4 -9
- package/ios/Layouts/Screen/ANNScreenSafeArea.mm +14 -16
- package/ios/Layouts/Screen/ANNScreenSettling.h +32 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +137 -0
- package/ios/Layouts/SideMenu/ANNSideMenuTypes.h +8 -0
- package/ios/Layouts/SideMenu/ANNSideMenuViewController.mm +83 -14
- package/ios/Layouts/SplitView/ANNSplitViewCommands.h +3 -2
- package/ios/Layouts/SplitView/ANNSplitViewCommands.mm +105 -39
- package/ios/Layouts/SplitView/ANNSplitViewController.mm +7 -8
- package/ios/Layouts/Stack/ANNPreviewPush.h +7 -6
- package/ios/Layouts/Stack/ANNPreviewPush.mm +142 -27
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.h +11 -2
- package/ios/Layouts/Stack/ANNStackAnimatingDelegate.mm +14 -7
- package/ios/Layouts/Stack/ANNStackCommands.mm +1 -0
- package/ios/Layouts/Stack/ANNStackController.h +8 -0
- package/ios/Layouts/Stack/ANNStackController.mm +184 -16
- package/ios/Layouts/Stack/ANNStackQueue.h +5 -2
- package/ios/Layouts/Stack/ANNStackQueue.mm +56 -43
- package/ios/Layouts/Stack/ANNSwipePopInteraction.h +26 -0
- package/ios/Layouts/Stack/ANNSwipePopInteraction.mm +185 -0
- package/ios/Layouts/Stack/InteractivePopGestureDelegate.mm +28 -4
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.h +4 -2
- package/ios/Layouts/Stack/UINavigationController+ANNCommands.mm +2 -3
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.h +4 -0
- package/ios/Layouts/Tabs/ANNBottomTabItemBuilder.mm +11 -0
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.h +12 -1
- package/ios/Layouts/Tabs/ANNBottomTabsAccessoryView.mm +23 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.h +3 -0
- package/ios/Layouts/Tabs/ANNBottomTabsController.mm +237 -57
- package/ios/Layouts/Tabs/ANNBottomTabsCustomRow.mm +8 -3
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.h +6 -2
- package/ios/Layouts/Tabs/ANNBottomTabsPresenter.mm +232 -43
- package/ios/Layouts/Tabs/ANNTabsDesign.h +6 -5
- package/ios/Layouts/Tabs/ANNTabsDesign.mm +9 -1
- package/ios/Layouts/Tabs/UITabBar+utils.h +5 -5
- package/ios/Layouts/Tabs/UITabBar+utils.mm +32 -13
- package/ios/Options/ANNAnimationOptions.h +2 -1
- package/ios/Options/ANNAnimationOptions.mm +1 -1
- package/ios/Options/ANNBottomTabsOptions.h +2 -0
- package/ios/Options/ANNBottomTabsOptions.mm +1 -0
- package/ios/Options/ANNOptions.h +25 -0
- package/ios/Options/ANNOptions.mm +157 -1
- package/ios/Options/ANNOptionsCache.h +7 -6
- package/ios/Options/ANNOptionsReader.mm +108 -0
- package/ios/Options/ANNSearchBarOptions.h +4 -3
- package/ios/Options/ANNSheetOptions.h +4 -1
- package/ios/Options/ANNSideMenuOptions.h +2 -0
- package/ios/Options/ANNSideMenuOptions.mm +2 -0
- package/ios/Options/ANNStackPopAnimationOptions.h +13 -0
- package/ios/Options/ANNStackPopAnimationOptions.mm +11 -0
- package/ios/Options/ANNUserChoice.h +57 -0
- package/ios/Options/ANNUserChoice.mm +44 -0
- package/ios/Options/Params/ANNImageSource.h +61 -0
- package/ios/Options/Params/ANNImageSource.mm +101 -0
- package/ios/Options/Params/ANNOptionImages.h +37 -0
- package/ios/Options/Params/ANNOptionImages.mm +284 -0
- package/ios/Options/Params/ANNParam.h +15 -0
- package/ios/Options/Params/ANNParam.mm +61 -0
- package/ios/Options/Params/Color.h +3 -0
- package/ios/Options/Params/Color.mm +21 -0
- package/ios/Options/Params/ColorParser.h +4 -3
- package/ios/Options/Params/ColorParser.mm +22 -4
- package/ios/Options/Params/Image.h +15 -2
- package/ios/Options/Params/Image.mm +35 -2
- package/ios/Options/Params/ImageParser.h +5 -5
- package/ios/Options/Params/ImageParser.mm +28 -46
- package/ios/Public/ApexNavigation/ANNSceneDelegate.h +3 -0
- package/ios/Public/ApexNavigation/ApexNavigation.h +1 -1
- package/ios/RECIPES.md +13 -6
- package/ios/React/ANNReactView.mm +6 -25
- package/ios/React/ANNSafeAreaViewComponentView.mm +28 -17
- package/ios/React/ANNSurfaceHostingView.h +14 -0
- package/ios/React/ANNSurfaceHostingView.mm +144 -1
- package/ios/React/Slots/ANNSlotComponentView.mm +24 -17
- package/ios/React/Slots/ANNSlotContainers.h +14 -6
- package/ios/React/Slots/ANNSlotContainers.mm +75 -2
- package/ios/React/Slots/ANNSlotHost.mm +1 -3
- package/ios/React/Slots/ANNSlotScreenView.mm +8 -2
- package/ios/TopBar/ANNBackButtonPresenter.mm +6 -5
- package/ios/TopBar/ANNBarAppearance.h +2 -1
- package/ios/TopBar/ANNBarAppearance.mm +111 -30
- package/ios/TopBar/ANNBarBackgroundComponent.mm +16 -0
- package/ios/TopBar/ANNBarButtonComponentView.h +4 -4
- package/ios/TopBar/ANNBarButtonComponentView.mm +1 -1
- package/ios/TopBar/ANNBarButtons.h +14 -8
- package/ios/TopBar/ANNBarButtons.mm +397 -80
- package/ios/TopBar/ANNIconButtonImage.h +1 -0
- package/ios/TopBar/ANNIconButtonImage.mm +34 -1
- package/ios/TopBar/ANNLargeTitlePresenter.h +13 -0
- package/ios/TopBar/ANNLargeTitlePresenter.mm +50 -7
- package/ios/TopBar/ANNMainList.h +3 -0
- package/ios/TopBar/ANNMainList.mm +4 -0
- package/ios/TopBar/ANNScrollEdgeEffects.h +22 -6
- package/ios/TopBar/ANNScrollEdgeEffects.mm +123 -16
- package/ios/TopBar/ANNSearchPresenter.mm +172 -21
- package/ios/TopBar/ANNSearchResultsViewController.mm +29 -6
- package/ios/TopBar/ANNTopBarPresenter.h +8 -2
- package/ios/TopBar/ANNTopBarPresenter.mm +155 -33
- package/ios/TurboModules/ANNTurboEventEmitter.mm +4 -35
- package/ios/TurboModules/ANNTurboModule.mm +104 -33
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.cpp +20 -0
- package/ios/cpp/react/renderer/components/ApexNavigationSpec/ANNSlotState.h +5 -14
- package/lib/module/ARCHITECTURE.md +40 -27
- package/lib/module/adapters/NativeANNTurboModule.js.map +1 -1
- package/lib/module/api/app/AppRegistry.js +14 -2
- package/lib/module/api/app/AppRegistry.js.map +1 -1
- package/lib/module/api/app/createNavigation.js +190 -66
- package/lib/module/api/app/createNavigation.js.map +1 -1
- package/lib/module/api/commands/commands.js +54 -6
- package/lib/module/api/commands/commands.js.map +1 -1
- package/lib/module/api/events/navigationEvents.js +6 -2
- package/lib/module/api/events/navigationEvents.js.map +1 -1
- package/lib/module/api/hooks/useNavigation.js +8 -3
- package/lib/module/api/hooks/useNavigation.js.map +1 -1
- package/lib/module/api/hooks/useSafeAreaInsets.js +4 -3
- package/lib/module/api/hooks/useSafeAreaInsets.js.map +1 -1
- package/lib/module/api/linking/dispatchedLinks.js +23 -0
- package/lib/module/api/linking/dispatchedLinks.js.map +1 -0
- package/lib/module/api/linking/linking.js +11 -0
- package/lib/module/api/linking/linking.js.map +1 -1
- package/lib/module/api/navigation.js.map +1 -1
- package/lib/module/api/options/OptionsChain.js +2 -2
- package/lib/module/api/screens/defineScreen.js +45 -3
- package/lib/module/api/screens/defineScreen.js.map +1 -1
- package/lib/module/api/screens/nativeScreens.js +31 -6
- package/lib/module/api/screens/nativeScreens.js.map +1 -1
- package/lib/module/api/screens/registerScreens.js +193 -35
- package/lib/module/api/screens/registerScreens.js.map +1 -1
- package/lib/module/api/theme/theme.js +5 -0
- package/lib/module/api/theme/theme.js.map +1 -1
- package/lib/module/engine/commands.js +51 -9
- package/lib/module/engine/commands.js.map +1 -1
- package/lib/module/engine/layout.js +20 -11
- package/lib/module/engine/layout.js.map +1 -1
- package/lib/module/engine/nativeScreens.js +9 -0
- package/lib/module/engine/nativeScreens.js.map +1 -1
- package/lib/module/engine/options.js +49 -15
- package/lib/module/engine/options.js.map +1 -1
- package/lib/module/engine/optionsChange.js +102 -0
- package/lib/module/engine/optionsChange.js.map +1 -0
- package/lib/module/engine/places.js +52 -7
- package/lib/module/engine/places.js.map +1 -1
- package/lib/module/engine/props.js +30 -1
- package/lib/module/engine/props.js.map +1 -1
- package/lib/module/engine/refresh.js +85 -0
- package/lib/module/engine/refresh.js.map +1 -0
- package/lib/module/engine/rememberedOptions.js +61 -1
- package/lib/module/engine/rememberedOptions.js.map +1 -1
- package/lib/module/engine/screens.js +77 -16
- package/lib/module/engine/screens.js.map +1 -1
- package/lib/module/interfaces/contract/commands.json +101 -0
- package/lib/module/interfaces/contract/errors.json +275 -0
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts +12 -2
- package/lib/typescript/adapters/NativeANNTurboModule.d.ts.map +1 -1
- package/lib/typescript/api/app/AppRegistry.d.ts.map +1 -1
- package/lib/typescript/api/app/createNavigation.d.ts +8 -3
- package/lib/typescript/api/app/createNavigation.d.ts.map +1 -1
- package/lib/typescript/api/commands/commands.d.ts.map +1 -1
- package/lib/typescript/api/commands/presentation.d.ts +4 -3
- package/lib/typescript/api/commands/presentation.d.ts.map +1 -1
- package/lib/typescript/api/events/navigationEvents.d.ts +3 -3
- package/lib/typescript/api/events/navigationEvents.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts +1 -1
- package/lib/typescript/api/hooks/useNavigation.d.ts.map +1 -1
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts +4 -3
- package/lib/typescript/api/hooks/useSafeAreaInsets.d.ts.map +1 -1
- package/lib/typescript/api/index.d.ts +1 -1
- package/lib/typescript/api/index.d.ts.map +1 -1
- package/lib/typescript/api/linking/dispatchedLinks.d.ts +7 -0
- package/lib/typescript/api/linking/dispatchedLinks.d.ts.map +1 -0
- package/lib/typescript/api/linking/linking.d.ts +8 -0
- package/lib/typescript/api/linking/linking.d.ts.map +1 -1
- package/lib/typescript/api/navigation.d.ts +4 -1
- package/lib/typescript/api/navigation.d.ts.map +1 -1
- package/lib/typescript/api/options/OptionsChain.d.ts +2 -2
- package/lib/typescript/api/screens/defineScreen.d.ts +23 -4
- package/lib/typescript/api/screens/defineScreen.d.ts.map +1 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts +8 -1
- package/lib/typescript/api/screens/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/api/screens/registerScreens.d.ts.map +1 -1
- package/lib/typescript/api/theme/theme.d.ts +2 -0
- package/lib/typescript/api/theme/theme.d.ts.map +1 -1
- package/lib/typescript/engine/commands.d.ts +5 -0
- package/lib/typescript/engine/commands.d.ts.map +1 -1
- package/lib/typescript/engine/layout.d.ts.map +1 -1
- package/lib/typescript/engine/nativeScreens.d.ts +5 -0
- package/lib/typescript/engine/nativeScreens.d.ts.map +1 -1
- package/lib/typescript/engine/options.d.ts +5 -2
- package/lib/typescript/engine/options.d.ts.map +1 -1
- package/lib/typescript/engine/optionsChange.d.ts +28 -0
- package/lib/typescript/engine/optionsChange.d.ts.map +1 -0
- package/lib/typescript/engine/places.d.ts +7 -2
- package/lib/typescript/engine/places.d.ts.map +1 -1
- package/lib/typescript/engine/props.d.ts +8 -1
- package/lib/typescript/engine/props.d.ts.map +1 -1
- package/lib/typescript/engine/refresh.d.ts +35 -0
- package/lib/typescript/engine/refresh.d.ts.map +1 -0
- package/lib/typescript/engine/rememberedOptions.d.ts +13 -0
- package/lib/typescript/engine/rememberedOptions.d.ts.map +1 -1
- package/lib/typescript/engine/screens.d.ts +27 -6
- package/lib/typescript/engine/screens.d.ts.map +1 -1
- package/lib/typescript/interfaces/ComponentEvents.d.ts +4 -4
- package/lib/typescript/interfaces/ComponentEvents.d.ts.map +1 -1
- package/lib/typescript/interfaces/Events.d.ts +28 -10
- package/lib/typescript/interfaces/Events.d.ts.map +1 -1
- package/lib/typescript/interfaces/Options.d.ts +1 -1
- package/lib/typescript/interfaces/Options.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/animations.d.ts +80 -22
- package/lib/typescript/interfaces/options/animations.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/bottomTabs.d.ts +21 -7
- package/lib/typescript/interfaces/options/bottomTabs.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/buttons.d.ts +23 -15
- package/lib/typescript/interfaces/options/buttons.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/modals.d.ts +34 -26
- package/lib/typescript/interfaces/options/modals.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/sideMenu.d.ts +23 -6
- package/lib/typescript/interfaces/options/sideMenu.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/stack.d.ts +17 -3
- package/lib/typescript/interfaces/options/stack.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/system.d.ts +18 -11
- package/lib/typescript/interfaces/options/system.d.ts.map +1 -1
- package/lib/typescript/interfaces/options/toolbar.d.ts +2 -2
- package/lib/typescript/interfaces/options/topBar.d.ts +68 -38
- package/lib/typescript/interfaces/options/topBar.d.ts.map +1 -1
- package/metro/acceptPlugin.js +57 -0
- package/metro/babelTransformer.js +45 -0
- package/metro/index.js +36 -0
- package/package.json +4 -25
- package/src/ARCHITECTURE.md +40 -27
- package/src/adapters/NativeANNTurboModule.ts +12 -2
- package/src/api/app/AppRegistry.ts +16 -2
- package/src/api/app/createNavigation.ts +203 -69
- package/src/api/commands/commands.ts +48 -7
- package/src/api/commands/presentation.ts +4 -3
- package/src/api/events/navigationEvents.ts +10 -4
- package/src/api/hooks/useNavigation.ts +9 -4
- package/src/api/hooks/useSafeAreaInsets.ts +4 -3
- package/src/api/index.ts +1 -0
- package/src/api/linking/dispatchedLinks.ts +18 -0
- package/src/api/linking/linking.ts +22 -1
- package/src/api/navigation.ts +4 -1
- package/src/api/options/OptionsChain.ts +2 -2
- package/src/api/screens/defineScreen.ts +49 -5
- package/src/api/screens/nativeScreens.ts +40 -4
- package/src/api/screens/registerScreens.tsx +185 -42
- package/src/api/theme/theme.ts +5 -0
- package/src/engine/commands.ts +70 -13
- package/src/engine/layout.ts +27 -11
- package/src/engine/nativeScreens.ts +10 -1
- package/src/engine/options.ts +45 -19
- package/src/engine/optionsChange.ts +107 -0
- package/src/engine/places.ts +65 -7
- package/src/engine/props.ts +30 -1
- package/src/engine/refresh.ts +97 -0
- package/src/engine/rememberedOptions.ts +74 -1
- package/src/engine/screens.tsx +76 -21
- package/src/interfaces/ComponentEvents.ts +4 -4
- package/src/interfaces/Events.ts +29 -10
- package/src/interfaces/Options.ts +1 -0
- package/src/interfaces/contract/commands.json +101 -0
- package/src/interfaces/contract/errors.json +275 -0
- package/src/interfaces/options/animations.ts +81 -22
- package/src/interfaces/options/bottomTabs.ts +21 -7
- package/src/interfaces/options/buttons.ts +23 -15
- package/src/interfaces/options/modals.ts +34 -26
- package/src/interfaces/options/sideMenu.ts +24 -6
- package/src/interfaces/options/stack.ts +17 -3
- package/src/interfaces/options/system.ts +18 -11
- package/src/interfaces/options/toolbar.ts +2 -2
- package/src/interfaces/options/topBar.ts +68 -38
- package/android/src/main/java/dev/apexnative/navigation/react/ArrangementStates.kt +0 -41
- package/android/src/main/java/dev/apexnative/navigation/react/ScreenInsets.kt +0 -69
- package/android/src/main/java/dev/apexnative/navigation/react/events/NavigationStateReporter.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/react/events/StateHold.kt +0 -62
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/bottomtabs/CustomTabRowPlacer.kt +0 -223
- package/android/src/main/java/dev/apexnative/navigation/views/element/ElementStub.kt +0 -31
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ImageMatrixAnimator.kt +0 -138
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PlainViewAnimator.kt +0 -88
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/PropertyAnimatorCreator.kt +0 -33
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ReactImageAnimator.kt +0 -66
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/TextChangeAnimator.kt +0 -179
- package/android/src/main/java/dev/apexnative/navigation/views/element/animators/ViewChangeAnimator.kt +0 -139
- package/ios/Layouts/Screen/ANNScreenInsets.h +0 -30
- package/ios/Layouts/Screen/ANNScreenInsets.mm +0 -68
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.h +0 -27
- package/ios/Layouts/Tabs/ANNTabsPreloadWindow.mm +0 -55
|
@@ -6,6 +6,7 @@ import android.view.ViewGroup
|
|
|
6
6
|
import dev.apexnative.navigation.options.DefaultOptions
|
|
7
7
|
import dev.apexnative.navigation.options.Options
|
|
8
8
|
import dev.apexnative.navigation.options.OptionsCache
|
|
9
|
+
import dev.apexnative.navigation.options.UserChoices
|
|
9
10
|
import dev.apexnative.navigation.options.params.Bool
|
|
10
11
|
import dev.apexnative.navigation.options.params.NullBool
|
|
11
12
|
import dev.apexnative.navigation.react.CommandListener
|
|
@@ -30,11 +31,11 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
30
31
|
var initialOptions: Options,
|
|
31
32
|
) {
|
|
32
33
|
/**
|
|
33
|
-
* The node's own options: those it was made with, with every `mergeOptions`
|
|
34
|
-
* Writing them is one of the
|
|
35
|
-
* options, keeps the object (a stripped copy when it has a one-shot option: the
|
|
36
|
-
* makes every resolved result stale. Don't change the object in place:
|
|
37
|
-
* changed copy.
|
|
34
|
+
* The node's own options: those it was made with, with every `mergeOptions` over them; what the user chose in the
|
|
35
|
+
* native UI is not here but in [choices]. Writing them is one of the places the options change ([OptionsCache]):
|
|
36
|
+
* the setter takes away the one-shot options, keeps the object (a stripped copy when it has a one-shot option: the
|
|
37
|
+
* caller's object never changes), and makes every resolved result stale. Don't change the object in place:
|
|
38
|
+
* [changeOptions] or [mergeOptions] write a changed copy.
|
|
38
39
|
*/
|
|
39
40
|
var options: Options = initialOptions.copy().also(Options::clearOneShotOptions)
|
|
40
41
|
set(value) {
|
|
@@ -42,6 +43,10 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
42
43
|
OptionsCache.optionsChanged()
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
// The user layer: what the user chose in the native UI (a menu's check, a search scope), over the node's own
|
|
47
|
+
// options as they resolve ([changeChoices]).
|
|
48
|
+
private val choices = UserChoices()
|
|
49
|
+
|
|
45
50
|
/**
|
|
46
51
|
* The JavaScript the node was made for (`ReloadCoordinator`): the events of the node and its screens reach only
|
|
47
52
|
* that one.
|
|
@@ -94,6 +99,19 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
94
99
|
open val isInSheet: Boolean
|
|
95
100
|
get() = shownAsSheet || parent?.isInSheet == true
|
|
96
101
|
|
|
102
|
+
/**
|
|
103
|
+
* The node is the root of an overlay: the overlays set it before the node's view is made, so its screens are drawn
|
|
104
|
+
* under the status bar from their first layout (`StatusBarOptions.isHiddenOrDrawBehind`).
|
|
105
|
+
*/
|
|
106
|
+
internal var shownAsOverlay = false
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The node is in an overlay: it covers the whole window, and is drawn under the status bar by default. It holds from
|
|
110
|
+
* the start of the show, while `OverlayCoordinator.isInOverlay` answers only for the overlays it lists.
|
|
111
|
+
*/
|
|
112
|
+
open val isInOverlay: Boolean
|
|
113
|
+
get() = shownAsOverlay || parent?.isInOverlay == true
|
|
114
|
+
|
|
97
115
|
/**
|
|
98
116
|
* The node is in a side of a side menu (its left or right menu, not its center): the side goes the whole height of
|
|
99
117
|
* the window, and the node keeps no room for the status bar. The layout around answers for it
|
|
@@ -143,9 +161,9 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
143
161
|
}
|
|
144
162
|
|
|
145
163
|
/**
|
|
146
|
-
* The node's options over those of the layouts around it, without the default options
|
|
147
|
-
* then the node's own. A new object at each call, which the caller may
|
|
148
|
-
* what it shows with: that is [resolveShownOptions].
|
|
164
|
+
* The node's options over those of the layouts around it, without the default options and without the user layer
|
|
165
|
+
* ([changeChoices]): the parents' resolution, then the node's own. A new object at each call, which the caller may
|
|
166
|
+
* change. For a layout of nodes this is not what it shows with: that is [resolveShownOptions].
|
|
149
167
|
*/
|
|
150
168
|
open fun resolveCurrentOptions(): Options {
|
|
151
169
|
val resolved = parent?.resolveChildOptions(this) ?: Options()
|
|
@@ -153,21 +171,21 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
153
171
|
}
|
|
154
172
|
|
|
155
173
|
/**
|
|
156
|
-
* The node's options over those of the layouts around it and [defaultOptions]
|
|
157
|
-
* default options ([DefaultOptions.current]) the result is
|
|
158
|
-
* ([OptionsCache]) and the layouts around the node and its current
|
|
159
|
-
* changes it copies it first. Main thread only.
|
|
174
|
+
* The node's options over those of the layouts around it and [defaultOptions], with the user layer over them
|
|
175
|
+
* ([changeChoices]): what it shows with. With the app's default options ([DefaultOptions.current]) the result is
|
|
176
|
+
* kept and given again while no options changed ([OptionsCache]) and the layouts around the node and its current
|
|
177
|
+
* children are the same: it is read-only, whoever changes it copies it first. Main thread only.
|
|
160
178
|
*
|
|
161
179
|
* For a layout of nodes (a stack, tabs, a side menu) it is the layout's own options over those around it, without
|
|
162
180
|
* any child's: not what the layout shows with, which [resolveShownOptions] gives.
|
|
163
181
|
*/
|
|
164
182
|
open fun resolveCurrentOptions(defaultOptions: Options): Options {
|
|
165
|
-
if (defaultOptions !== DefaultOptions.current) return
|
|
183
|
+
if (defaultOptions !== DefaultOptions.current) return withChoices(defaultOptions)
|
|
166
184
|
val generation = OptionsCache.generation
|
|
167
185
|
val along = resolvedAlong()
|
|
168
186
|
val kept = resolved
|
|
169
187
|
if (kept != null && resolvedGeneration == generation && sameNodes(along, resolvedAlong)) return kept
|
|
170
|
-
val result =
|
|
188
|
+
val result = withChoices(defaultOptions)
|
|
171
189
|
resolved = result
|
|
172
190
|
resolvedGeneration = generation
|
|
173
191
|
resolvedAlong = along.map(::WeakReference)
|
|
@@ -183,6 +201,10 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
183
201
|
*/
|
|
184
202
|
open fun resolveShownOptions(defaultOptions: Options): Options = resolveCurrentOptions(defaultOptions)
|
|
185
203
|
|
|
204
|
+
// The resolution in its order: the defaults, the parents, the node's own options, then the user layer over them.
|
|
205
|
+
private fun withChoices(defaultOptions: Options): Options =
|
|
206
|
+
choices.applyTo(resolveCurrentOptions().withDefaultOptions(defaultOptions))
|
|
207
|
+
|
|
186
208
|
// The layouts around this node, nearest first, then its current children down the visible chain.
|
|
187
209
|
private fun resolvedAlong(): List<ViewController<*>> {
|
|
188
210
|
val nodes = ArrayList<ViewController<*>>()
|
|
@@ -203,9 +225,9 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
203
225
|
nodes.size == kept.size && nodes.indices.all { nodes[it] === kept[it].get() }
|
|
204
226
|
|
|
205
227
|
/**
|
|
206
|
-
* Changes the node's own options: [change] gets a copy, which is stored ([options]).
|
|
207
|
-
*
|
|
208
|
-
*
|
|
228
|
+
* Changes the node's own options: [change] gets a copy, which is stored ([options]). It is for the library's own
|
|
229
|
+
* bookkeeping of a merge (a side color written into the node's buttons, the back button's visibility); what the
|
|
230
|
+
* user chose goes through [changeChoices].
|
|
209
231
|
*/
|
|
210
232
|
fun changeOptions(change: (Options) -> Unit) {
|
|
211
233
|
val copy = options.copy()
|
|
@@ -213,14 +235,40 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
213
235
|
options = copy
|
|
214
236
|
}
|
|
215
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Changes the node's user layer: what the user chose in the native UI (a single-selection menu's check, a search
|
|
240
|
+
* scope). It goes over the node's own options as they resolve, by the ids of the buttons, items and scopes, and
|
|
241
|
+
* stays through an unrelated `mergeOptions`, the same values sent again and `setDefaultOptions`; a merge that
|
|
242
|
+
* changes the chosen field takes it away ([mergeOwnOptions]). Every resolved result is stale after it
|
|
243
|
+
* ([OptionsCache]).
|
|
244
|
+
*/
|
|
245
|
+
internal fun changeChoices(change: (UserChoices) -> Unit) {
|
|
246
|
+
change(choices)
|
|
247
|
+
OptionsCache.optionsChanged()
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* [delta] of a `mergeOptions` goes over the node's own options ([options]); a choice of the user layer whose field
|
|
252
|
+
* the merge changes, or whose button, item or scope it took away, leaves, so the app's value shows
|
|
253
|
+
* (`UserChoices.yieldTo`). Every `mergeOptions` into a node writes its own options this way.
|
|
254
|
+
*/
|
|
255
|
+
protected fun mergeOwnOptions(delta: Options) {
|
|
256
|
+
val own = options
|
|
257
|
+
val before = if (choices.isEmpty) null else resolveCurrentOptions().withDefaultOptions(DefaultOptions.current)
|
|
258
|
+
options = own.copy().mergeWith(delta)
|
|
259
|
+
before ?: return
|
|
260
|
+
val after = resolveCurrentOptions().withDefaultOptions(DefaultOptions.current)
|
|
261
|
+
if (choices.yieldTo(delta, own, before, after)) OptionsCache.optionsChanged()
|
|
262
|
+
}
|
|
263
|
+
|
|
216
264
|
/**
|
|
217
265
|
* `mergeOptions` with the node's id (`mergeOptions`): [options] go over its own and stay there (one-shot options
|
|
218
|
-
* not kept); what shows applies them ([applyMergedOptions], when the view shows; otherwise as it
|
|
219
|
-
* layouts around it apply their part (`ParentController.mergeChildOptions`, each passes it on).
|
|
220
|
-
* carry the one-shot options to them. Containers that hand the merge to a child override it.
|
|
266
|
+
* not kept, [mergeOwnOptions]); what shows applies them ([applyMergedOptions], when the view shows; otherwise as it
|
|
267
|
+
* appears); the layouts around it apply their part (`ParentController.mergeChildOptions`, each passes it on).
|
|
268
|
+
* [options] still carry the one-shot options to them. Containers that hand the merge to a child override it.
|
|
221
269
|
*/
|
|
222
270
|
open fun mergeOptions(options: Options) {
|
|
223
|
-
|
|
271
|
+
mergeOwnOptions(options)
|
|
224
272
|
if (isViewShown) applyMergedOptions(options)
|
|
225
273
|
performOnParentController { it.mergeChildOptions(options, this) }
|
|
226
274
|
}
|
|
@@ -265,6 +313,12 @@ abstract class ViewController<V : ViewGroup>(
|
|
|
265
313
|
/** Whether [handleBack] would go back. */
|
|
266
314
|
open fun canHandleBack(): Boolean = false
|
|
267
315
|
|
|
316
|
+
/**
|
|
317
|
+
* The stack whose top [handleBack] would take away with the default pop, which a back gesture previews; none when
|
|
318
|
+
* back would do anything else (hold, close a menu or a pane, a pop of its own) or nothing.
|
|
319
|
+
*/
|
|
320
|
+
internal open fun stackPoppedByBack(): StackController? = null
|
|
321
|
+
|
|
268
322
|
/** Starts the node's content (a native screen's view, a React screen's surface). */
|
|
269
323
|
open fun start() = Unit
|
|
270
324
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package dev.apexnative.navigation.views.animations
|
|
2
|
+
|
|
3
|
+
import android.animation.Animator
|
|
4
|
+
import android.animation.AnimatorListenerAdapter
|
|
5
|
+
import android.animation.AnimatorSet
|
|
6
|
+
import android.animation.ObjectAnimator
|
|
7
|
+
import android.view.View
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A hardware layer on a view for the time of an animator that fades it. A view whose `alpha` is below 1 and whose
|
|
11
|
+
* rendering overlaps (any `ViewGroup` by default) is drawn into an offscreen buffer at every frame; through a layer it
|
|
12
|
+
* is drawn once and the GPU only composites it. The layer is taken as the animator starts and only from
|
|
13
|
+
* `LAYER_TYPE_NONE` (a layer someone else set stays theirs), and given back as it ends or is cancelled. A pure
|
|
14
|
+
* translation or scale needs none: RenderThread draws it. The stack's default transition has its own
|
|
15
|
+
* (`StackViews.dress`). Main thread only.
|
|
16
|
+
*/
|
|
17
|
+
internal object AnimationLayer {
|
|
18
|
+
private const val ALPHA = "alpha"
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* [view] draws through a hardware layer while [animator] plays, when [animator] changes the `alpha` of [view] and
|
|
22
|
+
* the view's rendering overlaps; [animator] itself, for chaining.
|
|
23
|
+
*/
|
|
24
|
+
fun during(view: View, animator: Animator): Animator {
|
|
25
|
+
if (!changesAlpha(animator, view)) return animator
|
|
26
|
+
val hold = Hold({ view.layerType }, { view.setLayerType(it, null) })
|
|
27
|
+
animator.addListener(object : AnimatorListenerAdapter() {
|
|
28
|
+
override fun onAnimationStart(animation: Animator) {
|
|
29
|
+
hold.take(changesAlpha = true, overlapping = view.hasOverlappingRendering())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun onAnimationCancel(animation: Animator) = hold.release()
|
|
33
|
+
|
|
34
|
+
override fun onAnimationEnd(animation: Animator) = hold.release()
|
|
35
|
+
})
|
|
36
|
+
return animator
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Whether an animation takes a layer: it fades, its view's rendering overlaps, and the view has no layer. */
|
|
40
|
+
fun takes(changesAlpha: Boolean, overlapping: Boolean, layerType: Int): Boolean =
|
|
41
|
+
changesAlpha && overlapping && layerType == View.LAYER_TYPE_NONE
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The layer one animation took on one view, through [layerType] and [setLayerType]: taken at most once at a time,
|
|
45
|
+
* given back once, and only while it is still the hardware layer it set.
|
|
46
|
+
*/
|
|
47
|
+
class Hold(private val layerType: () -> Int, private val setLayerType: (Int) -> Unit) {
|
|
48
|
+
/** Whether the animation holds the view's layer now. */
|
|
49
|
+
var isTaken = false
|
|
50
|
+
private set
|
|
51
|
+
|
|
52
|
+
/** The animation starts: the layer, when [takes] says so. */
|
|
53
|
+
fun take(changesAlpha: Boolean, overlapping: Boolean) {
|
|
54
|
+
if (isTaken || !takes(changesAlpha, overlapping, layerType())) return
|
|
55
|
+
setLayerType(View.LAYER_TYPE_HARDWARE)
|
|
56
|
+
isTaken = true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The animation ended or stopped: the layer goes, unless someone changed it meanwhile. */
|
|
60
|
+
fun release() {
|
|
61
|
+
if (!isTaken) return
|
|
62
|
+
isTaken = false
|
|
63
|
+
if (layerType() == View.LAYER_TYPE_HARDWARE) setLayerType(View.LAYER_TYPE_NONE)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Whether [animator], or an animator in it, writes the alpha of [view].
|
|
68
|
+
private fun changesAlpha(animator: Animator, view: View): Boolean = when (animator) {
|
|
69
|
+
is AnimatorSet -> animator.childAnimations.any { changesAlpha(it, view) }
|
|
70
|
+
is ObjectAnimator -> animator.target === view && animator.values.orEmpty().any { it.propertyName == ALPHA }
|
|
71
|
+
else -> false
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -96,6 +96,9 @@ internal object Curves {
|
|
|
96
96
|
* linear between them — the values of AndroidX's `FastOutSlowInInterpolator`, computed here.
|
|
97
97
|
*/
|
|
98
98
|
object FastOutSlowIn : Curve() {
|
|
99
|
+
// Before the table, which is made from it.
|
|
100
|
+
private val curve = CubicBezier(0.4, 0.0, 0.2, 1.0)
|
|
101
|
+
|
|
99
102
|
/** The 201 values. */
|
|
100
103
|
val table: DoubleArray = DoubleArray(TABLE_STEPS + 1) {
|
|
101
104
|
round(bezierAt(it.toDouble() / TABLE_STEPS) * DECIMALS) / DECIMALS
|
|
@@ -109,7 +112,25 @@ internal object Curves {
|
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
/** y of the Bézier at its x = [x], exactly (to 1e-12). */
|
|
112
|
-
fun bezierAt(x: Double): Double
|
|
115
|
+
fun bezierAt(x: Double): Double = curve.yAt(x)
|
|
116
|
+
|
|
117
|
+
private const val DECIMALS = 1e4
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A cubic Bézier from (0, 0) to (1, 1) with the control points ([x1], [y1]) and ([x2], [y2]), as the framework's
|
|
122
|
+
* `PathInterpolator` draws it, computed exactly: the system's curves without a framework class.
|
|
123
|
+
*/
|
|
124
|
+
class CubicBezier(
|
|
125
|
+
private val x1: Double,
|
|
126
|
+
private val y1: Double,
|
|
127
|
+
private val x2: Double,
|
|
128
|
+
private val y2: Double,
|
|
129
|
+
) : Curve() {
|
|
130
|
+
override fun at(p: Double): Double = yAt(p)
|
|
131
|
+
|
|
132
|
+
/** y of the curve at its x = [x], exactly (to 1e-12). */
|
|
133
|
+
fun yAt(x: Double): Double {
|
|
113
134
|
if (x <= 0.0) return 0.0
|
|
114
135
|
if (x >= 1.0) return 1.0
|
|
115
136
|
// x(t) only grows with t: a bisection finds t, then y(t).
|
|
@@ -118,23 +139,20 @@ internal object Curves {
|
|
|
118
139
|
var t = x
|
|
119
140
|
repeat(BISECTION_STEPS) {
|
|
120
141
|
t = (low + high) / 2
|
|
121
|
-
if (
|
|
142
|
+
if (coordinate(t, x1, x2) < x) low = t else high = t
|
|
122
143
|
}
|
|
123
|
-
return
|
|
144
|
+
return coordinate(t, y1, y2)
|
|
124
145
|
}
|
|
125
146
|
|
|
126
|
-
// One coordinate of the curve
|
|
127
|
-
private fun
|
|
147
|
+
// One coordinate of the curve with the control points' coordinates [c1], [c2].
|
|
148
|
+
private fun coordinate(t: Double, c1: Double, c2: Double): Double {
|
|
128
149
|
val u = 1 - t
|
|
129
150
|
return 3 * u * u * t * c1 + 3 * u * t * t * c2 + t * t * t
|
|
130
151
|
}
|
|
131
152
|
|
|
132
|
-
private
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
private const val Y2 = 1.0
|
|
136
|
-
private const val BISECTION_STEPS = 60
|
|
137
|
-
private const val DECIMALS = 1e4
|
|
153
|
+
private companion object {
|
|
154
|
+
const val BISECTION_STEPS = 60
|
|
155
|
+
}
|
|
138
156
|
}
|
|
139
157
|
|
|
140
158
|
/**
|
package/android/src/main/java/dev/apexnative/navigation/views/animations/ValueInterpolation.kt
CHANGED
|
@@ -18,6 +18,18 @@ internal object ValueInterpolation {
|
|
|
18
18
|
else -> from + fraction * (to - from)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* An angle in degrees at [fraction] of the way along the shorter arc, as iOS turns a shared element: 0 → 270 turns
|
|
23
|
+
* back by 90, 170 → −170 turns on by 20; half a turn goes on. At the end of the time exactly [to].
|
|
24
|
+
*/
|
|
25
|
+
fun angle(from: Float, to: Float, fraction: Float, time: Float = fraction): Float {
|
|
26
|
+
if (time <= 0f) return from
|
|
27
|
+
if (time >= 1f) return to
|
|
28
|
+
val forward = ((to - from) % FULL_TURN + FULL_TURN) % FULL_TURN
|
|
29
|
+
val turn = if (forward > HALF_TURN) forward - FULL_TURN else forward
|
|
30
|
+
return from + fraction * turn
|
|
31
|
+
}
|
|
32
|
+
|
|
21
33
|
/**
|
|
22
34
|
* A color (an sRGB color int, as React Native keeps a background; none is transparent) at [fraction] of the way
|
|
23
35
|
* from [from] to [to]: L, a and b in Lab (D65), the alpha linear, the result rounded; at the end of the time
|
|
@@ -90,4 +102,6 @@ internal object ValueInterpolation {
|
|
|
90
102
|
private const val WHITE_Z = 108.883
|
|
91
103
|
private const val EPSILON = 0.008856
|
|
92
104
|
private const val KAPPA = 903.3
|
|
105
|
+
private const val FULL_TURN = 360f
|
|
106
|
+
private const val HALF_TURN = 180f
|
|
93
107
|
}
|
|
@@ -98,8 +98,8 @@ class BottomTabs(context: Context) : BottomNavigationView(MaterialTheme.context(
|
|
|
98
98
|
var iconInactiveColor: Int? = null
|
|
99
99
|
var titleActiveColor: Int? = null
|
|
100
100
|
var titleInactiveColor: Int? = null
|
|
101
|
-
var iconWidth:
|
|
102
|
-
var iconHeight:
|
|
101
|
+
var iconWidth: Double? = null
|
|
102
|
+
var iconHeight: Double? = null
|
|
103
103
|
var typeface: Typeface? = null
|
|
104
104
|
var activeTextSize: Float? = null
|
|
105
105
|
var inactiveTextSize: Float? = null
|
|
@@ -228,13 +228,15 @@ class BottomTabs(context: Context) : BottomNavigationView(MaterialTheme.context(
|
|
|
228
228
|
applyLongPressesAgain()
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
|
|
231
|
+
/** Null: the item has no icon. */
|
|
232
|
+
fun setIcon(index: Int, icon: Drawable?) {
|
|
232
233
|
val item = items.getOrNull(index) ?: return
|
|
233
234
|
if (item.icon == icon) return
|
|
234
235
|
updateIcon(index, item.copy(icon = icon))
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
|
|
238
|
+
/** Null: the item shows its icon when selected too. */
|
|
239
|
+
fun setSelectedIcon(index: Int, icon: Drawable?) {
|
|
238
240
|
val item = items.getOrNull(index) ?: return
|
|
239
241
|
if (item.selectedIcon == icon) return
|
|
240
242
|
updateIcon(index, item.copy(selectedIcon = icon))
|
|
@@ -246,9 +248,9 @@ class BottomTabs(context: Context) : BottomNavigationView(MaterialTheme.context(
|
|
|
246
248
|
|
|
247
249
|
fun setTabTestId(index: Int, testId: String?) = updateStyle(index) { it.testId = testId }
|
|
248
250
|
|
|
249
|
-
fun setIconWidth(index: Int, width:
|
|
251
|
+
fun setIconWidth(index: Int, width: Double?) = updateStyle(index) { it.iconWidth = width }
|
|
250
252
|
|
|
251
|
-
fun setIconHeight(index: Int, height:
|
|
253
|
+
fun setIconHeight(index: Int, height: Double?) = updateStyle(index) { it.iconHeight = height }
|
|
252
254
|
|
|
253
255
|
fun setTitleTypeface(index: Int, typeface: Typeface?) = updateStyle(index) { it.typeface = typeface }
|
|
254
256
|
|
|
@@ -475,7 +477,7 @@ class BottomTabs(context: Context) : BottomNavigationView(MaterialTheme.context(
|
|
|
475
477
|
view.setIconTintList(tint(style.iconActiveColor, style.iconInactiveColor, itemIconTintList))
|
|
476
478
|
view.setTextColor(tint(style.titleActiveColor, style.titleInactiveColor, itemTextColor))
|
|
477
479
|
val iconSize = style.iconWidth ?: style.iconHeight
|
|
478
|
-
view.setIconSize(if (iconSize != null) UiUtils.
|
|
480
|
+
view.setIconSize(if (iconSize != null) UiUtils.dpToPixels(context, iconSize) else itemIconSize)
|
|
479
481
|
view.findViewById<TextView>(MaterialR.id.navigation_bar_item_small_label_view)?.let {
|
|
480
482
|
style.typeface?.let { typeface -> it.typeface = typeface }
|
|
481
483
|
style.inactiveTextSize?.let { size -> it.setTextSize(TypedValue.COMPLEX_UNIT_SP, size) }
|
package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/BottomTabsLayout.kt
CHANGED
|
@@ -10,13 +10,15 @@ import androidx.annotation.RestrictTo
|
|
|
10
10
|
import androidx.core.view.ViewCompat
|
|
11
11
|
import androidx.core.view.WindowInsetsCompat
|
|
12
12
|
import dev.apexnative.navigation.utils.MaterialTheme
|
|
13
|
+
import dev.apexnative.navigation.viewcontrollers.bottomtabs.CustomTabRowGeometry
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* The view of bottom tabs: the view of each tab made so far fills it, the selected one visible and the others invisible
|
|
16
17
|
* but laid out, so a switch shows a tab at once and its screens render; the bar's [container] lies over them at the
|
|
17
18
|
* bottom, the module's bar ([bar], `R.id.bottomTabs`) in it. The container's distance from the bottom ([barOffset]:
|
|
18
19
|
* `bottomMargin`, and the navigation bar under a compact bar) is this view's own inset, not a layout parameter a root
|
|
19
|
-
* may ignore. The
|
|
20
|
+
* may ignore. The custom [row], when the tabs have one, lies right after the container and over the bar. The window
|
|
21
|
+
* insets go on to every child as they came. Main thread only.
|
|
20
22
|
*/
|
|
21
23
|
@SuppressLint("ViewConstructor")
|
|
22
24
|
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
|
@@ -34,8 +36,25 @@ class BottomTabsLayout(context: Context) : FrameLayout(context) {
|
|
|
34
36
|
/** The window insets reached this view: the bar's room and the screens' room may have changed. */
|
|
35
37
|
internal var onInsets: (() -> Unit)? = null
|
|
36
38
|
|
|
37
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* The custom row of the tabs, when every tab draws its cell (`bottomTab.component`): a child right after the
|
|
41
|
+
* container, laid out over the bar, going with the container.
|
|
42
|
+
*/
|
|
38
43
|
internal var row: CustomTabRow? = null
|
|
44
|
+
set(value) {
|
|
45
|
+
if (field === value) return
|
|
46
|
+
field?.let {
|
|
47
|
+
removeView(it)
|
|
48
|
+
it.container = null
|
|
49
|
+
}
|
|
50
|
+
field = value
|
|
51
|
+
if (value == null) return
|
|
52
|
+
(value.parent as? ViewGroup)?.removeView(value)
|
|
53
|
+
value.container = container
|
|
54
|
+
value.place = null
|
|
55
|
+
// Its frame is absolute: the layout below puts it in its parameters.
|
|
56
|
+
addView(value, indexOfChild(container) + 1, LayoutParams(0, 0, Gravity.TOP or Gravity.LEFT))
|
|
57
|
+
}
|
|
39
58
|
|
|
40
59
|
/** The container's distance from the bottom, in pixels. */
|
|
41
60
|
internal var barOffset = 0
|
|
@@ -59,6 +78,16 @@ class BottomTabsLayout(context: Context) : FrameLayout(context) {
|
|
|
59
78
|
}
|
|
60
79
|
}
|
|
61
80
|
|
|
81
|
+
/**
|
|
82
|
+
* How far the container goes down to leave the screen whole: from the top of what the bar shows — the container, or
|
|
83
|
+
* the custom row that rises above it — to this view's bottom, in pixels.
|
|
84
|
+
*/
|
|
85
|
+
internal val hideDistance: Int
|
|
86
|
+
get() {
|
|
87
|
+
val rowTop = row?.takeIf { it.visibility != View.GONE }?.top ?: container.top
|
|
88
|
+
return (height - minOf(container.top, rowTop)).coerceAtLeast(0)
|
|
89
|
+
}
|
|
90
|
+
|
|
62
91
|
/** [view] of a tab joins under the bar, invisible until its tab shows. */
|
|
63
92
|
internal fun addTab(view: View) {
|
|
64
93
|
if (view.parent === this) return
|
|
@@ -85,5 +114,35 @@ class BottomTabsLayout(context: Context) : FrameLayout(context) {
|
|
|
85
114
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
86
115
|
super.onLayout(changed, left, top, right, bottom)
|
|
87
116
|
if (barOffset != 0) container.offsetTopAndBottom(-barOffset)
|
|
117
|
+
row?.let(::placeRow)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// The row over the bar where the bar rests (its container's motion the row takes before each frame), when its place
|
|
121
|
+
// changed: laid out there at once, and kept in its parameters, so the next passes measure it and put it there the
|
|
122
|
+
// same way. A hidden bar keeps the row where it was.
|
|
123
|
+
private fun placeRow(row: CustomTabRow) {
|
|
124
|
+
if (container.visibility == View.GONE || bar.width == 0) return
|
|
125
|
+
val barLeft = container.left + bar.left
|
|
126
|
+
val barTop = container.top + bar.top
|
|
127
|
+
val place = row.placeOver(
|
|
128
|
+
barLeft = barLeft,
|
|
129
|
+
barRight = barLeft + bar.width,
|
|
130
|
+
barBottom = barTop + bar.height,
|
|
131
|
+
barHeight = bar.height,
|
|
132
|
+
tabsHeight = height,
|
|
133
|
+
navigationBar = navigationBarInset,
|
|
134
|
+
)
|
|
135
|
+
if (!CustomTabRowGeometry.needsPlacing(row.place, place)) return
|
|
136
|
+
row.place = place
|
|
137
|
+
val params = row.layoutParams as LayoutParams
|
|
138
|
+
params.width = place.right - place.left
|
|
139
|
+
params.height = place.bottom - place.top
|
|
140
|
+
params.leftMargin = place.left
|
|
141
|
+
params.topMargin = place.top
|
|
142
|
+
row.measure(
|
|
143
|
+
MeasureSpec.makeMeasureSpec(params.width, MeasureSpec.EXACTLY),
|
|
144
|
+
MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY),
|
|
145
|
+
)
|
|
146
|
+
row.layout(place.left, place.top, place.right, place.bottom)
|
|
88
147
|
}
|
|
89
148
|
}
|
package/android/src/main/java/dev/apexnative/navigation/views/bottomtabs/CustomBottomTabItemView.kt
CHANGED
|
@@ -22,9 +22,6 @@ open class CustomBottomTabItemView(context: Context) : FrameLayout(context) {
|
|
|
22
22
|
private var state: TabCellState? = null
|
|
23
23
|
private var destroyed = false
|
|
24
24
|
|
|
25
|
-
/** Runs once as the cell stops: what was kept for its content's id goes. */
|
|
26
|
-
internal var onDestroyed: (() -> Unit)? = null
|
|
27
|
-
|
|
28
25
|
/** The content the cell shows, filling it, made with [state] as its first props. */
|
|
29
26
|
internal fun show(view: IReactView, state: TabCellState) {
|
|
30
27
|
content = view
|
|
@@ -68,8 +65,6 @@ open class CustomBottomTabItemView(context: Context) : FrameLayout(context) {
|
|
|
68
65
|
didDisappear()
|
|
69
66
|
destroyed = true
|
|
70
67
|
content?.destroy()
|
|
71
|
-
onDestroyed?.invoke()
|
|
72
|
-
onDestroyed = null
|
|
73
68
|
}
|
|
74
69
|
|
|
75
70
|
/** The props of [state] as React Native takes them. */
|
|
@@ -11,18 +11,21 @@ import android.view.MotionEvent
|
|
|
11
11
|
import android.view.View
|
|
12
12
|
import android.view.ViewGroup
|
|
13
13
|
import android.view.ViewOutlineProvider
|
|
14
|
+
import android.view.ViewTreeObserver
|
|
14
15
|
import android.widget.FrameLayout
|
|
15
16
|
import android.widget.LinearLayout
|
|
16
17
|
import dev.apexnative.navigation.customrow.BottomTabsCustomRowOptions
|
|
17
18
|
import dev.apexnative.navigation.utils.TestIds
|
|
19
|
+
import dev.apexnative.navigation.utils.UiUtils
|
|
18
20
|
import dev.apexnative.navigation.viewcontrollers.bottomtabs.CustomTabRowGeometry
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
|
-
* The custom row of bottom tabs on Android (`bottomTabs.customRow`): a container over the bar,
|
|
22
|
-
* that holds the tabs' cells in one row of equal widths in tab order. It owns its
|
|
23
|
-
* the touches: each cell's place takes them, the React elements in the cell don't, and a tap
|
|
24
|
-
* goes to [onPress] or [onLongPress] with the tab's index.
|
|
25
|
-
*
|
|
23
|
+
* The custom row of bottom tabs on Android (`bottomTabs.customRow`): a container over the bar, a child of the tabs'
|
|
24
|
+
* view right after the bar's container, that holds the tabs' cells in one row of equal widths in tab order. It owns its
|
|
25
|
+
* look, its visibility and the touches: each cell's place takes them, the React elements in the cell don't, and a tap
|
|
26
|
+
* or a long press of a place goes to [onPress] or [onLongPress] with the tab's index. The tabs' view lays it out over
|
|
27
|
+
* the bar ([placeOver]); before each frame it goes with the bar's [container]. What it looks like is its tabs'. Main
|
|
28
|
+
* thread only.
|
|
26
29
|
*/
|
|
27
30
|
@SuppressLint("ViewConstructor")
|
|
28
31
|
internal class CustomTabRow(context: Context) : FrameLayout(context) {
|
|
@@ -42,11 +45,23 @@ internal class CustomTabRow(context: Context) : FrameLayout(context) {
|
|
|
42
45
|
/** A cell's place was long-pressed. */
|
|
43
46
|
var onLongPress: ((Int) -> Unit)? = null
|
|
44
47
|
|
|
45
|
-
/** `bottomTabs.customRow` of the tabs, resolved:
|
|
48
|
+
/** `bottomTabs.customRow` of the tabs, resolved: its height and margins say where the row lies. */
|
|
46
49
|
var options = BottomTabsCustomRowOptions()
|
|
47
50
|
|
|
48
51
|
/**
|
|
49
|
-
*
|
|
52
|
+
* The bar's container the row goes with: its motion (a ride, a slide, the hide on scroll), its alpha, its height
|
|
53
|
+
* over the screens and whether it shows. The tabs' view sets it as the row joins it.
|
|
54
|
+
*/
|
|
55
|
+
var container: View? = null
|
|
56
|
+
|
|
57
|
+
// Before each frame of the window the row is in: it goes with the container.
|
|
58
|
+
private val following = ViewTreeObserver.OnPreDrawListener {
|
|
59
|
+
container?.let(::follow)
|
|
60
|
+
true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Where the tabs' view put the row last, in it; none before it did. The frame holds `bottomMargin` below the
|
|
50
65
|
* content: the row draws, clips, casts its shadow, lays its cells and takes touches only over the content, and the
|
|
51
66
|
* margin below lets the touches through to what is under it.
|
|
52
67
|
*/
|
|
@@ -117,10 +132,57 @@ internal class CustomTabRow(context: Context) : FrameLayout(context) {
|
|
|
117
132
|
return super.dispatchTouchEvent(event)
|
|
118
133
|
}
|
|
119
134
|
|
|
120
|
-
/**
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Where the row lies over the bar whose edges are [barLeft], [barRight] and [barBottom] and whose height is
|
|
137
|
+
* [barHeight], in the tabs' view of [tabsHeight] with the navigation bar's [navigationBar] at its bottom: its
|
|
138
|
+
* height and margins from [options].
|
|
139
|
+
*/
|
|
140
|
+
fun placeOver(barLeft: Int, barRight: Int, barBottom: Int, barHeight: Int, tabsHeight: Int, navigationBar: Int) =
|
|
141
|
+
CustomTabRowGeometry.inTabs(
|
|
142
|
+
barLeft = barLeft,
|
|
143
|
+
barRight = barRight,
|
|
144
|
+
barBottom = barBottom,
|
|
145
|
+
tabsHeight = tabsHeight,
|
|
146
|
+
navigationBar = navigationBar,
|
|
147
|
+
margin = UiUtils.dpToPixels(
|
|
148
|
+
context,
|
|
149
|
+
options.horizontalMargin.get(CustomTabRowGeometry.HORIZONTAL_MARGIN_DP.toDouble()),
|
|
150
|
+
),
|
|
151
|
+
content = CustomTabRowGeometry.content(
|
|
152
|
+
barHeight = barHeight,
|
|
153
|
+
height = options.height.get(null)?.let { UiUtils.dpToPixels(context, it) },
|
|
154
|
+
extra = UiUtils.dpToPixels(context, CustomTabRowGeometry.EXTRA_HEIGHT_DP.toDouble()),
|
|
155
|
+
),
|
|
156
|
+
bottomMargin = UiUtils.dpToPixels(context, options.bottomMargin.get(0.0)),
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
override fun onAttachedToWindow() {
|
|
160
|
+
super.onAttachedToWindow()
|
|
161
|
+
viewTreeObserver.addOnPreDrawListener(following)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
override fun onDetachedFromWindow() {
|
|
165
|
+
viewTreeObserver.removeOnPreDrawListener(following)
|
|
166
|
+
super.onDetachedFromWindow()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// The row hides with the bar and takes its motion and its alpha (the tabs' own alpha and motion, and their
|
|
170
|
+
// parents', the row has as their child); it stands as high as the container, and leaves accessibility while its
|
|
171
|
+
// tabs wait to show.
|
|
172
|
+
private fun follow(container: View) {
|
|
173
|
+
val wanted = if (container.visibility != View.GONE) View.VISIBLE else View.GONE
|
|
123
174
|
if (visibility != wanted) visibility = wanted
|
|
175
|
+
if (alpha != container.alpha) alpha = container.alpha
|
|
176
|
+
if (translationX != container.translationX) translationX = container.translationX
|
|
177
|
+
if (translationY != container.translationY) translationY = container.translationY
|
|
178
|
+
val lift = CustomTabRowGeometry.lift(container.z, elevation)
|
|
179
|
+
if (translationZ != lift) translationZ = lift
|
|
180
|
+
val mode = if (hiddenFromAccessibility()) {
|
|
181
|
+
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
|
182
|
+
} else {
|
|
183
|
+
View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
|
|
184
|
+
}
|
|
185
|
+
if (importantForAccessibility != mode) importantForAccessibility = mode
|
|
124
186
|
}
|
|
125
187
|
|
|
126
188
|
/** Draws [look]; nothing changes when it is the one drawn. */
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package dev.apexnative.navigation.views.element
|
|
2
|
+
|
|
3
|
+
import dev.apexnative.navigation.utils.DevelopmentLog
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The isolation of every element of the transitions: [work], a step of the element named [element] (its `nativeID` in
|
|
7
|
+
* quotes, or a pair's two), runs; an exception in it skips that element only — one line in the log
|
|
8
|
+
* ([elementSkipped]), and false — while the rest of the transition plays and its command completes.
|
|
9
|
+
*/
|
|
10
|
+
internal inline fun elementStep(
|
|
11
|
+
element: String,
|
|
12
|
+
noinline log: (String) -> Unit = DevelopmentLog::warn,
|
|
13
|
+
work: () -> Unit,
|
|
14
|
+
): Boolean = try {
|
|
15
|
+
work()
|
|
16
|
+
true
|
|
17
|
+
} catch (e: Exception) {
|
|
18
|
+
elementSkipped(element, e.toString(), log)
|
|
19
|
+
false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The line in the log for the element named [element], skipped for [reason]: it shows and hides with its screen. */
|
|
23
|
+
internal fun elementSkipped(element: String, reason: String, log: (String) -> Unit = DevelopmentLog::warn) =
|
|
24
|
+
log("[ApexNavigation] the transition's element $element is skipped, it shows and hides with its screen while the " +
|
|
25
|
+
"rest plays: $reason")
|
|
26
|
+
|
|
27
|
+
/** The name of an element in the log. */
|
|
28
|
+
internal fun elementName(nativeId: String) = "'$nativeId'"
|
|
29
|
+
|
|
30
|
+
/** The name of a shared pair in the log. */
|
|
31
|
+
internal fun pairName(fromId: String, toId: String) = "'$fromId' -> '$toId'"
|