@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,546 @@
|
|
|
1
|
+
// Drawer, the Angular lifecycle half. The open/closed + focused-route router
|
|
2
|
+
// (drawer-router-state) and the pure swipe/geometry math (drawer-options) live in
|
|
3
|
+
// @symbiote-native/navigation core, shared verbatim with the React/Vue adapters; here Angular
|
|
4
|
+
// supplies the lifecycle - a signal-backed router, a PanResponder (RN's own idiom, framework-
|
|
5
|
+
// agnostic per `@symbiote-native/engine` - built ONCE as a class field, callbacks read LIVE `this`
|
|
6
|
+
// state at call time, no ref-mirroring dance needed the way react/drawer.ts's `useRef`s are: a
|
|
7
|
+
// class instance already gives every callback a live view of current state, closing the exact gap
|
|
8
|
+
// React's own hook rules force it to work around), an Animated.Value driving the slide/opacity
|
|
9
|
+
// transforms via the real `AnimatedView` component (`@symbiote-native/angular`), and
|
|
10
|
+
// `openDrawer`/`closeDrawer`/`toggleDrawer`/`jumpTo` as plain public methods directly on the class,
|
|
11
|
+
// mirroring tabs.ts's shape (Tab is the closer sibling: both are fixed-route-list,
|
|
12
|
+
// no-react-native-screens navigators; Stack's push/pop + native-screen bridging don't apply here;
|
|
13
|
+
// `Drawer implements IDrawerNavigatorHandle`).
|
|
14
|
+
//
|
|
15
|
+
// FEASIBILITY NOTE (mirrors react/drawer.ts's own header): the REAL @react-navigation/drawer is
|
|
16
|
+
// built on react-native-gesture-handler + react-native-reanimated, neither of which this codebase
|
|
17
|
+
// depends on. This reaches the same swipe-to-open/close + front/back/slide/permanent behavior with
|
|
18
|
+
// only PanResponder + Animated, sufficient for a solid drawer but NOT byte-for-byte parity - same
|
|
19
|
+
// explicit gap list as react/drawer.ts's tail comment (not repeated here, nothing Angular-specific
|
|
20
|
+
// changes it).
|
|
21
|
+
//
|
|
22
|
+
// RESOLVED (see stack.ts's header, identical reasoning): `'Drawer'` has an `ANCHOR_HOST_COMPONENTS`
|
|
23
|
+
// entry in `adapters/angular/src/renderer.ts`, so a real device build paints `<Drawer>` correctly
|
|
24
|
+
// as a nested tag. `View`/`AnimatedView`, imported below, were already anchor-hosted.
|
|
25
|
+
//
|
|
26
|
+
// DRAWER CONTENT PROJECTION: react/drawer.ts's `renderDrawerContent` is a render-PROP callback
|
|
27
|
+
// (`(props) => ReactNode`) - per CLAUDE.md's <prop_types_split_agnostic_vs_per_adapter>, a
|
|
28
|
+
// render-callback returning a framework element is inherently per-adapter. Angular's own idiom for
|
|
29
|
+
// "a caller-supplied template that needs live data" is a `TemplateRef` + `NgTemplateOutlet` with a
|
|
30
|
+
// context object, NOT a callback @Input(): `<Drawer><ng-template #drawerContent let-ctx>...
|
|
31
|
+
// {{ ctx.state }}...</ng-template></Drawer>`, read here via `@ContentChild('drawerContent', {read:
|
|
32
|
+
// TemplateRef})`.
|
|
33
|
+
|
|
34
|
+
import {
|
|
35
|
+
ChangeDetectionStrategy,
|
|
36
|
+
Component,
|
|
37
|
+
ContentChild,
|
|
38
|
+
ContentChildren,
|
|
39
|
+
Input,
|
|
40
|
+
QueryList,
|
|
41
|
+
TemplateRef,
|
|
42
|
+
computed,
|
|
43
|
+
inject,
|
|
44
|
+
signal,
|
|
45
|
+
untracked,
|
|
46
|
+
type AfterContentInit,
|
|
47
|
+
type OnChanges,
|
|
48
|
+
type OnDestroy,
|
|
49
|
+
type Type,
|
|
50
|
+
} from '@angular/core';
|
|
51
|
+
import { NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
|
|
52
|
+
import {
|
|
53
|
+
PanResponder,
|
|
54
|
+
dlog,
|
|
55
|
+
flattenStyle,
|
|
56
|
+
type IPanResponderGestureState,
|
|
57
|
+
type IStyleProp,
|
|
58
|
+
type ISymbioteEvent,
|
|
59
|
+
type IViewStyle,
|
|
60
|
+
} from '@symbiote-native/engine';
|
|
61
|
+
import {
|
|
62
|
+
Animated,
|
|
63
|
+
AnimatedView,
|
|
64
|
+
SymbioteHostPropsDirective,
|
|
65
|
+
View,
|
|
66
|
+
WindowDimensionsService,
|
|
67
|
+
} from '@symbiote-native/angular';
|
|
68
|
+
import type { IDescriptor, IDescriptorChild } from '@symbiote-native/components';
|
|
69
|
+
import {
|
|
70
|
+
DRAWER_DEFAULT_OVERLAY_COLOR,
|
|
71
|
+
NAVIGATION_EVENT_BLUR,
|
|
72
|
+
NAVIGATION_EVENT_FOCUS,
|
|
73
|
+
createInitialDrawerRouterState,
|
|
74
|
+
createNavigationEmitter,
|
|
75
|
+
diffFocusedRoute,
|
|
76
|
+
drawerChildOrder,
|
|
77
|
+
drawerRouterReducer,
|
|
78
|
+
isDrawerAnimated,
|
|
79
|
+
renderDrawer,
|
|
80
|
+
resolveDragProgress,
|
|
81
|
+
resolveDrawerGeometry,
|
|
82
|
+
resolveDrawerSlotInterpolation,
|
|
83
|
+
resolveSwipeIntent,
|
|
84
|
+
shouldClaimDrawerSwipe,
|
|
85
|
+
} from '../../core';
|
|
86
|
+
import type {
|
|
87
|
+
IDrawerDescriptorMap,
|
|
88
|
+
IDrawerNavigatorHandle,
|
|
89
|
+
IDrawerOptions,
|
|
90
|
+
IDrawerPosition,
|
|
91
|
+
IDrawerRouterAction,
|
|
92
|
+
IDrawerRouterState,
|
|
93
|
+
IDrawerScreenOptions,
|
|
94
|
+
IDrawerSlot,
|
|
95
|
+
IDrawerType,
|
|
96
|
+
INavigationEmitter,
|
|
97
|
+
IRoute,
|
|
98
|
+
} from '../../core';
|
|
99
|
+
import { NavigationScopeDirective } from '../navigation-scope.directive';
|
|
100
|
+
import { DrawerScreenDirective } from '../drawer-screen.directive';
|
|
101
|
+
import type { IDrawerScreenOptionsArgs } from '../drawer-screen.directive';
|
|
102
|
+
|
|
103
|
+
export type { IDrawerNavigatorHandle, IDrawerDescriptorMap } from '../../core';
|
|
104
|
+
|
|
105
|
+
export type IDrawerContentContext = {
|
|
106
|
+
$implicit: {
|
|
107
|
+
state: IDrawerRouterState;
|
|
108
|
+
descriptors: IDrawerDescriptorMap;
|
|
109
|
+
navigation: IDrawerNavigatorHandle;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const DRAWER_SNAP_DURATION = 250;
|
|
114
|
+
|
|
115
|
+
let drawerInstanceCounter = 0;
|
|
116
|
+
|
|
117
|
+
@Component({
|
|
118
|
+
selector: 'Drawer',
|
|
119
|
+
standalone: true,
|
|
120
|
+
imports: [
|
|
121
|
+
NgComponentOutlet,
|
|
122
|
+
NgTemplateOutlet,
|
|
123
|
+
NavigationScopeDirective,
|
|
124
|
+
SymbioteHostPropsDirective,
|
|
125
|
+
View,
|
|
126
|
+
AnimatedView,
|
|
127
|
+
],
|
|
128
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
129
|
+
template: `
|
|
130
|
+
@if (state(); as currentState) {
|
|
131
|
+
<View [style]="rootStyle()" [symbioteHostProps]="rootPanHandlers()">
|
|
132
|
+
@for (slot of slotOrder(); track slot) {
|
|
133
|
+
@switch (slot) {
|
|
134
|
+
@case ('content') {
|
|
135
|
+
<AnimatedView [style]="contentStyle()" [animatedProps]="slotAnimatedProps('content')">
|
|
136
|
+
@if (focusedRoute(); as route) {
|
|
137
|
+
@if (componentForRoute(route); as component) {
|
|
138
|
+
<ng-container
|
|
139
|
+
[symbioteNavigationScope]="route"
|
|
140
|
+
[navigation]="this"
|
|
141
|
+
[emitter]="focusedRouteEmitter()"
|
|
142
|
+
>
|
|
143
|
+
<ng-container *ngComponentOutlet="component" />
|
|
144
|
+
</ng-container>
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
</AnimatedView>
|
|
148
|
+
}
|
|
149
|
+
@case ('overlay') {
|
|
150
|
+
<AnimatedView
|
|
151
|
+
[style]="overlayStyle()"
|
|
152
|
+
[animatedProps]="slotAnimatedProps('overlay')"
|
|
153
|
+
/>
|
|
154
|
+
}
|
|
155
|
+
@case ('panel') {
|
|
156
|
+
<AnimatedView [style]="panelStyle()" [animatedProps]="slotAnimatedProps('panel')">
|
|
157
|
+
@if (drawerContentTemplate) {
|
|
158
|
+
<ng-container
|
|
159
|
+
*ngTemplateOutlet="
|
|
160
|
+
drawerContentTemplate;
|
|
161
|
+
context: drawerContentContext(currentState)
|
|
162
|
+
"
|
|
163
|
+
/>
|
|
164
|
+
}
|
|
165
|
+
</AnimatedView>
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
</View>
|
|
170
|
+
}
|
|
171
|
+
`,
|
|
172
|
+
})
|
|
173
|
+
export class Drawer implements AfterContentInit, OnChanges, OnDestroy, IDrawerNavigatorHandle {
|
|
174
|
+
@ContentChildren(DrawerScreenDirective)
|
|
175
|
+
private readonly drawerScreenChildren!: QueryList<DrawerScreenDirective>;
|
|
176
|
+
@ContentChild('drawerContent', { read: TemplateRef })
|
|
177
|
+
drawerContentTemplate?: TemplateRef<IDrawerContentContext>;
|
|
178
|
+
|
|
179
|
+
@Input() initialRouteName?: string;
|
|
180
|
+
@Input() drawerStyle?: IStyleProp<IViewStyle>;
|
|
181
|
+
@Input() drawerType?: IDrawerType;
|
|
182
|
+
@Input() drawerPosition?: IDrawerPosition;
|
|
183
|
+
@Input() drawerWidth?: number;
|
|
184
|
+
@Input() overlayColor?: string;
|
|
185
|
+
@Input() swipeEnabled?: boolean;
|
|
186
|
+
@Input() swipeEdgeWidth?: number;
|
|
187
|
+
@Input() swipeMinDistance?: number;
|
|
188
|
+
@Input() swipeMinVelocity?: number;
|
|
189
|
+
|
|
190
|
+
private readonly windowDimensions = inject(WindowDimensionsService).dimensions;
|
|
191
|
+
|
|
192
|
+
private readonly routeIdPrefix = `drawer-${(drawerInstanceCounter += 1)}`;
|
|
193
|
+
// Keyed by name -> the LIVE DrawerScreenDirective instance - see stack.ts's matching comment
|
|
194
|
+
// for why a snapshot copy would go stale on an in-place `[options]`/`[component]` change.
|
|
195
|
+
private readonly registry = new Map<string, DrawerScreenDirective>();
|
|
196
|
+
private drawerScreenChildrenSubscription: { unsubscribe: () => void } | undefined;
|
|
197
|
+
|
|
198
|
+
private readonly stateSignal = signal<IDrawerRouterState | undefined>(undefined);
|
|
199
|
+
readonly state = this.stateSignal.asReadonly();
|
|
200
|
+
|
|
201
|
+
private currentEmitterKey: string | undefined;
|
|
202
|
+
private currentEmitter: INavigationEmitter | undefined;
|
|
203
|
+
|
|
204
|
+
// progress: 0 closed -> 1 open. Always starts closed (createInitialDrawerRouterState's own
|
|
205
|
+
// contract), so a plain field initializer is safe - no dependency on `state` existing yet.
|
|
206
|
+
private readonly progress = new Animated.Value(0);
|
|
207
|
+
// Where a drag STARTS from, in progress units - always exactly 0 or 1 (see react/drawer.ts's
|
|
208
|
+
// matching field for why).
|
|
209
|
+
private dragStartProgress = 0;
|
|
210
|
+
|
|
211
|
+
readonly openDrawer = (): void => {
|
|
212
|
+
this.animateProgressTo(true);
|
|
213
|
+
this.dispatch({ type: 'openDrawer' });
|
|
214
|
+
};
|
|
215
|
+
readonly closeDrawer = (): void => {
|
|
216
|
+
this.animateProgressTo(false);
|
|
217
|
+
this.dispatch({ type: 'closeDrawer' });
|
|
218
|
+
};
|
|
219
|
+
readonly toggleDrawer = (): void => {
|
|
220
|
+
this.animateProgressTo(!(this.stateSignal()?.isOpen ?? false));
|
|
221
|
+
this.dispatch({ type: 'toggleDrawer' });
|
|
222
|
+
};
|
|
223
|
+
readonly jumpTo = (name: string): void => {
|
|
224
|
+
// Captured BEFORE dispatch, mirroring vue/drawer/index.ts's jumpTo: a signal (like Vue's ref)
|
|
225
|
+
// mutates synchronously inside dispatch, so reading isOpen after it would already see the
|
|
226
|
+
// reducer's own isOpen: false and never animate the panel closed.
|
|
227
|
+
const wasOpen = this.stateSignal()?.isOpen ?? false;
|
|
228
|
+
this.dispatch({ type: 'jumpTo', name });
|
|
229
|
+
if (wasOpen) this.animateProgressTo(false);
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
readonly panResponder = PanResponder.create({
|
|
233
|
+
onStartShouldSetPanResponder: (
|
|
234
|
+
event: ISymbioteEvent,
|
|
235
|
+
gestureState: IPanResponderGestureState,
|
|
236
|
+
): boolean =>
|
|
237
|
+
shouldClaimDrawerSwipe(
|
|
238
|
+
event,
|
|
239
|
+
gestureState,
|
|
240
|
+
this.windowDimensions().width,
|
|
241
|
+
this.stateSignal()?.isOpen ?? false,
|
|
242
|
+
this.optionsSnapshot(),
|
|
243
|
+
'start',
|
|
244
|
+
),
|
|
245
|
+
onMoveShouldSetPanResponder: (
|
|
246
|
+
event: ISymbioteEvent,
|
|
247
|
+
gestureState: IPanResponderGestureState,
|
|
248
|
+
): boolean =>
|
|
249
|
+
shouldClaimDrawerSwipe(
|
|
250
|
+
event,
|
|
251
|
+
gestureState,
|
|
252
|
+
this.windowDimensions().width,
|
|
253
|
+
this.stateSignal()?.isOpen ?? false,
|
|
254
|
+
this.optionsSnapshot(),
|
|
255
|
+
'move',
|
|
256
|
+
),
|
|
257
|
+
onPanResponderGrant: (): void => {
|
|
258
|
+
dlog('Drawer: gesture grant');
|
|
259
|
+
this.dragStartProgress = (this.stateSignal()?.isOpen ?? false) ? 1 : 0;
|
|
260
|
+
},
|
|
261
|
+
onPanResponderMove: (_event: ISymbioteEvent, gestureState: IPanResponderGestureState): void => {
|
|
262
|
+
this.progress.setValue(
|
|
263
|
+
resolveDragProgress(gestureState, this.dragStartProgress, this.optionsSnapshot()),
|
|
264
|
+
);
|
|
265
|
+
},
|
|
266
|
+
onPanResponderRelease: (
|
|
267
|
+
_event: ISymbioteEvent,
|
|
268
|
+
gestureState: IPanResponderGestureState,
|
|
269
|
+
): void => {
|
|
270
|
+
const intent = resolveSwipeIntent(
|
|
271
|
+
gestureState,
|
|
272
|
+
this.stateSignal()?.isOpen ?? false,
|
|
273
|
+
this.optionsSnapshot(),
|
|
274
|
+
);
|
|
275
|
+
const open = intent === 'open';
|
|
276
|
+
dlog(`Drawer: gesture release -> ${open ? 'open' : 'close'}`);
|
|
277
|
+
this.animateProgressTo(open);
|
|
278
|
+
this.dispatch(open ? { type: 'openDrawer' } : { type: 'closeDrawer' });
|
|
279
|
+
},
|
|
280
|
+
onPanResponderTerminate: (): void => {
|
|
281
|
+
dlog('Drawer: gesture terminated, snapping back');
|
|
282
|
+
this.animateProgressTo(this.stateSignal()?.isOpen ?? false);
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
ngAfterContentInit(): void {
|
|
287
|
+
this.rebuildRegistry();
|
|
288
|
+
this.initializeState();
|
|
289
|
+
this.drawerScreenChildrenSubscription = this.drawerScreenChildren.changes.subscribe(() => {
|
|
290
|
+
this.rebuildRegistry();
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
ngOnDestroy(): void {
|
|
295
|
+
this.drawerScreenChildrenSubscription?.unsubscribe();
|
|
296
|
+
if (this.currentEmitter) this.currentEmitter.emit(NAVIGATION_EVENT_BLUR);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private rebuildRegistry(): void {
|
|
300
|
+
this.registry.clear();
|
|
301
|
+
for (const screen of this.drawerScreenChildren) {
|
|
302
|
+
this.registry.set(screen.name, screen);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private routesFromRegistry(): IRoute<unknown>[] {
|
|
307
|
+
return Array.from(this.registry.entries()).map(([name, entry]) => ({
|
|
308
|
+
key: `${this.routeIdPrefix}-${name}`,
|
|
309
|
+
name,
|
|
310
|
+
params: entry.initialParams,
|
|
311
|
+
}));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private initializeState(): void {
|
|
315
|
+
if (this.stateSignal() !== undefined) return;
|
|
316
|
+
const routes = this.routesFromRegistry();
|
|
317
|
+
if (routes.length === 0)
|
|
318
|
+
dlog('Drawer: no <ng-template symbioteDrawerScreen> children registered');
|
|
319
|
+
this.stateSignal.set(createInitialDrawerRouterState(routes, this.initialRouteName));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private dispatch(action: IDrawerRouterAction): void {
|
|
323
|
+
const current = this.stateSignal();
|
|
324
|
+
if (current === undefined) return;
|
|
325
|
+
this.stateSignal.set(drawerRouterReducer(current, action));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
private animateProgressTo(open: boolean): void {
|
|
329
|
+
dlog(`Drawer: animateProgressTo(open=${open})`);
|
|
330
|
+
Animated.timing(this.progress, {
|
|
331
|
+
toValue: open ? 1 : 0,
|
|
332
|
+
duration: DRAWER_SNAP_DURATION,
|
|
333
|
+
// Native-driver wiring is deferred for v1 - mirrors react/drawer.ts's own scope note.
|
|
334
|
+
useNativeDriver: false,
|
|
335
|
+
}).start();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// A plain writable signal, not a computed() - it mirrors @Input() properties, which are ordinary
|
|
339
|
+
// mutable fields Angular assigns directly rather than signals, so a computed() reading them would
|
|
340
|
+
// never register them as a tracked dependency and would go stale after its first evaluation.
|
|
341
|
+
// ngOnChanges (below) pushes every input change in here instead, which drawerRoot/slotsMap CAN
|
|
342
|
+
// track correctly since reading a signal (unlike a plain field) IS visible to computed()'s
|
|
343
|
+
// dependency collection.
|
|
344
|
+
private readonly optionsSnapshot = signal<IDrawerOptions>(this.buildOptionsSnapshot());
|
|
345
|
+
private readonly drawerStyleSnapshot = signal<IStyleProp<IViewStyle> | undefined>(
|
|
346
|
+
this.drawerStyle,
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
ngOnChanges(): void {
|
|
350
|
+
this.optionsSnapshot.set(this.buildOptionsSnapshot());
|
|
351
|
+
this.drawerStyleSnapshot.set(this.drawerStyle);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private buildOptionsSnapshot(): IDrawerOptions {
|
|
355
|
+
return {
|
|
356
|
+
drawerType: this.drawerType,
|
|
357
|
+
drawerPosition: this.drawerPosition,
|
|
358
|
+
drawerWidth: this.drawerWidth,
|
|
359
|
+
overlayColor: this.overlayColor,
|
|
360
|
+
swipeEnabled: this.swipeEnabled,
|
|
361
|
+
swipeEdgeWidth: this.swipeEdgeWidth,
|
|
362
|
+
swipeMinDistance: this.swipeMinDistance,
|
|
363
|
+
swipeMinVelocity: this.swipeMinVelocity,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private overlayResponderPassthrough(): Record<string, unknown> {
|
|
368
|
+
return {
|
|
369
|
+
pointerEvents: this.stateSignal()?.isOpen ? 'auto' : 'none',
|
|
370
|
+
onStartShouldSetResponder: () => true,
|
|
371
|
+
onResponderRelease: () => {
|
|
372
|
+
this.animateProgressTo(false);
|
|
373
|
+
this.dispatch({ type: 'closeDrawer' });
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Recomputed only when a dependency signal actually changes, so every template read within a
|
|
379
|
+
// single change-detection pass (rootStyle, plus slotStyle/slotAnimatedProps once per @for slot -
|
|
380
|
+
// 6-7 reads total) shares one cached descriptor tree instead of re-running renderDrawer /
|
|
381
|
+
// drawerChildOrder on each read.
|
|
382
|
+
private readonly drawerRoot = computed<IDescriptor>(() =>
|
|
383
|
+
renderDrawer(
|
|
384
|
+
{
|
|
385
|
+
overlayColor: this.optionsSnapshot().overlayColor ?? DRAWER_DEFAULT_OVERLAY_COLOR,
|
|
386
|
+
drawerStyle: this.drawerStyleSnapshot(),
|
|
387
|
+
contentPassthrough: {},
|
|
388
|
+
overlayPassthrough: this.isAnimated() ? this.overlayResponderPassthrough() : {},
|
|
389
|
+
panelPassthrough: {},
|
|
390
|
+
},
|
|
391
|
+
this.optionsSnapshot(),
|
|
392
|
+
),
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
private readonly slotsMap = computed<Map<IDrawerSlot, IDescriptor>>(() => {
|
|
396
|
+
const root = this.drawerRoot();
|
|
397
|
+
const order = drawerChildOrder(this.optionsSnapshot());
|
|
398
|
+
const map = new Map<IDrawerSlot, IDescriptor>();
|
|
399
|
+
order.forEach((slot, index) => {
|
|
400
|
+
const child: IDescriptorChild | undefined = root.children[index];
|
|
401
|
+
if (child !== undefined && typeof child !== 'string') map.set(slot, child);
|
|
402
|
+
});
|
|
403
|
+
return map;
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
isAnimated(): boolean {
|
|
407
|
+
return isDrawerAnimated(this.optionsSnapshot());
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
slotOrder(): readonly IDrawerSlot[] {
|
|
411
|
+
return drawerChildOrder(this.optionsSnapshot());
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
rootStyle(): Record<string, unknown> {
|
|
415
|
+
return flattenStyle(this.drawerRoot().props.style);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
rootPanHandlers(): Record<string, unknown> {
|
|
419
|
+
return { ...this.panResponder.panHandlers };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
slotAnimatedProps(slot: IDrawerSlot): Record<string, unknown> {
|
|
423
|
+
const descriptor = this.slotsMap().get(slot);
|
|
424
|
+
if (!descriptor) return {};
|
|
425
|
+
const { style: _style, ...rest } = descriptor.props;
|
|
426
|
+
return rest;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
private slotStyle(
|
|
430
|
+
slot: IDrawerSlot,
|
|
431
|
+
animatedStyle: () => Record<string, unknown>,
|
|
432
|
+
): Record<string, unknown> {
|
|
433
|
+
const base = this.slotsMap().get(slot)?.props.style;
|
|
434
|
+
return this.isAnimated() ? flattenStyle([base, animatedStyle()]) : flattenStyle(base);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
contentStyle(): Record<string, unknown> {
|
|
438
|
+
return this.slotStyle('content', () => {
|
|
439
|
+
const g = resolveDrawerGeometry(this.optionsSnapshot());
|
|
440
|
+
const { translateX } = resolveDrawerSlotInterpolation(g, 'content');
|
|
441
|
+
return {
|
|
442
|
+
transform: [{ translateX: this.progress.interpolate(translateX) }],
|
|
443
|
+
};
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// The overlay's translateX follows content's own delta (see render-drawer.ts's comment on
|
|
448
|
+
// `overlayTranslateX`): for `slide`, content itself moves away, and without the overlay
|
|
449
|
+
// following it the dimming stays pinned full-screen instead of tracking the revealed panel.
|
|
450
|
+
overlayStyle(): Record<string, unknown> {
|
|
451
|
+
return this.slotStyle('overlay', () => {
|
|
452
|
+
const g = resolveDrawerGeometry(this.optionsSnapshot());
|
|
453
|
+
const { opacity, translateX } = resolveDrawerSlotInterpolation(g, 'overlay');
|
|
454
|
+
return {
|
|
455
|
+
opacity: this.progress.interpolate(opacity),
|
|
456
|
+
transform: [{ translateX: this.progress.interpolate(translateX) }],
|
|
457
|
+
};
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
panelStyle(): Record<string, unknown> {
|
|
462
|
+
return this.slotStyle('panel', () => {
|
|
463
|
+
const g = resolveDrawerGeometry(this.optionsSnapshot());
|
|
464
|
+
const { translateX } = resolveDrawerSlotInterpolation(g, 'panel');
|
|
465
|
+
return {
|
|
466
|
+
transform: [{ translateX: this.progress.interpolate(translateX) }],
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
focusedRoute(): IRoute<unknown> | undefined {
|
|
472
|
+
const state = this.stateSignal();
|
|
473
|
+
return state?.routes[state.index];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
componentForRoute(route: IRoute<unknown>): Type<unknown> | null {
|
|
477
|
+
return this.registry.get(route.name)?.component ?? null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private resolveDrawerScreenOptions(
|
|
481
|
+
entry: DrawerScreenDirective,
|
|
482
|
+
route: IRoute<unknown>,
|
|
483
|
+
): IDrawerScreenOptions {
|
|
484
|
+
if (typeof entry.options === 'function') {
|
|
485
|
+
const props: IDrawerScreenOptionsArgs = { route, navigation: this };
|
|
486
|
+
return entry.options(props);
|
|
487
|
+
}
|
|
488
|
+
return entry.options ?? {};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Lazily creates/replaces the focused route's emitter and synthesizes focus/blur - Drawer paints
|
|
492
|
+
// its own panel in pure JS (no native onAppear/onDisappear the way Stack's RNSScreen has), so
|
|
493
|
+
// focus/blur is synthesized here exactly like react/drawer.ts's own useEffect does, just
|
|
494
|
+
// idempotent per read instead of dependency-array gated. Keyed on the route KEY, not the object,
|
|
495
|
+
// so a no-op re-focus of the already-focused route doesn't spuriously re-fire.
|
|
496
|
+
//
|
|
497
|
+
// Called from the template ([emitter]="focusedRouteEmitter()"), which runs inside Angular's
|
|
498
|
+
// reactive-read tracking context for the current CD pass - unlike React's useEffect, which runs
|
|
499
|
+
// in a separate post-commit phase. Two consequences of that, both fixed below (see tabs.ts's
|
|
500
|
+
// identical fix for the full mechanism):
|
|
501
|
+
//
|
|
502
|
+
// 1. Writing a signal from inside a tracked template read throws Angular's NG600 ("signal write
|
|
503
|
+
// during a template execution") - untracked() opts this whole synthesis out of that
|
|
504
|
+
// tracking context.
|
|
505
|
+
// 2. The NEW route's screen component (injectIsFocused's listener source) is created by
|
|
506
|
+
// *ngComponentOutlet AFTER this binding is evaluated but still within the SAME synchronous
|
|
507
|
+
// template refresh - emitting FOCUS right here fires to zero listeners and is silently lost
|
|
508
|
+
// forever. queueMicrotask defers the FOCUS emit past the end of the current refresh
|
|
509
|
+
// (including the new screen's construction). BLUR doesn't need this: the outgoing screen's
|
|
510
|
+
// listener was already attached on an earlier tick.
|
|
511
|
+
focusedRouteEmitter(): INavigationEmitter {
|
|
512
|
+
const key = this.focusedRoute()?.key;
|
|
513
|
+
return untracked(() => {
|
|
514
|
+
if (key === this.currentEmitterKey && this.currentEmitter) return this.currentEmitter;
|
|
515
|
+
const { blurKey, focusKey } = diffFocusedRoute(this.currentEmitterKey, key);
|
|
516
|
+
if (blurKey !== undefined && this.currentEmitter) {
|
|
517
|
+
dlog('Drawer: previous route blurred');
|
|
518
|
+
this.currentEmitter.emit(NAVIGATION_EVENT_BLUR);
|
|
519
|
+
}
|
|
520
|
+
const emitter = createNavigationEmitter();
|
|
521
|
+
this.currentEmitter = emitter;
|
|
522
|
+
this.currentEmitterKey = key;
|
|
523
|
+
if (focusKey !== undefined) {
|
|
524
|
+
queueMicrotask(() => {
|
|
525
|
+
if (this.currentEmitter !== emitter) return; // superseded by a later switch
|
|
526
|
+
dlog(`Drawer: route "${this.focusedRoute()?.name}" focused`);
|
|
527
|
+
emitter.emit(NAVIGATION_EVENT_FOCUS);
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
return emitter;
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
drawerContentContext(currentState: IDrawerRouterState): IDrawerContentContext {
|
|
535
|
+
const descriptors: IDrawerDescriptorMap = {};
|
|
536
|
+
for (const route of currentState.routes) {
|
|
537
|
+
const entry = this.registry.get(route.name);
|
|
538
|
+
if (entry === undefined) continue;
|
|
539
|
+
descriptors[route.key] = {
|
|
540
|
+
options: this.resolveDrawerScreenOptions(entry, route),
|
|
541
|
+
navigation: this,
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
return { $implicit: { state: currentState, descriptors, navigation: this } };
|
|
545
|
+
}
|
|
546
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// [symbioteDrawerScreen]: Drawer's twin of screen.directive.ts's ScreenDirective - a declarative
|
|
2
|
+
// marker read via @ContentChildren to build the static name -> {component, options} registry, then
|
|
3
|
+
// Drawer mounts the FOCUSED route's component. Mirrors react/drawer-screen.ts (Drawer's twin) and
|
|
4
|
+
// tab-screen.directive.ts (the closer sibling - both are fixed-route-list, no-push navigators).
|
|
5
|
+
|
|
6
|
+
import { Directive, Input, type Type } from '@angular/core';
|
|
7
|
+
import type { IDrawerScreenOptions, IRoute } from '../core';
|
|
8
|
+
import type { IDrawerNavigatorHandle } from '../core';
|
|
9
|
+
|
|
10
|
+
export type IDrawerScreenOptionsArgs = {
|
|
11
|
+
route: IRoute<unknown>;
|
|
12
|
+
navigation: IDrawerNavigatorHandle;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type IDrawerScreenOptionsResolver = (
|
|
16
|
+
props: IDrawerScreenOptionsArgs,
|
|
17
|
+
) => IDrawerScreenOptions;
|
|
18
|
+
|
|
19
|
+
@Directive({
|
|
20
|
+
selector: 'ng-template[symbioteDrawerScreen]',
|
|
21
|
+
standalone: true,
|
|
22
|
+
})
|
|
23
|
+
export class DrawerScreenDirective {
|
|
24
|
+
@Input({ required: true }) name!: string;
|
|
25
|
+
@Input({ required: true }) component!: Type<unknown>;
|
|
26
|
+
@Input() options?: IDrawerScreenOptions | IDrawerScreenOptionsResolver;
|
|
27
|
+
@Input() initialParams?: unknown;
|
|
28
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// @symbiote-native/navigation/angular: the Angular native-stack navigator over
|
|
2
|
+
// react-native-screens' native view primitives. Importing this barrel first registers the native
|
|
3
|
+
// views' ViewConfigs (../register, a side-effect import of the three codegen specs - never
|
|
4
|
+
// react-native-screens' own React components), then exposes Stack/Tab/Drawer with their Screen
|
|
5
|
+
// directives and navigator handles. Mirrors react/index.ts's barrel shape.
|
|
6
|
+
|
|
7
|
+
import '../register';
|
|
8
|
+
|
|
9
|
+
export { Stack } from './stack';
|
|
10
|
+
export type { INavigatorHandle } from './stack';
|
|
11
|
+
export { ScreenDirective } from './screen.directive';
|
|
12
|
+
export type {
|
|
13
|
+
IAngularScreenOptions,
|
|
14
|
+
IAngularSearchBarOptions,
|
|
15
|
+
IScreenOptionsArgs,
|
|
16
|
+
IScreenOptionsResolver,
|
|
17
|
+
} from './screen.directive';
|
|
18
|
+
export type { IScreenOptions, IStackAnimation, IStackPresentation } from '../core';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
injectNavigation,
|
|
22
|
+
injectStackNavigation,
|
|
23
|
+
injectTabNavigation,
|
|
24
|
+
injectDrawerNavigation,
|
|
25
|
+
injectRoute,
|
|
26
|
+
injectIsFocused,
|
|
27
|
+
injectFocusEffect,
|
|
28
|
+
injectNavigationState,
|
|
29
|
+
} from './injectors';
|
|
30
|
+
export type {
|
|
31
|
+
INavigationHandle,
|
|
32
|
+
IStackNavigationHandle,
|
|
33
|
+
ITabNavigationHandle,
|
|
34
|
+
IDrawerNavigationHandle,
|
|
35
|
+
IFocusEffectCallback,
|
|
36
|
+
} from './injectors';
|
|
37
|
+
export { NavigationContextService } from './navigation-context.service';
|
|
38
|
+
export type { IAnyNavigatorHandle } from './navigation-context.service';
|
|
39
|
+
export { NavigationScopeDirective } from './navigation-scope.directive';
|
|
40
|
+
|
|
41
|
+
export { injectLinkingIntegration } from './linking';
|
|
42
|
+
export type { ILinkingConfig, IScreenLinkingConfig } from '../core';
|
|
43
|
+
|
|
44
|
+
// Tab: the bottom-tabs navigator, a PURE-JS UI (no react-native-screens views involved, so no
|
|
45
|
+
// extra ViewConfig registration is needed beyond the ../register import above).
|
|
46
|
+
export { Tab } from './tabs';
|
|
47
|
+
export type { ITabNavigatorHandle } from './tabs';
|
|
48
|
+
export { TabScreenDirective } from './tab-screen.directive';
|
|
49
|
+
export type { ITabScreenOptionsArgs, ITabScreenOptionsResolver } from './tab-screen.directive';
|
|
50
|
+
export type { ITabOptions, ITabBarIcon } from '../core';
|
|
51
|
+
|
|
52
|
+
// Drawer: the swipeable drawer navigator, a PURE-JS UI (PanResponder + Animated, no
|
|
53
|
+
// react-native-screens views involved, so no extra ViewConfig registration is needed beyond the
|
|
54
|
+
// ../register import above). See drawer.ts's header for the feasibility note re:
|
|
55
|
+
// react-native-gesture-handler / react-native-reanimated parity gaps.
|
|
56
|
+
export { Drawer } from './drawer';
|
|
57
|
+
export type { IDrawerNavigatorHandle, IDrawerDescriptorMap, IDrawerContentContext } from './drawer';
|
|
58
|
+
export { DrawerScreenDirective } from './drawer-screen.directive';
|
|
59
|
+
export type {
|
|
60
|
+
IDrawerScreenOptionsArgs,
|
|
61
|
+
IDrawerScreenOptionsResolver,
|
|
62
|
+
} from './drawer-screen.directive';
|
|
63
|
+
export type { IDrawerOptions, IDrawerScreenOptions, IDrawerType, IDrawerPosition } from '../core';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { injectNavigation } from './inject-navigation';
|
|
2
|
+
export type { INavigationHandle } from './inject-navigation';
|
|
3
|
+
export { injectStackNavigation } from './inject-stack-navigation';
|
|
4
|
+
export type { IStackNavigationHandle } from './inject-stack-navigation';
|
|
5
|
+
export { injectTabNavigation } from './inject-tab-navigation';
|
|
6
|
+
export type { ITabNavigationHandle } from './inject-tab-navigation';
|
|
7
|
+
export { injectDrawerNavigation } from './inject-drawer-navigation';
|
|
8
|
+
export type { IDrawerNavigationHandle } from './inject-drawer-navigation';
|
|
9
|
+
export { injectRoute } from './inject-route';
|
|
10
|
+
export { injectIsFocused } from './inject-is-focused';
|
|
11
|
+
export { injectFocusEffect } from './inject-focus-effect';
|
|
12
|
+
export type { IFocusEffectCallback } from './inject-focus-effect';
|
|
13
|
+
export { injectNavigationState } from './inject-navigation-state';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Twin of inject-stack-navigation.ts, narrowing to a Drawer handle instead.
|
|
2
|
+
|
|
3
|
+
import type { IDrawerNavigatorHandle } from '../../core';
|
|
4
|
+
import { isDrawerNavigatorHandle } from '../../core';
|
|
5
|
+
import { injectNavigation } from './inject-navigation';
|
|
6
|
+
import type { INavigationHandle } from './inject-navigation';
|
|
7
|
+
|
|
8
|
+
export type IDrawerNavigationHandle = IDrawerNavigatorHandle &
|
|
9
|
+
Pick<INavigationHandle, 'addListener' | 'getParent'>;
|
|
10
|
+
|
|
11
|
+
export function injectDrawerNavigation(): IDrawerNavigationHandle {
|
|
12
|
+
const navigation = injectNavigation();
|
|
13
|
+
if (!isDrawerNavigatorHandle(navigation)) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'injectDrawerNavigation() was called from a component whose nearest navigator is not a ' +
|
|
16
|
+
'Drawer. Use injectNavigation() instead if this component can render under more than one ' +
|
|
17
|
+
'navigator kind.',
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return navigation;
|
|
21
|
+
}
|