@apexnative/navigation 1.0.0-alpha.1 → 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 +120 -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/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 +3 -1
- 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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { ComponentType } from 'react';
|
|
2
|
+
import { DevSettings } from 'react-native';
|
|
2
3
|
import { setDefaultOptions, setRoot } from '../../engine/commands';
|
|
3
4
|
import { type AppProvider, enableSlots, withSlots } from '../../engine/slots';
|
|
4
5
|
import { listenToNativeScreens, startHost } from '../../engine/nativeScreens';
|
|
6
|
+
import { sameValue } from '../../engine/optionsChange';
|
|
7
|
+
import { familyOf, keepStateOf, refreshRuns } from '../../engine/refresh';
|
|
5
8
|
import { listenToSplitViews } from '../../engine/places';
|
|
6
9
|
import { hasNativeScreenHooks } from '../../engine/screens';
|
|
7
10
|
import type { LayoutRoot } from '../../interfaces/Layout';
|
|
@@ -24,7 +27,10 @@ import type { ErrorFallbackProps } from '../screens/ScreenBoundary';
|
|
|
24
27
|
import { getAppContext, setAppContext } from '../context/appContext';
|
|
25
28
|
import {
|
|
26
29
|
type AppOptionsInput,
|
|
30
|
+
getDirection,
|
|
31
|
+
getTheme,
|
|
27
32
|
initTheme,
|
|
33
|
+
setTheme,
|
|
28
34
|
type NavigationDirection,
|
|
29
35
|
type NavigationTheme,
|
|
30
36
|
themedDefaultOptions,
|
|
@@ -43,6 +49,7 @@ import {
|
|
|
43
49
|
import { launchState } from '../../engine/launchState';
|
|
44
50
|
import { watchBackListeners } from '../../engine/backListeners';
|
|
45
51
|
import { resolveRoot, type RootsMap, type RootTarget, type UsesOfRootValue } from './roots';
|
|
52
|
+
import { listenToDispatchedLinks } from '../linking/dispatchedLinks';
|
|
46
53
|
import {
|
|
47
54
|
launchLink,
|
|
48
55
|
launchRoot,
|
|
@@ -50,6 +57,7 @@ import {
|
|
|
50
57
|
linksStarted,
|
|
51
58
|
reportLink,
|
|
52
59
|
setupLinking,
|
|
60
|
+
updateLinking,
|
|
53
61
|
} from '../linking/linking';
|
|
54
62
|
import type { LinkMatch } from '../linking/linkPaths';
|
|
55
63
|
import type { LinkingConfig } from '../linking/types';
|
|
@@ -85,6 +93,9 @@ const starts = new WeakMap<NavigationApp<any, any>, () => Promise<void>>();
|
|
|
85
93
|
|
|
86
94
|
/** Starts the app, or brings back its root when the native side launches again. */
|
|
87
95
|
export function startApp(app: NavigationApp<any, any>): Promise<void> {
|
|
96
|
+
// An app made after another launched knows once its module ran whether it is that app's next version.
|
|
97
|
+
const waiting = pending.get(app);
|
|
98
|
+
if (waiting) return waiting.then(() => startApp(app));
|
|
88
99
|
const start = starts.get(app);
|
|
89
100
|
if (!start) throw new Error('[navigation] Not an app made by createNavigation');
|
|
90
101
|
return start();
|
|
@@ -150,9 +161,9 @@ interface BaseConfig<
|
|
|
150
161
|
/** The look of the navigation: colors of the bars, tabs and backgrounds; `navigation.setTheme` changes it. */
|
|
151
162
|
theme?: NavigationTheme;
|
|
152
163
|
/**
|
|
153
|
-
* The edges on which every screen keeps its content out of its safe area. Without it:
|
|
154
|
-
*
|
|
155
|
-
* in its options.
|
|
164
|
+
* The edges on which every screen keeps its content out of its safe area. Without it: the top and the sides, but
|
|
165
|
+
* those where the content goes under a bar (`layout.safeAreaEdges`); the bottom is free and a list keeps clear of it
|
|
166
|
+
* with `useSafeAreaInsets()`. A screen gives its own with `safeArea(...)` in its options.
|
|
156
167
|
*/
|
|
157
168
|
safeArea?: { edges: SafeAreaEdge[] };
|
|
158
169
|
/** (iOS) The app's window, behind the screens: seen around a modal as it comes in. */
|
|
@@ -239,7 +250,11 @@ type CheckedRoots<Root, Roots, AppScreens> = {
|
|
|
239
250
|
};
|
|
240
251
|
|
|
241
252
|
export function isNavigationApp(value: unknown): value is NavigationApp {
|
|
242
|
-
return
|
|
253
|
+
return (
|
|
254
|
+
typeof value === 'object' &&
|
|
255
|
+
value !== null &&
|
|
256
|
+
(starts.has(value as NavigationApp) || pending.has(value as NavigationApp))
|
|
257
|
+
);
|
|
243
258
|
}
|
|
244
259
|
|
|
245
260
|
/**
|
|
@@ -276,14 +291,18 @@ export function createNavigation<
|
|
|
276
291
|
> &
|
|
277
292
|
NoInfer<CheckedRoots<FirstLayout, Roots, AllScreens<AppScreens, Groups>>>
|
|
278
293
|
): NavigationApp<Roots, AllScreens<AppScreens, Groups>> {
|
|
294
|
+
// The app that launched before, when this call may be its module running again after an edit (Fast Refresh): what
|
|
295
|
+
// the call starts waits until that is known.
|
|
296
|
+
const launched = __DEV__ ? hotCandidate() : undefined;
|
|
279
297
|
// Counted from here: a "back again to leave" listener of the app's entry file comes after this call.
|
|
280
|
-
watchBackListeners();
|
|
298
|
+
if (!launched) watchBackListeners();
|
|
281
299
|
// idle: not started yet, or the last start failed. mounting: the first root is on its way. mounted: it is shown.
|
|
282
300
|
let phase: 'idle' | 'mounting' | 'mounted' = 'idle';
|
|
283
301
|
let screensRegistered = false;
|
|
284
302
|
// The splash shows at the first start of this runtime only: a start that failed and runs again goes without it.
|
|
285
303
|
let splashChecked = false;
|
|
286
304
|
let listening = false;
|
|
305
|
+
let removeListeners: (() => void) | undefined;
|
|
287
306
|
let prepared: Promise<void> | undefined;
|
|
288
307
|
let markMounted!: () => void;
|
|
289
308
|
// A new activity came while the first root was on its way (Android): its link is taken once that root is shown.
|
|
@@ -324,6 +343,62 @@ export function createNavigation<
|
|
|
324
343
|
return buildRoot(typeof root === 'function' ? root(context) : root);
|
|
325
344
|
}
|
|
326
345
|
|
|
346
|
+
// The screens of the app, its groups, the screen of a failed start and the splash, with what wraps each of them.
|
|
347
|
+
function registerAppScreens() {
|
|
348
|
+
const wrapper = {
|
|
349
|
+
errorFallback: config.errorFallback,
|
|
350
|
+
loadingFallback: config.loadingFallback,
|
|
351
|
+
onError:
|
|
352
|
+
config.onError &&
|
|
353
|
+
((error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) =>
|
|
354
|
+
config.onError?.(error, { type: 'screen', screen, componentStack })),
|
|
355
|
+
};
|
|
356
|
+
registerScreens(
|
|
357
|
+
[
|
|
358
|
+
{ source: 'screens', screens: config.screens ?? {} },
|
|
359
|
+
...Object.entries(config.groups ?? {}).map(([group, { screens, options }]) => ({
|
|
360
|
+
source: `the group '${group}'`,
|
|
361
|
+
screens,
|
|
362
|
+
options,
|
|
363
|
+
})),
|
|
364
|
+
...(config.errorFallback
|
|
365
|
+
? [
|
|
366
|
+
{
|
|
367
|
+
source: 'the start',
|
|
368
|
+
screens: { [START_FAILURE_SCREEN]: startFailureScreen(config.errorFallback) },
|
|
369
|
+
},
|
|
370
|
+
]
|
|
371
|
+
: []),
|
|
372
|
+
],
|
|
373
|
+
{ ...wrapper, provider: config.screenProvider }
|
|
374
|
+
);
|
|
375
|
+
// The splash renders before willMount ends: a root of its own, without the app's providers, which may need what
|
|
376
|
+
// willMount prepares.
|
|
377
|
+
if (config.splash) {
|
|
378
|
+
registerScreens(
|
|
379
|
+
[
|
|
380
|
+
{
|
|
381
|
+
source: 'the splash',
|
|
382
|
+
screens: { [SPLASH_SCREEN]: config.splash.component },
|
|
383
|
+
ownRoot: true,
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
{
|
|
387
|
+
...wrapper,
|
|
388
|
+
// A splash that failed to render can't call hide(): the start goes on without waiting for it.
|
|
389
|
+
onError: (
|
|
390
|
+
error: unknown,
|
|
391
|
+
screen: ScreenInfo,
|
|
392
|
+
componentStack: string | null | undefined
|
|
393
|
+
) => {
|
|
394
|
+
releaseSplash();
|
|
395
|
+
wrapper.onError?.(error, screen, componentStack);
|
|
396
|
+
},
|
|
397
|
+
}
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
327
402
|
async function mount() {
|
|
328
403
|
phase = 'mounting';
|
|
329
404
|
// The state before the first root: the links wait for a newer one, which tells the screen they act from.
|
|
@@ -332,54 +407,7 @@ export function createNavigation<
|
|
|
332
407
|
let linkHandled = false;
|
|
333
408
|
try {
|
|
334
409
|
if (!screensRegistered) {
|
|
335
|
-
|
|
336
|
-
errorFallback: config.errorFallback,
|
|
337
|
-
loadingFallback: config.loadingFallback,
|
|
338
|
-
onError:
|
|
339
|
-
config.onError &&
|
|
340
|
-
((error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) =>
|
|
341
|
-
config.onError?.(error, { type: 'screen', screen, componentStack })),
|
|
342
|
-
};
|
|
343
|
-
registerScreens(
|
|
344
|
-
[
|
|
345
|
-
{ source: 'screens', screens: config.screens ?? {} },
|
|
346
|
-
...Object.entries(config.groups ?? {}).map(([group, { screens, options }]) => ({
|
|
347
|
-
source: `the group '${group}'`,
|
|
348
|
-
screens,
|
|
349
|
-
options,
|
|
350
|
-
})),
|
|
351
|
-
...(config.errorFallback
|
|
352
|
-
? [
|
|
353
|
-
{
|
|
354
|
-
source: 'the start',
|
|
355
|
-
screens: { [START_FAILURE_SCREEN]: startFailureScreen(config.errorFallback) },
|
|
356
|
-
},
|
|
357
|
-
]
|
|
358
|
-
: []),
|
|
359
|
-
],
|
|
360
|
-
{ ...wrapper, provider: config.screenProvider }
|
|
361
|
-
);
|
|
362
|
-
// The splash renders before willMount ends: a root of its own, without the app's providers, which may need what
|
|
363
|
-
// willMount prepares.
|
|
364
|
-
if (config.splash) {
|
|
365
|
-
registerScreens(
|
|
366
|
-
[
|
|
367
|
-
{
|
|
368
|
-
source: 'the splash',
|
|
369
|
-
screens: { [SPLASH_SCREEN]: config.splash.component },
|
|
370
|
-
ownRoot: true,
|
|
371
|
-
},
|
|
372
|
-
],
|
|
373
|
-
{
|
|
374
|
-
...wrapper,
|
|
375
|
-
// A splash that failed to render can't call hide(): the start goes on without waiting for it.
|
|
376
|
-
onError: (error: unknown, screen: ScreenInfo, componentStack: string | null | undefined) => {
|
|
377
|
-
releaseSplash();
|
|
378
|
-
wrapper.onError?.(error, screen, componentStack);
|
|
379
|
-
},
|
|
380
|
-
}
|
|
381
|
-
);
|
|
382
|
-
}
|
|
410
|
+
registerAppScreens();
|
|
383
411
|
screensRegistered = true;
|
|
384
412
|
}
|
|
385
413
|
// The link that launched the app is asked for first: on iOS the first React content to appear (the host below,
|
|
@@ -484,28 +512,22 @@ export function createNavigation<
|
|
|
484
512
|
}
|
|
485
513
|
|
|
486
514
|
async function launch() {
|
|
515
|
+
if (__DEV__) launchedApp = app;
|
|
487
516
|
setActiveApp({ roots: config.roots, presentation: config.presentation, mounted });
|
|
488
517
|
if (!listening) {
|
|
489
518
|
listening = true;
|
|
490
519
|
// The edges of `safeArea` go under the app's options; the window's color goes with them, as the native side
|
|
491
520
|
// takes it from the default options.
|
|
492
|
-
initTheme(
|
|
493
|
-
config.theme,
|
|
494
|
-
{
|
|
495
|
-
under: config.safeArea && { layout: { safeAreaEdges: config.safeArea.edges } },
|
|
496
|
-
options: config.options,
|
|
497
|
-
over: config.window && { window: config.window },
|
|
498
|
-
},
|
|
499
|
-
config.direction
|
|
500
|
-
);
|
|
521
|
+
initTheme(config.theme, appDefaults(), config.direction);
|
|
501
522
|
if (config.context !== undefined) setAppContext(config.context);
|
|
502
523
|
if (config.appProvider) enableSlots(config.appProvider);
|
|
503
524
|
listenToNavigationState();
|
|
525
|
+
listenToDispatchedLinks();
|
|
504
526
|
watchSideMenus();
|
|
505
527
|
listenToNativeScreens();
|
|
506
528
|
listenToSplitViews();
|
|
507
529
|
listenToNativeScreenCalls();
|
|
508
|
-
if (config.listeners) addNavigationListeners(config.listeners);
|
|
530
|
+
if (config.listeners) removeListeners = addNavigationListeners(config.listeners);
|
|
509
531
|
}
|
|
510
532
|
launchState.launch++;
|
|
511
533
|
// A new activity has no default options: the last ones set come back, else the theme's and the app's.
|
|
@@ -526,19 +548,131 @@ export function createNavigation<
|
|
|
526
548
|
relaunchWaiters.splice(0).forEach((resume) => resume());
|
|
527
549
|
}
|
|
528
550
|
|
|
529
|
-
// The
|
|
530
|
-
|
|
531
|
-
|
|
551
|
+
// The routes of the links, the roots they name and where their errors go.
|
|
552
|
+
function linkingOptions() {
|
|
553
|
+
return {
|
|
532
554
|
roots: config.roots,
|
|
533
|
-
onError:
|
|
534
|
-
|
|
555
|
+
onError:
|
|
556
|
+
config.onError &&
|
|
557
|
+
((error: unknown, url: string) => config.onError?.(error, { type: 'link', url })),
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Fast Refresh ran the module that makes the app again (development): its new config takes the place of the old.
|
|
562
|
+
// What only the start reads (the first root, willMount, the splash, the context) has done its part; the screens, the
|
|
563
|
+
// default options, the roots, the listeners and the links take the new one. A theme the same as before leaves the one
|
|
564
|
+
// the app set since. The providers and fallbacks are in the families of the ones before (`keepStateOf`): React
|
|
565
|
+
// Refresh puts the new ones in place, with the state of what they wrap.
|
|
566
|
+
function update(next: typeof config) {
|
|
567
|
+
const before = config;
|
|
568
|
+
// The app's one tree is set up at the start, or not: a provider added or taken out starts the app again.
|
|
569
|
+
if (!before.appProvider !== !next.appProvider) {
|
|
570
|
+
DevSettings.reload('[navigation] appProvider was added or taken out');
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
config = next;
|
|
574
|
+
if (screensRegistered) registerAppScreens();
|
|
575
|
+
setActiveApp({ roots: config.roots, presentation: config.presentation, mounted });
|
|
576
|
+
// A direction the app set since stays too, unless the edit changes the config's.
|
|
577
|
+
const defaultsBefore = themedDefaultOptions();
|
|
578
|
+
const direction = sameValue(before.direction, next.direction) ? getDirection() : next.direction;
|
|
579
|
+
initTheme(getTheme(), appDefaults(), direction);
|
|
580
|
+
if (!sameValue(before.theme, next.theme)) {
|
|
581
|
+
setTheme(next.theme ?? {});
|
|
582
|
+
} else {
|
|
583
|
+
const defaults = themedDefaultOptions();
|
|
584
|
+
if (!sameValue(defaultsBefore, defaults)) setDefaultOptions(defaults ?? {});
|
|
585
|
+
}
|
|
586
|
+
if (listening) {
|
|
587
|
+
removeListeners?.();
|
|
588
|
+
removeListeners = config.listeners && addNavigationListeners(config.listeners);
|
|
589
|
+
}
|
|
590
|
+
if (config.linking && linkingStarted) updateLinking(config.linking, linkingOptions());
|
|
591
|
+
else startLinking();
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// The default options of the app, under and over the theme's.
|
|
595
|
+
function appDefaults() {
|
|
596
|
+
return {
|
|
597
|
+
under: config.safeArea && { layout: { safeAreaEdges: config.safeArea.edges } },
|
|
598
|
+
options: config.options,
|
|
599
|
+
over: config.window && { window: config.window },
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// The links listen from now on: one that comes before the native side launches waits for the first root.
|
|
604
|
+
let linkingStarted = false;
|
|
605
|
+
function startLinking() {
|
|
606
|
+
if (!config.linking || linkingStarted) return;
|
|
607
|
+
linkingStarted = true;
|
|
608
|
+
setupLinking(config.linking, linkingOptions());
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// The components of the app keep their state across Fast Refresh, as the screens' do.
|
|
612
|
+
function keepComponentsState() {
|
|
613
|
+
if (!__DEV__) return;
|
|
614
|
+
keepStateOf(app, config.appProvider, 'appProvider');
|
|
615
|
+
keepStateOf(app, config.screenProvider, 'screenProvider');
|
|
616
|
+
keepStateOf(app, config.errorFallback, 'errorFallback');
|
|
617
|
+
keepStateOf(app, config.loadingFallback, 'loadingFallback');
|
|
618
|
+
keepStateOf(app, config.splash?.component, 'splash');
|
|
535
619
|
}
|
|
536
620
|
|
|
537
621
|
const app: NavigationApp<Roots, AllScreens<AppScreens, Groups>> = { [NAVIGATION_APP]: true };
|
|
538
|
-
|
|
622
|
+
keepComponentsState();
|
|
623
|
+
const start = () => {
|
|
624
|
+
startLinking();
|
|
625
|
+
starts.set(app, () => reportStart(launch));
|
|
626
|
+
if (__DEV__) updates.set(app, update as (config: unknown) => void);
|
|
627
|
+
};
|
|
628
|
+
if (!launched) {
|
|
629
|
+
start();
|
|
630
|
+
return app;
|
|
631
|
+
}
|
|
632
|
+
// Once the module ran, Metro has put its exports in the families of the ones of its run before: the same family as
|
|
633
|
+
// the app that launched, or the app's entry registering it under the app's name again (an app it doesn't export),
|
|
634
|
+
// means this is its module again, and the app that runs takes the new config.
|
|
635
|
+
pending.set(
|
|
636
|
+
app,
|
|
637
|
+
Promise.resolve().then(() => {
|
|
638
|
+
pending.delete(app);
|
|
639
|
+
const family = familyOf(app);
|
|
640
|
+
if ((family && family === familyOf(launched)) || replacing.delete(app)) {
|
|
641
|
+
updates.get(launched)?.(config);
|
|
642
|
+
starts.set(app, starts.get(launched)!);
|
|
643
|
+
updates.set(app, updates.get(launched)!);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
watchBackListeners();
|
|
647
|
+
start();
|
|
648
|
+
})
|
|
649
|
+
);
|
|
539
650
|
return app;
|
|
540
651
|
}
|
|
541
652
|
|
|
653
|
+
// The app that launched in this runtime, and what takes the config of its module when it runs again (development).
|
|
654
|
+
let launchedApp: NavigationApp<any, any> | undefined;
|
|
655
|
+
const updates = new WeakMap<NavigationApp<any, any>, (config: unknown) => void>();
|
|
656
|
+
// The apps made after the launch until their module ran, and those the app's entry registered again under its name.
|
|
657
|
+
const pending = new WeakMap<NavigationApp<any, any>, Promise<void>>();
|
|
658
|
+
const replacing = new WeakSet<NavigationApp<any, any>>();
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Notes an app the entry file registers under the name of the app that launched: the entry ran again after an edit
|
|
662
|
+
* (development), and the new app is the old one's next version.
|
|
663
|
+
*/
|
|
664
|
+
export function noteReplacingApp(app: unknown): void {
|
|
665
|
+
if (__DEV__ && launchedApp && typeof app === 'object' && app !== null && NAVIGATION_APP in app) {
|
|
666
|
+
replacing.add(app as NavigationApp<any, any>);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// The app that launched, when React Refresh runs and a new app may be its module running again: one its module
|
|
671
|
+
// exports (Metro gives it a family), or one the entry registers again under the app's name.
|
|
672
|
+
function hotCandidate(): NavigationApp<any, any> | undefined {
|
|
673
|
+
return launchedApp && refreshRuns() ? launchedApp : undefined;
|
|
674
|
+
}
|
|
675
|
+
|
|
542
676
|
// A willMount that never ends keeps the splash screen for good: in development the app hears of it.
|
|
543
677
|
function warnIfLong(willMount: Promise<void>) {
|
|
544
678
|
const timer = setTimeout(
|
|
@@ -19,7 +19,7 @@ import { stackChild, type StackEntry } from '../layout/Stack';
|
|
|
19
19
|
import { badgeText } from '../layout/Tabs';
|
|
20
20
|
import { mergeOptions } from '../../engine/mergeOptions';
|
|
21
21
|
import { buildScreenOptions, type ScreenOptionsInput } from '../screens/defineScreen';
|
|
22
|
-
import { coversColumn, placeOf } from '../../engine/places';
|
|
22
|
+
import { coversColumn, firstScreenOf, placeOf, type ScreenPlace } from '../../engine/places';
|
|
23
23
|
import { command, placeFor } from './errors';
|
|
24
24
|
import type { ColumnConfig, ModalConfig, OverlayConfig, PushConfig } from './presentation';
|
|
25
25
|
import { defined, modalAnimations, pushAnimations } from './transitions';
|
|
@@ -30,6 +30,10 @@ const CLOSE_BUTTON = 'CloseButton';
|
|
|
30
30
|
// The modals shown by `showModal`, for the ids of their first screens.
|
|
31
31
|
let modals = 0;
|
|
32
32
|
|
|
33
|
+
// The stacks of the modals shown with a close button, by id: `setStack` and `replace` there give it to the new first
|
|
34
|
+
// screen. A stack's id is its modal's layer.
|
|
35
|
+
const closeButtonStacks = new Set<string>();
|
|
36
|
+
|
|
33
37
|
// The settings of a command with the props of the screen it shows.
|
|
34
38
|
type WithProps<Config> = Config & { props?: object };
|
|
35
39
|
|
|
@@ -115,7 +119,19 @@ export function popToRoot(fromId: string): Promise<string> {
|
|
|
115
119
|
export function setStack(fromId: string, entries: StackEntry[]): Promise<string> {
|
|
116
120
|
return command('setStack', () => {
|
|
117
121
|
placeFor('setStack', fromId, { stack: true });
|
|
118
|
-
|
|
122
|
+
const children = entries.map(stackChild);
|
|
123
|
+
const first = children[0]?.component;
|
|
124
|
+
if (!first || !hasCloseButton(placeOf(fromId))) {
|
|
125
|
+
return withSlots(() => engine.setStackRoot(fromId, children));
|
|
126
|
+
}
|
|
127
|
+
return afterLoading([first.name], () => {
|
|
128
|
+
// The screen's own buttons stay after the close button: the options of the layout replace them.
|
|
129
|
+
const id = first.id ?? nextId('Component');
|
|
130
|
+
const own = screenOptions(first.name, first.passProps ?? {});
|
|
131
|
+
const options = withCloseButton(mergeOptions(own, first.options ?? {}), id);
|
|
132
|
+
const withButton = { component: { ...first, id, options } };
|
|
133
|
+
return withSlots(() => engine.setStackRoot(fromId, [withButton, ...children.slice(1)]));
|
|
134
|
+
});
|
|
119
135
|
});
|
|
120
136
|
}
|
|
121
137
|
|
|
@@ -133,11 +149,12 @@ export function replace(
|
|
|
133
149
|
return afterLoading([name], () => {
|
|
134
150
|
const { props } = config;
|
|
135
151
|
const base = getActiveApp()?.presentation?.push;
|
|
136
|
-
const
|
|
152
|
+
const id = nextId('Component');
|
|
153
|
+
let options = showOptions(name, props, AS_PUSH, base?.options, config.options, {
|
|
137
154
|
app: pushAnimations(base?.transition),
|
|
138
155
|
call: pushAnimations(config.transition),
|
|
139
156
|
});
|
|
140
|
-
|
|
157
|
+
if (hasCloseButton(placeOf(fromId))) options = withCloseButton(options, id);
|
|
141
158
|
return withSlots(() =>
|
|
142
159
|
engine.setStackRoot(fromId, [screenLayout(name, props, options, id)])
|
|
143
160
|
).then(() => id);
|
|
@@ -192,16 +209,25 @@ function showModalNow(name: string, config: WithProps<ModalConfig>): Promise<str
|
|
|
192
209
|
app: modalAnimations(base.transition),
|
|
193
210
|
call: modalAnimations(call.transition),
|
|
194
211
|
});
|
|
195
|
-
|
|
212
|
+
// The stack gets its id here, so that the commands in it later know the modal had a close button.
|
|
213
|
+
const stackId = nextId('Stack');
|
|
214
|
+
const closeButton = settings.closeButton && settings.stack !== false;
|
|
215
|
+
if (closeButton) {
|
|
196
216
|
options = withCloseButton(options, screenId);
|
|
217
|
+
closeButtonStacks.add(stackId);
|
|
218
|
+
forgetWithStack(stackId, screenId);
|
|
219
|
+
}
|
|
197
220
|
if (call.onDismiss) whenScreenUnmounts(screenId, call.onDismiss);
|
|
198
221
|
const screen = screenLayout(name, props, options, screenId);
|
|
199
222
|
const presentation = presentationOptions(settings);
|
|
200
223
|
const layout: Layout =
|
|
201
224
|
settings.stack === false
|
|
202
225
|
? mergeLayoutOptions(screen, presentation)
|
|
203
|
-
: { stack: { children: [screen], options: presentation } };
|
|
204
|
-
|
|
226
|
+
: { stack: { id: stackId, children: [screen], options: presentation } };
|
|
227
|
+
const shown = withSlots(() => engine.showModal(layout));
|
|
228
|
+
// A modal that never showed has no stack to remember.
|
|
229
|
+
if (closeButton) shown.catch(() => closeButtonStacks.delete(stackId));
|
|
230
|
+
return shown;
|
|
205
231
|
}
|
|
206
232
|
|
|
207
233
|
export function dismissModal(modalId: string): Promise<string> {
|
|
@@ -340,6 +366,21 @@ export function holdLeave(screenId: string, onAttempt: () => void): () => void {
|
|
|
340
366
|
};
|
|
341
367
|
}
|
|
342
368
|
|
|
369
|
+
// Whether a screen is in the stack of a modal shown with a close button: the modal's own stack, not one in it.
|
|
370
|
+
function hasCloseButton(place: ScreenPlace | undefined): boolean {
|
|
371
|
+
return place?.stack != null && place.stack === place.layer && closeButtonStacks.has(place.stack);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// The stack of a modal is gone with its last first screen: one that unmounts with no other first screen noted after
|
|
375
|
+
// it (`setStack`, `replace` note theirs before the old one goes).
|
|
376
|
+
function forgetWithStack(stackId: string, screenId: string): void {
|
|
377
|
+
whenScreenUnmounts(screenId, () => {
|
|
378
|
+
const next = firstScreenOf(stackId);
|
|
379
|
+
if (next) forgetWithStack(stackId, next);
|
|
380
|
+
else closeButtonStacks.delete(stackId);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
343
384
|
/** The options with a close button first at the leading edge, which dismisses the modal of the screen. */
|
|
344
385
|
function withCloseButton(options: Options, screenId: string): Options {
|
|
345
386
|
const close: NavigationButton = {
|
|
@@ -43,12 +43,13 @@ export interface ModalConfig {
|
|
|
43
43
|
stack?: boolean;
|
|
44
44
|
/**
|
|
45
45
|
* A close button at the leading edge of the modal's first screen, which dismisses the modal: the system one on iOS,
|
|
46
|
-
* an icon on Android. Its id and testID are `CloseButton`. Needs the stack.
|
|
46
|
+
* an icon on Android. Its id and testID are `CloseButton`. Needs the stack. A new first screen of that stack, from
|
|
47
|
+
* `setStack` or `replace`, gets it too.
|
|
47
48
|
*/
|
|
48
49
|
closeButton?: boolean;
|
|
49
50
|
/**
|
|
50
|
-
* Called once the modal is gone, whatever dismissed it: a command, a swipe, a new root. `setStack`
|
|
51
|
-
* modal
|
|
51
|
+
* Called once the modal is gone, whatever dismissed it: a command, a swipe, a new root. `setStack` and `replace`
|
|
52
|
+
* inside the modal replace its first screen, and call it too.
|
|
52
53
|
*/
|
|
53
54
|
onDismiss?: () => void;
|
|
54
55
|
/**
|
|
@@ -48,7 +48,7 @@ export interface NavigationEvents {
|
|
|
48
48
|
searchCancelled: ScreenEventOf<SearchBarCancelPressedEvent>;
|
|
49
49
|
/** #### (iOS 16+, Android) The user picked a suggestion of `searchBar.suggestions`; the text stays. */
|
|
50
50
|
searchSuggestionPicked: ScreenEventOf<NativeSearchSuggestionPickedEvent>;
|
|
51
|
-
/**
|
|
51
|
+
/** The user dragged a sheet to another detent. */
|
|
52
52
|
sheetDetentChanged: ScreenEventOf<NativeSheetDetentChangedEvent>;
|
|
53
53
|
/** #### (iOS specific) */
|
|
54
54
|
splitViewDisplayModeChanged: NativeSplitViewDisplayModeChangedEvent;
|
|
@@ -166,10 +166,16 @@ export function onNavigationEvent<Name extends NavigationEventName>(
|
|
|
166
166
|
return onNativeEvent(nativeName, deliver);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
/** Listens to the events of `listeners
|
|
170
|
-
export function addNavigationListeners(listeners: NavigationListeners) {
|
|
169
|
+
/** Listens to the events of `listeners` until the function it gives is called. */
|
|
170
|
+
export function addNavigationListeners(listeners: NavigationListeners): () => void {
|
|
171
|
+
const removers: (() => void)[] = [];
|
|
171
172
|
for (const name of Object.keys(listeners) as NavigationEventName[]) {
|
|
172
173
|
const handler = listeners[name];
|
|
173
|
-
if (handler)
|
|
174
|
+
if (handler) {
|
|
175
|
+
removers.push(
|
|
176
|
+
onNavigationEvent(name, handler as (event: NavigationEvents[typeof name]) => void)
|
|
177
|
+
);
|
|
178
|
+
}
|
|
174
179
|
}
|
|
180
|
+
return () => removers.forEach((remove) => remove());
|
|
175
181
|
}
|
|
@@ -22,7 +22,7 @@ import type { ScreenName, ShowArgs } from '../types';
|
|
|
22
22
|
interface ScreenCommands {
|
|
23
23
|
/** The screen the commands act from. */
|
|
24
24
|
readonly screen: ScreenInfo;
|
|
25
|
-
/** Shows a screen over this one in its stack; resolves with the id of the screen shown. */
|
|
25
|
+
/** Shows a screen over this one in its stack; resolves with the id of the screen shown (for a pair, the pair's id). */
|
|
26
26
|
push<Name extends ScreenName>(name: Name, ...args: ShowArgs<Name, PushConfig>): Promise<string>;
|
|
27
27
|
/**
|
|
28
28
|
* Goes back to the screen before this one in its stack. The first screen of a split view column shown over the list
|
|
@@ -177,14 +177,19 @@ function stackCommands(id: string): StackCommands {
|
|
|
177
177
|
};
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
/**
|
|
180
|
+
/**
|
|
181
|
+
* The commands of the center for a menu screen: the menu closes as the center changes, and the command resolves once
|
|
182
|
+
* both are done.
|
|
183
|
+
*/
|
|
181
184
|
function fromCenter(center: string, menuScreen: string): StackCommands {
|
|
182
185
|
const centerCommands = stackCommands(center);
|
|
186
|
+
// As in the system's apps, the menu starts to close at the pick and the center changes as it goes, so a push is seen
|
|
187
|
+
// sliding in. The command settles after both, so the next one acts from the center; either one's error rejects it.
|
|
183
188
|
const closing =
|
|
184
189
|
<Args extends unknown[], Result>(run: (...args: Args) => Promise<Result>) =>
|
|
185
190
|
async (...args: Args) => {
|
|
186
|
-
const
|
|
187
|
-
await
|
|
191
|
+
const closed = closeMenu(menuScreen);
|
|
192
|
+
const [result] = await Promise.all([run(...args), closed]);
|
|
188
193
|
return result;
|
|
189
194
|
};
|
|
190
195
|
return {
|
|
@@ -5,13 +5,14 @@ import { useScreen } from './screenHooks';
|
|
|
5
5
|
/**
|
|
6
6
|
* How much of this screen's content the bars and the system still cover on each side, past what the screen keeps its
|
|
7
7
|
* content off itself (`layout.safeAreaEdges`): 0 on an edge the screen pads, the whole inset on an edge its content goes
|
|
8
|
-
* under —
|
|
9
|
-
*
|
|
8
|
+
* under — the bottom by default (the home indicator, the navigation bar, a tab bar or toolbar the screen goes under),
|
|
9
|
+
* under a top bar, under the vertical bar at the side of iPhone Duo, every edge with `safeAreaEdges: []`. A list adds
|
|
10
|
+
* exactly this to its own padding. The native side measures every screen on its own, also the screens of
|
|
10
11
|
* `appProvider`.
|
|
11
12
|
*
|
|
12
13
|
* @example
|
|
13
14
|
* const insets = useSafeAreaInsets();
|
|
14
|
-
* <ScrollView contentContainerStyle={{
|
|
15
|
+
* <ScrollView contentContainerStyle={{ paddingBottom: 16 + insets.bottom }} />
|
|
15
16
|
*/
|
|
16
17
|
export function useSafeAreaInsets(): EdgeInsets {
|
|
17
18
|
const { id } = useScreen();
|
package/src/api/index.ts
CHANGED
|
@@ -109,6 +109,7 @@ export type { NativeScreen } from './screens/nativeScreens';
|
|
|
109
109
|
export { defineArrangement } from './screens/arrangement';
|
|
110
110
|
export type { Arrangement, ArrangementDefinition, ScreenArrangement } from './screens/arrangement';
|
|
111
111
|
export type {
|
|
112
|
+
DefinedScreen,
|
|
112
113
|
OptionsEnvironment,
|
|
113
114
|
ScreenDefinition,
|
|
114
115
|
ScreenOptionsInput,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DeviceEventEmitter, Platform } from 'react-native';
|
|
2
|
+
import { onNativeEvent } from '../../engine/native';
|
|
3
|
+
import type { DeepLinkDispatchedEvent } from '../../interfaces/Events';
|
|
4
|
+
|
|
5
|
+
let listening = false;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* (iOS) Hands `Linking` the links the app dispatched that it didn't take from the native side: on React Native 0.88
|
|
9
|
+
* and newer, in an app with a scene delegate, it takes only the links a scene opened. `Linking` listens to its `url`
|
|
10
|
+
* events through `DeviceEventEmitter`, so every listener of the app gets them, the navigation's links too.
|
|
11
|
+
*/
|
|
12
|
+
export function listenToDispatchedLinks() {
|
|
13
|
+
if (listening || Platform.OS !== 'ios') return;
|
|
14
|
+
listening = true;
|
|
15
|
+
onNativeEvent<DeepLinkDispatchedEvent>('DeepLinkDispatched', ({ url }) => {
|
|
16
|
+
DeviceEventEmitter.emit('url', { url });
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -6,7 +6,11 @@ import { commandsStarted, whenCommandsSettle } from '../commands/errors';
|
|
|
6
6
|
import { getAppContext, subscribeAppContext } from '../context/appContext';
|
|
7
7
|
import { buildRoot, type RootLayout } from '../layout/Root';
|
|
8
8
|
import { navigation } from '../navigation';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getNavigationState,
|
|
11
|
+
whenScreenAfter,
|
|
12
|
+
type NavigationState,
|
|
13
|
+
} from '../state/navigationState';
|
|
10
14
|
import {
|
|
11
15
|
compileRoutes,
|
|
12
16
|
matchLink,
|
|
@@ -68,6 +72,23 @@ export function setupLinking(
|
|
|
68
72
|
setPendingLinkOpener((link) => run(link, routeOf(link), false));
|
|
69
73
|
}
|
|
70
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Takes the routes, the roots and `onError` of an app whose module ran again after an edit (Fast Refresh, development):
|
|
77
|
+
* the links that come from now on find the new routes.
|
|
78
|
+
*/
|
|
79
|
+
export function updateLinking(
|
|
80
|
+
linking: Config,
|
|
81
|
+
options: {
|
|
82
|
+
roots: RootsMap | undefined;
|
|
83
|
+
onError: ((error: unknown, url: string) => void) | undefined;
|
|
84
|
+
}
|
|
85
|
+
): void {
|
|
86
|
+
config = linking;
|
|
87
|
+
roots = options.roots;
|
|
88
|
+
onError = options.onError;
|
|
89
|
+
routes = compileRoutes(Object.keys(linking.routes));
|
|
90
|
+
}
|
|
91
|
+
|
|
71
92
|
/**
|
|
72
93
|
* The link that launched the app, matched as the app starts (`unmatched` may run commands then); the same one for
|
|
73
94
|
* every try of the first start.
|
package/src/api/navigation.ts
CHANGED
|
@@ -55,7 +55,10 @@ export interface AppNavigation {
|
|
|
55
55
|
switchTo<const Layout extends Exclude<RootLayout, string>>(
|
|
56
56
|
layout: Layout & NoInfer<CheckedScreens<UsesOfRoot<Layout>, RegisteredScreens>>
|
|
57
57
|
): Promise<void>;
|
|
58
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Shows a screen in the stack of the screen the user sees; resolves with the id of the screen shown (for a pair, the
|
|
60
|
+
* pair's id).
|
|
61
|
+
*/
|
|
59
62
|
push<Name extends ScreenName>(name: Name, ...args: ShowArgs<Name, PushConfig>): Promise<string>;
|
|
60
63
|
/** Goes back in the stack of the screen the user sees; see `useNavigation().pop`. */
|
|
61
64
|
pop(): Promise<string>;
|