@symbiote-native/navigation 1.0.0
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/LICENSE +21 -0
- package/build/angular/drawer/index.d.ts +76 -0
- package/build/angular/drawer/index.js +508 -0
- package/build/angular/drawer-screen.directive.d.ts +14 -0
- package/build/angular/drawer-screen.directive.js +87 -0
- package/build/angular/index.d.ts +23 -0
- package/build/angular/index.js +22 -0
- package/build/angular/injectors/index.d.ts +13 -0
- package/build/angular/injectors/index.js +8 -0
- package/build/angular/injectors/inject-drawer-navigation.d.ts +4 -0
- package/build/angular/injectors/inject-drawer-navigation.js +12 -0
- package/build/angular/injectors/inject-focus-effect.d.ts +2 -0
- package/build/angular/injectors/inject-focus-effect.js +29 -0
- package/build/angular/injectors/inject-is-focused.d.ts +2 -0
- package/build/angular/injectors/inject-is-focused.js +20 -0
- package/build/angular/injectors/inject-navigation-state.d.ts +3 -0
- package/build/angular/injectors/inject-navigation-state.js +35 -0
- package/build/angular/injectors/inject-navigation.d.ts +7 -0
- package/build/angular/injectors/inject-navigation.js +16 -0
- package/build/angular/injectors/inject-route.d.ts +3 -0
- package/build/angular/injectors/inject-route.js +20 -0
- package/build/angular/injectors/inject-stack-navigation.d.ts +4 -0
- package/build/angular/injectors/inject-stack-navigation.js +15 -0
- package/build/angular/injectors/inject-tab-navigation.d.ts +4 -0
- package/build/angular/injectors/inject-tab-navigation.js +11 -0
- package/build/angular/linking.d.ts +3 -0
- package/build/angular/linking.js +43 -0
- package/build/angular/navigation-context.service.d.ts +13 -0
- package/build/angular/navigation-context.service.js +105 -0
- package/build/angular/navigation-scope.directive.d.ts +10 -0
- package/build/angular/navigation-scope.directive.js +90 -0
- package/build/angular/screen.directive.d.ts +22 -0
- package/build/angular/screen.directive.js +90 -0
- package/build/angular/search-bar-ref.directive.d.ts +10 -0
- package/build/angular/search-bar-ref.directive.js +88 -0
- package/build/angular/stack/index.d.ts +55 -0
- package/build/angular/stack/index.js +386 -0
- package/build/angular/tab-screen.directive.d.ts +14 -0
- package/build/angular/tab-screen.directive.js +87 -0
- package/build/angular/tabs/index.d.ts +42 -0
- package/build/angular/tabs/index.js +263 -0
- package/build/core/constants.d.ts +27 -0
- package/build/core/constants.js +61 -0
- package/build/core/drawer-options/index.d.ts +64 -0
- package/build/core/drawer-options/index.js +200 -0
- package/build/core/drawer-router-state/index.d.ts +21 -0
- package/build/core/drawer-router-state/index.js +40 -0
- package/build/core/guards.d.ts +2 -0
- package/build/core/guards.js +22 -0
- package/build/core/header-bar-buttons.d.ts +9 -0
- package/build/core/header-bar-buttons.js +163 -0
- package/build/core/index.d.ts +29 -0
- package/build/core/index.js +32 -0
- package/build/core/linking-config/index.d.ts +13 -0
- package/build/core/linking-config/index.js +171 -0
- package/build/core/navigation-events/index.d.ts +16 -0
- package/build/core/navigation-events/index.js +57 -0
- package/build/core/navigator-handles/index.d.ts +30 -0
- package/build/core/navigator-handles/index.js +15 -0
- package/build/core/navigator-props.d.ts +216 -0
- package/build/core/navigator-props.js +7 -0
- package/build/core/navigator-state/index.d.ts +36 -0
- package/build/core/navigator-state/index.js +81 -0
- package/build/core/render-drawer.d.ts +13 -0
- package/build/core/render-drawer.js +88 -0
- package/build/core/render-stack.d.ts +35 -0
- package/build/core/render-stack.js +294 -0
- package/build/core/render-tabs.d.ts +20 -0
- package/build/core/render-tabs.js +97 -0
- package/build/core/screen-options.d.ts +4 -0
- package/build/core/screen-options.js +133 -0
- package/build/core/search-bar-commands.d.ts +10 -0
- package/build/core/search-bar-commands.js +42 -0
- package/build/core/state-persistence/index.d.ts +3 -0
- package/build/core/state-persistence/index.js +23 -0
- package/build/core/tab-options.d.ts +13 -0
- package/build/core/tab-options.js +10 -0
- package/build/core/tab-router-state/index.d.ts +19 -0
- package/build/core/tab-router-state/index.js +51 -0
- package/build/react/collect-registry.d.ts +4 -0
- package/build/react/collect-registry.js +15 -0
- package/build/react/drawer/index.d.ts +29 -0
- package/build/react/drawer/index.js +277 -0
- package/build/react/drawer-screen.d.ts +14 -0
- package/build/react/drawer-screen.js +8 -0
- package/build/react/hooks/index.d.ts +12 -0
- package/build/react/hooks/index.js +8 -0
- package/build/react/hooks/use-drawer-navigation.d.ts +4 -0
- package/build/react/hooks/use-drawer-navigation.js +12 -0
- package/build/react/hooks/use-focus-effect.d.ts +2 -0
- package/build/react/hooks/use-focus-effect.js +29 -0
- package/build/react/hooks/use-is-focused.d.ts +1 -0
- package/build/react/hooks/use-is-focused.js +22 -0
- package/build/react/hooks/use-navigation-state/index.d.ts +2 -0
- package/build/react/hooks/use-navigation-state/index.js +39 -0
- package/build/react/hooks/use-navigation.d.ts +7 -0
- package/build/react/hooks/use-navigation.js +16 -0
- package/build/react/hooks/use-route.d.ts +2 -0
- package/build/react/hooks/use-route.js +8 -0
- package/build/react/hooks/use-stack-navigation.d.ts +4 -0
- package/build/react/hooks/use-stack-navigation.js +14 -0
- package/build/react/hooks/use-tab-navigation.d.ts +4 -0
- package/build/react/hooks/use-tab-navigation.js +12 -0
- package/build/react/index.d.ts +24 -0
- package/build/react/index.js +21 -0
- package/build/react/linking.d.ts +3 -0
- package/build/react/linking.js +47 -0
- package/build/react/navigation-context.d.ts +10 -0
- package/build/react/navigation-context.js +22 -0
- package/build/react/screen.d.ts +22 -0
- package/build/react/screen.js +7 -0
- package/build/react/stack/index.d.ts +13 -0
- package/build/react/stack/index.js +202 -0
- package/build/react/tab-screen.d.ts +15 -0
- package/build/react/tab-screen.js +8 -0
- package/build/react/tabs/index.d.ts +12 -0
- package/build/react/tabs/index.js +116 -0
- package/build/register.d.ts +7 -0
- package/build/register.js +58 -0
- package/build/vue/composables/index.d.ts +12 -0
- package/build/vue/composables/index.js +8 -0
- package/build/vue/composables/use-drawer-navigation.d.ts +5 -0
- package/build/vue/composables/use-drawer-navigation.js +15 -0
- package/build/vue/composables/use-focus-effect.d.ts +1 -0
- package/build/vue/composables/use-focus-effect.js +31 -0
- package/build/vue/composables/use-is-focused.d.ts +2 -0
- package/build/vue/composables/use-is-focused.js +28 -0
- package/build/vue/composables/use-navigation-state.d.ts +3 -0
- package/build/vue/composables/use-navigation-state.js +29 -0
- package/build/vue/composables/use-navigation.d.ts +8 -0
- package/build/vue/composables/use-navigation.js +13 -0
- package/build/vue/composables/use-route.d.ts +3 -0
- package/build/vue/composables/use-route.js +9 -0
- package/build/vue/composables/use-stack-navigation.d.ts +5 -0
- package/build/vue/composables/use-stack-navigation.js +18 -0
- package/build/vue/composables/use-tab-navigation.d.ts +5 -0
- package/build/vue/composables/use-tab-navigation.js +15 -0
- package/build/vue/drawer/index.d.ts +19 -0
- package/build/vue/drawer/index.js +390 -0
- package/build/vue/drawer-screen.d.ts +14 -0
- package/build/vue/drawer-screen.js +12 -0
- package/build/vue/index.d.ts +21 -0
- package/build/vue/index.js +19 -0
- package/build/vue/linking.d.ts +3 -0
- package/build/vue/linking.js +57 -0
- package/build/vue/navigation-context.d.ts +16 -0
- package/build/vue/navigation-context.js +65 -0
- package/build/vue/screen.d.ts +21 -0
- package/build/vue/screen.js +12 -0
- package/build/vue/stack/index.d.ts +9 -0
- package/build/vue/stack/index.js +279 -0
- package/build/vue/tab-screen.d.ts +14 -0
- package/build/vue/tab-screen.js +11 -0
- package/build/vue/tabs/index.d.ts +10 -0
- package/build/vue/tabs/index.js +209 -0
- package/build-ngc/angular/drawer/index.d.ts +79 -0
- package/build-ngc/angular/drawer/index.js +479 -0
- package/build-ngc/angular/drawer/index.js.map +1 -0
- package/build-ngc/angular/drawer-screen.directive.d.ts +17 -0
- package/build-ngc/angular/drawer-screen.directive.js +32 -0
- package/build-ngc/angular/drawer-screen.directive.js.map +1 -0
- package/build-ngc/angular/drawer.d.ts +79 -0
- package/build-ngc/angular/drawer.js +475 -0
- package/build-ngc/angular/drawer.js.map +1 -0
- package/build-ngc/angular/index.d.ts +23 -0
- package/build-ngc/angular/index.js +23 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/injectors/index.d.ts +13 -0
- package/build-ngc/angular/injectors/index.js +9 -0
- package/build-ngc/angular/injectors/index.js.map +1 -0
- package/build-ngc/angular/injectors/inject-drawer-navigation.d.ts +4 -0
- package/build-ngc/angular/injectors/inject-drawer-navigation.js +13 -0
- package/build-ngc/angular/injectors/inject-drawer-navigation.js.map +1 -0
- package/build-ngc/angular/injectors/inject-focus-effect.d.ts +2 -0
- package/build-ngc/angular/injectors/inject-focus-effect.js +30 -0
- package/build-ngc/angular/injectors/inject-focus-effect.js.map +1 -0
- package/build-ngc/angular/injectors/inject-is-focused.d.ts +2 -0
- package/build-ngc/angular/injectors/inject-is-focused.js +22 -0
- package/build-ngc/angular/injectors/inject-is-focused.js.map +1 -0
- package/build-ngc/angular/injectors/inject-navigation-state.d.ts +3 -0
- package/build-ngc/angular/injectors/inject-navigation-state.js +37 -0
- package/build-ngc/angular/injectors/inject-navigation-state.js.map +1 -0
- package/build-ngc/angular/injectors/inject-navigation.d.ts +7 -0
- package/build-ngc/angular/injectors/inject-navigation.js +17 -0
- package/build-ngc/angular/injectors/inject-navigation.js.map +1 -0
- package/build-ngc/angular/injectors/inject-route.d.ts +3 -0
- package/build-ngc/angular/injectors/inject-route.js +21 -0
- package/build-ngc/angular/injectors/inject-route.js.map +1 -0
- package/build-ngc/angular/injectors/inject-stack-navigation.d.ts +4 -0
- package/build-ngc/angular/injectors/inject-stack-navigation.js +16 -0
- package/build-ngc/angular/injectors/inject-stack-navigation.js.map +1 -0
- package/build-ngc/angular/injectors/inject-tab-navigation.d.ts +4 -0
- package/build-ngc/angular/injectors/inject-tab-navigation.js +12 -0
- package/build-ngc/angular/injectors/inject-tab-navigation.js.map +1 -0
- package/build-ngc/angular/linking.d.ts +3 -0
- package/build-ngc/angular/linking.js +44 -0
- package/build-ngc/angular/linking.js.map +1 -0
- package/build-ngc/angular/navigation-context.service.d.ts +16 -0
- package/build-ngc/angular/navigation-context.service.js +63 -0
- package/build-ngc/angular/navigation-context.service.js.map +1 -0
- package/build-ngc/angular/navigation-scope.directive.d.ts +13 -0
- package/build-ngc/angular/navigation-scope.directive.js +42 -0
- package/build-ngc/angular/navigation-scope.directive.js.map +1 -0
- package/build-ngc/angular/screen.directive.d.ts +25 -0
- package/build-ngc/angular/screen.directive.js +35 -0
- package/build-ngc/angular/screen.directive.js.map +1 -0
- package/build-ngc/angular/search-bar-ref.directive.d.ts +13 -0
- package/build-ngc/angular/search-bar-ref.directive.js +44 -0
- package/build-ngc/angular/search-bar-ref.directive.js.map +1 -0
- package/build-ngc/angular/stack/index.d.ts +58 -0
- package/build-ngc/angular/stack/index.js +406 -0
- package/build-ngc/angular/stack/index.js.map +1 -0
- package/build-ngc/angular/stack.d.ts +58 -0
- package/build-ngc/angular/stack.js +402 -0
- package/build-ngc/angular/stack.js.map +1 -0
- package/build-ngc/angular/tab-screen.directive.d.ts +17 -0
- package/build-ngc/angular/tab-screen.directive.js +32 -0
- package/build-ngc/angular/tab-screen.directive.js.map +1 -0
- package/build-ngc/angular/tabs/index.d.ts +45 -0
- package/build-ngc/angular/tabs/index.js +231 -0
- package/build-ngc/angular/tabs/index.js.map +1 -0
- package/build-ngc/angular/tabs.d.ts +45 -0
- package/build-ngc/angular/tabs.js +231 -0
- package/build-ngc/angular/tabs.js.map +1 -0
- package/build-ngc/core/constants.d.ts +27 -0
- package/build-ngc/core/constants.js +62 -0
- package/build-ngc/core/constants.js.map +1 -0
- package/build-ngc/core/drawer-options/index.d.ts +64 -0
- package/build-ngc/core/drawer-options/index.js +201 -0
- package/build-ngc/core/drawer-options/index.js.map +1 -0
- package/build-ngc/core/drawer-options.d.ts +64 -0
- package/build-ngc/core/drawer-options.js +201 -0
- package/build-ngc/core/drawer-options.js.map +1 -0
- package/build-ngc/core/drawer-router-state/index.d.ts +21 -0
- package/build-ngc/core/drawer-router-state/index.js +41 -0
- package/build-ngc/core/drawer-router-state/index.js.map +1 -0
- package/build-ngc/core/drawer-router-state.d.ts +21 -0
- package/build-ngc/core/drawer-router-state.js +41 -0
- package/build-ngc/core/drawer-router-state.js.map +1 -0
- package/build-ngc/core/guards.d.ts +2 -0
- package/build-ngc/core/guards.js +23 -0
- package/build-ngc/core/guards.js.map +1 -0
- package/build-ngc/core/header-bar-buttons.d.ts +9 -0
- package/build-ngc/core/header-bar-buttons.js +164 -0
- package/build-ngc/core/header-bar-buttons.js.map +1 -0
- package/build-ngc/core/href.d.ts +16 -0
- package/build-ngc/core/href.js +55 -0
- package/build-ngc/core/href.js.map +1 -0
- package/build-ngc/core/index.d.ts +29 -0
- package/build-ngc/core/index.js +33 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/linking-config/index.d.ts +13 -0
- package/build-ngc/core/linking-config/index.js +172 -0
- package/build-ngc/core/linking-config/index.js.map +1 -0
- package/build-ngc/core/linking-config.d.ts +13 -0
- package/build-ngc/core/linking-config.js +172 -0
- package/build-ngc/core/linking-config.js.map +1 -0
- package/build-ngc/core/navigation-events/index.d.ts +16 -0
- package/build-ngc/core/navigation-events/index.js +58 -0
- package/build-ngc/core/navigation-events/index.js.map +1 -0
- package/build-ngc/core/navigation-events.d.ts +16 -0
- package/build-ngc/core/navigation-events.js +58 -0
- package/build-ngc/core/navigation-events.js.map +1 -0
- package/build-ngc/core/navigator-handles/index.d.ts +30 -0
- package/build-ngc/core/navigator-handles/index.js +16 -0
- package/build-ngc/core/navigator-handles/index.js.map +1 -0
- package/build-ngc/core/navigator-handles.d.ts +30 -0
- package/build-ngc/core/navigator-handles.js +16 -0
- package/build-ngc/core/navigator-handles.js.map +1 -0
- package/build-ngc/core/navigator-props.d.ts +216 -0
- package/build-ngc/core/navigator-props.js +8 -0
- package/build-ngc/core/navigator-props.js.map +1 -0
- package/build-ngc/core/navigator-state/index.d.ts +36 -0
- package/build-ngc/core/navigator-state/index.js +82 -0
- package/build-ngc/core/navigator-state/index.js.map +1 -0
- package/build-ngc/core/navigator-state.d.ts +36 -0
- package/build-ngc/core/navigator-state.js +82 -0
- package/build-ngc/core/navigator-state.js.map +1 -0
- package/build-ngc/core/render-drawer.d.ts +13 -0
- package/build-ngc/core/render-drawer.js +89 -0
- package/build-ngc/core/render-drawer.js.map +1 -0
- package/build-ngc/core/render-stack.d.ts +35 -0
- package/build-ngc/core/render-stack.js +295 -0
- package/build-ngc/core/render-stack.js.map +1 -0
- package/build-ngc/core/render-tabs.d.ts +20 -0
- package/build-ngc/core/render-tabs.js +98 -0
- package/build-ngc/core/render-tabs.js.map +1 -0
- package/build-ngc/core/screen-options.d.ts +4 -0
- package/build-ngc/core/screen-options.js +134 -0
- package/build-ngc/core/screen-options.js.map +1 -0
- package/build-ngc/core/search-bar-commands.d.ts +10 -0
- package/build-ngc/core/search-bar-commands.js +43 -0
- package/build-ngc/core/search-bar-commands.js.map +1 -0
- package/build-ngc/core/search-params.d.ts +9 -0
- package/build-ngc/core/search-params.js +60 -0
- package/build-ngc/core/search-params.js.map +1 -0
- package/build-ngc/core/state-persistence/index.d.ts +3 -0
- package/build-ngc/core/state-persistence/index.js +24 -0
- package/build-ngc/core/state-persistence/index.js.map +1 -0
- package/build-ngc/core/state-persistence.d.ts +3 -0
- package/build-ngc/core/state-persistence.js +24 -0
- package/build-ngc/core/state-persistence.js.map +1 -0
- package/build-ngc/core/tab-options.d.ts +13 -0
- package/build-ngc/core/tab-options.js +11 -0
- package/build-ngc/core/tab-options.js.map +1 -0
- package/build-ngc/core/tab-router-state/index.d.ts +19 -0
- package/build-ngc/core/tab-router-state/index.js +52 -0
- package/build-ngc/core/tab-router-state/index.js.map +1 -0
- package/build-ngc/core/tab-router-state.d.ts +19 -0
- package/build-ngc/core/tab-router-state.js +52 -0
- package/build-ngc/core/tab-router-state.js.map +1 -0
- package/build-ngc/register.d.ts +7 -0
- package/build-ngc/register.js +59 -0
- package/build-ngc/register.js.map +1 -0
- package/codegen-specs/FullWindowOverlayNativeComponent.ts +13 -0
- package/codegen-specs/ModalScreenNativeComponent.ts +129 -0
- package/codegen-specs/NativeScreensModule.ts +8 -0
- package/codegen-specs/NativeScreensModule.web.ts +1 -0
- package/codegen-specs/ScreenContainerNativeComponent.ts +8 -0
- package/codegen-specs/ScreenContentWrapperNativeComponent.ts +9 -0
- package/codegen-specs/ScreenFooterNativeComponent.ts +6 -0
- package/codegen-specs/ScreenNativeComponent.ts +133 -0
- package/codegen-specs/ScreenNavigationContainerNativeComponent.ts +11 -0
- package/codegen-specs/ScreenStackHeaderConfigNativeComponent.ts +99 -0
- package/codegen-specs/ScreenStackHeaderSubviewNativeComponent.ts +25 -0
- package/codegen-specs/ScreenStackNativeComponent.ts +17 -0
- package/codegen-specs/SearchBarNativeComponent.ts +101 -0
- package/codegen-specs/codegenUtils.ts +6 -0
- package/codegen-specs/gamma/ScrollViewMarkerNativeComponent.ts +15 -0
- package/codegen-specs/gamma/modals/form-sheet/FormSheetContentWrapperNativeComponent.ts +10 -0
- package/codegen-specs/gamma/modals/form-sheet/FormSheetHostNativeComponent.ts +47 -0
- package/codegen-specs/gamma/split/SplitHostNativeComponent.ts +124 -0
- package/codegen-specs/gamma/split/SplitScreenNativeComponent.ts +24 -0
- package/codegen-specs/gamma/stack/StackHeaderConfigAndroidNativeComponent.ts +144 -0
- package/codegen-specs/gamma/stack/StackHeaderConfigIOSNativeComponent.ts +34 -0
- package/codegen-specs/gamma/stack/StackHeaderItemIOSNativeComponent.ts +47 -0
- package/codegen-specs/gamma/stack/StackHeaderItemSpacerIOSNativeComponent.ts +20 -0
- package/codegen-specs/gamma/stack/StackHeaderSubviewAndroidNativeComponent.ts +27 -0
- package/codegen-specs/gamma/stack/StackHostNativeComponent.ts +8 -0
- package/codegen-specs/gamma/stack/StackScreenNativeComponent.ts +42 -0
- package/codegen-specs/safe-area/SafeAreaViewNativeComponent.ts +24 -0
- package/codegen-specs/tabs/TabsBottomAccessoryContentNativeComponent.ts +15 -0
- package/codegen-specs/tabs/TabsBottomAccessoryNativeComponent.ts +19 -0
- package/codegen-specs/tabs/TabsHostAndroidNativeComponent.ts +69 -0
- package/codegen-specs/tabs/TabsHostIOSNativeComponent.ts +92 -0
- package/codegen-specs/tabs/TabsScreenAndroidNativeComponent.ts +112 -0
- package/codegen-specs/tabs/TabsScreenIOSNativeComponent.ts +171 -0
- package/package.json +201 -0
- package/react-native.config.cjs +58 -0
- package/src/angular/drawer/drawer.test.ts +299 -0
- package/src/angular/drawer/index.ts +546 -0
- package/src/angular/drawer-screen.directive.ts +28 -0
- package/src/angular/index.ts +63 -0
- package/src/angular/injectors/index.ts +13 -0
- package/src/angular/injectors/inject-drawer-navigation.ts +21 -0
- package/src/angular/injectors/inject-focus-effect.ts +37 -0
- package/src/angular/injectors/inject-is-focused.ts +28 -0
- package/src/angular/injectors/inject-navigation-state.ts +46 -0
- package/src/angular/injectors/inject-navigation.ts +26 -0
- package/src/angular/injectors/inject-route.ts +25 -0
- package/src/angular/injectors/inject-stack-navigation.ts +24 -0
- package/src/angular/injectors/inject-tab-navigation.ts +20 -0
- package/src/angular/injectors/injectors.test.ts +247 -0
- package/src/angular/injectors/use-typed-navigation.test.ts +229 -0
- package/src/angular/linking.ts +55 -0
- package/src/angular/navigation-context.service.ts +68 -0
- package/src/angular/navigation-scope.directive.ts +31 -0
- package/src/angular/nested-navigation.test.ts +189 -0
- package/src/angular/screen.directive.ts +48 -0
- package/src/angular/search-bar-ref.directive.ts +38 -0
- package/src/angular/stack/index.ts +401 -0
- package/src/angular/stack/stack.test.ts +419 -0
- package/src/angular/tab-screen.directive.ts +26 -0
- package/src/angular/tabs/index.ts +254 -0
- package/src/angular/tabs/tabs.test.ts +249 -0
- package/src/core/constants.ts +68 -0
- package/src/core/drawer-options/drawer-options.test.ts +415 -0
- package/src/core/drawer-options/index.ts +331 -0
- package/src/core/drawer-router-state/drawer-router-state.test.ts +116 -0
- package/src/core/drawer-router-state/index.ts +71 -0
- package/src/core/guards.ts +23 -0
- package/src/core/header-bar-buttons.ts +212 -0
- package/src/core/index.ts +170 -0
- package/src/core/linking-config/index.ts +209 -0
- package/src/core/linking-config/linking-config.test.ts +109 -0
- package/src/core/navigation-events/index.ts +94 -0
- package/src/core/navigation-events/navigation-events.test.ts +56 -0
- package/src/core/navigator-handles/index.ts +63 -0
- package/src/core/navigator-handles/navigator-handles.test.ts +46 -0
- package/src/core/navigator-props.ts +323 -0
- package/src/core/navigator-state/index.ts +112 -0
- package/src/core/navigator-state/navigator-state.test.ts +80 -0
- package/src/core/render-drawer.ts +123 -0
- package/src/core/render-stack.ts +414 -0
- package/src/core/render-tabs.ts +138 -0
- package/src/core/screen-options.ts +181 -0
- package/src/core/search-bar-commands.ts +57 -0
- package/src/core/state-persistence/index.ts +30 -0
- package/src/core/state-persistence/state-persistence.test.ts +42 -0
- package/src/core/tab-options.ts +25 -0
- package/src/core/tab-router-state/index.ts +75 -0
- package/src/core/tab-router-state/tab-router-state.test.ts +34 -0
- package/src/globals.d.ts +4 -0
- package/src/react/collect-registry.ts +19 -0
- package/src/react/drawer/drawer.test.tsx +472 -0
- package/src/react/drawer/index.ts +451 -0
- package/src/react/drawer-screen.ts +29 -0
- package/src/react/hooks/hooks.test.tsx +199 -0
- package/src/react/hooks/index.ts +12 -0
- package/src/react/hooks/use-drawer-navigation.ts +21 -0
- package/src/react/hooks/use-focus-effect.ts +36 -0
- package/src/react/hooks/use-is-focused.ts +26 -0
- package/src/react/hooks/use-navigation-state/index.ts +47 -0
- package/src/react/hooks/use-navigation-state/use-navigation-state.test.ts +85 -0
- package/src/react/hooks/use-navigation.ts +36 -0
- package/src/react/hooks/use-route.ts +11 -0
- package/src/react/hooks/use-stack-navigation.ts +23 -0
- package/src/react/hooks/use-tab-navigation.ts +21 -0
- package/src/react/hooks/use-typed-navigation.test.tsx +187 -0
- package/src/react/index.ts +52 -0
- package/src/react/linking.ts +59 -0
- package/src/react/navigation-context.ts +40 -0
- package/src/react/nested-navigation.test.tsx +145 -0
- package/src/react/screen.ts +44 -0
- package/src/react/stack/index.ts +323 -0
- package/src/react/stack/stack.test.tsx +514 -0
- package/src/react/tab-screen.ts +30 -0
- package/src/react/tabs/index.ts +204 -0
- package/src/react/tabs/tabs.test.tsx +256 -0
- package/src/register.ts +59 -0
- package/src/vue/composables/composables.test.ts +221 -0
- package/src/vue/composables/index.ts +12 -0
- package/src/vue/composables/use-drawer-navigation.ts +25 -0
- package/src/vue/composables/use-focus-effect.ts +37 -0
- package/src/vue/composables/use-is-focused.ts +34 -0
- package/src/vue/composables/use-navigation-state.ts +38 -0
- package/src/vue/composables/use-navigation.ts +30 -0
- package/src/vue/composables/use-route.ts +13 -0
- package/src/vue/composables/use-stack-navigation.ts +28 -0
- package/src/vue/composables/use-tab-navigation.ts +25 -0
- package/src/vue/composables/use-typed-navigation.test.ts +205 -0
- package/src/vue/drawer/drawer.test.ts +451 -0
- package/src/vue/drawer/index.ts +550 -0
- package/src/vue/drawer-screen.ts +32 -0
- package/src/vue/index.ts +70 -0
- package/src/vue/linking.ts +69 -0
- package/src/vue/navigation-context.ts +87 -0
- package/src/vue/nested-navigation.test.ts +155 -0
- package/src/vue/screen.ts +52 -0
- package/src/vue/stack/index.ts +376 -0
- package/src/vue/stack/stack.test.ts +501 -0
- package/src/vue/tab-screen.ts +29 -0
- package/src/vue/tabs/index.ts +302 -0
- package/src/vue/tabs/tabs.test.ts +278 -0
- package/symbiote-navigation.podspec +84 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// injectLinkingIntegration: wires the framework-agnostic linking config (../core's
|
|
2
|
+
// resolveRouteFromUrl) onto an existing Stack's INavigatorHandle. Deliberately NOT called from
|
|
3
|
+
// inside stack.ts - app code owns the wiring (call this from the component hosting `<Stack #nav>`,
|
|
4
|
+
// passing `nav` itself, since Stack now implements INavigatorHandle directly), the same
|
|
5
|
+
// top-level-prop shape @react-navigation keeps `linking` in on NavigationContainer rather than
|
|
6
|
+
// baking it into the router itself. Mirrors react/linking.ts's useLinkingIntegration; Angular
|
|
7
|
+
// needs none of its `configRef`/`handleRef` staleness workaround - this function runs its
|
|
8
|
+
// subscription ONCE per call (the natural `inject()` call-site convention), and Stack's methods
|
|
9
|
+
// already read live `this` state off the component instance, so there is no stale-closure risk to
|
|
10
|
+
// guard against here.
|
|
11
|
+
|
|
12
|
+
import { DestroyRef, inject } from '@angular/core';
|
|
13
|
+
import { Linking, dlog } from '@symbiote-native/engine';
|
|
14
|
+
import type { IUrlEvent } from '@symbiote-native/engine';
|
|
15
|
+
import { resolveRouteFromUrl } from '../core';
|
|
16
|
+
import type { ILinkingConfig } from '../core';
|
|
17
|
+
import type { INavigatorHandle } from './stack';
|
|
18
|
+
|
|
19
|
+
export function injectLinkingIntegration(
|
|
20
|
+
config: ILinkingConfig,
|
|
21
|
+
navigatorHandle: INavigatorHandle,
|
|
22
|
+
): void {
|
|
23
|
+
const destroyRef = inject(DestroyRef);
|
|
24
|
+
|
|
25
|
+
function applyRoute(url: string, dispatch: (name: string, params?: unknown) => void): void {
|
|
26
|
+
const route = resolveRouteFromUrl(config, url);
|
|
27
|
+
if (route === null) {
|
|
28
|
+
dlog(`injectLinkingIntegration: no route resolved for "${url}"`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
dispatch(route.name, route.params);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let cancelled = false;
|
|
35
|
+
|
|
36
|
+
Linking.getInitialURL()
|
|
37
|
+
.then(url => {
|
|
38
|
+
if (cancelled || url === null) return;
|
|
39
|
+
dlog(`injectLinkingIntegration: initial URL "${url}"`);
|
|
40
|
+
applyRoute(url, navigatorHandle.replace);
|
|
41
|
+
})
|
|
42
|
+
.catch((error: unknown) => {
|
|
43
|
+
dlog(`injectLinkingIntegration: getInitialURL failed: ${String(error)}`);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const subscription = Linking.addEventListener('url', (event: IUrlEvent) => {
|
|
47
|
+
dlog(`injectLinkingIntegration: url event "${event.url}"`);
|
|
48
|
+
applyRoute(event.url, navigatorHandle.push);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
destroyRef.onDestroy(() => {
|
|
52
|
+
cancelled = true;
|
|
53
|
+
subscription.remove();
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// The lifecycle half of the framework-agnostic emitter (../core/navigation-events), Angular's
|
|
2
|
+
// twin of react/navigation-context.ts's NavigationContext. React re-scopes a plain Context per
|
|
3
|
+
// screen via NavigationContext.Provider; Angular's equivalent of "nearest-provider lookup" is
|
|
4
|
+
// hierarchical DI - NavigationScopeDirective (./navigation-scope.directive) re-`providers: [...]`
|
|
5
|
+
// a fresh NavigationContextService instance per route, and this service's own constructor injects
|
|
6
|
+
// its PARENT instance (`@Optional() @SkipSelf()`), which Angular resolves to the nearest ANCESTOR
|
|
7
|
+
// provider automatically - the exact `parent` linked list react/navigation-context.ts builds by
|
|
8
|
+
// hand via `ambientContext`. A screen nested inside e.g. a Stack-screen-renders-a-Tab composition
|
|
9
|
+
// reaches the enclosing Stack the same way a React screen does: one hop up `parent`.
|
|
10
|
+
//
|
|
11
|
+
// Every navigator kind a screen might be rendered under; consumers narrow the union themselves
|
|
12
|
+
// ('push' in handle picks out a Stack handle) - mirrors react/navigation-context.ts's
|
|
13
|
+
// IAnyNavigatorHandle exactly, minus the React-specific import cycle avoidance (Angular's `inject`
|
|
14
|
+
// resolves this service by TOKEN, so no circular value import exists here at all - only the
|
|
15
|
+
// type-only imports below, erased at compile time).
|
|
16
|
+
|
|
17
|
+
import { Injectable, inject, signal, type Signal } from '@angular/core';
|
|
18
|
+
import type { INavigationEmitter, IRoute, IAnyNavigatorHandle } from '../core';
|
|
19
|
+
|
|
20
|
+
export type { IAnyNavigatorHandle } from '../core';
|
|
21
|
+
|
|
22
|
+
// NOT `providedIn: 'root'` - deliberately component-scoped (see CLAUDE.md's design note for this
|
|
23
|
+
// package): every NavigationScopeDirective usage re-provides this token, so DI naturally mints one
|
|
24
|
+
// instance per route/screen, exactly like a fresh React Context value per screen.
|
|
25
|
+
@Injectable()
|
|
26
|
+
export class NavigationContextService {
|
|
27
|
+
private readonly ambientParent = inject(NavigationContextService, {
|
|
28
|
+
optional: true,
|
|
29
|
+
skipSelf: true,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// `route` is the one field that legitimately changes over a mounted screen's lifetime (a
|
|
33
|
+
// setParams call swaps in a new route OBJECT with the same key/name) while the screen itself
|
|
34
|
+
// stays mounted - a plain field would go stale the moment a consumer reads it once (e.g. in a
|
|
35
|
+
// constructor, the natural `inject()` call site). A signal lets `injectRoute()`
|
|
36
|
+
// (./injectors/inject-route) hand back a live, reactive value with zero per-consumer
|
|
37
|
+
// subscription plumbing, matching this
|
|
38
|
+
// package's zoneless/signals-first convention. `navigation`/`emitter` are stable for a screen's
|
|
39
|
+
// whole lifetime, so they stay plain fields - no reactivity needed there.
|
|
40
|
+
private readonly routeSignal = signal<IRoute<unknown> | undefined>(undefined);
|
|
41
|
+
readonly route: Signal<IRoute<unknown> | undefined> = this.routeSignal.asReadonly();
|
|
42
|
+
|
|
43
|
+
navigation!: IAnyNavigatorHandle;
|
|
44
|
+
emitter!: INavigationEmitter;
|
|
45
|
+
|
|
46
|
+
get parent(): NavigationContextService | undefined {
|
|
47
|
+
return this.ambientParent ?? undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setRoute(route: IRoute<unknown>): void {
|
|
51
|
+
this.routeSignal.set(route);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Every injectX function (./injectors/*) opens with the same optional-inject-then-throw guard;
|
|
56
|
+
// this centralizes it so the "must be used within a screen rendered by..." message stays
|
|
57
|
+
// identical everywhere instead of six independently-typed copies. Must be called from an
|
|
58
|
+
// injection context, same requirement `inject()` itself has - every call site is the first line
|
|
59
|
+
// of an injectX function, which callers already only invoke from their own injection context.
|
|
60
|
+
export function requireNavigationContext(injectorName: string): NavigationContextService {
|
|
61
|
+
const context = inject(NavigationContextService, { optional: true });
|
|
62
|
+
if (!context) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`${injectorName} must be used within a screen rendered by <Stack>, <Tab>, or <Drawer>`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return context;
|
|
68
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// The Angular twin of react/navigation-context.ts's `NavigationContext.Provider` usage in
|
|
2
|
+
// stack.ts/tabs.ts/drawer.ts's render loops: one directive instance = one fresh scope. Applying
|
|
3
|
+
// `[symbioteNavigationScope]` to an element re-`providers: [NavigationContextService]`
|
|
4
|
+
// (component/directive-level DI), so every usage mints its OWN service instance - the DI twin of
|
|
5
|
+
// `createElement(NavigationContext.Provider, { value }, content)`. Descendants (a screen's own
|
|
6
|
+
// component tree, reached through `*ngComponentOutlet`) call `inject(NavigationContextService)`
|
|
7
|
+
// and resolve to the NEAREST enclosing instance, exactly like `useContext(NavigationContext)`
|
|
8
|
+
// walks to the nearest Provider.
|
|
9
|
+
|
|
10
|
+
import { Directive, Input, inject, type OnChanges } from '@angular/core';
|
|
11
|
+
import type { INavigationEmitter, IRoute } from '../core';
|
|
12
|
+
import { NavigationContextService, type IAnyNavigatorHandle } from './navigation-context.service';
|
|
13
|
+
|
|
14
|
+
@Directive({
|
|
15
|
+
selector: '[symbioteNavigationScope]',
|
|
16
|
+
standalone: true,
|
|
17
|
+
providers: [NavigationContextService],
|
|
18
|
+
})
|
|
19
|
+
export class NavigationScopeDirective implements OnChanges {
|
|
20
|
+
@Input({ required: true, alias: 'symbioteNavigationScope' }) route!: IRoute<unknown>;
|
|
21
|
+
@Input({ required: true }) navigation!: IAnyNavigatorHandle;
|
|
22
|
+
@Input({ required: true }) emitter!: INavigationEmitter;
|
|
23
|
+
|
|
24
|
+
private readonly context = inject(NavigationContextService);
|
|
25
|
+
|
|
26
|
+
ngOnChanges(): void {
|
|
27
|
+
this.context.setRoute(this.route);
|
|
28
|
+
this.context.navigation = this.navigation;
|
|
29
|
+
this.context.emitter = this.emitter;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
// Co-located Angular-driven test proving the DI "parent" chain: NavigationContextService reads
|
|
2
|
+
// the ambient (parent-scope) instance via `@Optional() @SkipSelf() inject(...)` in its own
|
|
3
|
+
// constructor (navigation-context.service.ts) BEFORE NavigationScopeDirective re-provides a fresh
|
|
4
|
+
// one for its own content, so when one navigator's screen renders ANOTHER navigator (here, a Stack
|
|
5
|
+
// screen renders a Tab), a screen deep inside the nested Tab can call injectNavigation().getParent()
|
|
6
|
+
// to reach the enclosing Stack's handle - with ZERO manual threading (unlike react/
|
|
7
|
+
// nested-navigation.test.tsx, which needs an explicit `ambientContext` read + re-provide in every
|
|
8
|
+
// navigator; Angular's own hierarchical DI does this automatically, see navigation-context.
|
|
9
|
+
// service.ts's header comment). Mirrors stack.test.ts's fixture since a real Stack is part of
|
|
10
|
+
// this composition; Tab needs no ViewConfig of its own.
|
|
11
|
+
|
|
12
|
+
import '@angular/compiler';
|
|
13
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, Input, ViewChild, type Type } from '@angular/core';
|
|
14
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
15
|
+
import { mount, unmount, setNativeViewConfigSource } from '@symbiote-native/angular';
|
|
16
|
+
import type { INativeViewConfig } from '@symbiote-native/engine';
|
|
17
|
+
import { installFabric, type IFakeNode } from '@symbiote-native/test-utils';
|
|
18
|
+
import { Stack } from './stack';
|
|
19
|
+
import { ScreenDirective } from './screen.directive';
|
|
20
|
+
import { Tab } from './tabs';
|
|
21
|
+
import { TabScreenDirective } from './tab-screen.directive';
|
|
22
|
+
import { injectNavigation } from './injectors';
|
|
23
|
+
import type { IAnyNavigatorHandle } from './navigation-context.service';
|
|
24
|
+
|
|
25
|
+
const ROOT_TAG = 5140;
|
|
26
|
+
const SCREEN_VIEW = 'RNSScreen';
|
|
27
|
+
const STACK_VIEW = 'RNSScreenStack';
|
|
28
|
+
const HEADER_CONFIG_VIEW = 'RNSScreenStackHeaderConfig';
|
|
29
|
+
|
|
30
|
+
function directEvent(registrationName: string): { registrationName: string } {
|
|
31
|
+
return { registrationName };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const VIEW_CONFIGS: Record<string, INativeViewConfig> = {
|
|
35
|
+
[SCREEN_VIEW]: {
|
|
36
|
+
directEventTypes: {
|
|
37
|
+
topAppear: directEvent('onAppear'),
|
|
38
|
+
topDisappear: directEvent('onDisappear'),
|
|
39
|
+
},
|
|
40
|
+
validAttributes: { screenId: true, activityState: true },
|
|
41
|
+
},
|
|
42
|
+
[STACK_VIEW]: { directEventTypes: {}, validAttributes: {} },
|
|
43
|
+
[HEADER_CONFIG_VIEW]: { directEventTypes: {}, validAttributes: {} },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const fabric = installFabric();
|
|
47
|
+
setNativeViewConfigSource(name => VIEW_CONFIGS[name]);
|
|
48
|
+
|
|
49
|
+
const tick = (): Promise<void> => new Promise(resolve => setTimeout(resolve, 0));
|
|
50
|
+
|
|
51
|
+
beforeEach(() => fabric.reset());
|
|
52
|
+
afterEach(() => unmount(ROOT_TAG));
|
|
53
|
+
|
|
54
|
+
function findAllText(nodes: readonly IFakeNode[]): string[] {
|
|
55
|
+
const found: string[] = [];
|
|
56
|
+
const collect = (list: readonly IFakeNode[]): void => {
|
|
57
|
+
for (const node of list) {
|
|
58
|
+
if (node.viewName === 'RCTRawText' && typeof node.props.text === 'string') {
|
|
59
|
+
found.push(node.props.text);
|
|
60
|
+
}
|
|
61
|
+
collect(node.children);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
collect(nodes);
|
|
65
|
+
return found;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Component({
|
|
69
|
+
selector: 'root-plain-screen',
|
|
70
|
+
standalone: true,
|
|
71
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
72
|
+
template: `<symbiote-text>root</symbiote-text>`,
|
|
73
|
+
})
|
|
74
|
+
class RootPlainScreenComponent {}
|
|
75
|
+
|
|
76
|
+
@Component({
|
|
77
|
+
selector: 'stack-details-screen',
|
|
78
|
+
standalone: true,
|
|
79
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
80
|
+
template: `<symbiote-text>stack-details</symbiote-text>`,
|
|
81
|
+
})
|
|
82
|
+
class StackDetailsScreenComponent {}
|
|
83
|
+
|
|
84
|
+
let capturedParent: IAnyNavigatorHandle | undefined;
|
|
85
|
+
let getParentCalled = false;
|
|
86
|
+
|
|
87
|
+
@Component({
|
|
88
|
+
selector: 'root-getparent-screen',
|
|
89
|
+
standalone: true,
|
|
90
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
91
|
+
template: `<symbiote-text>root</symbiote-text>`,
|
|
92
|
+
})
|
|
93
|
+
class RootGetParentScreenComponent {
|
|
94
|
+
constructor() {
|
|
95
|
+
capturedParent = injectNavigation().getParent();
|
|
96
|
+
getParentCalled = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@Component({
|
|
101
|
+
selector: 'nested-tab-home-screen',
|
|
102
|
+
standalone: true,
|
|
103
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
104
|
+
template: `<symbiote-text>tab-home</symbiote-text>`,
|
|
105
|
+
})
|
|
106
|
+
class NestedTabHomeScreenComponent {
|
|
107
|
+
constructor() {
|
|
108
|
+
capturedParent = injectNavigation().getParent();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// The Stack screen's own content: a Tab navigator, nested exactly the way a real app composes
|
|
113
|
+
// navigators (a Stack screen's content IS another navigator). Angular's DI naturally threads the
|
|
114
|
+
// `parent` chain - this component does NOT need to read or forward any ambient context itself.
|
|
115
|
+
@Component({
|
|
116
|
+
selector: 'root-renders-tab-screen',
|
|
117
|
+
standalone: true,
|
|
118
|
+
imports: [Tab, TabScreenDirective],
|
|
119
|
+
template: `
|
|
120
|
+
<Tab initialRouteName="TabHome">
|
|
121
|
+
<ng-template symbioteTabScreen name="TabHome" [component]="tabHomeComponent"></ng-template>
|
|
122
|
+
</Tab>
|
|
123
|
+
`,
|
|
124
|
+
})
|
|
125
|
+
class RootRendersTabScreenComponent {
|
|
126
|
+
tabHomeComponent = NestedTabHomeScreenComponent;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let capturedHost: NestedTestHost | undefined;
|
|
130
|
+
|
|
131
|
+
@Component({
|
|
132
|
+
selector: 'nested-test-host',
|
|
133
|
+
standalone: true,
|
|
134
|
+
imports: [Stack, ScreenDirective],
|
|
135
|
+
template: `
|
|
136
|
+
<Stack #nav initialRouteName="Root">
|
|
137
|
+
<ng-template symbioteScreen name="Root" [component]="rootComponent"></ng-template>
|
|
138
|
+
<ng-template symbioteScreen name="Details" [component]="detailsComponent"></ng-template>
|
|
139
|
+
</Stack>
|
|
140
|
+
`,
|
|
141
|
+
})
|
|
142
|
+
class NestedTestHost {
|
|
143
|
+
@ViewChild('nav') nav!: Stack;
|
|
144
|
+
|
|
145
|
+
@Input() rootComponent: Type<unknown> = RootPlainScreenComponent;
|
|
146
|
+
detailsComponent = StackDetailsScreenComponent;
|
|
147
|
+
|
|
148
|
+
constructor() {
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
150
|
+
capturedHost = this;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
describe('Angular nested navigators (DI parent chain)', () => {
|
|
155
|
+
it("a root Stack screen's injectNavigation().getParent() is undefined (no ambient navigator above it)", async () => {
|
|
156
|
+
capturedParent = undefined;
|
|
157
|
+
getParentCalled = false;
|
|
158
|
+
capturedHost = undefined;
|
|
159
|
+
mount(ROOT_TAG, NestedTestHost, {
|
|
160
|
+
initialProps: { rootComponent: RootGetParentScreenComponent },
|
|
161
|
+
});
|
|
162
|
+
await tick();
|
|
163
|
+
|
|
164
|
+
expect(getParentCalled).toBe(true);
|
|
165
|
+
expect(capturedParent).toBeUndefined();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('injectNavigation().getParent() from inside a Tab screen nested in a Stack screen reaches the enclosing Stack, and pushing through it adds a Stack route', async () => {
|
|
169
|
+
capturedParent = undefined;
|
|
170
|
+
capturedHost = undefined;
|
|
171
|
+
mount(ROOT_TAG, NestedTestHost, {
|
|
172
|
+
initialProps: { rootComponent: RootRendersTabScreenComponent },
|
|
173
|
+
});
|
|
174
|
+
await tick();
|
|
175
|
+
|
|
176
|
+
expect(findAllText(fabric.committed)).toContain('tab-home');
|
|
177
|
+
|
|
178
|
+
if (!capturedParent) throw new Error('getParent() returned undefined');
|
|
179
|
+
if (!('push' in capturedParent)) {
|
|
180
|
+
throw new Error('parent handle is not a Stack handle (missing push)');
|
|
181
|
+
}
|
|
182
|
+
// capturedParent is now narrowed to INavigatorHandle by the 'push in' guard above.
|
|
183
|
+
capturedParent.push('Details');
|
|
184
|
+
await tick();
|
|
185
|
+
|
|
186
|
+
expect(findAllText(fabric.committed)).toContain('stack-details');
|
|
187
|
+
expect(capturedHost!.nav.canGoBack()).toBe(true);
|
|
188
|
+
});
|
|
189
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// [symbioteScreen]: a declarative marker, never rendered on its own - Stack reads its inputs via
|
|
2
|
+
// @ContentChildren to build the static name -> {component, options} registry, then mounts the
|
|
3
|
+
// registered component itself for each pushed route. Angular's twin of react/screen.ts's Screen
|
|
4
|
+
// marker component; mirrors Angular Material's own `@ContentChildren(MatTab) tabs: QueryList<MatTab>`
|
|
5
|
+
// pattern (a directive applied to an inert `<ng-template>`, never instantiated as a view - see
|
|
6
|
+
// stack.ts's header for why that's safe: @ContentChildren resolves the light-DOM declaration,
|
|
7
|
+
// independent of whether the template is ever instantiated).
|
|
8
|
+
|
|
9
|
+
import { Directive, Input, type Type } from '@angular/core';
|
|
10
|
+
import type { ISearchBarCommands, ISearchBarOptions, IScreenOptions, IRoute } from '../core';
|
|
11
|
+
import type { INavigatorHandle } from '../core';
|
|
12
|
+
|
|
13
|
+
// The imperative ref (focus/blur/clearText/setText/cancelSearch/toggleCancelButton) carries a
|
|
14
|
+
// framework ref type, so - per CLAUDE.md's <prop_types_split_agnostic_vs_per_adapter> - it cannot
|
|
15
|
+
// live in the shared, agnostic ISearchBarOptions (core/navigator-props.ts). Angular has no
|
|
16
|
+
// `RefObject` primitive of its own, but the underlying shape (`{ current: T | null }`, mutated
|
|
17
|
+
// once the native view is available) is framework-agnostic in itself - the app constructs a plain
|
|
18
|
+
// mutable object and this adapter assigns `.current` once the search bar's native node exists
|
|
19
|
+
// (search-bar-ref.directive.ts), the same contract react/screen.ts's IReactSearchBarOptions uses.
|
|
20
|
+
export type IAngularSearchBarOptions = ISearchBarOptions & {
|
|
21
|
+
ref?: { current: ISearchBarCommands | null };
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type IAngularScreenOptions = Omit<IScreenOptions, 'headerSearchBarOptions'> & {
|
|
25
|
+
headerSearchBarOptions?: IAngularSearchBarOptions;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// A screen's options can be a plain object or a resolver run OUTSIDE the render lifecycle (when
|
|
29
|
+
// Stack folds a route's options): its `navigation` argument is a live navigator handle a bar-button
|
|
30
|
+
// onPress closes over, so this is NOT the props-based navigation the screen body reads via inject -
|
|
31
|
+
// it's a deliberate escape hatch that stays.
|
|
32
|
+
export type IScreenOptionsArgs = {
|
|
33
|
+
route: IRoute<unknown>;
|
|
34
|
+
navigation: INavigatorHandle;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type IScreenOptionsResolver = (args: IScreenOptionsArgs) => IAngularScreenOptions;
|
|
38
|
+
|
|
39
|
+
@Directive({
|
|
40
|
+
selector: 'ng-template[symbioteScreen]',
|
|
41
|
+
standalone: true,
|
|
42
|
+
})
|
|
43
|
+
export class ScreenDirective {
|
|
44
|
+
@Input({ required: true }) name!: string;
|
|
45
|
+
@Input({ required: true }) component!: Type<unknown>;
|
|
46
|
+
@Input() options?: IAngularScreenOptions | IScreenOptionsResolver;
|
|
47
|
+
@Input() initialParams?: unknown;
|
|
48
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Assigns the app-supplied `headerSearchBarOptions.ref` (a plain `{ current }` cell - see
|
|
2
|
+
// screen.directive.ts's IAngularSearchBarOptions) once the RNSSearchBar native node exists.
|
|
3
|
+
// Angular's twin of react/stack.ts's callback `ref` prop on the RNSSearchBar element: a directive
|
|
4
|
+
// applied directly onto the raw `<RNSSearchBar>` tag can `inject(ElementRef)` the same way
|
|
5
|
+
// SymbioteHostPropsDirective does (primitives/shared.ts's own pattern) - ElementRef.nativeElement
|
|
6
|
+
// is the real engine node the moment the element is created (synchronous, no whenCommitted wait
|
|
7
|
+
// needed here: buildSearchBarHandle's own methods are already a LAZY getter over the node,
|
|
8
|
+
// tolerant of the node existing-but-not-yet-committed, same contract every adapter shares).
|
|
9
|
+
|
|
10
|
+
import { Directive, Input, inject, type OnDestroy, type OnInit, ElementRef } from '@angular/core';
|
|
11
|
+
import { isSymbioteNode, dlog, debugNodeId } from '@symbiote-native/engine';
|
|
12
|
+
import { buildSearchBarHandle } from '../core';
|
|
13
|
+
import type { ISearchBarCommands } from '../core';
|
|
14
|
+
|
|
15
|
+
@Directive({
|
|
16
|
+
selector: '[symbioteSearchBarRef]',
|
|
17
|
+
standalone: true,
|
|
18
|
+
})
|
|
19
|
+
export class SearchBarRefDirective implements OnInit, OnDestroy {
|
|
20
|
+
@Input('symbioteSearchBarRef') ref: { current: ISearchBarCommands | null } | undefined;
|
|
21
|
+
|
|
22
|
+
private readonly elementRef = inject<ElementRef<unknown>>(ElementRef);
|
|
23
|
+
|
|
24
|
+
ngOnInit(): void {
|
|
25
|
+
if (!this.ref) return;
|
|
26
|
+
const node = this.elementRef.nativeElement;
|
|
27
|
+
if (!isSymbioteNode(node)) {
|
|
28
|
+
this.ref.current = null;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
dlog(`SearchBarRefDirective: attached to node=${debugNodeId(node)}`);
|
|
32
|
+
this.ref.current = buildSearchBarHandle(() => node);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
ngOnDestroy(): void {
|
|
36
|
+
if (this.ref) this.ref.current = null;
|
|
37
|
+
}
|
|
38
|
+
}
|