@react-navigation/core 8.0.0-alpha.23 → 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/NavigationBuilderContext.js.map +1 -1
- 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 +15 -7
- 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 +125 -96
- 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 +136 -78
- 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 +13 -0
- package/lib/module/types.js.map +1 -1
- package/lib/module/useEventEmitter.js +5 -2
- 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 +5 -21
- 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 +25 -3
- package/lib/module/useOnAction.js.map +1 -1
- package/lib/module/useOnPreventRemove.js +35 -24
- package/lib/module/useOnPreventRemove.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/useRoute.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 +50 -37
- 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/NavigationBuilderContext.d.ts +2 -2
- package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
- 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 +68 -42
- 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 +11 -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 +84 -29
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useEventEmitter.d.ts +1 -1
- package/lib/typescript/src/useEventEmitter.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/useOnPreventRemove.d.ts +2 -6
- package/lib/typescript/src/useOnPreventRemove.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/useRoute.d.ts +1 -1
- package/lib/typescript/src/useRoute.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 +21 -38
- package/lib/typescript/src/utilities.d.ts.map +1 -1
- package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
- package/package.json +6 -8
- package/src/BaseNavigationContainer.tsx +9 -2
- package/src/DataLoading.tsx +139 -0
- package/src/NavigationBuilderContext.tsx +5 -1
- 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 +164 -99
- package/src/StaticTreeContext.tsx +7 -0
- package/src/checkSerializable.tsx +20 -14
- package/src/createNavigationContainerRef.tsx +12 -9
- package/src/createNavigatorFactory.tsx +27 -18
- package/src/getActionFromState.tsx +18 -16
- package/src/getPathFromState.tsx +167 -132
- package/src/getPatternParts.tsx +2 -2
- package/src/getStateFromPath.tsx +260 -193
- package/src/index.tsx +3 -0
- package/src/types.tsx +298 -62
- package/src/useEventEmitter.tsx +7 -2
- package/src/useKeyedChildListeners.tsx +4 -2
- package/src/useNavigation.tsx +2 -21
- package/src/useNavigationBuilder.tsx +7 -24
- package/src/useNavigationCache.tsx +26 -19
- package/src/useNavigationHelpers.tsx +26 -9
- package/src/useNavigationState.tsx +90 -60
- package/src/useOnAction.tsx +55 -3
- package/src/useOnPreventRemove.tsx +68 -36
- package/src/useOptionsGetters.tsx +4 -1
- package/src/usePreventRemove.tsx +11 -2
- package/src/useRoute.tsx +3 -5
- package/src/useRouteCache.tsx +19 -11
- package/src/useScheduleUpdate.tsx +8 -7
- package/src/useSyncState.tsx +5 -1
- package/src/utilities.tsx +36 -41
- package/src/validatePathConfig.tsx +86 -58
|
@@ -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
|
@@ -22,8 +22,30 @@ type ConfigItem = {
|
|
|
22
22
|
screens?: Record<string, ConfigItem> | undefined;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
const encodePathParam = (value: string) => {
|
|
26
|
+
let result = '';
|
|
27
|
+
|
|
28
|
+
for (const char of value) {
|
|
29
|
+
const charCode = char.charCodeAt(0);
|
|
30
|
+
const safe =
|
|
31
|
+
(charCode >= 65 && charCode <= 90) ||
|
|
32
|
+
(charCode >= 97 && charCode <= 122) ||
|
|
33
|
+
(charCode >= 48 && charCode <= 57) ||
|
|
34
|
+
"-._~!$&'()*+,;=:@".includes(char);
|
|
35
|
+
|
|
36
|
+
result += safe ? char : encodeURIComponent(char);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
|
|
25
42
|
const getActiveRoute = (
|
|
26
|
-
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
|
|
27
49
|
): { name: string; params?: object | undefined } => {
|
|
28
50
|
const route =
|
|
29
51
|
typeof state.index === 'number'
|
|
@@ -34,74 +56,41 @@ const getActiveRoute = (
|
|
|
34
56
|
throw new Error(`Couldn't find the active route.`);
|
|
35
57
|
}
|
|
36
58
|
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
const config = configs?.[route.name];
|
|
60
|
+
const routeState = getRouteState(route, config);
|
|
61
|
+
|
|
62
|
+
if (routeState) {
|
|
63
|
+
return getActiveRoute(routeState, config?.screens, getRouteState);
|
|
39
64
|
}
|
|
40
65
|
|
|
41
66
|
return route;
|
|
42
67
|
};
|
|
43
68
|
|
|
44
69
|
const cachedNormalizedConfigs = new WeakMap<
|
|
45
|
-
|
|
70
|
+
Options<{}>,
|
|
46
71
|
Record<string, ConfigItem>
|
|
47
72
|
>();
|
|
48
73
|
|
|
49
74
|
const getNormalizedConfigs = (options?: Options<{}>) => {
|
|
50
|
-
if (!options
|
|
75
|
+
if (!options) {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
51
78
|
|
|
52
|
-
const cached = cachedNormalizedConfigs.get(options
|
|
79
|
+
const cached = cachedNormalizedConfigs.get(options);
|
|
80
|
+
|
|
81
|
+
if (cached) {
|
|
82
|
+
return cached;
|
|
83
|
+
}
|
|
53
84
|
|
|
54
|
-
|
|
85
|
+
validatePathConfig(options);
|
|
55
86
|
|
|
56
87
|
const normalizedConfigs = createNormalizedConfigs(options.screens);
|
|
57
88
|
|
|
58
|
-
cachedNormalizedConfigs.set(options
|
|
89
|
+
cachedNormalizedConfigs.set(options, normalizedConfigs);
|
|
59
90
|
|
|
60
91
|
return normalizedConfigs;
|
|
61
92
|
};
|
|
62
93
|
|
|
63
|
-
const getTransformedState = (
|
|
64
|
-
state: State,
|
|
65
|
-
configs: Record<string, ConfigItem> | undefined
|
|
66
|
-
): Omit<PartialState<NavigationState>, 'stale'> => {
|
|
67
|
-
const routes = state.routes.map(
|
|
68
|
-
(route): Omit<PartialState<NavigationState>, 'stale'>['routes'][number] => {
|
|
69
|
-
const config = configs?.[route.name];
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
route.state ||
|
|
73
|
-
(config?.screens &&
|
|
74
|
-
route.params &&
|
|
75
|
-
(('screen' in route.params &&
|
|
76
|
-
typeof route.params.screen === 'string' &&
|
|
77
|
-
config.screens[route.params.screen]) ||
|
|
78
|
-
'state' in route.params))
|
|
79
|
-
) {
|
|
80
|
-
const nestedState: State | undefined =
|
|
81
|
-
route.state ?? getStateFromRouteParams(route.params);
|
|
82
|
-
|
|
83
|
-
if (nestedState) {
|
|
84
|
-
return {
|
|
85
|
-
...route,
|
|
86
|
-
state: getTransformedState(
|
|
87
|
-
nestedState,
|
|
88
|
-
configs?.[route.name]?.screens
|
|
89
|
-
),
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// @ts-expect-error route.state is handled in previous condition
|
|
95
|
-
return route;
|
|
96
|
-
}
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
...state,
|
|
101
|
-
routes,
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
|
|
105
94
|
/**
|
|
106
95
|
* Utility to serialize a navigation state object to a path string.
|
|
107
96
|
*
|
|
@@ -141,15 +130,45 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
141
130
|
);
|
|
142
131
|
}
|
|
143
132
|
|
|
144
|
-
if (options) {
|
|
145
|
-
validatePathConfig(options);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
133
|
const configs = getNormalizedConfigs(options);
|
|
149
|
-
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);
|
|
150
169
|
|
|
151
170
|
let path = '/';
|
|
152
|
-
let current: State | undefined =
|
|
171
|
+
let current: State | undefined = state;
|
|
153
172
|
|
|
154
173
|
const allParams: Record<string, string> = {};
|
|
155
174
|
|
|
@@ -170,8 +189,6 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
170
189
|
let focusedParams: Record<string, string> | undefined;
|
|
171
190
|
let currentOptions = configs;
|
|
172
191
|
|
|
173
|
-
const focusedRoute = getActiveRoute(transformedState);
|
|
174
|
-
|
|
175
192
|
// Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
|
|
176
193
|
const nestedRouteNames = [];
|
|
177
194
|
|
|
@@ -190,30 +207,31 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
190
207
|
|
|
191
208
|
if (route.params) {
|
|
192
209
|
const options = config;
|
|
210
|
+
const params = route.params as Record<string, unknown>;
|
|
211
|
+
const currentParams: Record<string, string> = {};
|
|
212
|
+
|
|
213
|
+
for (const key in params) {
|
|
214
|
+
const value = params[key];
|
|
193
215
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
)?.optional;
|
|
202
|
-
|
|
203
|
-
if (optional) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
216
|
+
if (value === undefined) {
|
|
217
|
+
let optional = false;
|
|
218
|
+
|
|
219
|
+
for (const part of options.parts ?? []) {
|
|
220
|
+
if (part.param === key) {
|
|
221
|
+
optional = part.optional === true;
|
|
222
|
+
break;
|
|
209
223
|
}
|
|
224
|
+
}
|
|
210
225
|
|
|
211
|
-
|
|
226
|
+
if (optional) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
212
230
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
231
|
+
const stringify = options.stringify?.[key] ?? String;
|
|
232
|
+
|
|
233
|
+
currentParams[key] = stringify(value);
|
|
234
|
+
}
|
|
217
235
|
|
|
218
236
|
if (parts?.length) {
|
|
219
237
|
Object.assign(allParams, currentParams);
|
|
@@ -222,33 +240,40 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
222
240
|
if (focusedRoute === route) {
|
|
223
241
|
// If this is the focused route, keep the params for later use
|
|
224
242
|
// We save it here since it's been stringified already
|
|
225
|
-
focusedParams = {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
delete focusedParams[param];
|
|
235
|
-
}
|
|
243
|
+
focusedParams = {};
|
|
244
|
+
|
|
245
|
+
for (const key in currentParams) {
|
|
246
|
+
let inPattern = false;
|
|
247
|
+
|
|
248
|
+
for (const part of parts ?? []) {
|
|
249
|
+
if (part.param === key) {
|
|
250
|
+
inPattern = true;
|
|
251
|
+
break;
|
|
236
252
|
}
|
|
237
|
-
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const value = currentParams[key];
|
|
256
|
+
|
|
257
|
+
if (!inPattern && value !== undefined && value !== 'undefined') {
|
|
258
|
+
focusedParams[key] = value;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
238
261
|
}
|
|
239
262
|
}
|
|
240
263
|
|
|
241
264
|
// If there is no `screens` property or no nested state, we return pattern
|
|
242
|
-
|
|
265
|
+
const routeState = getRouteState(route, config);
|
|
266
|
+
|
|
267
|
+
if (!config.screens || routeState == null) {
|
|
243
268
|
hasNext = false;
|
|
244
269
|
} else {
|
|
245
270
|
index =
|
|
246
|
-
typeof
|
|
247
|
-
?
|
|
248
|
-
:
|
|
271
|
+
typeof routeState.index === 'number'
|
|
272
|
+
? routeState.index
|
|
273
|
+
: routeState.routes.length - 1;
|
|
249
274
|
|
|
250
275
|
const nextRoute: State['routes'][number] | undefined =
|
|
251
|
-
|
|
276
|
+
routeState.routes[index];
|
|
252
277
|
|
|
253
278
|
if (nextRoute == null) {
|
|
254
279
|
throw new Error(`Couldn't find a route at index ${index}.`);
|
|
@@ -267,14 +292,25 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
267
292
|
}
|
|
268
293
|
}
|
|
269
294
|
|
|
295
|
+
const routeState = getRouteState(route, currentOptions[route.name]);
|
|
296
|
+
|
|
270
297
|
if (currentOptions[route.name] != null) {
|
|
271
|
-
|
|
272
|
-
|
|
298
|
+
if (parts) {
|
|
299
|
+
let index = 0;
|
|
300
|
+
|
|
301
|
+
for (const { segment, param, optional } of parts) {
|
|
302
|
+
if (index > 0) {
|
|
303
|
+
path += '/';
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
index++;
|
|
307
|
+
|
|
273
308
|
// We don't know what to show for wildcard patterns
|
|
274
309
|
// Showing the route name seems ok, though whatever we show here will be incorrect
|
|
275
310
|
// Since the page doesn't actually exist
|
|
276
311
|
if (segment === '*') {
|
|
277
|
-
|
|
312
|
+
path += route.name;
|
|
313
|
+
continue;
|
|
278
314
|
}
|
|
279
315
|
|
|
280
316
|
// If the path has a pattern for a param, put the param in the path
|
|
@@ -283,46 +319,39 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
283
319
|
|
|
284
320
|
if (value === undefined && optional) {
|
|
285
321
|
// Optional params without value assigned in route.params should be ignored
|
|
286
|
-
|
|
322
|
+
continue;
|
|
287
323
|
}
|
|
288
324
|
|
|
289
325
|
// Valid characters according to
|
|
290
326
|
// https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 (see pchar definition)
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
/[^A-Za-z0-9\-._~!$&'()*+,;=:@]/g.test(char)
|
|
294
|
-
? encodeURIComponent(char)
|
|
295
|
-
: char
|
|
296
|
-
)
|
|
297
|
-
.join('');
|
|
327
|
+
path += encodePathParam(String(value));
|
|
328
|
+
continue;
|
|
298
329
|
}
|
|
299
330
|
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
|
|
331
|
+
path += encodeURIComponent(segment);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
303
334
|
} else {
|
|
304
335
|
path += encodeURIComponent(route.name);
|
|
305
336
|
}
|
|
306
337
|
|
|
307
338
|
if (!focusedParams && focusedRoute.params) {
|
|
308
|
-
focusedParams =
|
|
309
|
-
Object.entries(focusedRoute.params).map(([key, value]) => [
|
|
310
|
-
key,
|
|
311
|
-
String(value),
|
|
312
|
-
])
|
|
313
|
-
);
|
|
314
|
-
}
|
|
339
|
+
focusedParams = {};
|
|
315
340
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
341
|
+
const params = focusedRoute.params as Record<string, unknown>;
|
|
342
|
+
|
|
343
|
+
for (const key in params) {
|
|
344
|
+
const value = String(params[key]);
|
|
345
|
+
|
|
346
|
+
if (value !== 'undefined') {
|
|
347
|
+
focusedParams[key] = value;
|
|
323
348
|
}
|
|
324
349
|
}
|
|
350
|
+
}
|
|
325
351
|
|
|
352
|
+
if (routeState) {
|
|
353
|
+
path += '/';
|
|
354
|
+
} else if (focusedParams) {
|
|
326
355
|
const query = queryString.stringify(focusedParams, { sort: false });
|
|
327
356
|
|
|
328
357
|
if (query) {
|
|
@@ -330,7 +359,7 @@ export function getPathFromState<ParamList extends {}>(
|
|
|
330
359
|
}
|
|
331
360
|
}
|
|
332
361
|
|
|
333
|
-
current =
|
|
362
|
+
current = routeState;
|
|
334
363
|
}
|
|
335
364
|
|
|
336
365
|
// Include the root path if specified
|
|
@@ -399,11 +428,17 @@ const createConfigItem = (
|
|
|
399
428
|
const createNormalizedConfigs = (
|
|
400
429
|
options: PathConfigMap<object>,
|
|
401
430
|
parts?: PatternPart[]
|
|
402
|
-
): Record<string, ConfigItem> =>
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
431
|
+
): Record<string, ConfigItem> => {
|
|
432
|
+
const configs: Record<string, ConfigItem> = {};
|
|
433
|
+
const screens = options as Record<string, PathConfig<{}> | string>;
|
|
434
|
+
|
|
435
|
+
for (const name in screens) {
|
|
436
|
+
const config = screens[name];
|
|
437
|
+
|
|
438
|
+
if (config !== undefined) {
|
|
439
|
+
configs[name] = createConfigItem(config, parts);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return configs;
|
|
444
|
+
};
|
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
|
|