@react-navigation/core 8.0.0-alpha.22 → 8.0.0-alpha.24
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/NavigationBuilderContext.js.map +1 -1
- package/lib/module/StaticNavigation.js +1 -1
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/createNavigatorFactory.js.map +1 -1
- package/lib/module/getPathFromState.js +87 -57
- package/lib/module/getPathFromState.js.map +1 -1
- package/lib/module/getStateFromPath.js +77 -46
- package/lib/module/getStateFromPath.js.map +1 -1
- 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 +4 -1
- package/lib/module/useEventEmitter.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +11 -14
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useOnAction.js +4 -1
- 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/useRoute.js.map +1 -1
- package/lib/module/validatePathConfig.js +50 -37
- package/lib/module/validatePathConfig.js.map +1 -1
- package/lib/typescript/src/NavigationBuilderContext.d.ts +2 -2
- package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
- package/lib/typescript/src/StaticNavigation.d.ts +3 -3
- package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
- package/lib/typescript/src/createNavigatorFactory.d.ts +4 -2
- package/lib/typescript/src/createNavigatorFactory.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 +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +66 -33
- 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/useNavigationBuilder.d.ts +0 -7
- package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationHelpers.d.ts +0 -7
- package/lib/typescript/src/useNavigationHelpers.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/useRoute.d.ts +1 -1
- package/lib/typescript/src/useRoute.d.ts.map +1 -1
- package/lib/typescript/src/utilities.d.ts +4 -38
- package/lib/typescript/src/utilities.d.ts.map +1 -1
- package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/NavigationBuilderContext.tsx +5 -1
- package/src/StaticNavigation.tsx +7 -6
- package/src/createNavigatorFactory.tsx +23 -2
- package/src/getPathFromState.tsx +97 -66
- package/src/getStateFromPath.tsx +168 -142
- package/src/index.tsx +1 -0
- package/src/types.tsx +257 -54
- package/src/useEventEmitter.tsx +6 -1
- package/src/useNavigationBuilder.tsx +11 -15
- package/src/useOnAction.tsx +6 -2
- package/src/useOnPreventRemove.tsx +68 -36
- package/src/useRoute.tsx +3 -5
- package/src/utilities.tsx +8 -41
- package/src/validatePathConfig.tsx +85 -58
package/src/types.tsx
CHANGED
|
@@ -287,6 +287,45 @@ export class PrivateValueStore<T extends [any, any, any, any]> {
|
|
|
287
287
|
protected ''?: T;
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
type NavigatorLike =
|
|
291
|
+
| {
|
|
292
|
+
Navigator: React.ComponentType<any>;
|
|
293
|
+
Screen: unknown;
|
|
294
|
+
Group: unknown;
|
|
295
|
+
}
|
|
296
|
+
| {
|
|
297
|
+
config: unknown;
|
|
298
|
+
getComponent: () => React.ComponentType<any>;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
type ParamListForNavigator<T extends {}> = T extends NavigatorLike
|
|
302
|
+
? T extends PrivateValueStore<[infer ParamList extends {}, any, any, any]>
|
|
303
|
+
? ParamList
|
|
304
|
+
: T
|
|
305
|
+
: T;
|
|
306
|
+
|
|
307
|
+
// Remove `undefined` before checking for nested navigator params.
|
|
308
|
+
// If nothing remains, avoid matching `never` against `NavigatorScreenParams`
|
|
309
|
+
type NestedNavigatorForScreenParams<T, Params = NotUndefined<T>> = [
|
|
310
|
+
Params,
|
|
311
|
+
] extends [never]
|
|
312
|
+
? never
|
|
313
|
+
: Params extends NavigatorScreenParams<infer Navigator>
|
|
314
|
+
? Navigator extends PrivateValueStore<[any, any, any, any]>
|
|
315
|
+
? Navigator extends NavigatorLike
|
|
316
|
+
? Navigator
|
|
317
|
+
: never
|
|
318
|
+
: never
|
|
319
|
+
: never;
|
|
320
|
+
|
|
321
|
+
export type NestedNavigatorsForParamList<ParamList extends {}> = {
|
|
322
|
+
[RouteName in keyof ParamList as NestedNavigatorForScreenParams<
|
|
323
|
+
ParamList[RouteName]
|
|
324
|
+
> extends never
|
|
325
|
+
? never
|
|
326
|
+
: RouteName]: NestedNavigatorForScreenParams<ParamList[RouteName]>;
|
|
327
|
+
};
|
|
328
|
+
|
|
290
329
|
type NavigateOptions = {
|
|
291
330
|
merge?: boolean | undefined;
|
|
292
331
|
pop?: boolean | undefined;
|
|
@@ -336,27 +375,6 @@ type NavigationHelpersCommon<
|
|
|
336
375
|
: never
|
|
337
376
|
): void;
|
|
338
377
|
|
|
339
|
-
/**
|
|
340
|
-
* Navigate to a route in current navigation tree.
|
|
341
|
-
*
|
|
342
|
-
* @param options.name Name of the route to navigate to.
|
|
343
|
-
* @param [options.params] Params object for the route.
|
|
344
|
-
* @param [options.path] Path to associate the route with (e.g. for deep links).
|
|
345
|
-
* @param [options.merge] Whether to merge the params onto the route. Defaults to `false`.
|
|
346
|
-
* @param [options.pop] Whether to pop routes in a stack to go back to the matching route. Defaults to `false`.
|
|
347
|
-
*/
|
|
348
|
-
navigate<RouteName extends keyof ParamList>(
|
|
349
|
-
options: RouteName extends unknown
|
|
350
|
-
? {
|
|
351
|
-
name: RouteName;
|
|
352
|
-
params: ParamList[RouteName];
|
|
353
|
-
path?: string | undefined;
|
|
354
|
-
merge?: boolean | undefined;
|
|
355
|
-
pop?: boolean | undefined;
|
|
356
|
-
}
|
|
357
|
-
: never
|
|
358
|
-
): void;
|
|
359
|
-
|
|
360
378
|
/**
|
|
361
379
|
* Preloads the route in current navigation tree.
|
|
362
380
|
*
|
|
@@ -933,15 +951,19 @@ export type NavigationContainerEventMap = {
|
|
|
933
951
|
/**
|
|
934
952
|
* The data object passed when emitting the event.
|
|
935
953
|
*/
|
|
936
|
-
data
|
|
954
|
+
data?: unknown;
|
|
937
955
|
/**
|
|
938
956
|
* The key of the target route which received the event.
|
|
939
957
|
*/
|
|
940
|
-
target
|
|
958
|
+
target?: string | undefined;
|
|
941
959
|
/**
|
|
942
960
|
* Whether `event.preventDefault()` was called on this event.
|
|
943
961
|
*/
|
|
944
|
-
defaultPrevented
|
|
962
|
+
defaultPrevented?: boolean | undefined;
|
|
963
|
+
/**
|
|
964
|
+
* Prevent the default action which happens on this event.
|
|
965
|
+
*/
|
|
966
|
+
preventDefault?: (() => void) | undefined;
|
|
945
967
|
};
|
|
946
968
|
};
|
|
947
969
|
};
|
|
@@ -1021,8 +1043,8 @@ export type RouteForName<
|
|
|
1021
1043
|
// Look up route object by checking each level and recursing into the nested param lists
|
|
1022
1044
|
// This avoids building a union of all routes, which doesn't scale on large trees
|
|
1023
1045
|
type RouteForNameInternal<ParamList extends {}, RouteName extends string> =
|
|
1024
|
-
| (RouteName extends
|
|
1025
|
-
? RouteProp<ParamList,
|
|
1046
|
+
| (RouteName extends KeyOf<ParamList>
|
|
1047
|
+
? RouteProp<ParamList, RouteName>
|
|
1026
1048
|
: never)
|
|
1027
1049
|
| RouteForNameNested<NestedParamLists<ParamList>, RouteName>;
|
|
1028
1050
|
|
|
@@ -1031,11 +1053,7 @@ type RouteForNameNested<ParamLists, RouteName extends string> =
|
|
|
1031
1053
|
// e.g. if ParamLists is A | B
|
|
1032
1054
|
// TypeScript evaluates the branch once per member (A, then B)
|
|
1033
1055
|
// and unions the outcomes
|
|
1034
|
-
|
|
1035
|
-
// and re-asserts the {} constraint that RouteForNameInternal requires
|
|
1036
|
-
ParamLists extends infer ParamList extends {}
|
|
1037
|
-
? RouteForNameInternal<ParamList, RouteName>
|
|
1038
|
-
: never;
|
|
1056
|
+
ParamLists extends {} ? RouteForNameInternal<ParamLists, RouteName> : never;
|
|
1039
1057
|
|
|
1040
1058
|
/**
|
|
1041
1059
|
* Union of param lists of the nested navigators in a param list.
|
|
@@ -1043,7 +1061,7 @@ type RouteForNameNested<ParamLists, RouteName extends string> =
|
|
|
1043
1061
|
export type NestedParamLists<ParamList extends {}> = {
|
|
1044
1062
|
[RouteName in keyof ParamList]: NavigatorScreenParams<{}> extends ParamList[RouteName]
|
|
1045
1063
|
? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<infer T>
|
|
1046
|
-
? T
|
|
1064
|
+
? ParamListForNavigator<T>
|
|
1047
1065
|
: never
|
|
1048
1066
|
: never;
|
|
1049
1067
|
}[keyof ParamList];
|
|
@@ -1051,7 +1069,9 @@ export type NestedParamLists<ParamList extends {}> = {
|
|
|
1051
1069
|
type ParamListRoute<ParamList extends {}> = {
|
|
1052
1070
|
[RouteName in keyof ParamList]: NavigatorScreenParams<{}> extends ParamList[RouteName]
|
|
1053
1071
|
? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<infer T>
|
|
1054
|
-
?
|
|
1072
|
+
?
|
|
1073
|
+
| ParamListRoute<ParamListForNavigator<T>>
|
|
1074
|
+
| RouteProp<ParamList, RouteName>
|
|
1055
1075
|
: RouteProp<ParamList, RouteName>
|
|
1056
1076
|
: RouteProp<ParamList, RouteName>;
|
|
1057
1077
|
}[keyof ParamList];
|
|
@@ -1077,13 +1097,15 @@ type BasicNavigationList<
|
|
|
1077
1097
|
? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<
|
|
1078
1098
|
infer T
|
|
1079
1099
|
>
|
|
1080
|
-
?
|
|
1081
|
-
?
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1100
|
+
? ParamListForNavigator<T> extends infer NestedParamList extends {}
|
|
1101
|
+
? keyof NestedParamList extends ExcludedRouteNames
|
|
1102
|
+
? {}
|
|
1103
|
+
: BasicNavigationList<
|
|
1104
|
+
NestedParamList,
|
|
1105
|
+
ExcludedRouteNames,
|
|
1106
|
+
NavigationProp<ParamList, RouteName>
|
|
1107
|
+
>
|
|
1108
|
+
: {}
|
|
1087
1109
|
: {}
|
|
1088
1110
|
: {}) &
|
|
1089
1111
|
(RouteName extends ExcludedRouteNames
|
|
@@ -1097,6 +1119,105 @@ type BasicNavigationList<
|
|
|
1097
1119
|
}[keyof ParamList]
|
|
1098
1120
|
>;
|
|
1099
1121
|
|
|
1122
|
+
type InheritedParentParams<ParentParamList, ParamList> = {
|
|
1123
|
+
[K in keyof ParentParamList as K extends keyof ParamList
|
|
1124
|
+
? never
|
|
1125
|
+
: string extends K
|
|
1126
|
+
? never
|
|
1127
|
+
: K]: ParentParamList[K];
|
|
1128
|
+
};
|
|
1129
|
+
|
|
1130
|
+
type GenericNavigationComposite<
|
|
1131
|
+
ParamList extends ParamListBase,
|
|
1132
|
+
RouteName extends keyof ParamList,
|
|
1133
|
+
Parent,
|
|
1134
|
+
> =
|
|
1135
|
+
Parent extends NavigationProp<any, any, any, any, any>
|
|
1136
|
+
? ParamListOfNavigationProp<Parent> extends infer ParentParamList
|
|
1137
|
+
? NavigationProp<
|
|
1138
|
+
ParamList & InheritedParentParams<ParentParamList, ParamList>,
|
|
1139
|
+
RouteName
|
|
1140
|
+
> & { getParent: Parent['getParent'] }
|
|
1141
|
+
: never
|
|
1142
|
+
: NavigationProp<ParamList, RouteName>;
|
|
1143
|
+
|
|
1144
|
+
type NavigationListForScreenParams<
|
|
1145
|
+
T extends {},
|
|
1146
|
+
ParamList extends ParamListBase,
|
|
1147
|
+
RouteName extends keyof ParamList,
|
|
1148
|
+
ExcludedRouteNames,
|
|
1149
|
+
Parent extends NavigationProp<any, any, any, any, any> | undefined,
|
|
1150
|
+
> =
|
|
1151
|
+
T extends PrivateValueStore<[any, any, any, any]>
|
|
1152
|
+
? T extends NavigatorLike
|
|
1153
|
+
? NavigationListForNestedInternal<
|
|
1154
|
+
T,
|
|
1155
|
+
GenericNavigationComposite<ParamList, RouteName, Parent>
|
|
1156
|
+
>
|
|
1157
|
+
: NavigationListForParamListScreenParams<
|
|
1158
|
+
T,
|
|
1159
|
+
ParamList,
|
|
1160
|
+
RouteName,
|
|
1161
|
+
ExcludedRouteNames,
|
|
1162
|
+
Parent
|
|
1163
|
+
>
|
|
1164
|
+
: NavigationListForParamListScreenParams<
|
|
1165
|
+
T,
|
|
1166
|
+
ParamList,
|
|
1167
|
+
RouteName,
|
|
1168
|
+
ExcludedRouteNames,
|
|
1169
|
+
Parent
|
|
1170
|
+
>;
|
|
1171
|
+
|
|
1172
|
+
type NavigationListForParamListScreenParams<
|
|
1173
|
+
T extends {},
|
|
1174
|
+
ParamList extends ParamListBase,
|
|
1175
|
+
RouteName extends keyof ParamList,
|
|
1176
|
+
ExcludedRouteNames,
|
|
1177
|
+
Parent extends NavigationProp<any, any, any, any, any> | undefined,
|
|
1178
|
+
> =
|
|
1179
|
+
// `T` is only ever a plain param list here, since navigators are routed to
|
|
1180
|
+
// `NavigationListForNestedInternal` by `NavigationListForScreenParams`.
|
|
1181
|
+
// So there's no navigator to unwrap with `ParamListForNavigator`.
|
|
1182
|
+
T extends ParamListBase
|
|
1183
|
+
? BasicNavigationListForParamList<
|
|
1184
|
+
T,
|
|
1185
|
+
ExcludedRouteNames,
|
|
1186
|
+
GenericNavigationComposite<ParamList, RouteName, Parent>
|
|
1187
|
+
>
|
|
1188
|
+
: {};
|
|
1189
|
+
|
|
1190
|
+
type BasicNavigationListForParamList<
|
|
1191
|
+
ParamList extends ParamListBase,
|
|
1192
|
+
ExcludedRouteNames,
|
|
1193
|
+
Parent extends NavigationProp<any, any, any, any, any> | undefined,
|
|
1194
|
+
> = UnionToIntersection<
|
|
1195
|
+
{
|
|
1196
|
+
[RouteName in keyof ParamList]: (NavigatorScreenParams<{}> extends ParamList[RouteName]
|
|
1197
|
+
? NotUndefined<ParamList[RouteName]> extends NavigatorScreenParams<
|
|
1198
|
+
infer T
|
|
1199
|
+
>
|
|
1200
|
+
? NavigationListForScreenParams<
|
|
1201
|
+
T,
|
|
1202
|
+
ParamList,
|
|
1203
|
+
RouteName,
|
|
1204
|
+
ExcludedRouteNames,
|
|
1205
|
+
Parent
|
|
1206
|
+
>
|
|
1207
|
+
: {}
|
|
1208
|
+
: {}) &
|
|
1209
|
+
(RouteName extends ExcludedRouteNames
|
|
1210
|
+
? {}
|
|
1211
|
+
: {
|
|
1212
|
+
[Key in RouteName]: GenericNavigationComposite<
|
|
1213
|
+
ParamList,
|
|
1214
|
+
RouteName,
|
|
1215
|
+
Parent
|
|
1216
|
+
>;
|
|
1217
|
+
});
|
|
1218
|
+
}[keyof ParamList]
|
|
1219
|
+
>;
|
|
1220
|
+
|
|
1100
1221
|
export type NavigationListForNavigator<Navigator> =
|
|
1101
1222
|
Navigator extends PrivateValueStore<infer Value> ? Value[1] : {};
|
|
1102
1223
|
|
|
@@ -1115,13 +1236,14 @@ type NavigationListForNestedInternal<
|
|
|
1115
1236
|
Parent = undefined,
|
|
1116
1237
|
NavigatorList extends Record<string, any> =
|
|
1117
1238
|
NavigationListForNavigator<Navigator>,
|
|
1239
|
+
Navigators = NestedNavigatorsOf<Navigator>,
|
|
1118
1240
|
// This navigator's own routes, each composed with the accumulated parent.
|
|
1119
1241
|
// It's threaded into the recursion as the parent for nested navigators so
|
|
1120
1242
|
// each route is composed with its ancestors exactly once, instead of
|
|
1121
1243
|
// re-wrapping the whole descendant list at every level (which is quadratic
|
|
1122
1244
|
// in the nesting depth).
|
|
1123
1245
|
ComposedList = ComposeNavigationList<NavigatorList, Parent>,
|
|
1124
|
-
> = Navigator extends {
|
|
1246
|
+
> = (Navigator extends {
|
|
1125
1247
|
readonly config: {
|
|
1126
1248
|
readonly screens?: infer Screens;
|
|
1127
1249
|
readonly groups?: infer Groups;
|
|
@@ -1130,7 +1252,69 @@ type NavigationListForNestedInternal<
|
|
|
1130
1252
|
? ComposedList &
|
|
1131
1253
|
NavigationListForScreens<ComposedList, Screens> &
|
|
1132
1254
|
NavigationListForGroups<ComposedList, Groups>
|
|
1133
|
-
: ComposedList
|
|
1255
|
+
: ComposedList) &
|
|
1256
|
+
NavigationListForNestedNavigators<ComposedList, Navigators> &
|
|
1257
|
+
NavigationListForDynamicNestedParamLists<Navigator, ComposedList, Navigators>;
|
|
1258
|
+
|
|
1259
|
+
type NavigationListForDynamicNestedParamLists<
|
|
1260
|
+
Navigator,
|
|
1261
|
+
ParentList,
|
|
1262
|
+
Navigators,
|
|
1263
|
+
> = Navigator extends { readonly config: unknown }
|
|
1264
|
+
? {}
|
|
1265
|
+
: Navigator extends PrivateValueStore<[infer ParamList, any, any, any]>
|
|
1266
|
+
? NavigationListForNestedParamLists<ParentList, ParamList, Navigators>
|
|
1267
|
+
: {};
|
|
1268
|
+
|
|
1269
|
+
// Map of route name to nested navigator type
|
|
1270
|
+
// inferred from `NavigatorScreenParams<typeof Navigator>`
|
|
1271
|
+
type NestedNavigatorsOf<Navigator> =
|
|
1272
|
+
Navigator extends PrivateValueStore<[any, any, any, infer Nesting]>
|
|
1273
|
+
? Nesting extends Record<string, any>
|
|
1274
|
+
? Nesting
|
|
1275
|
+
: {}
|
|
1276
|
+
: {};
|
|
1277
|
+
|
|
1278
|
+
// Like `NavigationListForScreens`, but reads nested navigators from the brand
|
|
1279
|
+
// map instead of a static config.
|
|
1280
|
+
type NavigationListForNestedNavigators<ParentList, Navigators> =
|
|
1281
|
+
UnionToIntersection<
|
|
1282
|
+
{
|
|
1283
|
+
[K in keyof Navigators]: K extends keyof ParentList
|
|
1284
|
+
? NavigationListForNestedInternal<Navigators[K], ParentList[K]>
|
|
1285
|
+
: {};
|
|
1286
|
+
}[keyof Navigators]
|
|
1287
|
+
>;
|
|
1288
|
+
|
|
1289
|
+
// Fallback for dynamic nested routes declared through NavigatorScreenParams<ParamList>.
|
|
1290
|
+
// Param-list branches expose generic navigation props, while nested navigator
|
|
1291
|
+
// entries still recover their concrete navigator props.
|
|
1292
|
+
type NavigationListForNestedParamLists<ParentList, ParamList, Navigators> =
|
|
1293
|
+
ParentList extends Record<string, any>
|
|
1294
|
+
? ParamList extends ParamListBase
|
|
1295
|
+
? UnionToIntersection<
|
|
1296
|
+
{
|
|
1297
|
+
[K in keyof ParamList]: K extends keyof Navigators
|
|
1298
|
+
? {}
|
|
1299
|
+
: K extends keyof ParentList
|
|
1300
|
+
? NavigatorScreenParams<{}> extends ParamList[K]
|
|
1301
|
+
? NotUndefined<ParamList[K]> extends NavigatorScreenParams<
|
|
1302
|
+
infer T
|
|
1303
|
+
>
|
|
1304
|
+
? NavigationListForScreenParams<
|
|
1305
|
+
T,
|
|
1306
|
+
ParamList,
|
|
1307
|
+
K,
|
|
1308
|
+
keyof ParentList,
|
|
1309
|
+
ParentList[K]
|
|
1310
|
+
>
|
|
1311
|
+
: {}
|
|
1312
|
+
: {}
|
|
1313
|
+
: {};
|
|
1314
|
+
}[keyof ParamList]
|
|
1315
|
+
>
|
|
1316
|
+
: {}
|
|
1317
|
+
: {};
|
|
1134
1318
|
|
|
1135
1319
|
// Compose every entry in a navigator's list with the accumulated parent.
|
|
1136
1320
|
// When there's no parent (root navigator), the list is returned as-is so the
|
|
@@ -1291,6 +1475,7 @@ type TypedNavigatorStatic<
|
|
|
1291
1475
|
export type TypedNavigator<
|
|
1292
1476
|
Bag extends NavigatorTypeBagBase,
|
|
1293
1477
|
Config = unknown,
|
|
1478
|
+
Nesting = unknown,
|
|
1294
1479
|
> = (undefined extends Config
|
|
1295
1480
|
? TypedNavigatorInternal<
|
|
1296
1481
|
Bag['ParamList'],
|
|
@@ -1302,7 +1487,7 @@ export type TypedNavigator<
|
|
|
1302
1487
|
>
|
|
1303
1488
|
: TypedNavigatorStatic<Bag, Config>) &
|
|
1304
1489
|
PrivateValueStore<
|
|
1305
|
-
[Bag['ParamList'], Bag['NavigationList'], unknown,
|
|
1490
|
+
[Bag['ParamList'], Bag['NavigationList'], unknown, Nesting]
|
|
1306
1491
|
>;
|
|
1307
1492
|
|
|
1308
1493
|
type TypedNavigatorInternal<
|
|
@@ -1350,7 +1535,17 @@ type TypedNavigatorInternal<
|
|
|
1350
1535
|
) => null;
|
|
1351
1536
|
};
|
|
1352
1537
|
|
|
1353
|
-
|
|
1538
|
+
declare const NavigatorScreenParamsSymbol: unique symbol;
|
|
1539
|
+
|
|
1540
|
+
type NavigatorScreenParamsBrand<T extends {}> = {
|
|
1541
|
+
// Preserve the original generic for inference without affecting assignability.
|
|
1542
|
+
// - The symbol key hides the property from normal object usage
|
|
1543
|
+
// - The actual type is intersected for inference
|
|
1544
|
+
// - The `any` makes the property effectively `any` for assignability
|
|
1545
|
+
readonly [NavigatorScreenParamsSymbol]?: any & { readonly type: T };
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
type NavigatorScreenParamsForParamList<ParamList extends {}> =
|
|
1354
1549
|
| {
|
|
1355
1550
|
screen?: never;
|
|
1356
1551
|
params?: never;
|
|
@@ -1385,6 +1580,10 @@ export type NavigatorScreenParams<ParamList extends {}> =
|
|
|
1385
1580
|
};
|
|
1386
1581
|
}[keyof ParamList];
|
|
1387
1582
|
|
|
1583
|
+
export type NavigatorScreenParams<ParamList extends {}> =
|
|
1584
|
+
NavigatorScreenParamsForParamList<ParamListForNavigator<ParamList>> &
|
|
1585
|
+
NavigatorScreenParamsBrand<ParamList>;
|
|
1586
|
+
|
|
1388
1587
|
type ParseConfig<Params> = {
|
|
1389
1588
|
[K in keyof Params]?:
|
|
1390
1589
|
| ((value: string) => Params[K])
|
|
@@ -1452,16 +1651,20 @@ export type PathConfig<Params> = FlatType<
|
|
|
1452
1651
|
*/
|
|
1453
1652
|
alias?: (string | PathConfigAlias<Params>)[] | undefined;
|
|
1454
1653
|
} & (NonNullable<Params> extends NavigatorScreenParams<infer ParamList>
|
|
1455
|
-
? {
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1654
|
+
? ParamListForNavigator<ParamList> extends infer ChildParamList extends {}
|
|
1655
|
+
? {
|
|
1656
|
+
/**
|
|
1657
|
+
* Path configuration for child screens.
|
|
1658
|
+
*/
|
|
1659
|
+
screens?: PathConfigMap<ChildParamList> | undefined;
|
|
1660
|
+
/**
|
|
1661
|
+
* Name of the initial route to use for the navigator when the path matches.
|
|
1662
|
+
*/
|
|
1663
|
+
initialRouteName?:
|
|
1664
|
+
| Extract<keyof ChildParamList, string>
|
|
1665
|
+
| undefined;
|
|
1666
|
+
}
|
|
1667
|
+
: {}
|
|
1465
1668
|
: {})
|
|
1466
1669
|
>;
|
|
1467
1670
|
|
package/src/useEventEmitter.tsx
CHANGED
|
@@ -13,12 +13,15 @@ type Listeners = Set<(e: any) => void>;
|
|
|
13
13
|
* Hook to manage the event system used by the navigator to notify screens of various events.
|
|
14
14
|
*/
|
|
15
15
|
export function useEventEmitter<T extends Record<string, any>>(
|
|
16
|
-
listen?: (e: any) => void
|
|
16
|
+
listen?: (e: any) => void,
|
|
17
|
+
onPostEmit?: (e: any) => void
|
|
17
18
|
): NavigationEventEmitter<T> {
|
|
18
19
|
const listenRef = React.useRef(listen);
|
|
20
|
+
const onPostEmitRef = React.useRef(onPostEmit);
|
|
19
21
|
|
|
20
22
|
React.useEffect(() => {
|
|
21
23
|
listenRef.current = listen;
|
|
24
|
+
onPostEmitRef.current = onPostEmit;
|
|
22
25
|
});
|
|
23
26
|
|
|
24
27
|
const listeners = React.useRef<Record<string, Record<string, Listeners>>>(
|
|
@@ -124,6 +127,8 @@ export function useEventEmitter<T extends Record<string, any>>(
|
|
|
124
127
|
|
|
125
128
|
callbacks?.forEach((cb) => cb(event));
|
|
126
129
|
|
|
130
|
+
onPostEmitRef.current?.(event);
|
|
131
|
+
|
|
127
132
|
return event as any;
|
|
128
133
|
},
|
|
129
134
|
[]
|
|
@@ -687,13 +687,16 @@ export function useNavigationBuilder<
|
|
|
687
687
|
}
|
|
688
688
|
} else {
|
|
689
689
|
// If the route was updated with new screen name and/or params, we should navigate there
|
|
690
|
-
action =
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
690
|
+
action = {
|
|
691
|
+
type: 'NAVIGATE',
|
|
692
|
+
payload: {
|
|
693
|
+
name: route.params.screen,
|
|
694
|
+
params: route.params.params,
|
|
695
|
+
path: route.params.path,
|
|
696
|
+
merge: route.params.merge,
|
|
697
|
+
pop: route.params.pop,
|
|
698
|
+
},
|
|
699
|
+
} as const;
|
|
697
700
|
}
|
|
698
701
|
}
|
|
699
702
|
|
|
@@ -874,14 +877,7 @@ export function useNavigationBuilder<
|
|
|
874
877
|
|
|
875
878
|
listeners.forEach((listener) => listener?.(e));
|
|
876
879
|
}
|
|
877
|
-
|
|
878
|
-
onEmitEvent({
|
|
879
|
-
type: e.type,
|
|
880
|
-
data: e.data,
|
|
881
|
-
target: e.target,
|
|
882
|
-
defaultPrevented: e.defaultPrevented,
|
|
883
|
-
});
|
|
884
|
-
});
|
|
880
|
+
}, onEmitEvent);
|
|
885
881
|
|
|
886
882
|
useFocusEvents({ state, emitter });
|
|
887
883
|
|
package/src/useOnAction.tsx
CHANGED
|
@@ -88,8 +88,6 @@ export function useOnAction<State extends NavigationState>({
|
|
|
88
88
|
result === null && action.target === state.key ? state : result;
|
|
89
89
|
|
|
90
90
|
if (result !== null) {
|
|
91
|
-
onDispatchAction(action, state === result);
|
|
92
|
-
|
|
93
91
|
if (state !== result) {
|
|
94
92
|
const isPrevented = shouldPreventRemove(
|
|
95
93
|
emitter,
|
|
@@ -100,10 +98,16 @@ export function useOnAction<State extends NavigationState>({
|
|
|
100
98
|
);
|
|
101
99
|
|
|
102
100
|
if (isPrevented) {
|
|
101
|
+
onDispatchAction(action, true);
|
|
102
|
+
|
|
103
103
|
return true;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
onDispatchAction(action, false);
|
|
107
|
+
|
|
106
108
|
setState(result);
|
|
109
|
+
} else {
|
|
110
|
+
onDispatchAction(action, true);
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
if (onRouteFocusParent !== undefined) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
NavigationAction,
|
|
3
|
+
NavigationRoute,
|
|
3
4
|
NavigationState,
|
|
5
|
+
ParamListBase,
|
|
6
|
+
PartialRoute,
|
|
4
7
|
} from '@react-navigation/routers';
|
|
5
8
|
import * as React from 'react';
|
|
6
9
|
|
|
@@ -23,16 +26,18 @@ const VISITED_ROUTE_KEYS = Symbol('VISITED_ROUTE_KEYS');
|
|
|
23
26
|
export const shouldPreventRemove = (
|
|
24
27
|
emitter: NavigationEventEmitter<EventMapCore<any>>,
|
|
25
28
|
beforeRemoveListeners: Record<string, ChildBeforeRemoveListener | undefined>,
|
|
26
|
-
currentRoutes:
|
|
27
|
-
nextRoutes:
|
|
29
|
+
currentRoutes: NavigationRoute<ParamListBase, string>[],
|
|
30
|
+
nextRoutes: (
|
|
31
|
+
| NavigationRoute<ParamListBase, string>
|
|
32
|
+
| PartialRoute<NavigationRoute<ParamListBase, string>>
|
|
33
|
+
)[],
|
|
28
34
|
action: NavigationAction
|
|
29
35
|
) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.reverse();
|
|
36
|
+
const nextRoutesByKey = new Map(
|
|
37
|
+
nextRoutes
|
|
38
|
+
.map((route) => [route.key, route] as const)
|
|
39
|
+
.filter(([, route]) => route.key != null)
|
|
40
|
+
);
|
|
36
41
|
|
|
37
42
|
const visitedRouteKeys: Set<string> =
|
|
38
43
|
// @ts-expect-error: add this property to mark that we've already emitted this action
|
|
@@ -43,30 +48,53 @@ export const shouldPreventRemove = (
|
|
|
43
48
|
[VISITED_ROUTE_KEYS]: visitedRouteKeys,
|
|
44
49
|
};
|
|
45
50
|
|
|
46
|
-
|
|
51
|
+
// Call these in reverse order so last screens handle the event first
|
|
52
|
+
const reversedCurrentRoutes = [...currentRoutes].reverse();
|
|
53
|
+
|
|
54
|
+
for (const route of reversedCurrentRoutes) {
|
|
47
55
|
if (visitedRouteKeys.has(route.key)) {
|
|
48
56
|
// Skip if we've already emitted this action for this screen
|
|
49
57
|
continue;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
if (!nextRoutesByKey.has(route.key)) {
|
|
61
|
+
// The route is not in next state, so it's being removed
|
|
62
|
+
// First, we need to check if any child screens want to prevent it
|
|
63
|
+
const isPrevented = beforeRemoveListeners[route.key]?.(
|
|
64
|
+
beforeRemoveAction,
|
|
65
|
+
undefined
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (isPrevented) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
visitedRouteKeys.add(route.key);
|
|
73
|
+
|
|
74
|
+
const event = emitter.emit({
|
|
75
|
+
type: 'beforeRemove',
|
|
76
|
+
target: route.key,
|
|
77
|
+
data: { action: beforeRemoveAction },
|
|
78
|
+
canPreventDefault: true,
|
|
79
|
+
});
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
if (event.defaultPrevented) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
// The route is kept but its nested state changed, so propagate the check into the nested navigator
|
|
86
|
+
const nextRoute = nextRoutesByKey.get(route.key);
|
|
87
|
+
|
|
88
|
+
if (route.state != null && route.state !== nextRoute?.state) {
|
|
89
|
+
const isPrevented = beforeRemoveListeners[route.key]?.(
|
|
90
|
+
beforeRemoveAction,
|
|
91
|
+
nextRoute?.state
|
|
92
|
+
);
|
|
67
93
|
|
|
68
|
-
|
|
69
|
-
|
|
94
|
+
if (isPrevented) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
70
98
|
}
|
|
71
99
|
}
|
|
72
100
|
|
|
@@ -84,17 +112,21 @@ export function useOnPreventRemove({
|
|
|
84
112
|
|
|
85
113
|
React.useInsertionEffect(() => {
|
|
86
114
|
if (routeKey) {
|
|
87
|
-
return addKeyedListener?.(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
115
|
+
return addKeyedListener?.(
|
|
116
|
+
'beforeRemove',
|
|
117
|
+
routeKey,
|
|
118
|
+
(action, nextState) => {
|
|
119
|
+
const state = getState();
|
|
120
|
+
|
|
121
|
+
return shouldPreventRemove(
|
|
122
|
+
emitter,
|
|
123
|
+
beforeRemoveListeners,
|
|
124
|
+
state.routes,
|
|
125
|
+
nextState?.routes ?? [],
|
|
126
|
+
action
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
);
|
|
98
130
|
}
|
|
99
131
|
}, [addKeyedListener, beforeRemoveListeners, emitter, getState, routeKey]);
|
|
100
132
|
}
|
package/src/useRoute.tsx
CHANGED
|
@@ -22,11 +22,9 @@ type AllRouteNames<ParamList extends {}> =
|
|
|
22
22
|
| KeyOf<ParamList>
|
|
23
23
|
| AllNestedRouteNames<NestedParamLists<ParamList>>;
|
|
24
24
|
|
|
25
|
-
type AllNestedRouteNames<ParamLists> =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
? AllRouteNames<ParamList>
|
|
29
|
-
: never;
|
|
25
|
+
type AllNestedRouteNames<ParamLists> = ParamLists extends {}
|
|
26
|
+
? AllRouteNames<ParamLists>
|
|
27
|
+
: never;
|
|
30
28
|
|
|
31
29
|
/**
|
|
32
30
|
* Hook to access the route prop of the parent screen anywhere.
|