expo-router 1.2.0 → 1.2.2
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/_root.tsx +4 -3
- package/metro-require.d.ts +52 -0
- package/package.json +6 -3
- package/src/LocationProvider.tsx +1 -1
- package/src/NavigationContainer.tsx +1 -1
- package/src/fork/getPathFromState.ts +9 -12
- package/src/fork/getStateFromPath.ts +1 -0
- package/src/fork/useLinking.ts +1 -0
- package/src/link/path.ts +3 -3
- package/src/link/stateOperations.ts +6 -5
- package/src/link/useLinkToPath.ts +1 -2
- package/src/link/useLinkToPathProps.tsx +15 -9
- package/src/link/useLinkingContext.ts +16 -5
- package/src/link/useRouter.ts +2 -5
- package/src/renderRootComponent.tsx +3 -3
- package/src/static/renderStaticContent.tsx +9 -6
- package/src/static/useServerState.ts +1 -0
- package/src/useScreens.tsx +1 -1
- package/src/views/Navigator.tsx +5 -3
package/_root.tsx
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
/// <reference path="metro-require.d.ts" />
|
|
2
|
+
|
|
1
3
|
import "@expo/metro-runtime";
|
|
2
|
-
import React from "react";
|
|
3
4
|
|
|
4
5
|
import { ExpoRoot } from "expo-router";
|
|
6
|
+
import React from "react";
|
|
5
7
|
|
|
6
8
|
import { getNavigationConfig } from "./src/getLinkingConfig";
|
|
7
9
|
import { getRoutes } from "./src/getRoutes";
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
const ctx = require.context(process.env.EXPO_ROUTER_APP_ROOT);
|
|
11
|
+
const ctx = require.context(process.env.EXPO_ROUTER_APP_ROOT!);
|
|
11
12
|
|
|
12
13
|
// Must be exported or Fast Refresh won't update the context >:[
|
|
13
14
|
export default function ExpoRouterRoot() {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Based on https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/webpack-env/index.d.ts
|
|
2
|
+
// Adds support for the runtime `require.context` method.
|
|
3
|
+
// https://github.com/facebook/metro/pull/822/
|
|
4
|
+
|
|
5
|
+
declare var module: NodeModule;
|
|
6
|
+
|
|
7
|
+
declare namespace __MetroModuleApi {
|
|
8
|
+
interface RequireContext {
|
|
9
|
+
/** Return the keys that can be resolved. */
|
|
10
|
+
keys(): string[];
|
|
11
|
+
(id: string): any;
|
|
12
|
+
<T>(id: string): T;
|
|
13
|
+
/** **Unimplemented:** Return the module identifier for a user request. */
|
|
14
|
+
resolve(id: string): string;
|
|
15
|
+
/** **Unimplemented:** Readable identifier for the context module. */
|
|
16
|
+
id: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface RequireFunction {
|
|
20
|
+
/**
|
|
21
|
+
* Returns the exports from a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
|
|
22
|
+
*/
|
|
23
|
+
(path: string): any;
|
|
24
|
+
<T>(path: string): T;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* **Experimental:** Import all modules in a given directory. This module dynamically updates when the files in a directory are added or removed.
|
|
28
|
+
*
|
|
29
|
+
* **Enabling:** This feature can be enabled by setting the `transformer.unstable_allowRequireContext` property to `true` in your Metro configuration.
|
|
30
|
+
*
|
|
31
|
+
* @param path File path pointing to the directory to require.
|
|
32
|
+
* @param recursive Should search for files recursively. Optional, default `true` when `require.context` is used.
|
|
33
|
+
* @param filter Filename filter pattern for use in `require.context`. Optional, default `.*` (any file) when `require.context` is used.
|
|
34
|
+
* @param mode Mode for resolving dynamic dependencies. Defaults to `sync`.
|
|
35
|
+
*/
|
|
36
|
+
context(
|
|
37
|
+
path: string,
|
|
38
|
+
recursive?: boolean,
|
|
39
|
+
filter?: RegExp,
|
|
40
|
+
mode?: "sync" | "eager" | "weak" | "lazy" | "lazy-once"
|
|
41
|
+
): RequireContext;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Declare process variable
|
|
47
|
+
*/
|
|
48
|
+
declare namespace NodeJS {
|
|
49
|
+
interface Require extends __MetroModuleApi.RequireFunction {}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
declare var require: NodeRequire;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-router",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"main": "src/index.tsx",
|
|
5
5
|
"types": "src/index.tsx",
|
|
6
6
|
"files": [
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"drawer.ts",
|
|
14
14
|
"stack.ts",
|
|
15
15
|
"tabs.ts",
|
|
16
|
-
"head.ts"
|
|
16
|
+
"head.ts",
|
|
17
|
+
"metro-require.d.ts"
|
|
17
18
|
],
|
|
18
19
|
"repository": {
|
|
19
20
|
"url": "https://github.com/expo/router.git",
|
|
@@ -62,6 +63,7 @@
|
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
65
|
"@react-navigation/drawer": "^6.6.2",
|
|
66
|
+
"@types/url-parse": "^1.4.8",
|
|
65
67
|
"expo-splash-screen": "~0.18.1",
|
|
66
68
|
"expo-status-bar": "~1.4.4",
|
|
67
69
|
"react-native-gesture-handler": "~2.9.0",
|
|
@@ -71,12 +73,13 @@
|
|
|
71
73
|
},
|
|
72
74
|
"dependencies": {
|
|
73
75
|
"@bacons/react-views": "^1.1.3",
|
|
74
|
-
"@expo/metro-runtime": "1.
|
|
76
|
+
"@expo/metro-runtime": "1.1.0",
|
|
75
77
|
"@radix-ui/react-slot": "^1.0.0",
|
|
76
78
|
"@react-navigation/bottom-tabs": "~6.5.7",
|
|
77
79
|
"@react-navigation/native": "~6.1.6",
|
|
78
80
|
"@react-navigation/native-stack": "~6.9.12",
|
|
79
81
|
"expo-splash-screen": "*",
|
|
82
|
+
"query-string": "7.1.3",
|
|
80
83
|
"react-helmet-async": "^1.3.0",
|
|
81
84
|
"url": "^0.11.0"
|
|
82
85
|
}
|
package/src/LocationProvider.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import { RootNavigationRef } from "./useRootNavigation";
|
|
|
7
7
|
import { useRootRouteNodeContext } from "./useRootRouteNodeContext";
|
|
8
8
|
import { SplashScreen } from "./views/Splash";
|
|
9
9
|
|
|
10
|
-
const navigationRef = createNavigationContainerRef();
|
|
10
|
+
const navigationRef = createNavigationContainerRef<Record<string, unknown>>();
|
|
11
11
|
|
|
12
12
|
/** Get the root navigation container ref. */
|
|
13
13
|
export function getNavigationContainerRef() {
|
|
@@ -39,6 +39,8 @@ type CustomRoute = Route<string> & {
|
|
|
39
39
|
state?: State;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
+
const DEFAULT_SCREENS: PathConfigMap<object> = {};
|
|
43
|
+
|
|
42
44
|
const getActiveRoute = (state: State): { name: string; params?: object } => {
|
|
43
45
|
const route =
|
|
44
46
|
typeof state.index === "number"
|
|
@@ -118,22 +120,20 @@ function encodeURIComponentPreservingBrackets(str: string) {
|
|
|
118
120
|
*/
|
|
119
121
|
export default function getPathFromState<ParamList extends object>(
|
|
120
122
|
state: State,
|
|
121
|
-
// @ts-expect-error: non-standard options
|
|
122
123
|
_options?: Options<ParamList> & {
|
|
123
124
|
preserveGroups?: boolean;
|
|
124
125
|
preserveDynamicRoutes?: boolean;
|
|
125
|
-
}
|
|
126
|
+
}
|
|
126
127
|
): string {
|
|
127
128
|
return getPathDataFromState(state, _options).path;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
export function getPathDataFromState<ParamList extends object>(
|
|
131
132
|
state: State,
|
|
132
|
-
|
|
133
|
-
_options?: Options<ParamList> & {
|
|
133
|
+
_options: Options<ParamList> & {
|
|
134
134
|
preserveGroups?: boolean;
|
|
135
135
|
preserveDynamicRoutes?: boolean;
|
|
136
|
-
} = {}
|
|
136
|
+
} = { screens: DEFAULT_SCREENS }
|
|
137
137
|
) {
|
|
138
138
|
if (state == null) {
|
|
139
139
|
throw Error(
|
|
@@ -143,13 +143,10 @@ export function getPathDataFromState<ParamList extends object>(
|
|
|
143
143
|
|
|
144
144
|
const { preserveGroups, preserveDynamicRoutes, ...options } = _options;
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
validatePathConfig(options);
|
|
148
|
-
}
|
|
146
|
+
validatePathConfig(options);
|
|
149
147
|
|
|
150
|
-
const screens = options?.screens;
|
|
151
148
|
// Expo Router disallows usage without a linking config.
|
|
152
|
-
if (
|
|
149
|
+
if (Object.is(options.screens, DEFAULT_SCREENS)) {
|
|
153
150
|
throw Error(
|
|
154
151
|
"You must pass a 'screens' object to 'getPathFromState' to generate a path."
|
|
155
152
|
);
|
|
@@ -158,7 +155,7 @@ export function getPathDataFromState<ParamList extends object>(
|
|
|
158
155
|
return getPathFromResolvedState(
|
|
159
156
|
state,
|
|
160
157
|
// Create a normalized configs object which will be easier to use
|
|
161
|
-
createNormalizedConfigs(screens),
|
|
158
|
+
createNormalizedConfigs(options.screens),
|
|
162
159
|
{ preserveGroups, preserveDynamicRoutes }
|
|
163
160
|
);
|
|
164
161
|
}
|
|
@@ -515,7 +512,7 @@ function getParamsWithConventionsCollapsed({
|
|
|
515
512
|
routeName: string;
|
|
516
513
|
params: object;
|
|
517
514
|
}): Record<string, string> {
|
|
518
|
-
const processedParams = { ...params };
|
|
515
|
+
const processedParams: Record<string, string> = { ...params };
|
|
519
516
|
|
|
520
517
|
// Remove the params present in the pattern since we'll only use the rest for query string
|
|
521
518
|
|
package/src/fork/useLinking.ts
CHANGED
package/src/link/path.ts
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
// https://github.com/browserify/path-browserify/blob/master/index.js
|
|
23
23
|
|
|
24
|
-
function assertPath(path) {
|
|
24
|
+
function assertPath(path: string) {
|
|
25
25
|
if (typeof path !== "string") {
|
|
26
26
|
throw new TypeError(
|
|
27
27
|
"Path must be a string. Received " + JSON.stringify(path)
|
|
@@ -30,7 +30,7 @@ function assertPath(path) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Resolves . and .. elements in a path with directory names
|
|
33
|
-
function normalizeStringPosix(path, allowAboveRoot) {
|
|
33
|
+
function normalizeStringPosix(path: string, allowAboveRoot?: boolean) {
|
|
34
34
|
let res = "";
|
|
35
35
|
let lastSegmentLength = 0;
|
|
36
36
|
let lastSlash = -1;
|
|
@@ -98,7 +98,7 @@ function normalizeStringPosix(path, allowAboveRoot) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// path.resolve([from ...], to)
|
|
101
|
-
export function resolve(...segments) {
|
|
101
|
+
export function resolve(...segments: string[]) {
|
|
102
102
|
let resolvedPath = "";
|
|
103
103
|
let resolvedAbsolute = false;
|
|
104
104
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InitialState } from "@react-navigation/native";
|
|
1
|
+
import { InitialState, NavigationState } from "@react-navigation/native";
|
|
2
2
|
|
|
3
3
|
import { ResultState } from "../fork/getStateFromPath";
|
|
4
4
|
|
|
@@ -36,7 +36,7 @@ export function isMovingToSiblingRoute(
|
|
|
36
36
|
let currentRoot: InitialState | undefined = rootState;
|
|
37
37
|
|
|
38
38
|
while (current?.routes?.[current?.routes?.length - 1].state != null) {
|
|
39
|
-
const nextRoute = current?.routes?.[current?.routes?.length - 1];
|
|
39
|
+
const nextRoute: any = current?.routes?.[current?.routes?.length - 1];
|
|
40
40
|
|
|
41
41
|
if (
|
|
42
42
|
// Has more
|
|
@@ -74,9 +74,9 @@ export function getQualifiedStateForTopOfTargetState(
|
|
|
74
74
|
let currentRoot: InitialState | undefined = rootState;
|
|
75
75
|
|
|
76
76
|
while (current?.routes?.[current?.routes?.length - 1].state != null) {
|
|
77
|
-
const nextRoute = current?.routes?.[current?.routes?.length - 1];
|
|
77
|
+
const nextRoute: any = current?.routes?.[current?.routes?.length - 1];
|
|
78
78
|
|
|
79
|
-
const nextCurrentRoot = currentRoot?.routes?.find(
|
|
79
|
+
const nextCurrentRoot: InitialState | undefined = currentRoot?.routes?.find(
|
|
80
80
|
(route) => route.name === nextRoute.name
|
|
81
81
|
)?.state;
|
|
82
82
|
|
|
@@ -95,7 +95,8 @@ export function getQualifiedStateForTopOfTargetState(
|
|
|
95
95
|
return currentRoot;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
type SubState = {
|
|
98
|
+
type SubState = NavigationState & {
|
|
99
|
+
key?: string;
|
|
99
100
|
type: string;
|
|
100
101
|
routes?: { name: string; state?: SubState }[];
|
|
101
102
|
index?: number;
|
|
@@ -54,7 +54,6 @@ export function useLinkToPath() {
|
|
|
54
54
|
if (href.startsWith(".")) {
|
|
55
55
|
let base = linking.getPathFromState?.(navigation.getRootState(), {
|
|
56
56
|
...linking.config,
|
|
57
|
-
// @ts-expect-error: non-standard option
|
|
58
57
|
preserveGroups: true,
|
|
59
58
|
});
|
|
60
59
|
|
|
@@ -123,8 +122,8 @@ export function useLinkToPath() {
|
|
|
123
122
|
isAbsoluteInitialRoute(action)
|
|
124
123
|
) {
|
|
125
124
|
const earliest = getEarliestMismatchedRoute(
|
|
126
|
-
// @ts-expect-error
|
|
127
125
|
rootState,
|
|
126
|
+
// @ts-expect-error
|
|
128
127
|
action.payload
|
|
129
128
|
);
|
|
130
129
|
if (earliest) {
|
|
@@ -5,20 +5,26 @@ import { useLinkToPath } from "./useLinkToPath";
|
|
|
5
5
|
import { stripGroupSegmentsFromPath } from "../matchers";
|
|
6
6
|
|
|
7
7
|
function eventShouldPreventDefault(
|
|
8
|
-
e
|
|
8
|
+
e: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
|
|
9
9
|
): boolean {
|
|
10
|
+
if (e?.defaultPrevented) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
!
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// Only check MouseEvents
|
|
16
|
+
"button" in e &&
|
|
17
|
+
// ignore clicks with modifier keys
|
|
18
|
+
!e.metaKey &&
|
|
19
|
+
!e.altKey &&
|
|
20
|
+
!e.ctrlKey &&
|
|
21
|
+
!e.shiftKey &&
|
|
22
|
+
(e.button == null || e.button === 0) && // Only accept left clicks
|
|
23
|
+
[undefined, null, "", "self"].includes(e.currentTarget.target) // let browser handle "target=_blank" etc.
|
|
19
24
|
) {
|
|
20
25
|
return true;
|
|
21
26
|
}
|
|
27
|
+
|
|
22
28
|
return false;
|
|
23
29
|
}
|
|
24
30
|
|
|
@@ -5,20 +5,31 @@ import {
|
|
|
5
5
|
} from "@react-navigation/native";
|
|
6
6
|
import * as React from "react";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import getPathFromState from "../fork/getPathFromState";
|
|
9
|
+
|
|
10
|
+
export type RouterLinkingContext = Required<
|
|
9
11
|
Omit<LinkingOptions<ParamListBase>, "filter" | "enabled">
|
|
10
|
-
> {
|
|
12
|
+
> & {
|
|
13
|
+
getPathFromState: typeof getPathFromState;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function useLinkingContext(): RouterLinkingContext {
|
|
11
17
|
const linking = React.useContext(LinkingContext);
|
|
12
18
|
|
|
13
19
|
const { options } = linking;
|
|
14
20
|
|
|
21
|
+
assertLinkingOptions(options);
|
|
22
|
+
|
|
23
|
+
return options;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function assertLinkingOptions(
|
|
27
|
+
options: LinkingOptions<ParamListBase> | undefined
|
|
28
|
+
): asserts options is RouterLinkingContext {
|
|
15
29
|
if (!options?.config) {
|
|
16
30
|
// This should never happen in Expo Router.
|
|
17
31
|
throw new Error(
|
|
18
32
|
"Couldn't find a linking config. Is your component inside a navigator?"
|
|
19
33
|
);
|
|
20
34
|
}
|
|
21
|
-
|
|
22
|
-
// @ts-expect-error: non-standard option
|
|
23
|
-
return options;
|
|
24
35
|
}
|
package/src/link/useRouter.ts
CHANGED
|
@@ -47,11 +47,8 @@ export function useRouter(): Router {
|
|
|
47
47
|
push,
|
|
48
48
|
back,
|
|
49
49
|
replace,
|
|
50
|
-
setParams: (params) => {
|
|
51
|
-
root?.current?.setParams(
|
|
52
|
-
// @ts-expect-error
|
|
53
|
-
params
|
|
54
|
-
);
|
|
50
|
+
setParams: (params = {}) => {
|
|
51
|
+
root?.current?.setParams(params);
|
|
55
52
|
},
|
|
56
53
|
// TODO(EvanBacon): add `reload`
|
|
57
54
|
// TODO(EvanBacon): add `canGoBack` but maybe more like a `hasContext`
|
|
@@ -4,7 +4,7 @@ import { Platform, View } from "react-native";
|
|
|
4
4
|
import registerRootComponent from "./fork/expo/registerRootComponent";
|
|
5
5
|
import { SplashScreen } from "./views/Splash";
|
|
6
6
|
|
|
7
|
-
function isBaseObject(obj) {
|
|
7
|
+
function isBaseObject(obj: any) {
|
|
8
8
|
if (Object.prototype.toString.call(obj) !== "[object Object]") {
|
|
9
9
|
return false;
|
|
10
10
|
}
|
|
@@ -15,7 +15,7 @@ function isBaseObject(obj) {
|
|
|
15
15
|
return proto === Object.prototype;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function isErrorShaped(error) {
|
|
18
|
+
function isErrorShaped(error: any): error is Error {
|
|
19
19
|
return (
|
|
20
20
|
error &&
|
|
21
21
|
typeof error === "object" &&
|
|
@@ -28,7 +28,7 @@ function isErrorShaped(error) {
|
|
|
28
28
|
* After we throw this error, any number of tools could handle it.
|
|
29
29
|
* This check ensures the error is always in a reason state before surfacing it to the runtime.
|
|
30
30
|
*/
|
|
31
|
-
function convertError(error) {
|
|
31
|
+
function convertError(error: any) {
|
|
32
32
|
if (isErrorShaped(error)) {
|
|
33
33
|
return error;
|
|
34
34
|
}
|
|
@@ -30,12 +30,15 @@ export function getStaticContent(location: URL): string {
|
|
|
30
30
|
// TODO: Use RNW view after they fix hydration for React 18
|
|
31
31
|
// https://github.com/necolas/react-native-web/blob/e8098fd029102d7801c32c1ede792bce01808c00/packages/react-native-web/src/exports/render/index.js#L10
|
|
32
32
|
// Otherwise this wraps the app with two extra divs
|
|
33
|
-
children:
|
|
34
|
-
// Inject the root tag
|
|
35
|
-
|
|
33
|
+
children:
|
|
34
|
+
// Inject the root tag using createElement to prevent any transforms like the ones in `@expo/html-elements`.
|
|
35
|
+
React.createElement(
|
|
36
|
+
"div",
|
|
37
|
+
{
|
|
38
|
+
id: "root",
|
|
39
|
+
},
|
|
36
40
|
<App />
|
|
37
|
-
|
|
38
|
-
),
|
|
41
|
+
),
|
|
39
42
|
});
|
|
40
43
|
|
|
41
44
|
const html = ReactDOMServer.renderToString(
|
|
@@ -113,7 +116,7 @@ function StyleReset() {
|
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
// TODO(EvanBacon): Expose this to the developer
|
|
116
|
-
export function Root({ children }) {
|
|
119
|
+
export function Root({ children }: { children: React.ReactNode }) {
|
|
117
120
|
return (
|
|
118
121
|
<html lang="en" style={{ height: "100%" }}>
|
|
119
122
|
<head>
|
package/src/useScreens.tsx
CHANGED
|
@@ -165,7 +165,7 @@ export function createGetIdForRoute(
|
|
|
165
165
|
if (!route.dynamic?.length) {
|
|
166
166
|
return undefined;
|
|
167
167
|
}
|
|
168
|
-
return ({ params }) => {
|
|
168
|
+
return ({ params }: { params?: Record<string, any> }) => {
|
|
169
169
|
const getPreferredId = (segment: DynamicConvention) => {
|
|
170
170
|
// Params can be undefined when there are no params in the route.
|
|
171
171
|
const preferredId = params?.[segment.name];
|
package/src/views/Navigator.tsx
CHANGED
|
@@ -10,12 +10,14 @@ import { useContextKey } from "../Route";
|
|
|
10
10
|
import { useFilterScreenChildren } from "../layouts/withLayoutContext";
|
|
11
11
|
import { useSortedScreens } from "../useScreens";
|
|
12
12
|
|
|
13
|
+
type NavigatorTypes = ReturnType<typeof useNavigationBuilder>;
|
|
14
|
+
|
|
13
15
|
// TODO: This might already exist upstream, maybe something like `useCurrentRender` ?
|
|
14
16
|
export const NavigatorContext = React.createContext<{
|
|
15
17
|
contextKey: string;
|
|
16
|
-
state:
|
|
17
|
-
navigation:
|
|
18
|
-
descriptors:
|
|
18
|
+
state: NavigatorTypes["state"];
|
|
19
|
+
navigation: NavigatorTypes["navigation"];
|
|
20
|
+
descriptors: NavigatorTypes["descriptors"];
|
|
19
21
|
router: RouterFactory<any, any, any>;
|
|
20
22
|
} | null>(null);
|
|
21
23
|
|