@react-navigation/routers 7.0.0-alpha.4 → 7.0.0-alpha.5
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/commonjs/CommonActions.js +10 -0
- package/lib/commonjs/CommonActions.js.map +1 -1
- package/lib/commonjs/StackRouter.js +108 -1
- package/lib/commonjs/StackRouter.js.map +1 -1
- package/lib/commonjs/TabRouter.js +43 -4
- package/lib/commonjs/TabRouter.js.map +1 -1
- package/lib/module/CommonActions.js +9 -0
- package/lib/module/CommonActions.js.map +1 -1
- package/lib/module/StackRouter.js +108 -1
- package/lib/module/StackRouter.js.map +1 -1
- package/lib/module/TabRouter.js +43 -4
- package/lib/module/TabRouter.js.map +1 -1
- package/lib/typescript/src/BaseRouter.d.ts +1 -9
- package/lib/typescript/src/BaseRouter.d.ts.map +1 -1
- package/lib/typescript/src/CommonActions.d.ts +9 -0
- package/lib/typescript/src/CommonActions.d.ts.map +1 -1
- package/lib/typescript/src/StackRouter.d.ts +32 -1
- package/lib/typescript/src/StackRouter.d.ts.map +1 -1
- package/lib/typescript/src/TabRouter.d.ts +4 -0
- package/lib/typescript/src/TabRouter.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +1 -2
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/CommonActions.tsx +13 -0
- package/src/StackRouter.tsx +189 -14
- package/src/TabRouter.tsx +67 -3
- package/src/types.tsx +1 -1
package/src/StackRouter.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import { BaseRouter } from './BaseRouter';
|
|
|
4
4
|
import type {
|
|
5
5
|
CommonNavigationAction,
|
|
6
6
|
DefaultRouterOptions,
|
|
7
|
+
NavigationRoute,
|
|
7
8
|
NavigationState,
|
|
8
9
|
ParamListBase,
|
|
9
10
|
Route,
|
|
@@ -43,6 +44,20 @@ export type StackActionType =
|
|
|
43
44
|
};
|
|
44
45
|
source?: string;
|
|
45
46
|
target?: string;
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
type: 'REMOVE';
|
|
50
|
+
payload: {
|
|
51
|
+
name: string;
|
|
52
|
+
params?: object;
|
|
53
|
+
};
|
|
54
|
+
source?: string;
|
|
55
|
+
target?: string;
|
|
56
|
+
}
|
|
57
|
+
| {
|
|
58
|
+
type: 'RETAIN';
|
|
59
|
+
source?: string;
|
|
60
|
+
target?: string;
|
|
46
61
|
};
|
|
47
62
|
|
|
48
63
|
export type StackRouterOptions = DefaultRouterOptions;
|
|
@@ -53,6 +68,10 @@ export type StackNavigationState<ParamList extends ParamListBase> =
|
|
|
53
68
|
* Type of the router, in this case, it's stack.
|
|
54
69
|
*/
|
|
55
70
|
type: 'stack';
|
|
71
|
+
/**
|
|
72
|
+
* List of routes, which are supposed to be preloaded before navigating to.
|
|
73
|
+
*/
|
|
74
|
+
preloadedRoutes: NavigationRoute<ParamList, keyof ParamList>[];
|
|
56
75
|
};
|
|
57
76
|
|
|
58
77
|
export type StackActionHelpers<ParamList extends ParamListBase> = {
|
|
@@ -113,6 +132,29 @@ export type StackActionHelpers<ParamList extends ParamListBase> = {
|
|
|
113
132
|
| [screen: RouteName, params: ParamList[RouteName], merge: boolean]
|
|
114
133
|
: never
|
|
115
134
|
): void;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Remove a screen from the preloaded list in the navigator.
|
|
138
|
+
*
|
|
139
|
+
* @param name Name of the route to remove preload.
|
|
140
|
+
* @param [params] Params object for the route.
|
|
141
|
+
*/
|
|
142
|
+
remove<RouteName extends keyof ParamList>(
|
|
143
|
+
...args: RouteName extends unknown
|
|
144
|
+
? undefined extends ParamList[RouteName]
|
|
145
|
+
?
|
|
146
|
+
| [screen: RouteName]
|
|
147
|
+
| [screen: RouteName, params: ParamList[RouteName]]
|
|
148
|
+
: [screen: RouteName, params: ParamList[RouteName]]
|
|
149
|
+
: never
|
|
150
|
+
): void;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Removes a screen from the active routes, at the same time
|
|
154
|
+
* retaining the screen in the preloaded screens list,
|
|
155
|
+
* so it is not getting detached.
|
|
156
|
+
*/
|
|
157
|
+
retain(): void;
|
|
116
158
|
};
|
|
117
159
|
|
|
118
160
|
export const StackActions = {
|
|
@@ -131,6 +173,12 @@ export const StackActions = {
|
|
|
131
173
|
popTo(name: string, params?: object, merge?: boolean): StackActionType {
|
|
132
174
|
return { type: 'POP_TO', payload: { name, params, merge } };
|
|
133
175
|
},
|
|
176
|
+
remove(name: string, params?: object): StackActionType {
|
|
177
|
+
return { type: 'REMOVE', payload: { name, params } };
|
|
178
|
+
},
|
|
179
|
+
retain(): StackActionType {
|
|
180
|
+
return { type: 'RETAIN' };
|
|
181
|
+
},
|
|
134
182
|
};
|
|
135
183
|
|
|
136
184
|
export function StackRouter(options: StackRouterOptions) {
|
|
@@ -155,6 +203,7 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
155
203
|
key: `stack-${nanoid()}`,
|
|
156
204
|
index: 0,
|
|
157
205
|
routeNames,
|
|
206
|
+
preloadedRoutes: [],
|
|
158
207
|
routes: [
|
|
159
208
|
{
|
|
160
209
|
key: `${initialRouteName}-${nanoid()}`,
|
|
@@ -174,20 +223,35 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
174
223
|
|
|
175
224
|
const routes = state.routes
|
|
176
225
|
.filter((route) => routeNames.includes(route.name))
|
|
177
|
-
.map(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
226
|
+
.map((route) => ({
|
|
227
|
+
...route,
|
|
228
|
+
key: route.key || `${route.name}-${nanoid()}`,
|
|
229
|
+
params:
|
|
230
|
+
routeParamList[route.name] !== undefined
|
|
231
|
+
? {
|
|
232
|
+
...routeParamList[route.name],
|
|
233
|
+
...route.params,
|
|
234
|
+
}
|
|
235
|
+
: route.params,
|
|
236
|
+
}));
|
|
237
|
+
|
|
238
|
+
const preloadedRoutes =
|
|
239
|
+
state.preloadedRoutes
|
|
240
|
+
?.filter((route) => routeNames.includes(route.name))
|
|
241
|
+
.map(
|
|
242
|
+
(route) =>
|
|
243
|
+
({
|
|
244
|
+
...route,
|
|
245
|
+
key: route.key || `${route.name}-${nanoid()}`,
|
|
246
|
+
params:
|
|
247
|
+
routeParamList[route.name] !== undefined
|
|
248
|
+
? {
|
|
249
|
+
...routeParamList[route.name],
|
|
250
|
+
...route.params,
|
|
251
|
+
}
|
|
252
|
+
: route.params,
|
|
253
|
+
}) as Route<string>
|
|
254
|
+
) ?? [];
|
|
191
255
|
|
|
192
256
|
if (routes.length === 0) {
|
|
193
257
|
const initialRouteName =
|
|
@@ -209,6 +273,7 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
209
273
|
index: routes.length - 1,
|
|
210
274
|
routeNames,
|
|
211
275
|
routes,
|
|
276
|
+
preloadedRoutes,
|
|
212
277
|
};
|
|
213
278
|
},
|
|
214
279
|
|
|
@@ -327,6 +392,14 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
327
392
|
}
|
|
328
393
|
}
|
|
329
394
|
|
|
395
|
+
if (!route) {
|
|
396
|
+
route = state.preloadedRoutes.find(
|
|
397
|
+
(route) =>
|
|
398
|
+
route.name === action.payload.name &&
|
|
399
|
+
id === getId?.({ params: route.params })
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
330
403
|
let params;
|
|
331
404
|
|
|
332
405
|
if (action.type === 'NAVIGATE' && action.payload.merge && route) {
|
|
@@ -379,11 +452,23 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
379
452
|
return {
|
|
380
453
|
...state,
|
|
381
454
|
index: routes.length - 1,
|
|
455
|
+
preloadedRoutes: state.preloadedRoutes.filter(
|
|
456
|
+
(route) => routes[routes.length - 1].key !== route.key
|
|
457
|
+
),
|
|
382
458
|
routes,
|
|
383
459
|
};
|
|
384
460
|
}
|
|
385
461
|
|
|
386
462
|
case 'NAVIGATE_DEPRECATED': {
|
|
463
|
+
if (
|
|
464
|
+
state.preloadedRoutes.find(
|
|
465
|
+
(route) =>
|
|
466
|
+
route.name === action.payload.name &&
|
|
467
|
+
id === getId?.({ params: route.params })
|
|
468
|
+
)
|
|
469
|
+
) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
387
472
|
if (!state.routeNames.includes(action.payload.name)) {
|
|
388
473
|
return null;
|
|
389
474
|
}
|
|
@@ -606,6 +691,96 @@ export function StackRouter(options: StackRouterOptions) {
|
|
|
606
691
|
|
|
607
692
|
return null;
|
|
608
693
|
|
|
694
|
+
case 'PRELOAD': {
|
|
695
|
+
const getId = options.routeGetIdList[action.payload.name];
|
|
696
|
+
const id = getId?.({ params: action.payload.params });
|
|
697
|
+
|
|
698
|
+
let route: Route<string> | undefined;
|
|
699
|
+
|
|
700
|
+
if (id !== undefined) {
|
|
701
|
+
route = state.routes.find(
|
|
702
|
+
(route) =>
|
|
703
|
+
route.name === action.payload.name &&
|
|
704
|
+
id === getId?.({ params: route.params })
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (route) {
|
|
709
|
+
return {
|
|
710
|
+
...state,
|
|
711
|
+
routes: state.routes.map((r) => {
|
|
712
|
+
if (r.key !== route?.key) {
|
|
713
|
+
return r;
|
|
714
|
+
}
|
|
715
|
+
return {
|
|
716
|
+
...r,
|
|
717
|
+
params:
|
|
718
|
+
routeParamList[action.payload.name] !== undefined
|
|
719
|
+
? {
|
|
720
|
+
...routeParamList[action.payload.name],
|
|
721
|
+
...action.payload.params,
|
|
722
|
+
}
|
|
723
|
+
: action.payload.params,
|
|
724
|
+
};
|
|
725
|
+
}),
|
|
726
|
+
};
|
|
727
|
+
} else {
|
|
728
|
+
return {
|
|
729
|
+
...state,
|
|
730
|
+
preloadedRoutes: state.preloadedRoutes
|
|
731
|
+
.filter(
|
|
732
|
+
(r) =>
|
|
733
|
+
r.name !== action.payload.name ||
|
|
734
|
+
id !== getId?.({ params: r.params })
|
|
735
|
+
)
|
|
736
|
+
.concat({
|
|
737
|
+
key: `${action.payload.name}-${nanoid()}`,
|
|
738
|
+
name: action.payload.name,
|
|
739
|
+
params:
|
|
740
|
+
routeParamList[action.payload.name] !== undefined
|
|
741
|
+
? {
|
|
742
|
+
...routeParamList[action.payload.name],
|
|
743
|
+
...action.payload.params,
|
|
744
|
+
}
|
|
745
|
+
: action.payload.params,
|
|
746
|
+
}),
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
case 'RETAIN': {
|
|
751
|
+
const index =
|
|
752
|
+
action.target === state.key && action.source
|
|
753
|
+
? state.routes.findIndex((r) => r.key === action.source)
|
|
754
|
+
: state.index;
|
|
755
|
+
|
|
756
|
+
if (index === -1) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const route = state.routes[index];
|
|
761
|
+
|
|
762
|
+
const routes = state.routes.filter((r) => r !== route);
|
|
763
|
+
return {
|
|
764
|
+
...state,
|
|
765
|
+
index: routes.length - 1,
|
|
766
|
+
routes,
|
|
767
|
+
preloadedRoutes: state.preloadedRoutes.concat(route),
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
case 'REMOVE': {
|
|
772
|
+
const getId = options.routeGetIdList[action.payload.name];
|
|
773
|
+
const id = getId?.({ params: action.payload.params });
|
|
774
|
+
|
|
775
|
+
return {
|
|
776
|
+
...state,
|
|
777
|
+
preloadedRoutes: state.preloadedRoutes.filter(
|
|
778
|
+
(route) =>
|
|
779
|
+
route.name !== action.payload.name ||
|
|
780
|
+
id !== getId?.({ params: route.params })
|
|
781
|
+
),
|
|
782
|
+
};
|
|
783
|
+
}
|
|
609
784
|
default:
|
|
610
785
|
return BaseRouter.getStateForAction(state, action);
|
|
611
786
|
}
|
package/src/TabRouter.tsx
CHANGED
|
@@ -41,6 +41,10 @@ export type TabNavigationState<ParamList extends ParamListBase> = Omit<
|
|
|
41
41
|
* List of previously visited route keys.
|
|
42
42
|
*/
|
|
43
43
|
history: { type: 'route'; key: string }[];
|
|
44
|
+
/**
|
|
45
|
+
* List of routes' key, which are supposed to be preloaded before navigating to.
|
|
46
|
+
*/
|
|
47
|
+
preloadedRouteKeys: string[];
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
export type TabActionHelpers<ParamList extends ParamListBase> = {
|
|
@@ -178,6 +182,7 @@ export function TabRouter({
|
|
|
178
182
|
routeNames,
|
|
179
183
|
history,
|
|
180
184
|
routes,
|
|
185
|
+
preloadedRouteKeys: [],
|
|
181
186
|
};
|
|
182
187
|
},
|
|
183
188
|
|
|
@@ -217,9 +222,10 @@ export function TabRouter({
|
|
|
217
222
|
routes.length - 1
|
|
218
223
|
);
|
|
219
224
|
|
|
225
|
+
const routeKeys = routes.map((route) => route.key);
|
|
226
|
+
|
|
220
227
|
const history =
|
|
221
|
-
state.history?.filter((it) =>
|
|
222
|
-
[];
|
|
228
|
+
state.history?.filter((it) => routeKeys.includes(it.key)) ?? [];
|
|
223
229
|
|
|
224
230
|
return changeIndex(
|
|
225
231
|
{
|
|
@@ -230,6 +236,10 @@ export function TabRouter({
|
|
|
230
236
|
routeNames,
|
|
231
237
|
history,
|
|
232
238
|
routes,
|
|
239
|
+
preloadedRouteKeys:
|
|
240
|
+
state.preloadedRouteKeys?.filter((key) =>
|
|
241
|
+
routeKeys.includes(key)
|
|
242
|
+
) ?? [],
|
|
233
243
|
},
|
|
234
244
|
index,
|
|
235
245
|
backBehavior,
|
|
@@ -303,7 +313,7 @@ export function TabRouter({
|
|
|
303
313
|
return null;
|
|
304
314
|
}
|
|
305
315
|
|
|
306
|
-
|
|
316
|
+
const updatedState = changeIndex(
|
|
307
317
|
{
|
|
308
318
|
...state,
|
|
309
319
|
routes: state.routes.map((route) => {
|
|
@@ -362,6 +372,13 @@ export function TabRouter({
|
|
|
362
372
|
backBehavior,
|
|
363
373
|
initialRouteName
|
|
364
374
|
);
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
...updatedState,
|
|
378
|
+
preloadedRouteKeys: updatedState.preloadedRouteKeys.filter(
|
|
379
|
+
(key) => key !== state.routes[updatedState.index].key
|
|
380
|
+
),
|
|
381
|
+
};
|
|
365
382
|
}
|
|
366
383
|
|
|
367
384
|
case 'GO_BACK': {
|
|
@@ -380,11 +397,58 @@ export function TabRouter({
|
|
|
380
397
|
|
|
381
398
|
return {
|
|
382
399
|
...state,
|
|
400
|
+
preloadedRouteKeys: state.preloadedRouteKeys.filter(
|
|
401
|
+
(key) => key !== state.routes[index].key
|
|
402
|
+
),
|
|
383
403
|
history: state.history.slice(0, -1),
|
|
384
404
|
index,
|
|
385
405
|
};
|
|
386
406
|
}
|
|
387
407
|
|
|
408
|
+
case 'PRELOAD': {
|
|
409
|
+
const routeIndex = state.routes.findIndex(
|
|
410
|
+
(route) => route.name === action.payload.name
|
|
411
|
+
);
|
|
412
|
+
if (routeIndex === -1) {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const route = state.routes[routeIndex];
|
|
416
|
+
|
|
417
|
+
const getId = routeGetIdList[route.name];
|
|
418
|
+
|
|
419
|
+
const currentId = getId?.({ params: route.params });
|
|
420
|
+
const nextId = getId?.({ params: action.payload.params });
|
|
421
|
+
|
|
422
|
+
const key =
|
|
423
|
+
currentId === nextId ? route.key : `${route.name}-${nanoid()}`;
|
|
424
|
+
|
|
425
|
+
const params =
|
|
426
|
+
action.payload.params !== undefined ||
|
|
427
|
+
routeParamList[route.name] !== undefined
|
|
428
|
+
? {
|
|
429
|
+
...routeParamList[route.name],
|
|
430
|
+
...action.payload.params,
|
|
431
|
+
}
|
|
432
|
+
: undefined;
|
|
433
|
+
|
|
434
|
+
const newRoute =
|
|
435
|
+
params !== route.params ? { ...route, key, params } : route;
|
|
436
|
+
|
|
437
|
+
return {
|
|
438
|
+
...state,
|
|
439
|
+
preloadedRouteKeys: state.preloadedRouteKeys
|
|
440
|
+
.filter((key) => key !== route.key)
|
|
441
|
+
.concat(newRoute.key),
|
|
442
|
+
routes: state.routes.map((route, index) =>
|
|
443
|
+
index === routeIndex ? newRoute : route
|
|
444
|
+
),
|
|
445
|
+
history:
|
|
446
|
+
key === route.key
|
|
447
|
+
? state.history
|
|
448
|
+
: state.history.filter((record) => record.key !== route.key),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
388
452
|
default:
|
|
389
453
|
return BaseRouter.getStateForAction(state, action);
|
|
390
454
|
}
|
package/src/types.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import type * as CommonActions from './CommonActions';
|
|
|
2
2
|
|
|
3
3
|
export type CommonNavigationAction = CommonActions.Action;
|
|
4
4
|
|
|
5
|
-
type NavigationRoute<
|
|
5
|
+
export type NavigationRoute<
|
|
6
6
|
ParamList extends ParamListBase,
|
|
7
7
|
RouteName extends keyof ParamList,
|
|
8
8
|
> = Route<Extract<RouteName, string>, ParamList[RouteName]> & {
|