@symbiote-native/navigation 2.1.0 → 3.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/README.md +89 -14
- package/build/angular/drawer/index.js +23 -9
- package/build/angular/index.d.ts +4 -4
- package/build/angular/index.js +1 -1
- 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.js +20 -6
- package/build/angular/tabs/index.js +21 -7
- 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 +4 -4
- package/build/core/index.js +2 -2
- 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/state-persistence/index.js +6 -2
- package/build/core/tab-router-state/index.js +8 -2
- package/build/react/drawer/index.js +36 -13
- package/build/react/index.d.ts +7 -7
- package/build/react/index.js +3 -3
- package/build/react/stack/index.js +34 -8
- package/build/react/tabs/index.js +14 -4
- 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/descriptor-subtree.js +3 -1
- package/build/svelte/drawer/index.svelte +163 -25
- package/build/svelte/drawer-screen.svelte +2 -1
- package/build/svelte/index.d.ts +3 -3
- package/build/svelte/index.js +1 -1
- package/build/svelte/navigation-scope.svelte +4 -1
- package/build/svelte/runes/use-navigation.svelte.js +5 -1
- package/build/svelte/stack/index.svelte +43 -6
- package/build/svelte/stack/stack-screen.svelte +66 -9
- package/build/svelte/tabs/index.svelte +42 -20
- package/build/vue/composables/use-navigation.js +5 -1
- package/build/vue/drawer/index.js +30 -8
- package/build/vue/index.d.ts +3 -3
- package/build/vue/index.js +1 -1
- package/build/vue/navigation-context.js +1 -1
- package/build/vue/stack/index.js +17 -6
- package/build/vue/tabs/index.js +18 -5
- package/build-ngc/angular/drawer/index.js +31 -11
- package/build-ngc/angular/drawer/index.js.map +1 -1
- 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.map +1 -1
- package/build-ngc/angular/navigation-scope.directive.js +1 -1
- package/build-ngc/angular/navigation-scope.directive.js.map +1 -1
- package/build-ngc/angular/screen.directive.js.map +1 -1
- package/build-ngc/angular/search-bar-ref.directive.js +1 -1
- package/build-ngc/angular/search-bar-ref.directive.js.map +1 -1
- package/build-ngc/angular/stack/index.js +26 -8
- package/build-ngc/angular/stack/index.js.map +1 -1
- package/build-ngc/angular/tab-screen.directive.js.map +1 -1
- package/build-ngc/angular/tabs/index.js +21 -7
- 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 +4 -4
- package/build-ngc/core/index.js +2 -2
- 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.js.map +1 -1
- 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.js +8 -2
- package/build-ngc/core/tab-router-state/index.js.map +1 -1
- package/package.json +40 -15
- package/src/angular/drawer/index.ts +69 -25
- 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 +68 -22
- package/src/angular/tab-screen.directive.ts +3 -1
- package/src/angular/tabs/index.ts +36 -12
- 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 +18 -4
- 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 +5 -2
- package/src/core/state-persistence/index.ts +13 -3
- package/src/core/tab-router-state/index.ts +10 -3
- package/src/react/drawer/index.ts +408 -344
- 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 +294 -231
- package/src/react/tab-screen.ts +3 -1
- package/src/react/tabs/index.ts +188 -158
- 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 +3 -1
- package/src/svelte/descriptor-subtree.ts +3 -1
- package/src/svelte/drawer/index.svelte +163 -25
- package/src/svelte/drawer-screen-props.ts +8 -2
- package/src/svelte/drawer-screen.svelte +2 -1
- package/src/svelte/fabric-tree.test-helper.ts +37 -3
- package/src/svelte/index.ts +15 -3
- package/src/svelte/linking.svelte.ts +11 -5
- package/src/svelte/navigation-scope.svelte +4 -1
- package/src/svelte/runes/use-drawer-navigation.svelte.ts +3 -1
- package/src/svelte/runes/use-focus-effect.svelte.ts +8 -2
- package/src/svelte/runes/use-navigation-state.svelte.ts +3 -1
- package/src/svelte/runes/use-navigation.svelte.ts +13 -3
- package/src/svelte/runes/use-stack-navigation.svelte.ts +3 -1
- package/src/svelte/screen-props.ts +7 -2
- package/src/svelte/screen-registry.ts +9 -3
- package/src/svelte/stack/index.svelte +43 -6
- package/src/svelte/stack/stack-screen.svelte +66 -9
- package/src/svelte/svelte-compile.test-helper.ts +16 -12
- package/src/svelte/tab-screen-props.ts +3 -1
- package/src/svelte/tabs/index.svelte +42 -20
- 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 +122 -36
- 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 +82 -34
- package/src/vue/tab-screen.ts +3 -1
- package/src/vue/tabs/index.ts +51 -13
|
@@ -26,10 +26,13 @@ export function useNavigationState<TResult>(
|
|
|
26
26
|
let unsubscribe: (() => void) | undefined;
|
|
27
27
|
|
|
28
28
|
onMounted(() => {
|
|
29
|
-
unsubscribe = scope.value.emitter.addListener(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
unsubscribe = scope.value.emitter.addListener(
|
|
30
|
+
NAVIGATION_EVENT_STATE,
|
|
31
|
+
(state: unknown) => {
|
|
32
|
+
if (!isNavigatorState(state)) return;
|
|
33
|
+
result.value = selector(state);
|
|
34
|
+
},
|
|
35
|
+
);
|
|
33
36
|
});
|
|
34
37
|
|
|
35
38
|
onUnmounted(() => unsubscribe?.());
|
|
@@ -5,12 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
import { computed } from '@vue/runtime-core';
|
|
7
7
|
import type { ComputedRef } from '@vue/runtime-core';
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
INavigationEventListener,
|
|
10
|
+
INavigationEventName,
|
|
11
|
+
} from '../../core';
|
|
9
12
|
import { requireNavigationScope } from '../navigation-context';
|
|
10
13
|
import type { IAnyNavigatorHandle } from '../navigation-context';
|
|
11
14
|
|
|
12
15
|
export type INavigationHandle = IAnyNavigatorHandle & {
|
|
13
|
-
addListener: (
|
|
16
|
+
addListener: (
|
|
17
|
+
event: INavigationEventName,
|
|
18
|
+
listener: INavigationEventListener,
|
|
19
|
+
) => () => void;
|
|
14
20
|
// Walks exactly ONE hop up the scope's `parent` chain to the enclosing navigator's handle -
|
|
15
21
|
// e.g. a Tab screen nested inside a Stack screen calling getParent() to push a new Stack route.
|
|
16
22
|
// Callers narrow the union themselves ('push' in parent, etc.). Deliberately NOT
|
|
@@ -25,6 +31,10 @@ export function useNavigation(): ComputedRef<INavigationHandle> {
|
|
|
25
31
|
const scope = requireNavigationScope('useNavigation');
|
|
26
32
|
return computed(() => {
|
|
27
33
|
const { navigation, emitter, parent } = scope.value;
|
|
28
|
-
return {
|
|
34
|
+
return {
|
|
35
|
+
...navigation,
|
|
36
|
+
addListener: emitter.addListener,
|
|
37
|
+
getParent: () => parent?.navigation,
|
|
38
|
+
};
|
|
29
39
|
});
|
|
30
40
|
}
|
package/src/vue/drawer/index.ts
CHANGED
|
@@ -35,7 +35,10 @@ import {
|
|
|
35
35
|
normalizeVueAttrs,
|
|
36
36
|
useWindowDimensions,
|
|
37
37
|
} from '@symbiote-native/vue';
|
|
38
|
-
import type {
|
|
38
|
+
import type {
|
|
39
|
+
IPanResponderGestureState,
|
|
40
|
+
ISymbioteEvent,
|
|
41
|
+
} from '@symbiote-native/vue';
|
|
39
42
|
import type { IDescriptor } from '@symbiote-native/components';
|
|
40
43
|
import { dlog } from '@symbiote-native/engine';
|
|
41
44
|
import type { IStyleProp, IViewStyle } from '@symbiote-native/engine';
|
|
@@ -71,7 +74,10 @@ import type {
|
|
|
71
74
|
} from '../../core';
|
|
72
75
|
import { NavigationScope, injectNavigationScope } from '../navigation-context';
|
|
73
76
|
import { DrawerScreen } from '../drawer-screen';
|
|
74
|
-
import type {
|
|
77
|
+
import type {
|
|
78
|
+
IDrawerScreenOptionsArgs,
|
|
79
|
+
IDrawerScreenProps,
|
|
80
|
+
} from '../drawer-screen';
|
|
75
81
|
|
|
76
82
|
export type { IDrawerNavigatorHandle, IDrawerDescriptorMap } from '../../core';
|
|
77
83
|
|
|
@@ -113,7 +119,12 @@ function isStyleProp(value: unknown): value is IStyleProp<IViewStyle> {
|
|
|
113
119
|
return isRecord(value);
|
|
114
120
|
}
|
|
115
121
|
|
|
116
|
-
const DRAWER_TYPES: ReadonlyArray<IDrawerType> = [
|
|
122
|
+
const DRAWER_TYPES: ReadonlyArray<IDrawerType> = [
|
|
123
|
+
'front',
|
|
124
|
+
'back',
|
|
125
|
+
'slide',
|
|
126
|
+
'permanent',
|
|
127
|
+
];
|
|
117
128
|
// .some() itself doesn't narrow `value`'s type back at the call site - the `value is IDrawerType`
|
|
118
129
|
// predicate on THIS function is what lets asDrawerType's ternary return `value` typed, mirroring
|
|
119
130
|
// Modal's isOrientation guard (adapters/vue/src/components/modal.ts).
|
|
@@ -126,30 +137,45 @@ function asDrawerType(value: unknown): IDrawerType | undefined {
|
|
|
126
137
|
|
|
127
138
|
const DRAWER_POSITIONS: ReadonlyArray<IDrawerPosition> = ['left', 'right'];
|
|
128
139
|
function isDrawerPosition(value: unknown): value is IDrawerPosition {
|
|
129
|
-
return
|
|
140
|
+
return (
|
|
141
|
+
typeof value === 'string' &&
|
|
142
|
+
DRAWER_POSITIONS.some(position => position === value)
|
|
143
|
+
);
|
|
130
144
|
}
|
|
131
145
|
function asDrawerPosition(value: unknown): IDrawerPosition | undefined {
|
|
132
146
|
return isDrawerPosition(value) ? value : undefined;
|
|
133
147
|
}
|
|
134
148
|
|
|
135
|
-
function asComponent(
|
|
136
|
-
|
|
137
|
-
|
|
149
|
+
function asComponent(
|
|
150
|
+
value: unknown,
|
|
151
|
+
): IDrawerScreenProps['component'] | undefined {
|
|
152
|
+
if (typeof value === 'function')
|
|
153
|
+
return value as IDrawerScreenProps['component'];
|
|
154
|
+
return isRecord(value)
|
|
155
|
+
? (value as IDrawerScreenProps['component'])
|
|
156
|
+
: undefined;
|
|
138
157
|
}
|
|
139
158
|
|
|
140
159
|
// IDrawerScreenOptions carries only `title`/`drawerLabel`, small enough for direct field guards -
|
|
141
160
|
// kept as a single cast-at-the-edge helper anyway for symmetry with stack.ts/tabs.ts's
|
|
142
161
|
// asScreenOptions/asTabOptions (same CLAUDE.md-sanctioned I/O-edge narrowing).
|
|
143
|
-
function asDrawerScreenOptions(
|
|
162
|
+
function asDrawerScreenOptions(
|
|
163
|
+
value: unknown,
|
|
164
|
+
): IDrawerScreenOptions | undefined {
|
|
144
165
|
return isRecord(value) ? (value as IDrawerScreenOptions) : undefined;
|
|
145
166
|
}
|
|
146
167
|
|
|
147
|
-
function asDrawerScreenOptionsOrResolver(
|
|
148
|
-
|
|
168
|
+
function asDrawerScreenOptionsOrResolver(
|
|
169
|
+
value: unknown,
|
|
170
|
+
): IDrawerScreenProps['options'] {
|
|
171
|
+
if (typeof value === 'function')
|
|
172
|
+
return value as IDrawerScreenProps['options'];
|
|
149
173
|
return asDrawerScreenOptions(value);
|
|
150
174
|
}
|
|
151
175
|
|
|
152
|
-
function collectRegistry(
|
|
176
|
+
function collectRegistry(
|
|
177
|
+
vnodes: readonly VNode[],
|
|
178
|
+
): Map<string, IDrawerRegistryEntry> {
|
|
153
179
|
const registry = new Map<string, IDrawerRegistryEntry>();
|
|
154
180
|
for (const vnode of vnodes) {
|
|
155
181
|
if (vnode.type !== DrawerScreen || !isRecord(vnode.props)) continue;
|
|
@@ -169,7 +195,8 @@ function resolveDrawerScreenOptions(
|
|
|
169
195
|
entry: IDrawerRegistryEntry,
|
|
170
196
|
screenComponentProps: IDrawerScreenOptionsArgs,
|
|
171
197
|
): IDrawerScreenOptions {
|
|
172
|
-
if (typeof entry.options === 'function')
|
|
198
|
+
if (typeof entry.options === 'function')
|
|
199
|
+
return entry.options(screenComponentProps);
|
|
173
200
|
return entry.options ?? {};
|
|
174
201
|
}
|
|
175
202
|
|
|
@@ -200,7 +227,9 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
200
227
|
let routeSequence = 0;
|
|
201
228
|
const routeIdPrefix = useId();
|
|
202
229
|
|
|
203
|
-
function buildRoutes(
|
|
230
|
+
function buildRoutes(
|
|
231
|
+
registry: Map<string, IDrawerRegistryEntry>,
|
|
232
|
+
): IRoute<unknown>[] {
|
|
204
233
|
return Array.from(registry.entries()).map(([name, entry]) => {
|
|
205
234
|
routeSequence += 1;
|
|
206
235
|
return {
|
|
@@ -213,10 +242,14 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
213
242
|
|
|
214
243
|
const initialRegistry = collectRegistry(slots.default?.() ?? []);
|
|
215
244
|
const initialRoutes = buildRoutes(initialRegistry);
|
|
216
|
-
if (initialRoutes.length === 0)
|
|
245
|
+
if (initialRoutes.length === 0)
|
|
246
|
+
dlog('Drawer: no <Drawer.Screen> children registered');
|
|
217
247
|
|
|
218
248
|
const state = shallowRef(
|
|
219
|
-
createInitialDrawerRouterState(
|
|
249
|
+
createInitialDrawerRouterState(
|
|
250
|
+
initialRoutes,
|
|
251
|
+
asString(attrs.initialRouteName),
|
|
252
|
+
),
|
|
220
253
|
);
|
|
221
254
|
|
|
222
255
|
function dispatch(action: Parameters<typeof drawerRouterReducer>[1]): void {
|
|
@@ -235,7 +268,9 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
235
268
|
let dragStartProgress = 0;
|
|
236
269
|
|
|
237
270
|
function animateProgressTo(open: boolean): void {
|
|
238
|
-
dlog(
|
|
271
|
+
dlog(
|
|
272
|
+
`Drawer: animateProgressTo(open=${open}) starting at t=${Date.now()}`,
|
|
273
|
+
);
|
|
239
274
|
Animated.timing(progress, {
|
|
240
275
|
toValue: open ? 1 : 0,
|
|
241
276
|
duration: DRAWER_SNAP_DURATION,
|
|
@@ -248,17 +283,23 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
248
283
|
|
|
249
284
|
const handle: IDrawerNavigatorHandle = {
|
|
250
285
|
openDrawer: () => {
|
|
251
|
-
dlog(
|
|
286
|
+
dlog(
|
|
287
|
+
`Drawer: openDrawer() called, isOpen=${state.value.isOpen} at t=${Date.now()}`,
|
|
288
|
+
);
|
|
252
289
|
animateProgressTo(true);
|
|
253
290
|
dispatch({ type: 'openDrawer' });
|
|
254
291
|
},
|
|
255
292
|
closeDrawer: () => {
|
|
256
|
-
dlog(
|
|
293
|
+
dlog(
|
|
294
|
+
`Drawer: closeDrawer() called, isOpen=${state.value.isOpen} at t=${Date.now()}`,
|
|
295
|
+
);
|
|
257
296
|
animateProgressTo(false);
|
|
258
297
|
dispatch({ type: 'closeDrawer' });
|
|
259
298
|
},
|
|
260
299
|
toggleDrawer: () => {
|
|
261
|
-
dlog(
|
|
300
|
+
dlog(
|
|
301
|
+
`Drawer: toggleDrawer() called, isOpen=${state.value.isOpen} at t=${Date.now()}`,
|
|
302
|
+
);
|
|
262
303
|
animateProgressTo(!state.value.isOpen);
|
|
263
304
|
dispatch({ type: 'toggleDrawer' });
|
|
264
305
|
},
|
|
@@ -308,13 +349,23 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
308
349
|
_event: ISymbioteEvent,
|
|
309
350
|
gestureState: IPanResponderGestureState,
|
|
310
351
|
): void => {
|
|
311
|
-
progress.setValue(
|
|
352
|
+
progress.setValue(
|
|
353
|
+
resolveDragProgress(
|
|
354
|
+
gestureState,
|
|
355
|
+
dragStartProgress,
|
|
356
|
+
currentOptions(),
|
|
357
|
+
),
|
|
358
|
+
);
|
|
312
359
|
},
|
|
313
360
|
onPanResponderRelease: (
|
|
314
361
|
_event: ISymbioteEvent,
|
|
315
362
|
gestureState: IPanResponderGestureState,
|
|
316
363
|
): void => {
|
|
317
|
-
const intent = resolveSwipeIntent(
|
|
364
|
+
const intent = resolveSwipeIntent(
|
|
365
|
+
gestureState,
|
|
366
|
+
state.value.isOpen,
|
|
367
|
+
currentOptions(),
|
|
368
|
+
);
|
|
318
369
|
const open = intent === 'open';
|
|
319
370
|
dlog(`Drawer: gesture release -> ${open ? 'open' : 'close'}`);
|
|
320
371
|
animateProgressTo(open);
|
|
@@ -367,7 +418,10 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
367
418
|
watch(
|
|
368
419
|
() => focusedKeyOf(state.value),
|
|
369
420
|
nextKey => {
|
|
370
|
-
const { blurKey, focusKey } = diffFocusedRoute(
|
|
421
|
+
const { blurKey, focusKey } = diffFocusedRoute(
|
|
422
|
+
focusedRouteKey,
|
|
423
|
+
nextKey,
|
|
424
|
+
);
|
|
371
425
|
if (blurKey === undefined && focusKey === undefined) return;
|
|
372
426
|
focusedRouteKey = nextKey;
|
|
373
427
|
nextTick(() => {
|
|
@@ -383,24 +437,32 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
383
437
|
},
|
|
384
438
|
);
|
|
385
439
|
onUnmounted(() => {
|
|
386
|
-
if (focusedRouteKey !== undefined)
|
|
440
|
+
if (focusedRouteKey !== undefined)
|
|
441
|
+
emitterFor(focusedRouteKey).emit(NAVIGATION_EVENT_BLUR);
|
|
387
442
|
});
|
|
388
443
|
|
|
389
444
|
return () => {
|
|
390
445
|
const registry = collectRegistry(slots.default?.() ?? []);
|
|
391
446
|
const options = currentOptions();
|
|
392
|
-
const drawerStyle = isStyleProp(attrs.drawerStyle)
|
|
447
|
+
const drawerStyle = isStyleProp(attrs.drawerStyle)
|
|
448
|
+
? attrs.drawerStyle
|
|
449
|
+
: undefined;
|
|
393
450
|
|
|
394
|
-
if (registry.size === 0)
|
|
451
|
+
if (registry.size === 0)
|
|
452
|
+
dlog('Drawer: no <Drawer.Screen> children registered');
|
|
395
453
|
|
|
396
454
|
const animated = isDrawerAnimated(options);
|
|
397
455
|
const geometry = resolveDrawerGeometry(options);
|
|
398
456
|
|
|
399
457
|
const panelTranslateX = animated
|
|
400
|
-
? progress.interpolate(
|
|
458
|
+
? progress.interpolate(
|
|
459
|
+
resolveDrawerSlotInterpolation(geometry, 'panel').translateX,
|
|
460
|
+
)
|
|
401
461
|
: undefined;
|
|
402
462
|
const contentTranslateX = animated
|
|
403
|
-
? progress.interpolate(
|
|
463
|
+
? progress.interpolate(
|
|
464
|
+
resolveDrawerSlotInterpolation(geometry, 'content').translateX,
|
|
465
|
+
)
|
|
404
466
|
: undefined;
|
|
405
467
|
// The overlay is a full-screen absolutely-positioned sibling BELOW content in paint order
|
|
406
468
|
// (see render-drawer.ts's drawerChildOrder) - for 'front' that's fine since content never
|
|
@@ -419,9 +481,13 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
419
481
|
: undefined;
|
|
420
482
|
|
|
421
483
|
const focusedRoute = state.value.routes[state.value.index];
|
|
422
|
-
const focusedEntry = focusedRoute
|
|
484
|
+
const focusedEntry = focusedRoute
|
|
485
|
+
? registry.get(focusedRoute.name)
|
|
486
|
+
: undefined;
|
|
423
487
|
if (focusedRoute && !focusedEntry) {
|
|
424
|
-
dlog(
|
|
488
|
+
dlog(
|
|
489
|
+
`Drawer: no screen registered for route name "${focusedRoute.name}"`,
|
|
490
|
+
);
|
|
425
491
|
}
|
|
426
492
|
|
|
427
493
|
const content =
|
|
@@ -447,17 +513,25 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
447
513
|
const entry = registry.get(route.name);
|
|
448
514
|
if (entry === undefined) continue;
|
|
449
515
|
descriptors[route.key] = {
|
|
450
|
-
options: resolveDrawerScreenOptions(entry, {
|
|
516
|
+
options: resolveDrawerScreenOptions(entry, {
|
|
517
|
+
route,
|
|
518
|
+
navigation: handle,
|
|
519
|
+
}),
|
|
451
520
|
navigation: handle,
|
|
452
521
|
};
|
|
453
522
|
}
|
|
454
523
|
|
|
455
524
|
const drawerContent =
|
|
456
|
-
slots.drawerContent?.({
|
|
525
|
+
slots.drawerContent?.({
|
|
526
|
+
state: state.value,
|
|
527
|
+
descriptors,
|
|
528
|
+
navigation: handle,
|
|
529
|
+
}) ?? null;
|
|
457
530
|
|
|
458
531
|
const root = renderDrawer(
|
|
459
532
|
{
|
|
460
|
-
overlayColor:
|
|
533
|
+
overlayColor:
|
|
534
|
+
asString(attrs.overlayColor) ?? DRAWER_DEFAULT_OVERLAY_COLOR,
|
|
461
535
|
drawerStyle,
|
|
462
536
|
contentPassthrough: {},
|
|
463
537
|
overlayPassthrough: animated
|
|
@@ -479,7 +553,8 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
479
553
|
const slotDescriptors = new Map<IDrawerSlot, IDescriptor>();
|
|
480
554
|
order.forEach((slot, index) => {
|
|
481
555
|
const descriptor = root.children[index];
|
|
482
|
-
if (typeof descriptor !== 'string')
|
|
556
|
+
if (typeof descriptor !== 'string')
|
|
557
|
+
slotDescriptors.set(slot, descriptor);
|
|
483
558
|
});
|
|
484
559
|
|
|
485
560
|
const slotChildren: Record<IDrawerSlot, VNode[] | null> = {
|
|
@@ -498,7 +573,10 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
498
573
|
overlay:
|
|
499
574
|
overlayOpacity === undefined
|
|
500
575
|
? undefined
|
|
501
|
-
: {
|
|
576
|
+
: {
|
|
577
|
+
opacity: overlayOpacity,
|
|
578
|
+
transform: [{ translateX: overlayTranslateX }],
|
|
579
|
+
},
|
|
502
580
|
panel:
|
|
503
581
|
panelTranslateX === undefined
|
|
504
582
|
? undefined
|
|
@@ -511,10 +589,18 @@ const DrawerImpl = defineComponent<IDrawerProps>(
|
|
|
511
589
|
const children = slotChildren[slot] ?? [];
|
|
512
590
|
const animatedStyle = slotAnimatedStyle[slot];
|
|
513
591
|
if (animatedStyle === undefined) {
|
|
514
|
-
return h(
|
|
592
|
+
return h(
|
|
593
|
+
descriptor.type,
|
|
594
|
+
{ key: descriptor.key, ...descriptor.props },
|
|
595
|
+
children,
|
|
596
|
+
);
|
|
515
597
|
}
|
|
516
598
|
const style = [descriptor.props.style, animatedStyle];
|
|
517
|
-
return h(
|
|
599
|
+
return h(
|
|
600
|
+
Animated.View,
|
|
601
|
+
{ key: descriptor.key, ...descriptor.props, style },
|
|
602
|
+
children,
|
|
603
|
+
);
|
|
518
604
|
}
|
|
519
605
|
|
|
520
606
|
const drawerChildren = order
|
package/src/vue/drawer-screen.ts
CHANGED
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
import { defineComponent } from '@vue/runtime-core';
|
|
10
10
|
import type { Component } from '@vue/runtime-core';
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
IDrawerScreenOptions,
|
|
13
|
+
IRoute,
|
|
14
|
+
IDrawerNavigatorHandle,
|
|
15
|
+
} from '../core';
|
|
12
16
|
|
|
13
17
|
export type IDrawerScreenOptionsArgs = {
|
|
14
18
|
route: IRoute<unknown>;
|
|
@@ -26,7 +30,10 @@ export type IDrawerScreenProps = {
|
|
|
26
30
|
initialParams?: unknown;
|
|
27
31
|
};
|
|
28
32
|
|
|
29
|
-
export const DrawerScreen = defineComponent<IDrawerScreenProps>(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
export const DrawerScreen = defineComponent<IDrawerScreenProps>(
|
|
34
|
+
() => () => null,
|
|
35
|
+
{
|
|
36
|
+
name: 'DrawerScreen',
|
|
37
|
+
inheritAttrs: false,
|
|
38
|
+
},
|
|
39
|
+
);
|
package/src/vue/index.ts
CHANGED
|
@@ -15,7 +15,11 @@ export type {
|
|
|
15
15
|
IVueScreenOptions,
|
|
16
16
|
IVueSearchBarOptions,
|
|
17
17
|
} from './screen';
|
|
18
|
-
export type {
|
|
18
|
+
export type {
|
|
19
|
+
IScreenOptions,
|
|
20
|
+
IStackAnimation,
|
|
21
|
+
IStackPresentation,
|
|
22
|
+
} from '../core';
|
|
19
23
|
|
|
20
24
|
export {
|
|
21
25
|
useNavigation,
|
|
@@ -33,7 +37,10 @@ export type {
|
|
|
33
37
|
ITabNavigationHandle,
|
|
34
38
|
IDrawerNavigationHandle,
|
|
35
39
|
} from './composables';
|
|
36
|
-
export type {
|
|
40
|
+
export type {
|
|
41
|
+
INavigationScopeValue,
|
|
42
|
+
IAnyNavigatorHandle,
|
|
43
|
+
} from './navigation-context';
|
|
37
44
|
|
|
38
45
|
export { useLinkingIntegration } from './linking';
|
|
39
46
|
export type { ILinkingConfig, IScreenLinkingConfig } from '../core';
|
|
@@ -67,4 +74,9 @@ export type {
|
|
|
67
74
|
IDrawerScreenOptionsResolver,
|
|
68
75
|
IDrawerScreenProps,
|
|
69
76
|
} from './drawer-screen';
|
|
70
|
-
export type {
|
|
77
|
+
export type {
|
|
78
|
+
IDrawerOptions,
|
|
79
|
+
IDrawerScreenOptions,
|
|
80
|
+
IDrawerType,
|
|
81
|
+
IDrawerPosition,
|
|
82
|
+
} from '../core';
|
package/src/vue/linking.ts
CHANGED
|
@@ -30,7 +30,10 @@ export function useLinkingIntegration(
|
|
|
30
30
|
let cancelled = false;
|
|
31
31
|
let subscription: IEventSubscription | undefined;
|
|
32
32
|
|
|
33
|
-
function applyRoute(
|
|
33
|
+
function applyRoute(
|
|
34
|
+
url: string,
|
|
35
|
+
dispatch: (name: string, params?: unknown) => void,
|
|
36
|
+
): void {
|
|
34
37
|
const route = resolveRouteFromUrl(config, url);
|
|
35
38
|
if (route === null) {
|
|
36
39
|
dlog(`useLinkingIntegration: no route resolved for "${url}"`);
|
|
@@ -42,7 +45,9 @@ export function useLinkingIntegration(
|
|
|
42
45
|
onMounted(() => {
|
|
43
46
|
const handle = navigatorHandle.value;
|
|
44
47
|
if (handle === null) {
|
|
45
|
-
dlog(
|
|
48
|
+
dlog(
|
|
49
|
+
'useLinkingIntegration: navigatorHandle is not yet available at mount time',
|
|
50
|
+
);
|
|
46
51
|
return;
|
|
47
52
|
}
|
|
48
53
|
|
|
@@ -27,7 +27,12 @@
|
|
|
27
27
|
// screen nested inside e.g. a Stack-screen-renders-a-Tab composition reach the enclosing Stack via
|
|
28
28
|
// useNavigation().getParent().
|
|
29
29
|
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
defineComponent,
|
|
32
|
+
inject,
|
|
33
|
+
provide,
|
|
34
|
+
shallowRef,
|
|
35
|
+
} from '@vue/runtime-core';
|
|
31
36
|
import type { InjectionKey, ShallowRef } from '@vue/runtime-core';
|
|
32
37
|
import type { INavigationEmitter, IRoute, IAnyNavigatorHandle } from '../core';
|
|
33
38
|
export type { IAnyNavigatorHandle };
|
|
@@ -44,7 +49,9 @@ const NAVIGATION_SCOPE_KEY: InjectionKey<ShallowRef<INavigationScopeValue>> =
|
|
|
44
49
|
|
|
45
50
|
// The setter half of the pair - writes the CURRENT route's scope onto the shared key. Called only
|
|
46
51
|
// from NavigationScope's own setup below (never directly by app code).
|
|
47
|
-
function provideNavigationScope(
|
|
52
|
+
function provideNavigationScope(
|
|
53
|
+
value: ShallowRef<INavigationScopeValue>,
|
|
54
|
+
): void {
|
|
48
55
|
provide(NAVIGATION_SCOPE_KEY, value);
|
|
49
56
|
}
|
|
50
57
|
|
|
@@ -52,7 +59,8 @@ function provideNavigationScope(value: ShallowRef<INavigationScopeValue>): void
|
|
|
52
59
|
// (stack.ts/tabs.ts/drawer.ts, reading the AMBIENT/parent scope on their own mount) calls this
|
|
53
60
|
// directly; undefined simply means "no ancestor NavigationScope", which is a legitimate state (the
|
|
54
61
|
// nesting root) rather than an error - callers that require one throw their own message.
|
|
55
|
-
export function injectNavigationScope():
|
|
62
|
+
export function injectNavigationScope():
|
|
63
|
+
ShallowRef<INavigationScopeValue> | undefined {
|
|
56
64
|
return inject(NAVIGATION_SCOPE_KEY, undefined);
|
|
57
65
|
}
|
|
58
66
|
|
|
@@ -60,7 +68,9 @@ export function injectNavigationScope(): ShallowRef<INavigationScopeValue> | und
|
|
|
60
68
|
// useIsFocused, useFocusEffect, useNavigationState) - they all called injectNavigationScope() and
|
|
61
69
|
// threw the same shaped error, differing only in which hook name the message names. Centralized
|
|
62
70
|
// here so a wording change lands once instead of five times.
|
|
63
|
-
export function requireNavigationScope(
|
|
71
|
+
export function requireNavigationScope(
|
|
72
|
+
hookName: string,
|
|
73
|
+
): ShallowRef<INavigationScopeValue> {
|
|
64
74
|
const scope = injectNavigationScope();
|
|
65
75
|
if (scope === undefined) {
|
|
66
76
|
throw new Error(
|
|
@@ -74,7 +84,9 @@ export function requireNavigationScope(hookName: string): ShallowRef<INavigation
|
|
|
74
84
|
// declaration here, not stylistic - without it Vue would route the incoming `value` into `attrs`
|
|
75
85
|
// instead of a tracked reactive `props` field, and the render closure's refresh below would
|
|
76
86
|
// silently keep re-reading a stale initial snapshot.
|
|
77
|
-
export const NavigationScope = defineComponent<{
|
|
87
|
+
export const NavigationScope = defineComponent<{
|
|
88
|
+
value: INavigationScopeValue;
|
|
89
|
+
}>(
|
|
78
90
|
(props, { slots }) => {
|
|
79
91
|
const current = shallowRef(props.value);
|
|
80
92
|
provideNavigationScope(current);
|
package/src/vue/screen.ts
CHANGED
|
@@ -25,7 +25,10 @@ export type IVueSearchBarOptions = ISearchBarOptions & {
|
|
|
25
25
|
ref?: Ref<ISearchBarCommands | null>;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export type IVueScreenOptions = Omit<
|
|
28
|
+
export type IVueScreenOptions = Omit<
|
|
29
|
+
IScreenOptions,
|
|
30
|
+
'headerSearchBarOptions'
|
|
31
|
+
> & {
|
|
29
32
|
headerSearchBarOptions?: IVueSearchBarOptions;
|
|
30
33
|
};
|
|
31
34
|
|
|
@@ -37,7 +40,9 @@ export type IScreenOptionsArgs = {
|
|
|
37
40
|
navigation: INavigatorHandle;
|
|
38
41
|
};
|
|
39
42
|
|
|
40
|
-
export type IScreenOptionsResolver = (
|
|
43
|
+
export type IScreenOptionsResolver = (
|
|
44
|
+
args: IScreenOptionsArgs,
|
|
45
|
+
) => IVueScreenOptions;
|
|
41
46
|
|
|
42
47
|
export type IScreenProps = {
|
|
43
48
|
name: string;
|