@apexnative/navigation 1.0.0-alpha.1 → 1.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ApexNavigation.podspec +2 -1
- package/CHANGELOG.md +132 -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/ArrangementDefinition.kt +9 -3
- package/android/src/main/java/dev/apexnative/navigation/viewcontrollers/arrangement/ArrangementPlanner.kt +20 -15
- 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/arrangement.md +17 -1
- 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 +61 -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 +195 -21
- 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 +34 -0
- package/ios/Layouts/Screen/ANNScreenSettling.mm +171 -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/arrangement.js +5 -2
- package/lib/module/api/screens/arrangement.js.map +1 -1
- 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/arrangement.d.ts +12 -2
- package/lib/typescript/api/screens/arrangement.d.ts.map +1 -1
- 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/arrangement.ts +17 -4
- 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
|
@@ -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>;
|
|
@@ -68,8 +68,8 @@ export abstract class OptionsChain {
|
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* The edges on which the screen keeps its content out of its safe area (bars, status bar, home indicator, cutout);
|
|
71
|
-
* none with no edge. Without it:
|
|
72
|
-
* a
|
|
71
|
+
* none with no edge. Without it: the top and the sides, but those where the content goes under a bar; the bottom is
|
|
72
|
+
* free, and a list keeps clear of it with `useSafeAreaInsets()`. A large title leaves the top out by itself.
|
|
73
73
|
*/
|
|
74
74
|
safeArea(...edges: SafeAreaEdge[]): this {
|
|
75
75
|
return this.layout({ safeAreaEdges: edges });
|
|
@@ -26,13 +26,23 @@ export interface ScreenArrangement<Props extends object = {}> {
|
|
|
26
26
|
|
|
27
27
|
/** A pair under a name of its own, with every setting: `defineArrangement`. */
|
|
28
28
|
export interface ArrangementDefinition<Props extends object = {}> extends ScreenArrangement<Props> {
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* The screen that owns the bar: its title, buttons, toolbar and status bar are the pair's. It shows alone outside a
|
|
31
|
+
* large window (`compact: 'primary'`), and `primaryEdge` puts it on either side. A name of `screens`.
|
|
32
|
+
*/
|
|
30
33
|
primary: string;
|
|
31
34
|
/** The axes the pair may use. Where the window allows none of them, only the primary shows. @default 'both' */
|
|
32
35
|
axes?: 'horizontal' | 'vertical' | 'both';
|
|
33
36
|
/** `split`: the primary's share along the split, above 0 and below 1, where the fold does not decide. @default 0.5 */
|
|
34
37
|
fraction?: number;
|
|
35
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* The edge the primary takes. `split`: `leading` or `top` puts the primary first, at the leading side or on top;
|
|
40
|
+
* `trailing` or `bottom` puts it second, at the trailing side or at the bottom (one setting for both ways the pair
|
|
41
|
+
* may lie). `overlay`: the primary's edge when the pair goes side by side; an edge of the other axis counts as the
|
|
42
|
+
* nearest one (`top` as leading, `bottom` as trailing). Whatever the edge, the primary is the screen that shows
|
|
43
|
+
* alone outside a large window with `compact: 'primary'`: to show the other screen there, make it the primary.
|
|
44
|
+
* @default 'leading' for split, 'trailing' for overlay
|
|
45
|
+
*/
|
|
36
46
|
primaryEdge?: 'leading' | 'trailing' | 'top' | 'bottom';
|
|
37
47
|
/**
|
|
38
48
|
* Outside a large window: `primary` — the primary alone, as a plain screen; `pair` — the pair as the system lays it
|
|
@@ -85,14 +95,17 @@ export function toEngineArrangement(
|
|
|
85
95
|
): EngineArrangement {
|
|
86
96
|
const full = arrangement as ArrangementDefinition<any>;
|
|
87
97
|
checkFraction(full.fraction);
|
|
98
|
+
const style = arrangement.style ?? 'split';
|
|
88
99
|
return {
|
|
89
100
|
primary,
|
|
90
101
|
secondary: arrangement.secondary,
|
|
91
102
|
secondaryProps: arrangement.secondaryProps,
|
|
92
|
-
style
|
|
103
|
+
style,
|
|
93
104
|
axes: full.axes ?? 'both',
|
|
94
105
|
fraction: full.fraction ?? 0.5,
|
|
95
|
-
|
|
106
|
+
// Where UIKit puts the primary of each style without an edge set: first in a split, at the trailing side of an
|
|
107
|
+
// overlay that goes side by side.
|
|
108
|
+
primaryEdge: full.primaryEdge ?? (style === 'split' ? 'leading' : 'trailing'),
|
|
96
109
|
compact: full.compact ?? 'primary',
|
|
97
110
|
};
|
|
98
111
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ComponentType, createElement } from 'react';
|
|
2
2
|
import type { Options } from '../../interfaces/Options';
|
|
3
|
+
import { keepStateOf, newestType, redefined } from '../../engine/refresh';
|
|
3
4
|
import { getAppContext } from '../context/appContext';
|
|
4
5
|
import { readScreenOptions, ScreenOptions } from '../options/ScreenOptions';
|
|
5
6
|
import { getTheme, type NavigationTheme } from '../theme/theme';
|
|
@@ -38,12 +39,55 @@ export interface ScreenDefinition<Props = any> {
|
|
|
38
39
|
arrangement?: ScreenArrangement<Props & object>;
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
const SCREEN_DEFINITION = Symbol('apexnative.navigation.screenDefinition');
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A screen of `defineScreen`: a component of its own, which renders the screen's component and carries the screen's
|
|
46
|
+
* definition. It goes right into `screens` of createNavigation, and rendered on its own (a test) it renders the screen.
|
|
47
|
+
*/
|
|
48
|
+
export type DefinedScreen<Props> = ComponentType<Props> & {
|
|
49
|
+
readonly [SCREEN_DEFINITION]: ScreenDefinition<Props>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Describes a screen next to its component, so its registration stays one line. It gives a component that renders the
|
|
54
|
+
* screen and goes right into `screens` of createNavigation: a file that exports only its screens stays a boundary of
|
|
55
|
+
* Fast Refresh, so an edit of the screen, its options too, updates it in place instead of reloading the app.
|
|
56
|
+
*/
|
|
57
|
+
export function defineScreen<Props>(definition: ScreenDefinition<Props>): DefinedScreen<Props> {
|
|
58
|
+
const { component } = definition;
|
|
59
|
+
// A component of each definition, so the app's own component stays as it is for any other use of it.
|
|
60
|
+
const Component = component as ComponentType<object>;
|
|
61
|
+
function Screen(props: Props) {
|
|
62
|
+
return createElement(Component, props as object);
|
|
63
|
+
}
|
|
64
|
+
Screen.displayName = component.displayName ?? component.name;
|
|
65
|
+
Object.defineProperty(Screen, SCREEN_DEFINITION, { value: definition });
|
|
66
|
+
keepStateOf(Screen, component);
|
|
67
|
+
redefined(Screen);
|
|
68
|
+
return Screen as DefinedScreen<Props>;
|
|
69
|
+
}
|
|
70
|
+
|
|
41
71
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
72
|
+
* The definition a screen of `defineScreen` carries, the newest one after Fast Refresh ran the screen's module again;
|
|
73
|
+
* undefined for anything else.
|
|
44
74
|
*/
|
|
45
|
-
export function
|
|
46
|
-
return
|
|
75
|
+
export function definitionOf(value: unknown): ScreenDefinition | undefined {
|
|
76
|
+
return isDefinedScreen(value) ? ownDefinitionOf(newestType(value)) : undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** The definition a screen of `defineScreen` carries itself, not a newer one; undefined for anything else. */
|
|
80
|
+
export function ownDefinitionOf(value: unknown): ScreenDefinition | undefined {
|
|
81
|
+
return isDefinedScreen(value) ? value[SCREEN_DEFINITION] : undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Whether the value is a screen of `defineScreen`. */
|
|
85
|
+
export function isDefinedScreen(value: unknown): value is DefinedScreen<any> {
|
|
86
|
+
return (
|
|
87
|
+
(typeof value === 'function' || typeof value === 'object') &&
|
|
88
|
+
value !== null &&
|
|
89
|
+
SCREEN_DEFINITION in value
|
|
90
|
+
);
|
|
47
91
|
}
|
|
48
92
|
|
|
49
93
|
export function buildScreenOptions<Props>(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { redefined, resetOnEdit } from '../../engine/refresh';
|
|
1
3
|
import type { ScreenArrangement } from './arrangement';
|
|
2
4
|
import type { ScreenOptionsInput } from './defineScreen';
|
|
3
5
|
|
|
@@ -30,7 +32,9 @@ export interface NativeScreenDefinition<Props extends object> {
|
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* A native screen for `screens`: commands and layouts name it like any other screen, and its props go to the native
|
|
33
|
-
* creator. `nativeName` is the name it is registered under natively (`ApexNavigation.registerNativeScreen`).
|
|
35
|
+
* creator. `nativeName` is the name it is registered under natively (`ApexNavigation.registerNativeScreen`). It is a
|
|
36
|
+
* component that runs `useProps`, so a file that exports only its screens updates by Fast Refresh, the hook and the
|
|
37
|
+
* options too.
|
|
34
38
|
*
|
|
35
39
|
* @example
|
|
36
40
|
* const Settings = nativeScreen('Settings', {
|
|
@@ -49,10 +53,42 @@ export function nativeScreen<Props extends object = {}>(
|
|
|
49
53
|
nativeName: string,
|
|
50
54
|
definition: NativeScreenDefinition<Props> = {}
|
|
51
55
|
): NativeScreen<Props> {
|
|
52
|
-
const { options, useProps, arrangement } = definition;
|
|
53
|
-
|
|
56
|
+
const { options, useProps = noProps, arrangement } = definition;
|
|
57
|
+
// A component that runs the hook, so that a file exporting only its screens stays a boundary of Fast Refresh: React
|
|
58
|
+
// Refresh puts the new version in place, with the edited hook.
|
|
59
|
+
function NativeScreen({ props, onProps }: NativeScreenHookProps<Props>) {
|
|
60
|
+
const result = useProps(props);
|
|
61
|
+
// After each render React committed, so the native side never shows what the app did not.
|
|
62
|
+
useEffect(() => onProps(result));
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const screen = Object.assign(NativeScreen, {
|
|
66
|
+
[NATIVE_SCREEN]: true as const,
|
|
67
|
+
nativeName,
|
|
68
|
+
options,
|
|
69
|
+
useProps: definition.useProps,
|
|
70
|
+
arrangement,
|
|
71
|
+
});
|
|
72
|
+
// The hook is the app's and may have other hooks after an edit: its new version mounts anew.
|
|
73
|
+
resetOnEdit(screen);
|
|
74
|
+
redefined(screen);
|
|
75
|
+
return screen;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function noProps(): object {
|
|
79
|
+
return {};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** What the component of a native screen renders with: the props of the command, and where the hook's result goes. */
|
|
83
|
+
export interface NativeScreenHookProps<Props> {
|
|
84
|
+
props: Props;
|
|
85
|
+
onProps(result: object): void;
|
|
54
86
|
}
|
|
55
87
|
|
|
56
88
|
export function isNativeScreen(value: unknown): value is NativeScreen<any> {
|
|
57
|
-
return
|
|
89
|
+
return (
|
|
90
|
+
(typeof value === 'function' || typeof value === 'object') &&
|
|
91
|
+
value !== null &&
|
|
92
|
+
NATIVE_SCREEN in value
|
|
93
|
+
);
|
|
58
94
|
}
|