@react-navigation/core 8.0.0-alpha.24 → 8.0.0-alpha.25
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/lib/module/BaseNavigationContainer.js +5 -2
- package/lib/module/BaseNavigationContainer.js.map +1 -1
- package/lib/module/DataLoading.js +102 -0
- package/lib/module/DataLoading.js.map +1 -0
- package/lib/module/NavigationIndependentTree.js +7 -6
- package/lib/module/NavigationIndependentTree.js.map +1 -1
- package/lib/module/NavigationProvider.js +12 -12
- package/lib/module/NavigationProvider.js.map +1 -1
- package/lib/module/PreventRemoveContext.js.map +1 -1
- package/lib/module/PreventRemoveProvider.js +34 -24
- package/lib/module/PreventRemoveProvider.js.map +1 -1
- package/lib/module/StaticNavigation.js +14 -6
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/StaticTreeContext.js +5 -0
- package/lib/module/StaticTreeContext.js.map +1 -0
- package/lib/module/checkSerializable.js +7 -9
- package/lib/module/checkSerializable.js.map +1 -1
- package/lib/module/createNavigationContainerRef.js +6 -8
- package/lib/module/createNavigationContainerRef.js.map +1 -1
- package/lib/module/createNavigatorFactory.js.map +1 -1
- package/lib/module/getActionFromState.js +11 -11
- package/lib/module/getActionFromState.js.map +1 -1
- package/lib/module/getPathFromState.js +38 -39
- package/lib/module/getPathFromState.js.map +1 -1
- package/lib/module/getPatternParts.js +2 -2
- package/lib/module/getPatternParts.js.map +1 -1
- package/lib/module/getStateFromPath.js +72 -45
- package/lib/module/getStateFromPath.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/useEventEmitter.js +1 -1
- package/lib/module/useEventEmitter.js.map +1 -1
- package/lib/module/useKeyedChildListeners.js +4 -2
- package/lib/module/useKeyedChildListeners.js.map +1 -1
- package/lib/module/useNavigation.js +2 -15
- package/lib/module/useNavigation.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +4 -14
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useNavigationCache.js +19 -14
- package/lib/module/useNavigationCache.js.map +1 -1
- package/lib/module/useNavigationHelpers.js +27 -9
- package/lib/module/useNavigationHelpers.js.map +1 -1
- package/lib/module/useNavigationState.js +69 -36
- package/lib/module/useNavigationState.js.map +1 -1
- package/lib/module/useOnAction.js +21 -2
- package/lib/module/useOnAction.js.map +1 -1
- package/lib/module/useOptionsGetters.js +3 -1
- package/lib/module/useOptionsGetters.js.map +1 -1
- package/lib/module/usePreventRemove.js +9 -2
- package/lib/module/usePreventRemove.js.map +1 -1
- package/lib/module/useRouteCache.js +14 -7
- package/lib/module/useRouteCache.js.map +1 -1
- package/lib/module/useScheduleUpdate.js +8 -8
- package/lib/module/useScheduleUpdate.js.map +1 -1
- package/lib/module/useSyncState.js +4 -1
- package/lib/module/useSyncState.js.map +1 -1
- package/lib/module/validatePathConfig.js.map +1 -1
- package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
- package/lib/typescript/src/DataLoading.d.ts +20 -0
- package/lib/typescript/src/DataLoading.d.ts.map +1 -0
- package/lib/typescript/src/NavigationProvider.d.ts +0 -1
- package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
- package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
- package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
- package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
- package/lib/typescript/src/StaticNavigation.d.ts +65 -39
- package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
- package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
- package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
- package/lib/typescript/src/checkSerializable.d.ts +4 -2
- package/lib/typescript/src/checkSerializable.d.ts.map +1 -1
- package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
- package/lib/typescript/src/createNavigatorFactory.d.ts +9 -5
- package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
- package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
- package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
- package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +19 -13
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
- package/lib/typescript/src/useNavigation.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationHelpers.d.ts +3 -4
- package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationState.d.ts +11 -1
- package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
- package/lib/typescript/src/useOnAction.d.ts.map +1 -1
- package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
- package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
- package/lib/typescript/src/usePreventRemoveContext.d.ts +1 -0
- package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
- package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
- package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
- package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
- package/lib/typescript/src/useSyncState.d.ts.map +1 -1
- package/lib/typescript/src/utilities.d.ts +17 -0
- package/lib/typescript/src/utilities.d.ts.map +1 -1
- package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
- package/package.json +3 -5
- package/src/BaseNavigationContainer.tsx +9 -2
- package/src/DataLoading.tsx +139 -0
- package/src/NavigationIndependentTree.tsx +11 -11
- package/src/NavigationProvider.tsx +13 -16
- package/src/PreventRemoveContext.tsx +1 -0
- package/src/PreventRemoveProvider.tsx +48 -43
- package/src/StaticNavigation.tsx +157 -93
- package/src/StaticTreeContext.tsx +7 -0
- package/src/checkSerializable.tsx +20 -14
- package/src/createNavigationContainerRef.tsx +12 -9
- package/src/createNavigatorFactory.tsx +16 -28
- package/src/getActionFromState.tsx +18 -16
- package/src/getPathFromState.tsx +69 -65
- package/src/getPatternParts.tsx +2 -2
- package/src/getStateFromPath.tsx +107 -66
- package/src/index.tsx +2 -0
- package/src/types.tsx +62 -50
- package/src/useEventEmitter.tsx +1 -1
- package/src/useKeyedChildListeners.tsx +4 -2
- package/src/useNavigation.tsx +2 -21
- package/src/useNavigationBuilder.tsx +6 -16
- package/src/useNavigationCache.tsx +26 -19
- package/src/useNavigationHelpers.tsx +26 -9
- package/src/useNavigationState.tsx +90 -60
- package/src/useOnAction.tsx +49 -1
- package/src/useOptionsGetters.tsx +4 -1
- package/src/usePreventRemove.tsx +11 -2
- package/src/useRouteCache.tsx +19 -11
- package/src/useScheduleUpdate.tsx +8 -7
- package/src/useSyncState.tsx +5 -1
- package/src/utilities.tsx +28 -0
- package/src/validatePathConfig.tsx +1 -0
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
type Success = { serializable: true };
|
|
2
|
+
|
|
3
|
+
type Failure = {
|
|
4
|
+
serializable: false;
|
|
5
|
+
location: (string | number)[];
|
|
6
|
+
reason: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type Result = Success | Failure;
|
|
8
10
|
|
|
9
11
|
const checkSerializableWithoutCircularReference = (
|
|
10
12
|
o: { [key: string]: any },
|
|
11
13
|
seen: Set<any>,
|
|
12
14
|
location: (string | number)[]
|
|
13
|
-
):
|
|
15
|
+
): Failure | undefined => {
|
|
14
16
|
if (
|
|
15
17
|
o === undefined ||
|
|
16
18
|
o === null ||
|
|
@@ -18,7 +20,7 @@ const checkSerializableWithoutCircularReference = (
|
|
|
18
20
|
typeof o === 'number' ||
|
|
19
21
|
typeof o === 'string'
|
|
20
22
|
) {
|
|
21
|
-
return
|
|
23
|
+
return undefined;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
if (
|
|
@@ -52,7 +54,7 @@ const checkSerializableWithoutCircularReference = (
|
|
|
52
54
|
);
|
|
53
55
|
location.pop();
|
|
54
56
|
|
|
55
|
-
if (
|
|
57
|
+
if (childResult) {
|
|
56
58
|
seen.delete(o);
|
|
57
59
|
return childResult;
|
|
58
60
|
}
|
|
@@ -67,7 +69,7 @@ const checkSerializableWithoutCircularReference = (
|
|
|
67
69
|
);
|
|
68
70
|
location.pop();
|
|
69
71
|
|
|
70
|
-
if (
|
|
72
|
+
if (childResult) {
|
|
71
73
|
seen.delete(o);
|
|
72
74
|
return childResult;
|
|
73
75
|
}
|
|
@@ -76,9 +78,13 @@ const checkSerializableWithoutCircularReference = (
|
|
|
76
78
|
|
|
77
79
|
seen.delete(o);
|
|
78
80
|
|
|
79
|
-
return
|
|
81
|
+
return undefined;
|
|
80
82
|
};
|
|
81
83
|
|
|
82
|
-
export function checkSerializable(o: { [key: string]: any }) {
|
|
83
|
-
return
|
|
84
|
+
export function checkSerializable(o: { [key: string]: any }): Result {
|
|
85
|
+
return (
|
|
86
|
+
checkSerializableWithoutCircularReference(o, new Set<any>(), []) ?? {
|
|
87
|
+
serializable: true,
|
|
88
|
+
}
|
|
89
|
+
);
|
|
84
90
|
}
|
|
@@ -30,6 +30,8 @@ export function createNavigationContainerRef<
|
|
|
30
30
|
|
|
31
31
|
const listeners: Record<string, ((...args: any[]) => void)[]> = {};
|
|
32
32
|
|
|
33
|
+
let current: NavigationContainerRef<ParamList> | null = null;
|
|
34
|
+
|
|
33
35
|
const removeListener = (
|
|
34
36
|
event: string,
|
|
35
37
|
callback: (...args: any[]) => void
|
|
@@ -37,9 +39,12 @@ export function createNavigationContainerRef<
|
|
|
37
39
|
if (listeners[event]) {
|
|
38
40
|
listeners[event] = listeners[event].filter((cb) => cb !== callback);
|
|
39
41
|
}
|
|
40
|
-
};
|
|
41
42
|
|
|
42
|
-
|
|
43
|
+
current?.removeListener(
|
|
44
|
+
event as keyof NavigationContainerEventMap,
|
|
45
|
+
callback
|
|
46
|
+
);
|
|
47
|
+
};
|
|
43
48
|
|
|
44
49
|
const ref: NavigationContainerRefWithCurrent<ParamList> = {
|
|
45
50
|
get current() {
|
|
@@ -68,7 +73,11 @@ export function createNavigationContainerRef<
|
|
|
68
73
|
},
|
|
69
74
|
...methods.reduce<any>((acc, name) => {
|
|
70
75
|
acc[name] = (...args: any[]) => {
|
|
71
|
-
if (
|
|
76
|
+
if (name === 'removeListener') {
|
|
77
|
+
const [event, callback] = args;
|
|
78
|
+
|
|
79
|
+
removeListener(event, callback);
|
|
80
|
+
} else if (current == null) {
|
|
72
81
|
switch (name) {
|
|
73
82
|
case 'addListener': {
|
|
74
83
|
const [event, callback] = args;
|
|
@@ -78,12 +87,6 @@ export function createNavigationContainerRef<
|
|
|
78
87
|
|
|
79
88
|
return () => removeListener(event, callback);
|
|
80
89
|
}
|
|
81
|
-
case 'removeListener': {
|
|
82
|
-
const [event, callback] = args;
|
|
83
|
-
|
|
84
|
-
removeListener(event, callback);
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
90
|
default:
|
|
88
91
|
console.error(NOT_INITIALIZED_ERROR);
|
|
89
92
|
}
|
|
@@ -5,6 +5,7 @@ import { Group } from './Group';
|
|
|
5
5
|
import { Screen } from './Screen';
|
|
6
6
|
import {
|
|
7
7
|
createComponentForStaticConfig,
|
|
8
|
+
type NoExcessStaticConfig,
|
|
8
9
|
type StaticConfig,
|
|
9
10
|
type StaticParamList,
|
|
10
11
|
} from './StaticNavigation';
|
|
@@ -14,25 +15,24 @@ import type {
|
|
|
14
15
|
NestedNavigatorsForParamList,
|
|
15
16
|
TypedNavigator,
|
|
16
17
|
} from './types';
|
|
17
|
-
import type { KeysOf } from './utilities';
|
|
18
|
+
import type { KeysOf, NoExcessObject } from './utilities';
|
|
18
19
|
|
|
19
|
-
type
|
|
20
|
-
ParamList
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
? Nesting
|
|
25
|
-
|
|
20
|
+
type NavigatorNesting<ParamList extends ParamListBase, Nesting> = {
|
|
21
|
+
[RouteName in keyof ParamList]?: unknown;
|
|
22
|
+
} & Record<Exclude<KeysOf<Nesting>, keyof ParamList>, never>;
|
|
23
|
+
|
|
24
|
+
type ValidNavigatorNesting<ParamList extends ParamListBase, Nesting> =
|
|
25
|
+
Nesting extends NavigatorNesting<ParamList, Nesting> ? Nesting : never;
|
|
26
|
+
|
|
27
|
+
type AnyStaticConfig<TypeBag extends NavigatorTypeBagBase> = StaticConfig<
|
|
28
|
+
NavigatorTypeBagFor<TypeBag, ParamListBase>
|
|
29
|
+
>;
|
|
26
30
|
|
|
27
31
|
export type TypedNavigatorFactory<in out TypeBag extends NavigatorTypeBagBase> =
|
|
28
32
|
{
|
|
29
33
|
<
|
|
30
34
|
const ParamList extends ParamListBase,
|
|
31
|
-
const Nesting extends
|
|
32
|
-
// Extra keys satisfy the structural constraint via width subtyping,
|
|
33
|
-
// Force any key in `Nesting` that isn't in the param list to `never`.
|
|
34
|
-
// So typos in the nesting config will cause an error.
|
|
35
|
-
Record<Exclude<keyof Nesting, keyof ParamList>, never> =
|
|
35
|
+
const Nesting extends NavigatorNesting<ParamList, Nesting> =
|
|
36
36
|
ValidNavigatorNesting<
|
|
37
37
|
ParamList,
|
|
38
38
|
NestedNavigatorsForParamList<ParamList>
|
|
@@ -43,22 +43,10 @@ export type TypedNavigatorFactory<in out TypeBag extends NavigatorTypeBagBase> =
|
|
|
43
43
|
Nesting
|
|
44
44
|
>;
|
|
45
45
|
<
|
|
46
|
-
const Config extends
|
|
47
|
-
|
|
48
|
-
> &
|
|
49
|
-
// TS only checks for excess properties for non-generic object literal types.
|
|
50
|
-
// Since `Config` is generic, extra keys satisfy the constraint and slip through.
|
|
51
|
-
// So we force any key in `Config` that isn't a known key to have the type `never`,
|
|
52
|
-
// Thus causing an error for any extra key.
|
|
53
|
-
Record<
|
|
54
|
-
Exclude<
|
|
55
|
-
keyof Config,
|
|
56
|
-
KeysOf<StaticConfig<NavigatorTypeBagFor<TypeBag, ParamListBase>>>
|
|
57
|
-
>,
|
|
58
|
-
never
|
|
59
|
-
>,
|
|
46
|
+
const Config extends AnyStaticConfig<TypeBag> &
|
|
47
|
+
NoExcessObject<Config, AnyStaticConfig<TypeBag>>,
|
|
60
48
|
>(
|
|
61
|
-
config: Config
|
|
49
|
+
config: Config & NoExcessStaticConfig<NoInfer<Config>, TypeBag>
|
|
62
50
|
): TypedNavigator<
|
|
63
51
|
NavigatorTypeBagFor<TypeBag, StaticParamList<{ config: Config }>>,
|
|
64
52
|
Config
|
|
@@ -51,25 +51,27 @@ export function getActionFromState(
|
|
|
51
51
|
normalizedConfig = {};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const
|
|
55
|
-
state.index
|
|
54
|
+
const routesLength =
|
|
55
|
+
state.index == null || state.index >= state.routes.length
|
|
56
|
+
? state.routes.length
|
|
57
|
+
: state.index + 1;
|
|
56
58
|
|
|
57
|
-
if (
|
|
59
|
+
if (routesLength === 0) {
|
|
58
60
|
return undefined;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
const firstRoute = routes[0];
|
|
63
|
+
const firstRoute = state.routes[0];
|
|
62
64
|
|
|
63
65
|
if (firstRoute == null) {
|
|
64
66
|
return undefined;
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
const secondRoute = routes[1];
|
|
69
|
+
const secondRoute = state.routes[1];
|
|
68
70
|
|
|
69
71
|
if (
|
|
70
72
|
!(
|
|
71
|
-
(
|
|
72
|
-
(
|
|
73
|
+
(routesLength === 1 && firstRoute.key == null) ||
|
|
74
|
+
(routesLength === 2 &&
|
|
73
75
|
firstRoute.key == null &&
|
|
74
76
|
firstRoute.name === normalizedConfig?.initialRouteName &&
|
|
75
77
|
secondRoute?.key == null)
|
|
@@ -121,24 +123,24 @@ export function getActionFromState(
|
|
|
121
123
|
return undefined;
|
|
122
124
|
}
|
|
123
125
|
|
|
124
|
-
const
|
|
125
|
-
current.index
|
|
126
|
-
? current.routes.
|
|
127
|
-
: current.
|
|
126
|
+
const routesLength =
|
|
127
|
+
current.index == null || current.index >= current.routes.length
|
|
128
|
+
? current.routes.length
|
|
129
|
+
: current.index + 1;
|
|
128
130
|
|
|
129
|
-
const route = routes[
|
|
131
|
+
const route = current.routes[routesLength - 1];
|
|
130
132
|
|
|
131
133
|
if (route == null) {
|
|
132
134
|
return undefined;
|
|
133
135
|
}
|
|
134
136
|
|
|
135
|
-
const firstRoute = routes[0];
|
|
137
|
+
const firstRoute = current.routes[0];
|
|
136
138
|
|
|
137
139
|
if (firstRoute == null) {
|
|
138
140
|
return undefined;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
const secondRoute = routes[1];
|
|
143
|
+
const secondRoute = current.routes[1];
|
|
142
144
|
|
|
143
145
|
// Explicitly set to override existing value when merging params
|
|
144
146
|
Object.assign(params, {
|
|
@@ -148,11 +150,11 @@ export function getActionFromState(
|
|
|
148
150
|
state: undefined,
|
|
149
151
|
});
|
|
150
152
|
|
|
151
|
-
if (
|
|
153
|
+
if (routesLength === 1 && firstRoute.key == null) {
|
|
152
154
|
params.initial = true;
|
|
153
155
|
params.screen = route.name;
|
|
154
156
|
} else if (
|
|
155
|
-
|
|
157
|
+
routesLength === 2 &&
|
|
156
158
|
firstRoute.key == null &&
|
|
157
159
|
firstRoute.name === config?.initialRouteName &&
|
|
158
160
|
secondRoute?.key == null
|
package/src/getPathFromState.tsx
CHANGED
|
@@ -40,7 +40,12 @@ const encodePathParam = (value: string) => {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
const getActiveRoute = (
|
|
43
|
-
state: State
|
|
43
|
+
state: State,
|
|
44
|
+
configs: Record<string, ConfigItem> | undefined,
|
|
45
|
+
getRouteState: (
|
|
46
|
+
route: State['routes'][number],
|
|
47
|
+
config: ConfigItem | undefined
|
|
48
|
+
) => State | undefined
|
|
44
49
|
): { name: string; params?: object | undefined } => {
|
|
45
50
|
const route =
|
|
46
51
|
typeof state.index === 'number'
|
|
@@ -51,74 +56,41 @@ const getActiveRoute = (
|
|
|
51
56
|
throw new Error(`Couldn't find the active route.`);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
const config = configs?.[route.name];
|
|
60
|
+
const routeState = getRouteState(route, config);
|
|
61
|
+
|
|
62
|
+
if (routeState) {
|
|
63
|
+
return getActiveRoute(routeState, config?.screens, getRouteState);
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
return route;
|
|
59
67
|
};
|
|
60
68
|
|
|
61
69
|
const cachedNormalizedConfigs = new WeakMap<
|
|
62
|
-
|
|
70
|
+
Options<{}>,
|
|
63
71
|
Record<string, ConfigItem>
|
|
64
72
|
>();
|
|
65
73
|
|
|
66
74
|
const getNormalizedConfigs = (options?: Options<{}>) => {
|
|
67
|
-
if (!options
|
|
75
|
+
if (!options) {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const cached = cachedNormalizedConfigs.get(options);
|
|
68
80
|
|
|
69
|
-
|
|
81
|
+
if (cached) {
|
|
82
|
+
return cached;
|
|
83
|
+
}
|
|
70
84
|
|
|
71
|
-
|
|
85
|
+
validatePathConfig(options);
|
|
72
86
|
|
|
73
87
|
const normalizedConfigs = createNormalizedConfigs(options.screens);
|
|
74
88
|
|
|
75
|
-
cachedNormalizedConfigs.set(options
|
|
89
|
+
cachedNormalizedConfigs.set(options, normalizedConfigs);
|
|
76
90
|
|
|
77
91
|
return normalizedConfigs;
|
|
78
92
|
};
|
|
79
93
|
|
|
80
|
-
const getTransformedState = (
|
|
81
|
-
state: State,
|
|
82
|
-
configs: Record<string, ConfigItem> | undefined
|
|
83
|
-
): Omit<PartialState<NavigationState>, 'stale'> => {
|
|
84
|
-
const routes = state.routes.map(
|
|
85
|
-
(route): Omit<PartialState<NavigationState>, 'stale'>['routes'][number] => {
|
|
86
|
-
const config = configs?.[route.name];
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
route.state ||
|
|
90
|
-
(config?.screens &&
|
|
91
|
-
route.params &&
|
|
92
|
-
(('screen' in route.params &&
|
|
93
|
-
typeof route.params.screen === 'string' &&
|
|
94
|
-
config.screens[route.params.screen]) ||
|
|
95
|
-
'state' in route.params))
|
|
96
|
-
) {
|
|
97
|
-
const nestedState: State | undefined =
|
|
98
|
-
route.state ?? getStateFromRouteParams(route.params);
|
|
99
|
-
|
|
100
|
-
if (nestedState) {
|
|
101
|
-
return {
|
|
102
|
-
...route,
|
|
103
|
-
state: getTransformedState(
|
|
104
|
-
nestedState,
|
|
105
|
-
configs?.[route.name]?.screens
|
|
106
|
-
),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// @ts-expect-error route.state is handled in previous condition
|
|
112
|
-
return route;
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
return {
|
|
117
|
-
...state,
|
|
118
|
-
routes,
|
|
119
|
-
};
|
|
120
|
-
};
|
|
121
|
-
|
|
122
94
|
/**
|
|
123
95
|
* Utility to serialize a navigation state object to a path string.
|
|
124
96
|
*
|
|
@@ -158,15 +130,45 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
158
130
|
);
|
|
159
131
|
}
|
|
160
132
|
|
|
161
|
-
if (options) {
|
|
162
|
-
validatePathConfig(options);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
133
|
const configs = getNormalizedConfigs(options);
|
|
166
|
-
const
|
|
134
|
+
const cachedRouteStates = new Map<object, State | undefined>();
|
|
135
|
+
|
|
136
|
+
const getRouteState = (
|
|
137
|
+
route: State['routes'][number],
|
|
138
|
+
config: ConfigItem | undefined
|
|
139
|
+
) => {
|
|
140
|
+
if (route.state) {
|
|
141
|
+
return route.state;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const hasScreenParams =
|
|
145
|
+
route.params &&
|
|
146
|
+
'screen' in route.params &&
|
|
147
|
+
typeof route.params.screen === 'string' &&
|
|
148
|
+
config?.screens?.[route.params.screen];
|
|
149
|
+
|
|
150
|
+
const hasStateParams =
|
|
151
|
+
route.params && 'state' in route.params && config?.screens;
|
|
152
|
+
|
|
153
|
+
if (
|
|
154
|
+
!route.params ||
|
|
155
|
+
!config?.screens ||
|
|
156
|
+
(!hasScreenParams && !hasStateParams)
|
|
157
|
+
) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!cachedRouteStates.has(route)) {
|
|
162
|
+
cachedRouteStates.set(route, getStateFromRouteParams(route.params));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return cachedRouteStates.get(route);
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const focusedRoute = getActiveRoute(state, configs, getRouteState);
|
|
167
169
|
|
|
168
170
|
let path = '/';
|
|
169
|
-
let current: State | undefined =
|
|
171
|
+
let current: State | undefined = state;
|
|
170
172
|
|
|
171
173
|
const allParams: Record<string, string> = {};
|
|
172
174
|
|
|
@@ -187,8 +189,6 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
187
189
|
let focusedParams: Record<string, string> | undefined;
|
|
188
190
|
let currentOptions = configs;
|
|
189
191
|
|
|
190
|
-
const focusedRoute = getActiveRoute(transformedState);
|
|
191
|
-
|
|
192
192
|
// Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
|
|
193
193
|
const nestedRouteNames = [];
|
|
194
194
|
|
|
@@ -262,16 +262,18 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
// If there is no `screens` property or no nested state, we return pattern
|
|
265
|
-
|
|
265
|
+
const routeState = getRouteState(route, config);
|
|
266
|
+
|
|
267
|
+
if (!config.screens || routeState == null) {
|
|
266
268
|
hasNext = false;
|
|
267
269
|
} else {
|
|
268
270
|
index =
|
|
269
|
-
typeof
|
|
270
|
-
?
|
|
271
|
-
:
|
|
271
|
+
typeof routeState.index === 'number'
|
|
272
|
+
? routeState.index
|
|
273
|
+
: routeState.routes.length - 1;
|
|
272
274
|
|
|
273
275
|
const nextRoute: State['routes'][number] | undefined =
|
|
274
|
-
|
|
276
|
+
routeState.routes[index];
|
|
275
277
|
|
|
276
278
|
if (nextRoute == null) {
|
|
277
279
|
throw new Error(`Couldn't find a route at index ${index}.`);
|
|
@@ -290,6 +292,8 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
294
|
|
|
295
|
+
const routeState = getRouteState(route, currentOptions[route.name]);
|
|
296
|
+
|
|
293
297
|
if (currentOptions[route.name] != null) {
|
|
294
298
|
if (parts) {
|
|
295
299
|
let index = 0;
|
|
@@ -345,7 +349,7 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
345
349
|
}
|
|
346
350
|
}
|
|
347
351
|
|
|
348
|
-
if (
|
|
352
|
+
if (routeState) {
|
|
349
353
|
path += '/';
|
|
350
354
|
} else if (focusedParams) {
|
|
351
355
|
const query = queryString.stringify(focusedParams, { sort: false });
|
|
@@ -355,7 +359,7 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
355
359
|
}
|
|
356
360
|
}
|
|
357
361
|
|
|
358
|
-
current =
|
|
362
|
+
current = routeState;
|
|
359
363
|
}
|
|
360
364
|
|
|
361
365
|
// Include the root path if specified
|
package/src/getPatternParts.tsx
CHANGED
|
@@ -52,8 +52,8 @@ export function getPatternParts(path: string): PatternPart[] {
|
|
|
52
52
|
if (regexInnerParens) {
|
|
53
53
|
// The ')' is part of the regex if we're already inside one
|
|
54
54
|
regexInnerParens--;
|
|
55
|
-
current.regex += char;
|
|
56
55
|
} else {
|
|
56
|
+
current.regex += char;
|
|
57
57
|
isRegex = false;
|
|
58
58
|
isParam = false;
|
|
59
59
|
}
|
|
@@ -62,7 +62,7 @@ export function getPatternParts(path: string): PatternPart[] {
|
|
|
62
62
|
`Encountered ')' without preceding '(' in path: ${path}`
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
|
-
} else if (char === '?') {
|
|
65
|
+
} else if (char === '?' && !isRegex) {
|
|
66
66
|
if (current.param) {
|
|
67
67
|
isParam = false;
|
|
68
68
|
|