@symbiote-native/navigation 2.0.3 → 2.2.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/README.md +42 -12
- package/build/angular/drawer/index.js +29 -13
- package/build/angular/index.d.ts +4 -4
- package/build/angular/injectors/inject-navigation.js +1 -1
- package/build/angular/navigation-scope.directive.js +1 -1
- package/build/angular/search-bar-ref.directive.js +1 -1
- package/build/angular/stack/index.d.ts +2 -0
- package/build/angular/stack/index.js +43 -9
- package/build/angular/tabs/index.d.ts +1 -1
- package/build/angular/tabs/index.js +40 -13
- package/build/core/drawer-options/index.js +19 -5
- package/build/core/drawer-router-state/index.js +8 -2
- package/build/core/guards.js +3 -1
- package/build/core/header-bar-buttons.js +14 -4
- package/build/core/index.d.ts +6 -5
- package/build/core/index.js +7 -3
- package/build/core/navigator-state/index.js +12 -4
- package/build/core/render-drawer.js +4 -1
- package/build/core/render-stack.js +13 -4
- package/build/core/screen-options.js +1 -1
- package/build/core/search-bar-commands.js +1 -1
- package/build/core/stack-router-state/index.d.ts +2 -0
- package/build/core/stack-router-state/index.js +44 -0
- package/build/core/state-persistence/index.js +6 -2
- package/build/core/tab-router-state/index.d.ts +1 -0
- package/build/core/tab-router-state/index.js +27 -2
- package/build/react/drawer/index.js +59 -26
- package/build/react/index.d.ts +7 -7
- package/build/react/index.js +2 -2
- package/build/react/stack/index.js +47 -10
- package/build/react/tabs/index.js +36 -12
- package/build/solid/drawer/index.d.ts +22 -0
- package/build/solid/drawer/index.js +394 -0
- package/build/solid/drawer-screen-props.d.ts +13 -0
- package/build/solid/drawer-screen-props.js +2 -0
- package/build/solid/host.d.ts +2 -0
- package/build/solid/host.js +23 -0
- package/build/solid/index.d.ts +19 -0
- package/build/solid/index.js +24 -0
- package/build/solid/linking.d.ts +3 -0
- package/build/solid/linking.js +55 -0
- package/build/solid/navigation-context.d.ts +13 -0
- package/build/solid/navigation-context.js +37 -0
- package/build/solid/primitives/create-focus-effect.d.ts +1 -0
- package/build/solid/primitives/create-focus-effect.js +30 -0
- package/build/solid/primitives/create-is-focused.d.ts +2 -0
- package/build/solid/primitives/create-is-focused.js +31 -0
- package/build/solid/primitives/create-navigation-state.d.ts +3 -0
- package/build/solid/primitives/create-navigation-state.js +30 -0
- package/build/solid/primitives/index.d.ts +12 -0
- package/build/solid/primitives/index.js +8 -0
- package/build/solid/primitives/use-drawer-navigation.d.ts +5 -0
- package/build/solid/primitives/use-drawer-navigation.js +15 -0
- package/build/solid/primitives/use-navigation.d.ts +8 -0
- package/build/solid/primitives/use-navigation.js +23 -0
- package/build/solid/primitives/use-route.d.ts +3 -0
- package/build/solid/primitives/use-route.js +14 -0
- package/build/solid/primitives/use-stack-navigation.d.ts +5 -0
- package/build/solid/primitives/use-stack-navigation.js +19 -0
- package/build/solid/primitives/use-tab-navigation.d.ts +5 -0
- package/build/solid/primitives/use-tab-navigation.js +15 -0
- package/build/solid/screen-props.d.ts +19 -0
- package/build/solid/screen-props.js +9 -0
- package/build/solid/screen-registry.d.ts +31 -0
- package/build/solid/screen-registry.js +86 -0
- package/build/solid/screen.d.ts +6 -0
- package/build/solid/screen.js +69 -0
- package/build/solid/stack/index.d.ts +15 -0
- package/build/solid/stack/index.js +348 -0
- package/build/solid/tab-screen-props.d.ts +13 -0
- package/build/solid/tab-screen-props.js +3 -0
- package/build/solid/tabs/index.d.ts +14 -0
- package/build/solid/tabs/index.js +228 -0
- package/build/svelte/attachments.d.ts +5 -0
- package/build/svelte/attachments.js +61 -0
- package/build/svelte/descriptor-subtree.d.ts +3 -0
- package/build/svelte/descriptor-subtree.js +39 -0
- package/build/svelte/drawer/drawer-props.d.ts +14 -0
- package/build/svelte/drawer/drawer-props.js +3 -0
- package/build/svelte/drawer/index.d.ts +10 -0
- package/build/svelte/drawer/index.js +6 -0
- package/build/svelte/drawer/index.svelte +559 -0
- package/build/svelte/drawer/index.svelte.d.ts +10 -0
- package/build/svelte/drawer-screen-props.d.ts +13 -0
- package/build/svelte/drawer-screen-props.js +4 -0
- package/build/svelte/drawer-screen.svelte +25 -0
- package/build/svelte/drawer-screen.svelte.d.ts +4 -0
- package/build/svelte/index.d.ts +21 -0
- package/build/svelte/index.js +20 -0
- package/build/svelte/linking.svelte.d.ts +2 -0
- package/build/svelte/linking.svelte.js +55 -0
- package/build/svelte/navigation-context.d.ts +14 -0
- package/build/svelte/navigation-context.js +44 -0
- package/build/svelte/navigation-scope.svelte +27 -0
- package/build/svelte/navigation-scope.svelte.d.ts +9 -0
- package/build/svelte/registry-host.d.ts +1 -0
- package/build/svelte/registry-host.js +26 -0
- package/build/svelte/runes/index.d.ts +12 -0
- package/build/svelte/runes/index.js +12 -0
- package/build/svelte/runes/use-drawer-navigation.svelte.d.ts +6 -0
- package/build/svelte/runes/use-drawer-navigation.svelte.js +19 -0
- package/build/svelte/runes/use-focus-effect.svelte.d.ts +1 -0
- package/build/svelte/runes/use-focus-effect.svelte.js +31 -0
- package/build/svelte/runes/use-is-focused.svelte.d.ts +3 -0
- package/build/svelte/runes/use-is-focused.svelte.js +34 -0
- package/build/svelte/runes/use-navigation-state.svelte.d.ts +4 -0
- package/build/svelte/runes/use-navigation-state.svelte.js +39 -0
- package/build/svelte/runes/use-navigation.svelte.d.ts +9 -0
- package/build/svelte/runes/use-navigation.svelte.js +26 -0
- package/build/svelte/runes/use-route.svelte.d.ts +4 -0
- package/build/svelte/runes/use-route.svelte.js +12 -0
- package/build/svelte/runes/use-stack-navigation.svelte.d.ts +6 -0
- package/build/svelte/runes/use-stack-navigation.svelte.js +22 -0
- package/build/svelte/runes/use-tab-navigation.svelte.d.ts +6 -0
- package/build/svelte/runes/use-tab-navigation.svelte.js +19 -0
- package/build/svelte/screen-props.d.ts +21 -0
- package/build/svelte/screen-props.js +6 -0
- package/build/svelte/screen-registry.d.ts +17 -0
- package/build/svelte/screen-registry.js +57 -0
- package/build/svelte/screen.svelte +28 -0
- package/build/svelte/screen.svelte.d.ts +4 -0
- package/build/svelte/stack/index.d.ts +14 -0
- package/build/svelte/stack/index.js +7 -0
- package/build/svelte/stack/index.svelte +261 -0
- package/build/svelte/stack/index.svelte.d.ts +15 -0
- package/build/svelte/stack/stack-props.d.ts +20 -0
- package/build/svelte/stack/stack-props.js +4 -0
- package/build/svelte/stack/stack-screen.svelte +205 -0
- package/build/svelte/stack/stack-screen.svelte.d.ts +4 -0
- package/build/svelte/tab-screen-props.d.ts +13 -0
- package/build/svelte/tab-screen-props.js +4 -0
- package/build/svelte/tab-screen.svelte +26 -0
- package/build/svelte/tab-screen.svelte.d.ts +4 -0
- package/build/svelte/tabs/index.d.ts +8 -0
- package/build/svelte/tabs/index.js +6 -0
- package/build/svelte/tabs/index.svelte +269 -0
- package/build/svelte/tabs/index.svelte.d.ts +8 -0
- package/build/svelte/tabs/tab-props.d.ts +7 -0
- package/build/svelte/tabs/tab-props.js +3 -0
- package/build/vue/composables/use-navigation.js +5 -1
- package/build/vue/drawer/index.js +36 -13
- package/build/vue/index.d.ts +3 -3
- package/build/vue/navigation-context.js +1 -1
- package/build/vue/stack/index.js +43 -18
- package/build/vue/tabs/index.js +65 -39
- package/build-ngc/angular/drawer/index.js +40 -18
- package/build-ngc/angular/drawer/index.js.map +1 -1
- package/build-ngc/angular/drawer-screen.directive.js +3 -3
- package/build-ngc/angular/index.d.ts +4 -4
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/injectors/inject-focus-effect.js.map +1 -1
- package/build-ngc/angular/injectors/inject-is-focused.js.map +1 -1
- package/build-ngc/angular/injectors/inject-navigation-state.js.map +1 -1
- package/build-ngc/angular/injectors/inject-navigation.js +1 -1
- package/build-ngc/angular/injectors/inject-navigation.js.map +1 -1
- package/build-ngc/angular/linking.js.map +1 -1
- package/build-ngc/angular/navigation-context.service.js +3 -3
- package/build-ngc/angular/navigation-context.service.js.map +1 -1
- package/build-ngc/angular/navigation-scope.directive.js +4 -4
- package/build-ngc/angular/navigation-scope.directive.js.map +1 -1
- package/build-ngc/angular/screen.directive.js +3 -3
- package/build-ngc/angular/screen.directive.js.map +1 -1
- package/build-ngc/angular/search-bar-ref.directive.js +4 -4
- package/build-ngc/angular/search-bar-ref.directive.js.map +1 -1
- package/build-ngc/angular/stack/index.d.ts +2 -0
- package/build-ngc/angular/stack/index.js +52 -14
- package/build-ngc/angular/stack/index.js.map +1 -1
- package/build-ngc/angular/tab-screen.directive.js +3 -3
- package/build-ngc/angular/tab-screen.directive.js.map +1 -1
- package/build-ngc/angular/tabs/index.d.ts +1 -1
- package/build-ngc/angular/tabs/index.js +43 -16
- package/build-ngc/angular/tabs/index.js.map +1 -1
- package/build-ngc/core/constants.js.map +1 -1
- package/build-ngc/core/drawer-options/index.js +19 -5
- package/build-ngc/core/drawer-options/index.js.map +1 -1
- package/build-ngc/core/drawer-router-state/index.js +8 -2
- package/build-ngc/core/drawer-router-state/index.js.map +1 -1
- package/build-ngc/core/guards.js +3 -1
- package/build-ngc/core/guards.js.map +1 -1
- package/build-ngc/core/header-bar-buttons.js +14 -4
- package/build-ngc/core/header-bar-buttons.js.map +1 -1
- package/build-ngc/core/index.d.ts +6 -5
- package/build-ngc/core/index.js +7 -3
- package/build-ngc/core/index.js.map +1 -1
- package/build-ngc/core/linking-config/index.js.map +1 -1
- package/build-ngc/core/navigation-events/index.js.map +1 -1
- package/build-ngc/core/navigator-handles/index.js.map +1 -1
- package/build-ngc/core/navigator-state/index.js +12 -4
- package/build-ngc/core/navigator-state/index.js.map +1 -1
- package/build-ngc/core/render-drawer.js +4 -1
- package/build-ngc/core/render-drawer.js.map +1 -1
- package/build-ngc/core/render-stack.js +13 -4
- package/build-ngc/core/render-stack.js.map +1 -1
- package/build-ngc/core/render-tabs.js.map +1 -1
- package/build-ngc/core/screen-options.js +1 -1
- package/build-ngc/core/screen-options.js.map +1 -1
- package/build-ngc/core/search-bar-commands.js +1 -1
- package/build-ngc/core/search-bar-commands.js.map +1 -1
- package/build-ngc/core/stack-router-state/index.d.ts +2 -0
- package/build-ngc/core/stack-router-state/index.js +45 -0
- package/build-ngc/core/stack-router-state/index.js.map +1 -0
- package/build-ngc/core/state-persistence/index.js +6 -2
- package/build-ngc/core/state-persistence/index.js.map +1 -1
- package/build-ngc/core/tab-router-state/index.d.ts +1 -0
- package/build-ngc/core/tab-router-state/index.js +27 -2
- package/build-ngc/core/tab-router-state/index.js.map +1 -1
- package/package.json +44 -16
- package/src/angular/drawer/index.ts +75 -29
- package/src/angular/index.ts +20 -4
- package/src/angular/injectors/inject-focus-effect.ts +8 -2
- package/src/angular/injectors/inject-is-focused.ts +6 -4
- package/src/angular/injectors/inject-navigation-state.ts +7 -4
- package/src/angular/injectors/inject-navigation.ts +12 -3
- package/src/angular/linking.ts +4 -1
- package/src/angular/navigation-context.service.ts +5 -2
- package/src/angular/navigation-scope.directive.ts +6 -2
- package/src/angular/screen.directive.ts +13 -3
- package/src/angular/search-bar-ref.directive.ts +10 -2
- package/src/angular/stack/index.ts +91 -24
- package/src/angular/tab-screen.directive.ts +3 -1
- package/src/angular/tabs/index.ts +54 -16
- package/src/core/constants.ts +6 -3
- package/src/core/drawer-options/index.ts +40 -13
- package/src/core/drawer-router-state/index.ts +11 -3
- package/src/core/guards.ts +3 -1
- package/src/core/header-bar-buttons.ts +41 -12
- package/src/core/index.ts +29 -5
- package/src/core/linking-config/index.ts +31 -10
- package/src/core/navigation-events/index.ts +8 -2
- package/src/core/navigator-handles/index.ts +8 -3
- package/src/core/navigator-props.ts +13 -4
- package/src/core/navigator-state/index.ts +24 -7
- package/src/core/render-drawer.ts +24 -9
- package/src/core/render-stack.ts +52 -13
- package/src/core/render-tabs.ts +24 -6
- package/src/core/screen-options.ts +15 -5
- package/src/core/search-bar-commands.ts +12 -3
- package/src/core/stack-router-state/index.ts +52 -0
- package/src/core/state-persistence/index.ts +13 -3
- package/src/core/tab-router-state/index.ts +35 -3
- package/src/react/drawer/index.ts +409 -330
- package/src/react/drawer-screen.ts +8 -2
- package/src/react/hooks/use-focus-effect.ts +8 -2
- package/src/react/hooks/use-is-focused.ts +6 -2
- package/src/react/hooks/use-navigation.ts +8 -2
- package/src/react/index.ts +37 -7
- package/src/react/linking.ts +4 -1
- package/src/react/navigation-context.ts +6 -2
- package/src/react/screen.ts +12 -3
- package/src/react/stack/index.ts +297 -220
- package/src/react/tab-screen.ts +3 -1
- package/src/react/tabs/index.ts +202 -139
- package/src/solid/drawer/index.ts +570 -0
- package/src/solid/drawer-screen-props.ts +24 -0
- package/src/solid/host.ts +29 -0
- package/src/solid/index.ts +87 -0
- package/src/solid/linking.ts +74 -0
- package/src/solid/navigation-context.ts +56 -0
- package/src/solid/primitives/create-focus-effect.ts +41 -0
- package/src/solid/primitives/create-is-focused.ts +41 -0
- package/src/solid/primitives/create-navigation-state.ts +44 -0
- package/src/solid/primitives/index.ts +12 -0
- package/src/solid/primitives/use-drawer-navigation.ts +25 -0
- package/src/solid/primitives/use-navigation.ts +44 -0
- package/src/solid/primitives/use-route.ts +18 -0
- package/src/solid/primitives/use-stack-navigation.ts +29 -0
- package/src/solid/primitives/use-tab-navigation.ts +25 -0
- package/src/solid/screen-props.ts +51 -0
- package/src/solid/screen-registry.ts +159 -0
- package/src/solid/screen.ts +80 -0
- package/src/solid/stack/index.ts +528 -0
- package/src/solid/tab-screen-props.ts +21 -0
- package/src/solid/tabs/index.ts +327 -0
- package/src/svelte/attachments.ts +70 -0
- package/src/svelte/descriptor-subtree.ts +51 -0
- package/src/svelte/drawer/drawer-props.ts +28 -0
- package/src/svelte/drawer/index.svelte +559 -0
- package/src/svelte/drawer/index.ts +10 -0
- package/src/svelte/drawer-screen-props.ts +26 -0
- package/src/svelte/drawer-screen.svelte +25 -0
- package/src/svelte/fabric-tree.test-helper.ts +95 -0
- package/src/svelte/index.ts +83 -0
- package/src/svelte/linking.svelte.ts +72 -0
- package/src/svelte/navigation-context.ts +62 -0
- package/src/svelte/navigation-scope.svelte +27 -0
- package/src/svelte/registry-host.ts +26 -0
- package/src/svelte/runes/index.ts +17 -0
- package/src/svelte/runes/use-drawer-navigation.svelte.ts +31 -0
- package/src/svelte/runes/use-focus-effect.svelte.ts +41 -0
- package/src/svelte/runes/use-is-focused.svelte.ts +38 -0
- package/src/svelte/runes/use-navigation-state.svelte.ts +48 -0
- package/src/svelte/runes/use-navigation.svelte.ts +49 -0
- package/src/svelte/runes/use-route.svelte.ts +16 -0
- package/src/svelte/runes/use-stack-navigation.svelte.ts +34 -0
- package/src/svelte/runes/use-tab-navigation.svelte.ts +29 -0
- package/src/svelte/screen-props.ts +50 -0
- package/src/svelte/screen-registry.ts +98 -0
- package/src/svelte/screen.svelte +28 -0
- package/src/svelte/stack/index.svelte +261 -0
- package/src/svelte/stack/index.ts +11 -0
- package/src/svelte/stack/stack-props.ts +31 -0
- package/src/svelte/stack/stack-screen.svelte +205 -0
- package/src/svelte/svelte-ambient.d.ts +6 -0
- package/src/svelte/svelte-compile.test-helper.ts +147 -0
- package/src/svelte/tab-screen-props.ts +22 -0
- package/src/svelte/tab-screen.svelte +26 -0
- package/src/svelte/tabs/index.svelte +269 -0
- package/src/svelte/tabs/index.ts +10 -0
- package/src/svelte/tabs/tab-props.ts +13 -0
- package/src/vue/composables/use-navigation-state.ts +7 -4
- package/src/vue/composables/use-navigation.ts +13 -3
- package/src/vue/drawer/index.ts +128 -41
- package/src/vue/drawer-screen.ts +12 -5
- package/src/vue/index.ts +15 -3
- package/src/vue/linking.ts +7 -2
- package/src/vue/navigation-context.ts +17 -5
- package/src/vue/screen.ts +7 -2
- package/src/vue/stack/index.ts +108 -43
- package/src/vue/tab-screen.ts +3 -1
- package/src/vue/tabs/index.ts +109 -68
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Twin of use-stack-navigation.svelte.ts, narrowing to a Tab handle instead.
|
|
2
|
+
|
|
3
|
+
import type { ITabNavigatorHandle } from '../../core';
|
|
4
|
+
import { isTabNavigatorHandle } from '../../core';
|
|
5
|
+
import { useNavigation } from './use-navigation.svelte';
|
|
6
|
+
import type { INavigationHandle } from './use-navigation.svelte';
|
|
7
|
+
|
|
8
|
+
export type ITabNavigationHandle = ITabNavigatorHandle &
|
|
9
|
+
Pick<INavigationHandle, 'addListener' | 'getParent'>;
|
|
10
|
+
|
|
11
|
+
export function useTabNavigation(): { readonly current: ITabNavigationHandle } {
|
|
12
|
+
const navigation = useNavigation();
|
|
13
|
+
const narrowed = $derived.by<ITabNavigationHandle>(() => {
|
|
14
|
+
const value = navigation.current;
|
|
15
|
+
if (!isTabNavigatorHandle(value)) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'useTabNavigation() was called from a component whose nearest navigator is not a Tab. ' +
|
|
18
|
+
'Use useNavigation() instead if this component can render under more than one navigator kind.',
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
get current(): ITabNavigationHandle {
|
|
26
|
+
return narrowed;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Stack.Screen's public prop surface. Split out of `screen.svelte` because plain `tsc --build`
|
|
2
|
+
// resolves an import of a `.svelte` file through svelte's own ambient `declare module '*.svelte'`
|
|
3
|
+
// fallback (a bare default export only) and never parses the real `<script module>` block - so a
|
|
4
|
+
// NAMED type re-exported from a `.svelte` file is invisible to `tsc`. Same rule the Svelte
|
|
5
|
+
// adapter's own `view-props.ts` / `switch-props.ts` follow.
|
|
6
|
+
|
|
7
|
+
import type { Component } from 'svelte';
|
|
8
|
+
import type {
|
|
9
|
+
INavigatorHandle,
|
|
10
|
+
IRoute,
|
|
11
|
+
IScreenOptions,
|
|
12
|
+
ISearchBarCommands,
|
|
13
|
+
ISearchBarOptions,
|
|
14
|
+
} from '../core';
|
|
15
|
+
|
|
16
|
+
// The imperative search-bar handle (focus/blur/clearText/setText/cancelSearch/
|
|
17
|
+
// toggleCancelButton) is delivered through a MUTABLE CELL the app owns, not a Svelte rune: per
|
|
18
|
+
// CLAUDE.md's <prop_types_split_agnostic_vs_per_adapter> a framework ref cannot live in the
|
|
19
|
+
// shared, agnostic ISearchBarOptions, and Svelte has no `Ref`/`RefObject` type of its own to
|
|
20
|
+
// name here. `{ current }` is the same shape Angular's IAngularSearchBarOptions uses, and an app
|
|
21
|
+
// that wants to react to it simply declares the cell with `$state`.
|
|
22
|
+
export type ISvelteSearchBarOptions = ISearchBarOptions & {
|
|
23
|
+
ref?: { current: ISearchBarCommands | null };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type ISvelteScreenOptions = Omit<
|
|
27
|
+
IScreenOptions,
|
|
28
|
+
'headerSearchBarOptions'
|
|
29
|
+
> & {
|
|
30
|
+
headerSearchBarOptions?: ISvelteSearchBarOptions;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// The options resolver runs OUTSIDE render (during the options fold), so it still receives the
|
|
34
|
+
// route + navigator handle explicitly - screens read those through runes, but a resolver has no
|
|
35
|
+
// component scope to read context from.
|
|
36
|
+
export type IScreenOptionsArgs = {
|
|
37
|
+
route: IRoute<unknown>;
|
|
38
|
+
navigation: INavigatorHandle;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type IScreenOptionsResolver = (
|
|
42
|
+
args: IScreenOptionsArgs,
|
|
43
|
+
) => ISvelteScreenOptions;
|
|
44
|
+
|
|
45
|
+
export type IScreenProps = {
|
|
46
|
+
name: string;
|
|
47
|
+
component: Component;
|
|
48
|
+
options?: ISvelteScreenOptions | IScreenOptionsResolver;
|
|
49
|
+
initialParams?: unknown;
|
|
50
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// How a navigator learns about its `<Stack.Screen>` / `<Tab.Screen>` / `<Drawer.Screen>` markers.
|
|
2
|
+
//
|
|
3
|
+
// React reads `children` as an inspectable array; Vue scans the default slot's vnodes
|
|
4
|
+
// (`vnode.type === Screen`); Angular queries `@ContentChildren`. Svelte has NO equivalent: a
|
|
5
|
+
// component receives its children as an opaque `Snippet`, with no way to enumerate or inspect
|
|
6
|
+
// what is inside it (the same wall the Svelte adapter's ScrollView hit for
|
|
7
|
+
// `stickyHeaderIndices`, svelte-adapter-dom-shim skill §18). So registration is INVERTED here:
|
|
8
|
+
// the navigator publishes a collector on the context, each marker registers ITSELF during its own
|
|
9
|
+
// init, and the navigator's route list derives from what came back.
|
|
10
|
+
//
|
|
11
|
+
// Ordering works out because Svelte's initial render is synchronous and top-down: a navigator
|
|
12
|
+
// renders the children snippet BEFORE the `{#each}` that paints its routes, so by the time the
|
|
13
|
+
// route list is first read every marker has already registered. Verified against the real
|
|
14
|
+
// compiler, not assumed.
|
|
15
|
+
//
|
|
16
|
+
// ONE key, not one per navigator kind: nearest-navigator-wins shadowing falls out of Svelte's own
|
|
17
|
+
// context lookup, so a Stack nested inside a Tab screen automatically captures its own markers.
|
|
18
|
+
// The `kind` tag then rejects a MISMATCHED marker (a `<Tab.Screen>` written inside a `<Stack>`)
|
|
19
|
+
// instead of letting it silently register with some far-away ancestor Tab - the failure mode a
|
|
20
|
+
// per-kind key would have.
|
|
21
|
+
|
|
22
|
+
import { getContext, onDestroy, setContext } from 'svelte';
|
|
23
|
+
import type { Component } from 'svelte';
|
|
24
|
+
import { dlog } from '@symbiote-native/engine';
|
|
25
|
+
|
|
26
|
+
export type INavigatorKind = 'stack' | 'tab' | 'drawer';
|
|
27
|
+
|
|
28
|
+
// Every field is a GETTER on the marker's own `$props()` bindings, so an app that reassigns
|
|
29
|
+
// `options`/`component` on an already-mounted marker keeps the navigator's view of it live -
|
|
30
|
+
// the same reason Angular's Stack stores the ScreenDirective INSTANCE rather than a snapshot of
|
|
31
|
+
// its fields. `name` is read live too, so renaming a screen re-keys it rather than going stale.
|
|
32
|
+
export type IRegisteredScreen<TOptions> = {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly component: Component;
|
|
35
|
+
readonly options: TOptions | undefined;
|
|
36
|
+
readonly initialParams: unknown;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type IScreenCollector<TOptions> = {
|
|
40
|
+
readonly kind: INavigatorKind;
|
|
41
|
+
register(screen: IRegisteredScreen<TOptions>): void;
|
|
42
|
+
unregister(screen: IRegisteredScreen<TOptions>): void;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const SCREEN_COLLECTOR_KEY = Symbol('symbiote-navigation-screen-collector');
|
|
46
|
+
|
|
47
|
+
// Called once from a navigator's own init, before it renders the children snippet.
|
|
48
|
+
export function setScreenCollector<TOptions>(
|
|
49
|
+
collector: IScreenCollector<TOptions>,
|
|
50
|
+
): void {
|
|
51
|
+
setContext(SCREEN_COLLECTOR_KEY, collector);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Called once from a marker's own init. Registration is undone on destroy, so a marker behind an
|
|
55
|
+
// `{#if}` disappears from the registry exactly like a Vue slot scan stops seeing a removed vnode.
|
|
56
|
+
export function collectScreen<TOptions>(
|
|
57
|
+
kind: INavigatorKind,
|
|
58
|
+
screen: IRegisteredScreen<TOptions>,
|
|
59
|
+
): void {
|
|
60
|
+
const collector = getContext<IScreenCollector<TOptions> | undefined>(
|
|
61
|
+
SCREEN_COLLECTOR_KEY,
|
|
62
|
+
);
|
|
63
|
+
if (collector === undefined) {
|
|
64
|
+
dlog(
|
|
65
|
+
`navigation: <${kind} screen "${screen.name}"> rendered outside any navigator, ignored`,
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (collector.kind !== kind) {
|
|
70
|
+
dlog(
|
|
71
|
+
`navigation: a ${kind} screen marker ("${screen.name}") was rendered inside a ` +
|
|
72
|
+
`${collector.kind} navigator, ignored`,
|
|
73
|
+
);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
collector.register(screen);
|
|
77
|
+
onDestroy(() => collector.unregister(screen));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The navigator side of the pair: a plain, non-reactive list plus the two mutators the collector
|
|
81
|
+
// exposes. The navigator holds the list in `$state.raw` and reassigns it (never mutates in place)
|
|
82
|
+
// so a component reference - a plain function - is never wrapped in a deep reactive proxy, which
|
|
83
|
+
// would break both the getters above and Svelte's own component identity checks.
|
|
84
|
+
export function withoutScreen<TOptions>(
|
|
85
|
+
screens: readonly IRegisteredScreen<TOptions>[],
|
|
86
|
+
screen: IRegisteredScreen<TOptions>,
|
|
87
|
+
): IRegisteredScreen<TOptions>[] {
|
|
88
|
+
return screens.filter(candidate => candidate !== screen);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// name -> entry, last registration wins, exactly like Vue's collectRegistry Map.
|
|
92
|
+
export function toRegistry<TOptions>(
|
|
93
|
+
screens: readonly IRegisteredScreen<TOptions>[],
|
|
94
|
+
): Map<string, IRegisteredScreen<TOptions>> {
|
|
95
|
+
const registry = new Map<string, IRegisteredScreen<TOptions>>();
|
|
96
|
+
for (const screen of screens) registry.set(screen.name, screen);
|
|
97
|
+
return registry;
|
|
98
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// Stack.Screen: a declarative marker that paints nothing. Stack reads it through the
|
|
3
|
+
// context-based collector (screen-registry.ts) rather than by scanning children the way React
|
|
4
|
+
// and Vue can, then mounts the registered component itself for each pushed route.
|
|
5
|
+
//
|
|
6
|
+
// Every field is handed over as a GETTER over this component's own `$props()` bindings, so the
|
|
7
|
+
// navigator always sees the CURRENT value - reassigning `options` on an already-mounted marker
|
|
8
|
+
// reaches the next options fold without re-registering.
|
|
9
|
+
import { collectScreen } from './screen-registry';
|
|
10
|
+
import type { IScreenProps } from './screen-props';
|
|
11
|
+
|
|
12
|
+
let { name, component, options, initialParams }: IScreenProps = $props();
|
|
13
|
+
|
|
14
|
+
collectScreen('stack', {
|
|
15
|
+
get name(): IScreenProps['name'] {
|
|
16
|
+
return name;
|
|
17
|
+
},
|
|
18
|
+
get component(): IScreenProps['component'] {
|
|
19
|
+
return component;
|
|
20
|
+
},
|
|
21
|
+
get options(): IScreenProps['options'] {
|
|
22
|
+
return options;
|
|
23
|
+
},
|
|
24
|
+
get initialParams(): unknown {
|
|
25
|
+
return initialParams;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
// Stack, the Svelte lifecycle half. The route-stack transitions (navigator-state) and the
|
|
3
|
+
// options/props folds (screen-options, render-stack) live in @symbiote-native/navigation core,
|
|
4
|
+
// shared verbatim with the React/Vue/Angular entries; here Svelte supplies the lifecycle -
|
|
5
|
+
// `$state.raw` for the pushed-route stack (its twin of useReducer: reassign from the same pure
|
|
6
|
+
// reducer), a module counter for route-key generation, `export function`s for the push/pop/
|
|
7
|
+
// replace navigator handle (Svelte's twin of Vue's expose(), reachable via `bind:this`) - plus
|
|
8
|
+
// the react-native-screens chrome per route (stack-screen.svelte). Pushing/popping a route is
|
|
9
|
+
// an ordinary child mount/unmount: RNSScreenStack diffs its RNSScreen children natively, so no
|
|
10
|
+
// imperative native command is needed here at all. Neither this nor the Screen marker imports
|
|
11
|
+
// react-native-screens' own React components (ScreenStack.tsx et al - hooks, crashes a
|
|
12
|
+
// non-React adapter); the native views are driven directly through the ViewConfig ../../register
|
|
13
|
+
// registers. See CLAUDE.md <third_party_rn_packages_are_react_only>.
|
|
14
|
+
//
|
|
15
|
+
// HOW SCREENS ARE DISCOVERED: not by reading `children`, which Svelte hands over as an opaque
|
|
16
|
+
// Snippet - the markers register themselves through the context collector (../screen-registry.ts)
|
|
17
|
+
// while the snippet renders, and the route list derives from that. The snippet is rendered
|
|
18
|
+
// inside a collapsed `symbiote-text` (../registry-host.ts) so whitespace between two markers
|
|
19
|
+
// can never become an illegal raw-text child of a native view.
|
|
20
|
+
|
|
21
|
+
// Route keys must be unique per Stack INSTANCE (Svelte has no useId); a module counter is the
|
|
22
|
+
// same mechanism the Angular entry uses.
|
|
23
|
+
let stackInstanceCounter = 0;
|
|
24
|
+
|
|
25
|
+
const STACK_ROOT_PROPS: Record<string, unknown> = { style: { flex: 1 } };
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import type { Component } from 'svelte';
|
|
30
|
+
import { dlog } from '@symbiote-native/engine';
|
|
31
|
+
import {
|
|
32
|
+
NAVIGATION_EVENT_STATE,
|
|
33
|
+
RNS_SCREEN_STACK_VIEW_NAME,
|
|
34
|
+
STACK_ON_FINISH_TRANSITIONING,
|
|
35
|
+
createInitialNavigatorState,
|
|
36
|
+
createNavigationEmitter,
|
|
37
|
+
navigatorReducer,
|
|
38
|
+
reconcileStackRoutes,
|
|
39
|
+
resolveStackProps,
|
|
40
|
+
} from '../../core';
|
|
41
|
+
import type {
|
|
42
|
+
INavigationEmitter,
|
|
43
|
+
INavigatorAction,
|
|
44
|
+
INavigatorHandle,
|
|
45
|
+
INavigatorState,
|
|
46
|
+
IRoute,
|
|
47
|
+
} from '../../core';
|
|
48
|
+
import { hostProps } from '../attachments';
|
|
49
|
+
import { getNavigationScope } from '../navigation-context';
|
|
50
|
+
import { SCREEN_REGISTRY_HOST_PROPS } from '../registry-host';
|
|
51
|
+
import {
|
|
52
|
+
setScreenCollector,
|
|
53
|
+
toRegistry,
|
|
54
|
+
withoutScreen,
|
|
55
|
+
} from '../screen-registry';
|
|
56
|
+
import type { IRegisteredScreen } from '../screen-registry';
|
|
57
|
+
import type { IScreenProps, ISvelteScreenOptions } from '../screen-props';
|
|
58
|
+
import StackScreen from './stack-screen.svelte';
|
|
59
|
+
import type { IStackProps } from './stack-props';
|
|
60
|
+
|
|
61
|
+
let { initialRouteName, screenOptions, children }: IStackProps = $props();
|
|
62
|
+
|
|
63
|
+
// Read BEFORE this Stack establishes its own per-screen NavigationScope - becomes the `parent`
|
|
64
|
+
// link a nested screen's useNavigation().getParent() walks (e.g. this Stack rendered as a Tab
|
|
65
|
+
// screen's content reaches that Tab via this value). undefined when this Stack is the nesting
|
|
66
|
+
// root. Kept as the BOX, not its unwrapped value, so every read below sees the current one.
|
|
67
|
+
const parentScope = getNavigationScope();
|
|
68
|
+
|
|
69
|
+
const routeIdPrefix = `stack-${(stackInstanceCounter += 1)}`;
|
|
70
|
+
|
|
71
|
+
// `$state.raw` + reassignment, never a mutated array: an entry holds a component reference (a
|
|
72
|
+
// plain function) behind live getters, and a deep reactive proxy would wrap both.
|
|
73
|
+
let screens = $state.raw<IRegisteredScreen<IScreenProps['options']>[]>([]);
|
|
74
|
+
setScreenCollector<IScreenProps['options']>({
|
|
75
|
+
kind: 'stack',
|
|
76
|
+
register: screen => {
|
|
77
|
+
screens = [...screens, screen];
|
|
78
|
+
},
|
|
79
|
+
unregister: screen => {
|
|
80
|
+
screens = withoutScreen(screens, screen);
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const registry = $derived(toRegistry(screens));
|
|
85
|
+
|
|
86
|
+
let routeSequence = 0;
|
|
87
|
+
function createRoute(name: string, params: unknown): IRoute<unknown> {
|
|
88
|
+
routeSequence += 1;
|
|
89
|
+
return { key: `${routeIdPrefix}-${name}-${routeSequence}`, name, params };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The pushed stack only exists once something has dispatched; until then the state derives from
|
|
93
|
+
// whatever the markers registered. `seededState` is a PLAIN local (not `$state`), so memoizing
|
|
94
|
+
// it inside the derivation below is not a state write during a derivation - it just makes the
|
|
95
|
+
// one route-key-allocating call happen exactly once, no matter how often the derivation re-runs
|
|
96
|
+
// as markers register.
|
|
97
|
+
let pushedState = $state.raw<INavigatorState | null>(null);
|
|
98
|
+
let seededState: INavigatorState | undefined;
|
|
99
|
+
|
|
100
|
+
function seedState(): INavigatorState {
|
|
101
|
+
if (seededState !== undefined) return seededState;
|
|
102
|
+
const startRouteName = initialRouteName ?? registry.keys().next().value;
|
|
103
|
+
if (startRouteName === undefined) {
|
|
104
|
+
dlog('Stack: no <Stack.Screen> children registered');
|
|
105
|
+
// Deliberately NOT memoized: markers may still be registering, and the next derivation run
|
|
106
|
+
// should get a real initial route rather than being stuck on this placeholder.
|
|
107
|
+
return createInitialNavigatorState({
|
|
108
|
+
key: routeIdPrefix,
|
|
109
|
+
name: '',
|
|
110
|
+
params: undefined,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
seededState = createInitialNavigatorState(
|
|
114
|
+
createRoute(startRouteName, registry.get(startRouteName)?.initialParams),
|
|
115
|
+
);
|
|
116
|
+
return seededState;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// A `<Stack.Screen>` marker can unregister while its route is still in the pushed history (a
|
|
120
|
+
// marker behind an `{#if}`, a data-driven screen list), which would leave that entry with nothing
|
|
121
|
+
// for componentFor() to mount (reconcileStackRoutes' header). The reconciliation belongs in the
|
|
122
|
+
// derivation because it is PURE - it hands back the same state reference when nothing changed, so
|
|
123
|
+
// it writes no state and cannot re-trigger itself; `dispatch` below then persists the pruned
|
|
124
|
+
// history, since it reduces over this value rather than over `pushedState`.
|
|
125
|
+
const state = $derived(
|
|
126
|
+
reconcileStackRoutes(pushedState ?? seedState(), [...registry.keys()]),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
function dispatch(action: INavigatorAction): void {
|
|
130
|
+
pushedState = navigatorReducer(state, action);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// One emitter per route.key, created lazily the first time a route is rendered and pruned once
|
|
134
|
+
// it is popped off the stack (the broadcast effect below).
|
|
135
|
+
const emitters = new Map<string, INavigationEmitter>();
|
|
136
|
+
function emitterFor(routeKey: string): INavigationEmitter {
|
|
137
|
+
let emitter = emitters.get(routeKey);
|
|
138
|
+
if (emitter === undefined) {
|
|
139
|
+
emitter = createNavigationEmitter();
|
|
140
|
+
emitters.set(routeKey, emitter);
|
|
141
|
+
}
|
|
142
|
+
return emitter;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function push(name: string, params?: unknown): void {
|
|
146
|
+
dispatch({ type: 'push', route: createRoute(name, params) });
|
|
147
|
+
}
|
|
148
|
+
export function pop(count?: number): void {
|
|
149
|
+
dispatch({ type: 'pop', count });
|
|
150
|
+
}
|
|
151
|
+
export function popToTop(): void {
|
|
152
|
+
dispatch({ type: 'popToTop' });
|
|
153
|
+
}
|
|
154
|
+
export function popTo(key: string): void {
|
|
155
|
+
dispatch({ type: 'popTo', key });
|
|
156
|
+
}
|
|
157
|
+
export function replace(name: string, params?: unknown): void {
|
|
158
|
+
dispatch({ type: 'replace', route: createRoute(name, params) });
|
|
159
|
+
}
|
|
160
|
+
export function setParams(params: unknown, key?: string): void {
|
|
161
|
+
dispatch({ type: 'setParams', key, params });
|
|
162
|
+
}
|
|
163
|
+
export function reset(nextState: INavigatorState): void {
|
|
164
|
+
dispatch({ type: 'reset', state: nextState });
|
|
165
|
+
}
|
|
166
|
+
export function canGoBack(): boolean {
|
|
167
|
+
return state.routes.length > 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// The same handle, as a value, for everything that needs it INSIDE this component (the options
|
|
171
|
+
// fold's `navigation` argument, every route's NavigationScope). `bind:this` exposes the
|
|
172
|
+
// `export function`s above; this object is the internal twin of that surface.
|
|
173
|
+
const handle: INavigatorHandle = {
|
|
174
|
+
push,
|
|
175
|
+
pop,
|
|
176
|
+
popToTop,
|
|
177
|
+
popTo,
|
|
178
|
+
replace,
|
|
179
|
+
setParams,
|
|
180
|
+
reset,
|
|
181
|
+
canGoBack,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
function popOne(): void {
|
|
185
|
+
dispatch({ type: 'pop', count: 1 });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Broadcasts the router state to every still-live route's emitter (useNavigationState's source)
|
|
189
|
+
// after each commit, and prunes emitters for routes popped off the stack. Runs as an $effect
|
|
190
|
+
// rather than inline in the render path (Vue's shape), so the first broadcast lands AFTER the
|
|
191
|
+
// initial route's own screen has mounted and subscribed.
|
|
192
|
+
$effect(() => {
|
|
193
|
+
const current = state;
|
|
194
|
+
for (const route of current.routes) {
|
|
195
|
+
emitterFor(route.key).emit(NAVIGATION_EVENT_STATE, current);
|
|
196
|
+
}
|
|
197
|
+
for (const routeKey of [...emitters.keys()]) {
|
|
198
|
+
if (!current.routes.some(route => route.key === routeKey))
|
|
199
|
+
emitters.delete(routeKey);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Investigation instrumentation (flicker-on-focus bug): STACK_ON_FINISH_TRANSITIONING is the
|
|
204
|
+
// native signal that the WHOLE push/pop animation has finished (as opposed to onAppear/
|
|
205
|
+
// onDisappear, which are per-screen) - logging it lets the per-screen appear/disappear
|
|
206
|
+
// timestamps be checked against the actual transition-complete moment. Kept behind DEBUG,
|
|
207
|
+
// never removed.
|
|
208
|
+
const stackProps = resolveStackProps({
|
|
209
|
+
passthrough: {
|
|
210
|
+
[STACK_ON_FINISH_TRANSITIONING]: () =>
|
|
211
|
+
dlog(`Stack: onFinishTransitioning at t=${Date.now()}`),
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
function optionsFor(route: IRoute<unknown>): ISvelteScreenOptions {
|
|
216
|
+
const entry = registry.get(route.name);
|
|
217
|
+
const own =
|
|
218
|
+
entry === undefined
|
|
219
|
+
? undefined
|
|
220
|
+
: typeof entry.options === 'function'
|
|
221
|
+
? entry.options({ route, navigation: handle })
|
|
222
|
+
: entry.options;
|
|
223
|
+
return { ...screenOptions, ...own };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function componentFor(route: IRoute<unknown>): Component | undefined {
|
|
227
|
+
const entry = registry.get(route.name);
|
|
228
|
+
if (entry === undefined) {
|
|
229
|
+
dlog(`Stack: no screen registered for route name "${route.name}"`);
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
return entry.component;
|
|
233
|
+
}
|
|
234
|
+
</script>
|
|
235
|
+
|
|
236
|
+
<symbiote-view p={STACK_ROOT_PROPS}>
|
|
237
|
+
<symbiote-text p={SCREEN_REGISTRY_HOST_PROPS}>
|
|
238
|
+
{@render children?.()}
|
|
239
|
+
</symbiote-text>
|
|
240
|
+
<svelte:element
|
|
241
|
+
this={RNS_SCREEN_STACK_VIEW_NAME}
|
|
242
|
+
{@attach hostProps(stackProps)}
|
|
243
|
+
>
|
|
244
|
+
{#each state.routes as route, index (route.key)}
|
|
245
|
+
{@const screenComponent = componentFor(route)}
|
|
246
|
+
{#if screenComponent !== undefined}
|
|
247
|
+
<StackScreen
|
|
248
|
+
{route}
|
|
249
|
+
{index}
|
|
250
|
+
routeCount={state.routes.length}
|
|
251
|
+
options={optionsFor(route)}
|
|
252
|
+
navigation={handle}
|
|
253
|
+
emitter={emitterFor(route.key)}
|
|
254
|
+
parentScope={parentScope?.current}
|
|
255
|
+
component={screenComponent}
|
|
256
|
+
onPopRequested={popOne}
|
|
257
|
+
/>
|
|
258
|
+
{/if}
|
|
259
|
+
{/each}
|
|
260
|
+
</svelte:element>
|
|
261
|
+
</symbiote-view>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// `Stack.Screen` alongside the standalone `Screen` export, matching React's and Vue's barrels.
|
|
2
|
+
// A compiled Svelte component is an ordinary function object, so attaching the marker to it is
|
|
3
|
+
// the same Object.assign the other entries do - and `<Stack.Screen />` resolves through Svelte's
|
|
4
|
+
// member-expression component tags (verified against the real compiler).
|
|
5
|
+
import StackImpl from './index.svelte';
|
|
6
|
+
import Screen from '../screen.svelte';
|
|
7
|
+
|
|
8
|
+
export const Stack = Object.assign(StackImpl, { Screen });
|
|
9
|
+
|
|
10
|
+
export type { INavigatorHandle } from '../../core';
|
|
11
|
+
export type { IStackProps } from './stack-props';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Stack's own public prop surface, and the internal per-route prop surface stack-screen.svelte
|
|
2
|
+
// takes. Both live in a plain `.ts` file for the tsc-cannot-see-a-`.svelte`-named-export reason
|
|
3
|
+
// ../screen-props.ts documents.
|
|
4
|
+
|
|
5
|
+
import type { Component, Snippet } from 'svelte';
|
|
6
|
+
import type { INavigationEmitter, INavigatorHandle, IRoute } from '../../core';
|
|
7
|
+
import type { INavigationScopeValue } from '../navigation-context';
|
|
8
|
+
import type { ISvelteScreenOptions } from '../screen-props';
|
|
9
|
+
|
|
10
|
+
// React's `children?: ReactNode` / Vue's default slot become a Svelte Snippet holding the
|
|
11
|
+
// `<Stack.Screen>` markers.
|
|
12
|
+
export type IStackProps = {
|
|
13
|
+
initialRouteName?: string;
|
|
14
|
+
screenOptions?: ISvelteScreenOptions;
|
|
15
|
+
children?: Snippet;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type IStackScreenProps = {
|
|
19
|
+
route: IRoute<unknown>;
|
|
20
|
+
index: number;
|
|
21
|
+
routeCount: number;
|
|
22
|
+
options: ISvelteScreenOptions;
|
|
23
|
+
navigation: INavigatorHandle;
|
|
24
|
+
emitter: INavigationEmitter;
|
|
25
|
+
// The ambient scope the Stack itself read on mount (undefined at the nesting root) - becomes
|
|
26
|
+
// the `parent` link a nested screen's useNavigation().getParent() walks.
|
|
27
|
+
parentScope: INavigationScopeValue | undefined;
|
|
28
|
+
component: Component;
|
|
29
|
+
// Fired by RNSScreen's own onDismissed / header back button; the Stack pops one route.
|
|
30
|
+
onPopRequested: () => void;
|
|
31
|
+
};
|